@aapicoits/powermap-web-sdk 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -352,7 +352,7 @@
|
|
|
352
352
|
<div class="pm-draw-divider" data-for="settings" style="display: none;"></div>
|
|
353
353
|
<button class="pm-draw-btn" data-tool="settings" title="Settings" style="display: none;">${d}</button>
|
|
354
354
|
`:""}
|
|
355
|
-
`,this.toolbar.innerHTML=b,this.tooltip&&this.tooltip.attachToToolbar(this.toolbar)}_exportGeoJSON(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometryExported",{data:t,format:e});const o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),i=URL.createObjectURL(o),n=document.createElement("a");n.href=i,n.download=`powermap-export-${new Date().getTime()}.json`,n.click(),URL.revokeObjectURL(i)}catch(e){const t=e instanceof PowerMapError?e:new PowerMapError(`Failed to export data: ${e.message}`,ErrorCode.UNKNOWN,"editor",{originalError:e});this.eventBus.emit("error",t)}}_triggerImport(){const e=document.createElement("input");e.type="file",e.accept=".json,application/json",e.onchange=t=>{const o=t.target.files[0];if(!o)return;const i=new FileReader;i.onload=n=>{try{const s=JSON.parse(n.target.result),a=this.mode==="indoor"?"imdf":"standard";this.geometryManager.import(s,{format:a})}catch(s){const a=s instanceof PowerMapError?s:new PowerMapError(`Failed to parse or import GeoJSON: ${s.message}`,ErrorCode.INVALID_PARAMETERS,"editor",{originalError:s});this.eventBus.emit("error",a)}},i.onerror=()=>{const n=new PowerMapError("Failed to read the selected file.",ErrorCode.UNKNOWN,"editor");this.eventBus.emit("error",n)},i.readAsText(o)},e.click()}_triggerSave(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometrySaveRequested",{data:t,format:e})}catch(e){typeof PowerMapError<"u"&&e instanceof PowerMapError?this.eventBus.emit("error",e):console.error(e)}}}class An{constructor(e){this.mapManager=e.registry.get("map"),this.geometryManager=e.registry.get("geometry"),this.eventBus=e.eventBus,this.isEnabled=!1,this.control=null,this.mode=e.mode||"standard"}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t){this.eventBus.on("mapLoaded",()=>this.enable(e));return}this.geometryManager.getDrawInstance()||this.geometryManager.initDraw(t);const o=e.position||"bottom-left";this.mode=e.mode||this.mode;try{this.control=new mn(this.geometryManager,this.eventBus,{mode:this.mode}),this.control.setMode&&this.control.setMode(this.mode),t.addControl(this.control,o),this.isEnabled=!0}catch(i){const n=new w(`Failed to enable editor: ${i.message}`,C.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}setMode(e){this.mode=e,this.control&&this.control.setMode&&this.control.setMode(e)}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&this.control&&e.removeControl(this.control),this.control=null,this.isEnabled=!1}attach(e){const t=typeof e=="object"?e.id:e;if(!t)throw new w("Feature ID is required to attach editor.",C.INVALID_PARAMETERS,"editor");const o=this.geometryManager.getDrawInstance();if(!o)throw new w("Cannot attach: Draw instance not initialized.",C.MAP_NOT_INITIALIZED,"editor");try{o.changeMode("direct_select",{featureId:t})}catch(i){const n=new w(`Could not attach to feature ${t}: ${i.message}`,C.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}detach(){const e=this.geometryManager.getDrawInstance();e&&e.changeMode("simple_select")}}class yn{constructor(e){this.mapManager=e.registry.get("map"),this.eventBus=e.eventBus,this.isEnabled=!1,this.panel=null,this.fps=0,this.frameCount=0,this.lastTime=performance.now(),this.lastFpsCalc=this.lastTime,this._onRender=this._onRender.bind(this),this._onMove=this._onMove.bind(this),this.showFps=!0,this.showCoord=!0}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t)throw new w("Cannot enable debug panel: Map is not initialized.",C.MAP_NOT_INITIALIZED,"debug");const o=e.position||"top-left";this.panel=document.createElement("div"),this.panel.className="pm-debug-panel",Object.assign(this.panel.style,{position:"absolute",background:"rgba(0, 0, 0, 0.7)",color:"#0f0",padding:"12px",fontFamily:'"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',fontSize:"13px",borderRadius:"8px",zIndex:"9999",pointerEvents:"none",lineHeight:"1.6",boxShadow:"0 4px 6px rgba(0,0,0,0.3)",border:"1px solid rgba(0,255,0,0.3)"}),o.includes("top")&&(this.panel.style.top="10px"),o.includes("bottom")&&(this.panel.style.bottom="40px"),o.includes("left")&&(this.panel.style.left="10px"),o.includes("right")&&(this.panel.style.right="10px"),t.getContainer().appendChild(this.panel),t.on("render",this._onRender),t.on("move",this._onMove),this.isEnabled=!0,this._updateUI()}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&(e.off("render",this._onRender),e.off("move",this._onMove)),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null,this.isEnabled=!1}showFPS(e=!0){this.showFps=e,this._updateUI()}showCoordinate(e=!0){this.showCoord=e,this._updateUI()}_onRender(){const e=performance.now();this.frameCount++,e>=this.lastFpsCalc+1e3&&(this.fps=Math.round(this.frameCount*1e3/(e-this.lastFpsCalc)),this.frameCount=0,this.lastFpsCalc=e,this._updateUI())}_onMove(){this._updateUI()}_updateUI(){if(!this.isEnabled||!this.panel)return;const e=this.mapManager.getMap();if(!e)return;let t="<strong>PowerMap Debug</strong><br/>";if(this.showFps){const o=this.fps<30?"red":this.fps<50?"orange":"#0f0";t+=`FPS: <span style="color:${o}">${this.fps}</span><br/>`}if(this.showCoord){const o=e.getCenter();t+=`Lng: ${o.lng.toFixed(5)}<br/>`,t+=`Lat: ${o.lat.toFixed(5)}<br/>`,t+=`Zoom: ${e.getZoom().toFixed(2)}<br/>`,t+=`Pitch: ${e.getPitch().toFixed(1)}°<br/>`,t+=`Bearing: ${e.getBearing().toFixed(1)}°<br/>`;const i=e.getBounds();t+='<div style="font-size:10px; color:#aaa; margin-top:8px;">',t+=`NE: ${i.getNorthEast().lng.toFixed(3)}, ${i.getNorthEast().lat.toFixed(3)}<br/>`,t+=`SW: ${i.getSouthWest().lng.toFixed(3)}, ${i.getSouthWest().lat.toFixed(3)}`,t+="</div>"}this.panel.innerHTML=t}}const ct=new Map;async function bn(r){if(ct.has(r))return ct.get(r);const e=await fetch(r);if(!e.ok)throw new w(`Fetch style failed: ${r}`,C.API_REQUEST_FAILED,"layers");const t=await e.json();return ct.set(r,t),t}function wn(r){return`${r}/api/v2/map/vtile`}function ue(r,e){if(!e||r.includes("apikey="))return r;const t=r.includes("?")?"&":"?";return`${r}${t}apikey=${encodeURIComponent(e)}`}function vn(r,e,t){if(!r)return r;if(r.startsWith(e))return ue(r,t);if(r.startsWith("mbtiles://")){const i=r.replace("mbtiles://","").replace(/\.mbtiles$/i,"");return ue(`${e}/data/${i}.json`,t)}const o=r.match(/\/data\/([^/]+)\.json$/i);return o?ue(`${e}/data/${o[1]}.json`,t):r}function Cn(r,e,t){if(!r)return r;if(r.startsWith(e))return ue(r,t);const o=r.match(/^https?:\/\/[^/]+\/data\/([^/]+)\/\{z\}\/\{x\}\/\{y\}\.pbf(?:\?.*)?$/i);return o?ue(`${e}/data/${o[1]}/{z}/{x}/{y}.pbf`,t):r}function En(r,e,t,o,i,n=()=>!0){var s;try{if(!n()||!((s=r==null?void 0:r.getStyle)!=null&&s.call(r))||r.getSource(e))return;const a={type:"vector"};if(Array.isArray(t.tiles)&&t.tiles.length)a.tiles=t.tiles.map(l=>Cn(l,o,i));else if(t.url&&t.url.startsWith("mbtiles://")){const l=t.url.replace("mbtiles://","").replace(/\.mbtiles$/i,"");a.tiles=[ue(`${o}/data/${l}/{z}/{x}/{y}.pbf`,i)]}else if(t.url){const l=t.url.match(/\/data\/([^/]+)\.json(?:\?.*)?$/i);l?a.tiles=[ue(`${o}/data/${l[1]}/{z}/{x}/{y}.pbf`,i)]:a.url=vn(t.url,o,i)}if(!n())return;r.addSource(e,a)}catch{}}function xn(r){var e,t,o;try{return(o=(((t=(e=r==null?void 0:r.getStyle)==null?void 0:e.call(r))==null?void 0:t.layers)||[]).find(i=>i.type==="symbol"))==null?void 0:o.id}catch{return}}async function Le(r,e,{ns:t="rp",includeFn:o=()=>!0,defaultVis:i="none",beforeId:n=void 0,base:s,apiKey:a}={}){var g;if(!(r!=null&&r.getStyle))return;const l=r.__pmNonce,c=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==l?!1:!!r.getStyle()}catch{return!1}},u=f=>{try{return c()?r.getLayer(f):void 0}catch{return}};if(!c())return;let d=null;try{d=await bn(e)}catch{console.warn("fetchStyle failed:",e);return}if(!c())return;const p={};for(const[f,m]of Object.entries(d.sources||{})){if(!c())return;const y=`${t}-src-${f}`;En(r,y,m,s,a,c),p[f]=y}for(const f of d.layers||[]){if(!o(f))continue;if(!c())return;const m=`${t}-${f.id}`;if(u(m))continue;const y=JSON.parse(JSON.stringify(f));y.id=m,p[y.source]&&(y.source=p[y.source]),y.layout=y.layout||{},y.layout.visibility=i;try{if(!c())return;r.addLayer(y,n)}catch{}}if(!c())return;const h=(g=r.__pmDesiredVis)==null?void 0:g[t];return typeof h=="boolean"&&lo(r,t,h,c),{prefix:t}}function lo(r,e,t,o=()=>!0){var i;try{if(!o())return;const n=t?"visible":"none",s=(((i=r.getStyle())==null?void 0:i.layers)||[]).filter(a=>a.id.startsWith(e+"-"));for(const a of s){if(!o())return;try{r.setLayoutProperty(a.id,"visibility",n)}catch{}}}catch{}}async function Ft(r,e,t=e,o){if(!(r!=null&&r.getStyle))return;const i=r.__pmNonce,n=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==i?!1:!!r.getStyle()}catch{return!1}},s=y=>{try{return n()?!!(r.hasImage&&r.hasImage(y)):!1}catch{return!1}};if(r.isStyleLoaded&&!r.isStyleLoaded()&&await new Promise(y=>{if(!n())return y();const b=()=>{E(),y()},E=()=>{try{r.off("styledata",b)}catch{}try{r.off("load",b)}catch{}};r.on("styledata",b),r.on("load",b),setTimeout(()=>{E(),y()},1500)}),!n()||(r.__pmSpriteLoaded=r.__pmSpriteLoaded||{},r.__pmSpriteLoaded[t]))return;const a=y=>ue(y,o),c=(window.devicePixelRatio||1)>1.5?[a(`${e}@2x.json`),a(`${e}@2x.png`),a(`${e}.json`),a(`${e}.png`)]:[a(`${e}.json`),a(`${e}.png`),a(`${e}@2x.json`),a(`${e}@2x.png`)];let u,d,p=1;for(let y=0;y<c.length;y+=2){if(!n())return;try{const[b,E]=[c[y],c[y+1]],x=await fetch(b);if(!x.ok)throw 0;if(u=await x.json(),!n())return;const M=await fetch(E);if(!M.ok)throw 0;const T=await M.blob();if(!n())return;d="createImageBitmap"in window?await createImageBitmap(T):await m(T),p=b.includes("@2x")?2:1;break}catch{}}if(!n())return;if(!u||!d){console.warn("sprite load failed for",e);return}const h="createImageBitmap"in window&&d instanceof ImageBitmap,g=h?null:document.createElement("canvas"),f=g?g.getContext("2d"):null;for(const[y,b]of Object.entries(u)){if(!n())return;if(s(y))continue;const{x:E,y:x,width:M,height:T,sdf:k}=b;let R;if(h?R=await createImageBitmap(d,E,x,M,T):(g.width=M,g.height=T,f.clearRect(0,0,M,T),f.drawImage(d,E,x,M,T,0,0,M,T),R=g),!n())return;try{r.addImage(y,R,{pixelRatio:p,sdf:!!k})}catch{}}if(!n())return;r.__pmSpriteLoaded[t]=!0;function m(y){return new Promise((b,E)=>{const x=new Image;x.onload=()=>b(x),x.onerror=E,x.crossOrigin="anonymous",x.src=URL.createObjectURL(y)})}}function Mn(r,e){const t=o=>ue(o,e);return[{key:"city",label:"CITY PLAN",items:[se("pm-bangkok-layer","Bangkok","PM_Bangkok",r,e),se("pm-nakhon-pathom-layer","Nakhon Pathom","PM_Nakhon_Pathom",r,e),se("pm-ayutthaya-layer","Ayutthaya","PM_Phra_Nakhon_Si_Ayutthaya",r,e),se("pm-chonburi-layer","Chon Buri","PM_Chon_Buri",r,e),se("pm-samutprakan-layer","Samut Prakan","PM_Samut_Prakan",r,e),se("pm-rayong-layer","Rayong","PM_Rayong",r,e),se("pm-samutsakhon-layer","Samut Sakhon","PM_Samut_Sakhon",r,e,{tileSize:128}),se("pm-pathumthani-layer","Pathum Thani","PM_Pathumthani",r,e,{tileSize:128}),se("pm-ubonratchathani-layer","Ubon Ratchathani","PM_Ubon_Ratchathani",r,e,{tileSize:128}),se("pm-nonthaburi-layer","Nonthaburi","PM_Nonthaburi",r,e,{tileSize:128}),se("pm-chachoengsao-layer","Chachoengsao","PM_Chachoengsao",r,e,{tileSize:128})]},{key:"transport",label:"TRANSPORT",items:[{id:"pm-road-vt",name:"Road",groupPrefix:"vt-road",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/road_poi/style.json`);o.__pmRoadVt||(await Le(o,i,{ns:"vt-road",defaultVis:"none",includeFn:n=>n?n.type==="line"?!0:n.type==="symbol"&&n.source==="road"?n["source-layer"]==="road_name":!1:!1,base:r,apiKey:e}),o.__pmRoadVt=!0)}},{id:"pm-post-elec-vt",name:"Post Election",groupPrefix:"vt-postelec",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/post_elec/style.json`),n=`${r}/transport/post_elec/sprite`;o.__pmGroupReady=o.__pmGroupReady||{},!o.__pmGroupReady["vt-postelec"]&&(await Ft(o,n,"post_elec",e),await Le(o,i,{ns:"vt-postelec",defaultVis:"none",includeFn:s=>(s==null?void 0:s.type)==="symbol",base:r,apiKey:e}),o.__pmGroupReady["vt-postelec"]=!0)}},Ie({id:"pm-future-motorway-th-vt",name:"Future Motorway TH",ns:"vt-fmw-th",stylePath:"transport/future_motorway_th",flagPrefix:"__pmFutureMwTh",base:r,apiKey:e,tk:t}),Ie({id:"pm-future-motorway-en-vt",name:"Future Motorway EN",ns:"vt-fmw-en",stylePath:"transport/future_motorway_en",flagPrefix:"__pmFutureMwEn",base:r,apiKey:e,tk:t}),Ie({id:"pm-current-railway-th-vt",name:"Current Railway TH",ns:"vt-railth-cur",stylePath:"transport/current_railway_th",flagPrefix:"__pmRailTh",base:r,apiKey:e,tk:t}),Ie({id:"pm-current-railway-en-vt",name:"Current Railway EN",ns:"vt-railen-cur",stylePath:"transport/current_railway_en",flagPrefix:"__pmRailEn",base:r,apiKey:e,tk:t}),Ie({id:"pm-future-railway-th-vt",name:"Future Railway TH",ns:"vt-railth-future",stylePath:"transport/future_railway_th",flagPrefix:"__pmFRailTh",base:r,apiKey:e,tk:t}),Ie({id:"pm-future-railway-en-vt",name:"Future Railway EN",ns:"vt-railen-future",stylePath:"transport/future_railway_en",flagPrefix:"__pmFRailEn",base:r,apiKey:e,tk:t}),Ye({id:"pm-current-bts-mrt-th-vt",name:"Current BTS MRT TH",ns:"vt-btsmrt-cur-th",stylePath:"transport/current_bts_mrt_th",flagPrefix:"__pmBTSMRTTH",base:r,apiKey:e,tk:t}),Ye({id:"pm-current-bts-mrt-en-vt",name:"Current BTS MRT EN",ns:"vt-btsmrt-cur-en",stylePath:"transport/current_bts_mrt_en",flagPrefix:"__pmBTSMRTEN",base:r,apiKey:e,tk:t}),Ye({id:"pm-future-bts-mrt-th-vt",name:"Future BTS MRT TH",ns:"vt-btsmrt-fut-th",stylePath:"transport/future_bts_mrt_th",flagPrefix:"__pmBTSMRT_FUTTH",base:r,apiKey:e,tk:t}),Ye({id:"pm-future-bts-mrt-en-vt",name:"Future BTS MRT EN",ns:"vt-btsmrt-fut-en",stylePath:"transport/future_bts_mrt_en",flagPrefix:"__pmBTSMRT_FUTEN",base:r,apiKey:e,tk:t})]},{key:"insight",label:"INSIGHT DATA",items:[{id:"pm-viirs-blackmarble-layer",name:"Night Lights",ensure:o=>{o!=null&&o.getStyle()&&(o.getSource("pm-viirs-blackmarble-source")||o.addSource("pm-viirs-blackmarble-source",{type:"raster",tiles:["https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/VIIRS_Black_Marble/default/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.png"],tileSize:256,minzoom:0,maxzoom:8}),o.getLayer("pm-viirs-blackmarble-layer")||o.addLayer({id:"pm-viirs-blackmarble-layer",type:"raster",source:"pm-viirs-blackmarble-source",paint:{"raster-opacity":.7},layout:{visibility:"none"}}))}},{id:"pm-maptiler-satellite-layer",name:"Satellite",ensure:o=>{if(!(o!=null&&o.getStyle()))return;const i=o.__pmMaptilerKey;if(!i){console.warn("PowerMap LayerManager: maptilerKey not provided, satellite layer skipped.");return}if(o.getSource("pm-maptiler-satellite-source")||o.addSource("pm-maptiler-satellite-source",{type:"raster",tiles:[`https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=${encodeURIComponent(i)}`],tileSize:256,minzoom:0,maxzoom:22}),!o.getLayer("pm-maptiler-satellite-layer")){const n=xn(o);o.addLayer({id:"pm-maptiler-satellite-layer",type:"raster",source:"pm-maptiler-satellite-source",paint:{"raster-opacity":1},layout:{visibility:"none"}},n)}}}]}]}const ut={"pm-road-vt":{prefix:"vt-road"},"pm-road-poi-vt":{prefix:"vt-roadpoi"},"pm-post-elec-vt":{prefix:"vt-postelec"},"pm-future-motorway-th-vt":{prefix:"vt-fmw-th"},"pm-future-motorway-en-vt":{prefix:"vt-fmw-en"},"pm-current-railway-th-vt":{prefix:"vt-railth-cur"},"pm-current-railway-en-vt":{prefix:"vt-railen-cur"},"pm-future-railway-th-vt":{prefix:"vt-railth-future"},"pm-future-railway-en-vt":{prefix:"vt-railen-future"},"pm-current-bts-mrt-th-vt":{prefix:"vt-btsmrt-cur-th"},"pm-current-bts-mrt-en-vt":{prefix:"vt-btsmrt-cur-en"},"pm-future-bts-mrt-th-vt":{prefix:"vt-btsmrt-fut-th"},"pm-future-bts-mrt-en-vt":{prefix:"vt-btsmrt-fut-en"}};function se(r,e,t,o,i,n={}){const s=n.tileSize||256;return{id:r,name:e,ensure:a=>{if(!(a!=null&&a.getStyle()))return;const l=r.replace("-layer","-source");a.getSource(l)||a.addSource(l,{type:"raster",tiles:[ue(`${o}/data/${t}/{z}/{x}/{y}.png`,i)],tileSize:s,minzoom:8,maxzoom:16}),a.getLayer(r)||a.addLayer({id:r,type:"raster",source:l,paint:{"raster-opacity":1},layout:{visibility:"none"}})}}}function Ie({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}Round1`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}Round1`]=!0),l[`${i}Sprite`]||(await Ft(l,u,o.replace("/","_"),s),l[`${i}Sprite`]=!0),l[`${i}Round2`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol",base:n,apiKey:s}),l[`${i}Round2`]=!0)}}}function Ye({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}_Lines`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}_Lines`]=!0),l[`${i}_Sprite`]||(await Ft(l,u,o.replace("/","_"),s),l[`${i}_Sprite`]=!0),l[`${i}_Symbols`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol"&&d["source-layer"]==="bts_mrt_station",base:n,apiKey:s}),l[`${i}_Symbols`]=!0)}}}class In{constructor(e){this.context=e,this.eventBus=e.eventBus,this.authManager=e.authManager;const t=this.authManager.getBaseUrl();this._base=wn(t),this._apiKey=e.options.mapApiKey,this._catalog=Mn(this._base,this._apiKey),this._ensured=new Set,this._layerState=new Map,e.options.maptilerKey&&(this._maptilerKey=e.options.maptilerKey),this.eventBus.on("mapLoaded",({map:o})=>{this._maptilerKey&&o&&(o.__pmMaptilerKey=this._maptilerKey),o.on("style.load",async()=>{for(const[i,n]of this._layerState.entries())try{const s=this._findItem(i);s&&await s.item.ensure(o),n.visible!==void 0&&this._setVisibility(i,n.visible),n.opacity!==void 0&&this.setOpacity(i,n.opacity)}catch(s){console.warn(`LayerManager: Failed to auto-restore layer ${i}`,s)}})})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}_findItem(e){for(const t of this._catalog){const o=t.items.find(i=>i.id===e);if(o)return{item:o,group:t}}return null}getCatalog(){return this._catalog.map(e=>({key:e.key,label:e.label,items:e.items.map(t=>({id:t.id,name:t.name,groupPrefix:t.groupPrefix||null}))}))}getGroup(e){const t=this._catalog.find(o=>o.key===e);return t?t.items.map(o=>({id:o.id,name:o.name})):null}getLayerState(e){var n;const t=this._getMap(),o=this._ensured.has(e);let i=null;if(t&&o){const s=ut[e];if(s)try{const a=(((n=t.getStyle())==null?void 0:n.layers)||[]).filter(l=>l.id.startsWith(s.prefix+"-"));i=a.length>0&&a.some(l=>t.getLayoutProperty(l.id,"visibility")==="visible")}catch{i=!1}else try{i=t.getLayoutProperty(e,"visibility")==="visible"}catch{i=!1}}return{loaded:o,visible:i}}async ensure(e){const t=this._getMap();if(!t)throw new w("Map is not ready. Call ensure() after mapLoaded event.",C.INVALID_PARAMETERS,"layers");const o=this._findItem(e);if(!o)throw new w(`Layer "${e}" not found in catalog. Use getCatalog() to see available layers.`,C.INVALID_PARAMETERS,"layers");try{await o.item.ensure(t),this._ensured.add(e),this.eventBus.emit("layerEnsured",{layerId:e,group:o.group.key})}catch(i){throw new w(`Failed to ensure layer "${e}": ${i.message}`,C.API_REQUEST_FAILED,"layers",{originalError:i})}}async show(e){this._ensured.has(e)||await this.ensure(e);const t=this._layerState.get(e)||{};t.visible=!0,this._layerState.set(e,t),this._setVisibility(e,!0),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!0})}hide(e){const t=this._layerState.get(e)||{};t.visible=!1,this._layerState.set(e,t),this._setVisibility(e,!1),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!1})}async toggle(e){const t=this.getLayerState(e);t.loaded?t.visible?this.hide(e):this.show(e):await this.show(e)}setOpacity(e,t){var s;const o=this._layerState.get(e)||{};o.opacity=t,this._layerState.set(e,o);const i=this._getMap();if(!i)return;const n=ut[e];if(n)try{const a=(((s=i.getStyle())==null?void 0:s.layers)||[]).filter(l=>l.id.startsWith(n.prefix+"-"));for(const l of a)try{l.type==="line"?i.setPaintProperty(l.id,"line-opacity",t):l.type==="symbol"?(i.setPaintProperty(l.id,"icon-opacity",t),i.setPaintProperty(l.id,"text-opacity",t)):l.type==="fill"&&i.setPaintProperty(l.id,"fill-opacity",t)}catch{}}catch{}else try{const a=i.getLayer(e);a&&(a.type==="raster"?i.setPaintProperty(e,"raster-opacity",t):a.type==="line"?i.setPaintProperty(e,"line-opacity",t):a.type==="fill"&&i.setPaintProperty(e,"fill-opacity",t))}catch{}}async showGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)await this.show(o.id)}hideGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)this.hide(o.id)}hideAll(){for(const e of this._catalog)for(const t of e.items)this.hide(t.id)}_setVisibility(e,t){const o=this._getMap();if(!o)return;const i=ut[e];if(i){const n=!!t;if(o.__pmDesiredVis=o.__pmDesiredVis||{},o.__pmDesiredVis[i.prefix]=n,lo(o,i.prefix,n),o.getLayer(e))try{o.setLayoutProperty(e,"visibility",n?"visible":"none")}catch{}else try{o.addLayer({id:e,type:"background",layout:{visibility:n?"visible":"none"},paint:{"background-opacity":0}})}catch{}return}if(o.getLayer(e))try{o.setLayoutProperty(e,"visibility",t?"visible":"none")}catch{}}}class kn{constructor(e){this.context=e,this.baseUrl="http://localhost:3000/indoor-api",this._geojsonCache={}}setBaseUrl(e){return this.baseUrl=e.replace(/\/$/,""),this}async getVenues(){return this._fetchJSON("/venues")}async getBuildings(e){const t=e?`/buildings?venueId=${e}`:"/buildings";return this._fetchJSON(t)}async getFloors(e){if(!e)throw new Error("buildingId is required");return this._fetchJSON(`/floors?buildingId=${e}`)}async getFloorGeoJSON(e){if(!e)throw new Error("floorId is required");if(this._geojsonCache[e])return JSON.parse(JSON.stringify(this._geojsonCache[e]));const t=await this._fetchJSON(`/floors/${e}/geojson`);return this._geojsonCache[e]=JSON.parse(JSON.stringify(t)),t}async search(e,t={}){if(!e)throw new Error("Search query is required");if(!t.buildingId)throw new w("buildingId is required for indoor search",C.INVALID_PARAMETERS,"indoor");let o=`/search?q=${encodeURIComponent(e)}&buildingId=${t.buildingId}`;return t.category&&(o+=`&category=${t.category}`),t.limit&&(o+=`&limit=${t.limit}`),this._fetchJSON(o)}async _fetchJSON(e){const t=this.context.authManager;if(!t)throw new w("AuthManager not found in SDK context.",C.MAP_NOT_INITIALIZED,"indoor");const o=`${this.baseUrl}${e}`,i=await t.fetchWithAuth(o);if(!i.ok)throw new w(`API Request failed with status ${i.status}`,C.UNKNOWN,"indoor",{status:i.status});return await i.json()}}class Bn{constructor(e){var t,o;this.context=e,this.map=(t=this.context.mapManager)==null?void 0:t.getMap(),this.routeData=null,this.activeFloorId=null,this.markers={start:null,end:null},this.backendUrl=(o=this.context.options)!=null&&o.baseUrl?this.context.options.baseUrl+"/indoor-api":"https://maps.powermap.live/indoor-api"}_getMap(){var e;if(this.map)return this.map;if(this.context.mapManager)return this.context.mapManager.getMap();if(this.context.registry&&this.context.registry.get){const t=this.context.registry.get("map");return(t==null?void 0:t.map)||((e=t==null?void 0:t.getMap)==null?void 0:e.call(t))}return null}setMap(e){this.map=e}async calculateRoute(e,t,o,i,n){var a,l;const s=new URL(`${this.backendUrl}/route`);s.searchParams.set("buildingId",e),s.searchParams.set("startFloorId",t),s.searchParams.set("startLng",o[0]),s.searchParams.set("startLat",o[1]),s.searchParams.set("endFloorId",i),s.searchParams.set("endLng",n[0]),s.searchParams.set("endLat",n[1]);try{let c;if(this.context.authManager?c=await this.context.authManager.fetchWithAuth(s.toString(),{source:"indoor-route"}):c=await fetch(s.toString(),{headers:{"x-client-id":this.context.mapApiKey||((a=this.context.auth)==null?void 0:a.clientId),"x-client-secret":(l=this.context.auth)==null?void 0:l.clientSecret}}),!c.ok)throw new Error("Failed to fetch indoor route");const u=await c.json();this.routeData=u,this.activeFloorId=t,this.drawRoute(this.activeFloorId);let d=0,p=0,h=[],g=null;if(u&&u.type==="FeatureCollection"){const m=u.properties||(u.features.length>0?u.features[0].properties:{});d=m.distance||0,p=m.duration||Math.round(d/1.4),h=m.instructions||[],g=u.features.length>0?u.features[0].geometry:null;const y=u.features.flatMap(b=>{var E;return((E=b.geometry)==null?void 0:E.coordinates)||[]});if(y.length>1){const b=y.reduce((E,x)=>E.extend(x),new H.LngLatBounds(y[0],y[0]));this._getMap()&&this._getMap().fitBounds(b,{padding:60,duration:1e3})}}const f=h.map(m=>{var E;let y=null;(E=m.maneuver)!=null&&E.location?y=m.maneuver.location:m.interval&&coords.length>0&&(y=coords[m.interval[0]]);const b=m.maneuver||{type:"turn",instruction:m.text};return!b.location&&y&&(b.location=y),{distance:m.distance,duration:m.time?m.time/1e3:Math.round((m.distance||0)/1.4),name:m.street_name||"",floorId:m.floorId,maneuver:b}});return{distance:d,duration:p,steps:f,geometry:g,raw:u}}catch(c){throw console.error("PowerMap SDK: Indoor routing failed",c),this.clearRoute(),c}}setActiveFloor(e){this.activeFloorId=e,this.routeData&&this.drawRoute(e),this._updateMarkerVisibility()}clearRoute(){this.routeData=null,this._removeLayers(),this.markers.start&&this.markers.start.remove(),this.markers.end&&this.markers.end.remove(),this.markers={start:null,end:null}}drawRoute(e){const t=this._getMap();if(!t||!this.routeData)return;let o=this.routeData;o.type==="FeatureCollection"&&e&&(o={...o,features:o.features.filter(s=>{var a;return!((a=s.properties)!=null&&a.floorId)||String(s.properties.floorId)===String(e)})});const i="pm-indoor-route",n=t.getSource(i);n?n.setData(o):t.addSource(i,{type:"geojson",data:o}),this._ensureLayers(i)}_ensureLayers(e){const t=this._getMap();t&&(t.getLayer(`${e}-casing`)||t.addLayer({id:`${e}-casing`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#1d4ed8","line-width":8,"line-opacity":.3}}),t.getLayer(`${e}-line`)||t.addLayer({id:`${e}-line`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#3b82f6","line-width":5}}))}_removeLayers(){const e=this._getMap();if(!e)return;const t="pm-indoor-route";e.getLayer(`${t}-line`)&&e.removeLayer(`${t}-line`),e.getLayer(`${t}-casing`)&&e.removeLayer(`${t}-casing`),e.getSource(t)&&e.removeSource(t)}drawMarkers(e,t){const o=this._getMap();if(o){if(!e&&this.markers.start&&(this.markers.start.remove(),this.markers.start=null),!t&&this.markers.end&&(this.markers.end.remove(),this.markers.end=null),e){if(this.markers.start)this.markers.start.setLngLat([e.lng,e.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-start",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#10b981",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.start=new H.Marker({element:i}).setLngLat([e.lng,e.lat]).addTo(o)}this.markers.start.getElement().dataset.floorId=e.floorId}if(t){if(this.markers.end)this.markers.end.setLngLat([t.lng,t.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-end",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#ef4444",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.end=new H.Marker({element:i}).setLngLat([t.lng,t.lat]).addTo(o)}this.markers.end.getElement().dataset.floorId=t.floorId}this._updateMarkerVisibility()}}_updateMarkerVisibility(){if(this.markers.start){const e=this.markers.start.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}if(this.markers.end){const e=this.markers.end.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}}}class Sn{constructor(e){this.context=e,this.eventBus=e.eventBus,this.api=new kn(e),this.router=new Bn(e),this.currentFloor=0,this._isTransitioning=!1,this.layerGroups={poi:["pm-draw-special-point-inactive","pm-draw-special-point-active"],beacon:["pm-draw-special-point-inactive","pm-draw-special-point-active"],walkway:["pm-draw-line-active","pm-draw-line-static","pm-draw-point-vertex","pm-draw-point-mid"],obstacle:["pm-draw-polygon-fill","pm-draw-polygon-outline","pm-draw-polygon-fill-static","pm-draw-polygon-outline-static","pm-draw-point-vertex","pm-draw-point-mid","pm-user-3d-buildings-fill"],model3d:["three-glb-layer"]},this.eventBus.on("mapLoaded",()=>{this.currentFloor!==0&&this.setFloor(this.currentFloor)}),this.eventBus.on("layerVisibilityChanged",()=>{this._applyFilters()})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}async setFloor(e,t={}){var n;if(typeof e!="number")throw new w("Floor ordinal must be a number.",C.INVALID_PARAMETERS,"indoor");if(this._isTransitioning)return this;const o=t.animate!==!1,i=t.duration||300;if(o&&this.currentFloor!==e){this._isTransitioning=!0;const s=this._getMap(),a=(n=s==null?void 0:s.getContainer)==null?void 0:n.call(s);a&&(a.style.pointerEvents="none");try{await this._transitionOpacity(0,i/2),this.currentFloor=e,this._applyFilters(),await this._transitionOpacity(1,i/2)}finally{this._isTransitioning=!1,a&&(a.style.pointerEvents="auto")}}else this.currentFloor=e,this._applyFilters();return this.eventBus.emit("floorChanged",e),this}getAvailableFloors(){var i;const e=new Set,t=this.context.registry.get("geometry");t&&typeof t.getAvailableFloors=="function"&&t.getAvailableFloors().forEach(n=>e.add(n));const o=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;return o&&typeof o.getAvailableFloors=="function"&&o.getAvailableFloors().forEach(n=>e.add(n)),Array.from(e).sort((n,s)=>n-s)}getCurrentFloor(){return this.currentFloor}async _transitionOpacity(e,t){if(!this._getMap())return;const i=this.context.registry.get("geometry");return i&&typeof i.setMarkerOpacity=="function"&&i.setMarkerOpacity(e),this._getAllIndoorLayerIds().forEach(s=>{this._setLayerOpacity(s,e,t)}),new Promise(s=>setTimeout(s,t))}_setLayerOpacity(e,t,o=0){const i=this._getMap();if(!i||!i.getLayer(e))return;const n=i.getLayer(e).type,s=[];n==="fill"?s.push("fill-opacity"):n==="line"?s.push("line-opacity"):n==="circle"?s.push("circle-opacity","circle-stroke-opacity"):n==="symbol"?s.push("icon-opacity","text-opacity"):n==="raster"?s.push("raster-opacity"):n==="fill-extrusion"&&s.push("fill-extrusion-opacity"),s.forEach(a=>{i.setPaintProperty(e,`${a}-transition`,{duration:o,delay:0}),i.setPaintProperty(e,a,t)})}_getAllIndoorLayerIds(){return[...this.layerGroups.poi,...this.layerGroups.beacon,...this.layerGroups.walkway,...this.layerGroups.obstacle]}_applyFilters(){var i;const e=this._getMap();if(!e)return;const t=this.currentFloor;try{const n=this.context.registry.get("geometry");n&&typeof n.syncFloorVisibility=="function"&&n.syncFloorVisibility(t)}catch(n){console.warn("FloorManager: Failed to sync Draw features",n)}try{const n=this.context.registry.get("geometry");n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch(n){console.warn("FloorManager: Failed to filter DOM markers",n)}Object.entries(this.layerGroups).forEach(([n,s])=>{s.forEach(a=>{e.getLayer(a)&&(a.startsWith("pm-draw-")||e.setLayoutProperty(a,"visibility","visible"))})}),["pm-user-3d-buildings-fill"].forEach(n=>{if(e.getLayer(n))try{e.setLayoutProperty(n,"visibility","visible");const s=["all",["==",["coalesce",["get","user_floorOrdinal"],["get","floorOrdinal"],["get","user_ordinal"],["get","ordinal"],0],t],["!=",["get","user_isHidden"],!0]];e.setFilter(n,s)}catch(s){console.warn(`FloorManager: Failed to set filter on layer ${n}`,s)}});try{const n=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch{}}_setActiveVenue(e){this._activeVenue=e||null,e&&this.eventBus.emit("venueChanged",this.getVenueInfo())}getActiveVenue(){return this._activeVenue||null}getVenues(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("venue").toArray(),...e.query().byKind("floor").where("category","eq","venue").toArray(),...e.query().byKind("floor").where("feature_type","eq","venue").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"venue",feature:i}})}getVenueInfo(){var s,a;if(!this._activeVenue)return null;const e=this._activeVenue.properties||{},t=e.user_name||e.name,o=this.getAvailableFloors(),i=this.getBuildings();let n=null;try{const l=((s=this._activeVenue.geometry)==null?void 0:s.type)==="Polygon"?this._activeVenue.geometry.coordinates[0]:((a=this._activeVenue.geometry)==null?void 0:a.type)==="Point"?[this._activeVenue.geometry.coordinates]:[];if(l.length>0){let c=1/0,u=1/0,d=-1/0,p=-1/0;for(const h of l)h[0]<c&&(c=h[0]),h[1]<u&&(u=h[1]),h[0]>d&&(d=h[0]),h[1]>p&&(p=h[1]);n=[[c,u],[d,p]]}}catch{}return{id:e.user_id||this._activeVenue.id,name:typeof t=="object"?t==null?void 0:t.en:t||"",category:e.user_category||e.category||"venue",floors:o,bounds:n,buildingCount:i.length}}getFloorInfo(e){const t=this.context.registry.get("geometry");if(!t||!t.query)return null;const o=t.query().byKind("floor").where("feature_type","eq","level").byFloor(e).first()||t.query().byKind("floor").byFloor(e).first();if(!o)return null;const i=o.properties||{},n=i.user_name||i.name,s=t.query().byKind("poi").byFloor(e).count(),a=t.query().byKind("beacon").byFloor(e).count(),l=t.query().byKind("unit").byFloor(e).count()+t.query().byKind("obstacle").byFloor(e).count();return{id:i.user_id||o.id,name:typeof n=="object"?n==null?void 0:n.en:n||"",shortName:i.user_short_name||i.short_name||"",ordinal:e,outdoor:!!(i.user_outdoor||i.outdoor),unitCount:l,poiCount:s,beaconCount:a}}getBuildings(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("building").toArray(),...e.query().byKind("floor").where("category","eq","building").toArray(),...e.query().byKind("floor").where("feature_type","eq","building").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"building"}})}}class Ln{constructor(e={}){this.options=e,this.container=null,this.floors=[],this.activeFloorId=null,this._map=null}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl maplibregl-ctrl-group pm-indoor-floor-selector",this._render(),this.container}onRemove(){var e;(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setFloors(e){this.floors=e||[],this._render()}setActiveFloor(e){this.activeFloorId=e,this._updateActiveState()}_render(){if(this.container){if(this.container.innerHTML="",this.floors.length===0){this.container.style.display="none";return}this.container.style.display="flex",this.floors.forEach(e=>{const t=document.createElement("button");t.className="pm-indoor-floor-btn",t.type="button",t.textContent=e.name||e.id,t.setAttribute("data-floor-id",e.id),t.addEventListener("click",()=>{this.setActiveFloor(e.id),this.options.onChange&&this.options.onChange(e.id,e)}),this.container.appendChild(t)}),this._updateActiveState()}}_updateActiveState(){if(!this.container)return;this.container.querySelectorAll(".pm-indoor-floor-btn").forEach(t=>{t.getAttribute("data-floor-id")===String(this.activeFloorId)?t.classList.add("active"):t.classList.remove("active")})}}class Tn{constructor(e={}){this.options=e,this.buildingId=e.buildingId||null,this.router=e.router||null,this.container=null,this._map=null,this._mapInstance=null,this._focusMarker=null,this.origin=null,this.destination=null,this.routeResult=null,this._originSearchTimer=null,this._destSearchTimer=null,this._onMapClick=this._onMapClick.bind(this),this.activeInput=null,this._icons={depart:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>',arrive:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>',elevator:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 4v16M8 8l4-4 4 4M8 16l4 4 4-4"/></svg>',left:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 14l-4-4 4-4"/><path d="M5 10h11a4 4 0 0 1 4 4v4"/></svg>',right:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 14l4-4-4-4"/><path d="M19 10H8a4 4 0 0 0-4 4v4"/></svg>',straight:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',uturn:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 10l-4 4 4 4"/><path d="M5 14h10a4 4 0 0 0 4-4v-4"/></svg>'}}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl pm-indoor-routing-panel",this._render(),this._map&&this._map.on("click",this._onMapClick),this.container}onRemove(){var e;this._map&&this._map.off("click",this._onMapClick),(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setBuildingId(e){this.buildingId=e}setMapInstance(e){this._mapInstance=e}_render(){if(!this.container)return;this.container.innerHTML=`
|
|
355
|
+
`,this.toolbar.innerHTML=b,this.tooltip&&this.tooltip.attachToToolbar(this.toolbar)}_exportGeoJSON(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometryExported",{data:t,format:e});const o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),i=URL.createObjectURL(o),n=document.createElement("a");n.href=i,n.download=`powermap-export-${new Date().getTime()}.json`,n.click(),URL.revokeObjectURL(i)}catch(e){const t=e instanceof PowerMapError?e:new PowerMapError(`Failed to export data: ${e.message}`,ErrorCode.UNKNOWN,"editor",{originalError:e});this.eventBus.emit("error",t)}}_triggerImport(){const e=document.createElement("input");e.type="file",e.accept=".json,application/json",e.onchange=t=>{const o=t.target.files[0];if(!o)return;const i=new FileReader;i.onload=n=>{try{const s=JSON.parse(n.target.result),a=this.mode==="indoor"?"imdf":"standard";this.geometryManager.import(s,{format:a})}catch(s){const a=s instanceof PowerMapError?s:new PowerMapError(`Failed to parse or import GeoJSON: ${s.message}`,ErrorCode.INVALID_PARAMETERS,"editor",{originalError:s});this.eventBus.emit("error",a)}},i.onerror=()=>{const n=new PowerMapError("Failed to read the selected file.",ErrorCode.UNKNOWN,"editor");this.eventBus.emit("error",n)},i.readAsText(o)},e.click()}_triggerSave(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometrySaveRequested",{data:t,format:e})}catch(e){typeof PowerMapError<"u"&&e instanceof PowerMapError?this.eventBus.emit("error",e):console.error(e)}}}class An{constructor(e){this.mapManager=e.registry.get("map"),this.geometryManager=e.registry.get("geometry"),this.eventBus=e.eventBus,this.isEnabled=!1,this.control=null,this.mode=e.mode||"standard"}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t){this.eventBus.on("mapLoaded",()=>this.enable(e));return}this.geometryManager.getDrawInstance()||this.geometryManager.initDraw(t);const o=e.position||"bottom-left";this.mode=e.mode||this.mode;try{this.control=new mn(this.geometryManager,this.eventBus,{mode:this.mode}),this.control.setMode&&this.control.setMode(this.mode),t.addControl(this.control,o),this.isEnabled=!0}catch(i){const n=new w(`Failed to enable editor: ${i.message}`,C.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}setMode(e){this.mode=e,this.control&&this.control.setMode&&this.control.setMode(e)}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&this.control&&e.removeControl(this.control),this.control=null,this.isEnabled=!1}attach(e){const t=typeof e=="object"?e.id:e;if(!t)throw new w("Feature ID is required to attach editor.",C.INVALID_PARAMETERS,"editor");const o=this.geometryManager.getDrawInstance();if(!o)throw new w("Cannot attach: Draw instance not initialized.",C.MAP_NOT_INITIALIZED,"editor");try{o.changeMode("direct_select",{featureId:t})}catch(i){const n=new w(`Could not attach to feature ${t}: ${i.message}`,C.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}detach(){const e=this.geometryManager.getDrawInstance();e&&e.changeMode("simple_select")}}class yn{constructor(e){this.mapManager=e.registry.get("map"),this.eventBus=e.eventBus,this.isEnabled=!1,this.panel=null,this.fps=0,this.frameCount=0,this.lastTime=performance.now(),this.lastFpsCalc=this.lastTime,this._onRender=this._onRender.bind(this),this._onMove=this._onMove.bind(this),this.showFps=!0,this.showCoord=!0}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t)throw new w("Cannot enable debug panel: Map is not initialized.",C.MAP_NOT_INITIALIZED,"debug");const o=e.position||"top-left";this.panel=document.createElement("div"),this.panel.className="pm-debug-panel",Object.assign(this.panel.style,{position:"absolute",background:"rgba(0, 0, 0, 0.7)",color:"#0f0",padding:"12px",fontFamily:'"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',fontSize:"13px",borderRadius:"8px",zIndex:"9999",pointerEvents:"none",lineHeight:"1.6",boxShadow:"0 4px 6px rgba(0,0,0,0.3)",border:"1px solid rgba(0,255,0,0.3)"}),o.includes("top")&&(this.panel.style.top="10px"),o.includes("bottom")&&(this.panel.style.bottom="40px"),o.includes("left")&&(this.panel.style.left="10px"),o.includes("right")&&(this.panel.style.right="10px"),t.getContainer().appendChild(this.panel),t.on("render",this._onRender),t.on("move",this._onMove),this.isEnabled=!0,this._updateUI()}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&(e.off("render",this._onRender),e.off("move",this._onMove)),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null,this.isEnabled=!1}showFPS(e=!0){this.showFps=e,this._updateUI()}showCoordinate(e=!0){this.showCoord=e,this._updateUI()}_onRender(){const e=performance.now();this.frameCount++,e>=this.lastFpsCalc+1e3&&(this.fps=Math.round(this.frameCount*1e3/(e-this.lastFpsCalc)),this.frameCount=0,this.lastFpsCalc=e,this._updateUI())}_onMove(){this._updateUI()}_updateUI(){if(!this.isEnabled||!this.panel)return;const e=this.mapManager.getMap();if(!e)return;let t="<strong>PowerMap Debug</strong><br/>";if(this.showFps){const o=this.fps<30?"red":this.fps<50?"orange":"#0f0";t+=`FPS: <span style="color:${o}">${this.fps}</span><br/>`}if(this.showCoord){const o=e.getCenter();t+=`Lng: ${o.lng.toFixed(5)}<br/>`,t+=`Lat: ${o.lat.toFixed(5)}<br/>`,t+=`Zoom: ${e.getZoom().toFixed(2)}<br/>`,t+=`Pitch: ${e.getPitch().toFixed(1)}°<br/>`,t+=`Bearing: ${e.getBearing().toFixed(1)}°<br/>`;const i=e.getBounds();t+='<div style="font-size:10px; color:#aaa; margin-top:8px;">',t+=`NE: ${i.getNorthEast().lng.toFixed(3)}, ${i.getNorthEast().lat.toFixed(3)}<br/>`,t+=`SW: ${i.getSouthWest().lng.toFixed(3)}, ${i.getSouthWest().lat.toFixed(3)}`,t+="</div>"}this.panel.innerHTML=t}}const ct=new Map;async function bn(r){if(ct.has(r))return ct.get(r);const e=await fetch(r);if(!e.ok)throw new w(`Fetch style failed: ${r}`,C.API_REQUEST_FAILED,"layers");const t=await e.json();return ct.set(r,t),t}function wn(r){return`${r}/api/v2/map/vtile`}function ue(r,e){if(!e||r.includes("apikey="))return r;const t=r.includes("?")?"&":"?";return`${r}${t}apikey=${encodeURIComponent(e)}`}function vn(r,e,t){if(!r)return r;if(r.startsWith(e))return ue(r,t);if(r.startsWith("mbtiles://")){const i=r.replace("mbtiles://","").replace(/\.mbtiles$/i,"");return ue(`${e}/data/${i}.json`,t)}const o=r.match(/\/data\/([^/]+)\.json$/i);return o?ue(`${e}/data/${o[1]}.json`,t):r}function Cn(r,e,t){if(!r)return r;if(r.startsWith(e))return ue(r,t);const o=r.match(/^https?:\/\/[^/]+\/data\/([^/]+)\/\{z\}\/\{x\}\/\{y\}\.pbf(?:\?.*)?$/i);return o?ue(`${e}/data/${o[1]}/{z}/{x}/{y}.pbf`,t):r}function En(r,e,t,o,i,n=()=>!0){var s;try{if(!n()||!((s=r==null?void 0:r.getStyle)!=null&&s.call(r))||r.getSource(e))return;const a={type:"vector"};if(Array.isArray(t.tiles)&&t.tiles.length)a.tiles=t.tiles.map(l=>Cn(l,o,i));else if(t.url&&t.url.startsWith("mbtiles://")){const l=t.url.replace("mbtiles://","").replace(/\.mbtiles$/i,"");a.tiles=[ue(`${o}/data/${l}/{z}/{x}/{y}.pbf`,i)]}else if(t.url){const l=t.url.match(/\/data\/([^/]+)\.json(?:\?.*)?$/i);l?a.tiles=[ue(`${o}/data/${l[1]}/{z}/{x}/{y}.pbf`,i)]:a.url=vn(t.url,o,i)}if(!n())return;r.addSource(e,a)}catch{}}function xn(r){var e,t,o;try{return(o=(((t=(e=r==null?void 0:r.getStyle)==null?void 0:e.call(r))==null?void 0:t.layers)||[]).find(i=>i.type==="symbol"))==null?void 0:o.id}catch{return}}async function Le(r,e,{ns:t="rp",includeFn:o=()=>!0,defaultVis:i="none",beforeId:n=void 0,base:s,apiKey:a}={}){var g;if(!(r!=null&&r.getStyle))return;const l=r.__pmNonce,c=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==l?!1:!!r.getStyle()}catch{return!1}},u=f=>{try{return c()?r.getLayer(f):void 0}catch{return}};if(!c())return;let d=null;try{d=await bn(e)}catch{console.warn("fetchStyle failed:",e);return}if(!c())return;const p={};for(const[f,m]of Object.entries(d.sources||{})){if(!c())return;const y=`${t}-src-${f}`;En(r,y,m,s,a,c),p[f]=y}for(const f of d.layers||[]){if(!o(f))continue;if(!c())return;const m=`${t}-${f.id}`;if(u(m))continue;const y=JSON.parse(JSON.stringify(f));y.id=m,p[y.source]&&(y.source=p[y.source]),y.layout=y.layout||{},y.layout.visibility=i;try{if(!c())return;r.addLayer(y,n)}catch{}}if(!c())return;const h=(g=r.__pmDesiredVis)==null?void 0:g[t];return typeof h=="boolean"&&lo(r,t,h,c),{prefix:t}}function lo(r,e,t,o=()=>!0){var i;try{if(!o())return;const n=t?"visible":"none",s=(((i=r.getStyle())==null?void 0:i.layers)||[]).filter(a=>a.id.startsWith(e+"-"));for(const a of s){if(!o())return;try{r.setLayoutProperty(a.id,"visibility",n)}catch{}}}catch{}}async function Ft(r,e,t=e,o){if(!(r!=null&&r.getStyle))return;const i=r.__pmNonce,n=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==i?!1:!!r.getStyle()}catch{return!1}},s=y=>{try{return n()?!!(r.hasImage&&r.hasImage(y)):!1}catch{return!1}};if(r.isStyleLoaded&&!r.isStyleLoaded()&&await new Promise(y=>{if(!n())return y();const b=()=>{E(),y()},E=()=>{try{r.off("styledata",b)}catch{}try{r.off("load",b)}catch{}};r.on("styledata",b),r.on("load",b),setTimeout(()=>{E(),y()},1500)}),!n()||(r.__pmSpriteLoaded=r.__pmSpriteLoaded||{},r.__pmSpriteLoaded[t]))return;const a=y=>ue(y,o),c=(window.devicePixelRatio||1)>1.5?[a(`${e}@2x.json`),a(`${e}@2x.png`),a(`${e}.json`),a(`${e}.png`)]:[a(`${e}.json`),a(`${e}.png`),a(`${e}@2x.json`),a(`${e}@2x.png`)];let u,d,p=1;for(let y=0;y<c.length;y+=2){if(!n())return;try{const[b,E]=[c[y],c[y+1]],x=await fetch(b);if(!x.ok)throw 0;if(u=await x.json(),!n())return;const M=await fetch(E);if(!M.ok)throw 0;const T=await M.blob();if(!n())return;d="createImageBitmap"in window?await createImageBitmap(T):await m(T),p=b.includes("@2x")?2:1;break}catch{}}if(!n())return;if(!u||!d){console.warn("sprite load failed for",e);return}const h="createImageBitmap"in window&&d instanceof ImageBitmap,g=h?null:document.createElement("canvas"),f=g?g.getContext("2d"):null;for(const[y,b]of Object.entries(u)){if(!n())return;if(s(y))continue;const{x:E,y:x,width:M,height:T,sdf:k}=b;let R;if(h?R=await createImageBitmap(d,E,x,M,T):(g.width=M,g.height=T,f.clearRect(0,0,M,T),f.drawImage(d,E,x,M,T,0,0,M,T),R=g),!n())return;try{r.addImage(y,R,{pixelRatio:p,sdf:!!k})}catch{}}if(!n())return;r.__pmSpriteLoaded[t]=!0;function m(y){return new Promise((b,E)=>{const x=new Image;x.onload=()=>b(x),x.onerror=E,x.crossOrigin="anonymous",x.src=URL.createObjectURL(y)})}}function Mn(r,e){const t=o=>ue(o,e);return[{key:"city",label:"CITY PLAN",items:[se("pm-bangkok-layer","Bangkok","PM_Bangkok",r,e),se("pm-nakhon-pathom-layer","Nakhon Pathom","PM_Nakhon_Pathom",r,e),se("pm-ayutthaya-layer","Ayutthaya","PM_Phra_Nakhon_Si_Ayutthaya",r,e),se("pm-chonburi-layer","Chon Buri","PM_Chon_Buri",r,e),se("pm-samutprakan-layer","Samut Prakan","PM_Samut_Prakan",r,e),se("pm-rayong-layer","Rayong","PM_Rayong",r,e),se("pm-samutsakhon-layer","Samut Sakhon","PM_Samut_Sakhon",r,e,{tileSize:128}),se("pm-pathumthani-layer","Pathum Thani","PM_Pathumthani",r,e,{tileSize:128}),se("pm-ubonratchathani-layer","Ubon Ratchathani","PM_Ubon_Ratchathani",r,e,{tileSize:128}),se("pm-nonthaburi-layer","Nonthaburi","PM_Nonthaburi",r,e,{tileSize:128}),se("pm-chachoengsao-layer","Chachoengsao","PM_Chachoengsao",r,e,{tileSize:128})]},{key:"transport",label:"TRANSPORT",items:[{id:"pm-road-vt",name:"Road",groupPrefix:"vt-road",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/road_poi/style.json`);o.__pmRoadVt||(await Le(o,i,{ns:"vt-road",defaultVis:"none",includeFn:n=>n?n.type==="line"?!0:n.type==="symbol"&&n.source==="road"?n["source-layer"]==="road_name":!1:!1,base:r,apiKey:e}),o.__pmRoadVt=!0)}},{id:"pm-post-elec-vt",name:"Post Election",groupPrefix:"vt-postelec",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/post_elec/style.json`),n=`${r}/transport/post_elec/sprite`;o.__pmGroupReady=o.__pmGroupReady||{},!o.__pmGroupReady["vt-postelec"]&&(await Ft(o,n,"post_elec",e),await Le(o,i,{ns:"vt-postelec",defaultVis:"none",includeFn:s=>(s==null?void 0:s.type)==="symbol",base:r,apiKey:e}),o.__pmGroupReady["vt-postelec"]=!0)}},Ie({id:"pm-future-motorway-th-vt",name:"Future Motorway TH",ns:"vt-fmw-th",stylePath:"transport/future_motorway_th",flagPrefix:"__pmFutureMwTh",base:r,apiKey:e,tk:t}),Ie({id:"pm-future-motorway-en-vt",name:"Future Motorway EN",ns:"vt-fmw-en",stylePath:"transport/future_motorway_en",flagPrefix:"__pmFutureMwEn",base:r,apiKey:e,tk:t}),Ie({id:"pm-current-railway-th-vt",name:"Current Railway TH",ns:"vt-railth-cur",stylePath:"transport/current_railway_th",flagPrefix:"__pmRailTh",base:r,apiKey:e,tk:t}),Ie({id:"pm-current-railway-en-vt",name:"Current Railway EN",ns:"vt-railen-cur",stylePath:"transport/current_railway_en",flagPrefix:"__pmRailEn",base:r,apiKey:e,tk:t}),Ie({id:"pm-future-railway-th-vt",name:"Future Railway TH",ns:"vt-railth-future",stylePath:"transport/future_railway_th",flagPrefix:"__pmFRailTh",base:r,apiKey:e,tk:t}),Ie({id:"pm-future-railway-en-vt",name:"Future Railway EN",ns:"vt-railen-future",stylePath:"transport/future_railway_en",flagPrefix:"__pmFRailEn",base:r,apiKey:e,tk:t}),Ye({id:"pm-current-bts-mrt-th-vt",name:"Current BTS MRT TH",ns:"vt-btsmrt-cur-th",stylePath:"transport/current_bts_mrt_th",flagPrefix:"__pmBTSMRTTH",base:r,apiKey:e,tk:t}),Ye({id:"pm-current-bts-mrt-en-vt",name:"Current BTS MRT EN",ns:"vt-btsmrt-cur-en",stylePath:"transport/current_bts_mrt_en",flagPrefix:"__pmBTSMRTEN",base:r,apiKey:e,tk:t}),Ye({id:"pm-future-bts-mrt-th-vt",name:"Future BTS MRT TH",ns:"vt-btsmrt-fut-th",stylePath:"transport/future_bts_mrt_th",flagPrefix:"__pmBTSMRT_FUTTH",base:r,apiKey:e,tk:t}),Ye({id:"pm-future-bts-mrt-en-vt",name:"Future BTS MRT EN",ns:"vt-btsmrt-fut-en",stylePath:"transport/future_bts_mrt_en",flagPrefix:"__pmBTSMRT_FUTEN",base:r,apiKey:e,tk:t})]},{key:"insight",label:"INSIGHT DATA",items:[{id:"pm-viirs-blackmarble-layer",name:"Night Lights",ensure:o=>{o!=null&&o.getStyle()&&(o.getSource("pm-viirs-blackmarble-source")||o.addSource("pm-viirs-blackmarble-source",{type:"raster",tiles:["https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/VIIRS_Black_Marble/default/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.png"],tileSize:256,minzoom:0,maxzoom:8}),o.getLayer("pm-viirs-blackmarble-layer")||o.addLayer({id:"pm-viirs-blackmarble-layer",type:"raster",source:"pm-viirs-blackmarble-source",paint:{"raster-opacity":.7},layout:{visibility:"none"}}))}},{id:"pm-maptiler-satellite-layer",name:"Satellite",ensure:o=>{if(!(o!=null&&o.getStyle()))return;const i=o.__pmMaptilerKey;if(!i){console.warn("PowerMap LayerManager: maptilerKey not provided, satellite layer skipped.");return}if(o.getSource("pm-maptiler-satellite-source")||o.addSource("pm-maptiler-satellite-source",{type:"raster",tiles:[`https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=${encodeURIComponent(i)}`],tileSize:256,minzoom:0,maxzoom:22}),!o.getLayer("pm-maptiler-satellite-layer")){const n=xn(o);o.addLayer({id:"pm-maptiler-satellite-layer",type:"raster",source:"pm-maptiler-satellite-source",paint:{"raster-opacity":1},layout:{visibility:"none"}},n)}}}]}]}const ut={"pm-road-vt":{prefix:"vt-road"},"pm-road-poi-vt":{prefix:"vt-roadpoi"},"pm-post-elec-vt":{prefix:"vt-postelec"},"pm-future-motorway-th-vt":{prefix:"vt-fmw-th"},"pm-future-motorway-en-vt":{prefix:"vt-fmw-en"},"pm-current-railway-th-vt":{prefix:"vt-railth-cur"},"pm-current-railway-en-vt":{prefix:"vt-railen-cur"},"pm-future-railway-th-vt":{prefix:"vt-railth-future"},"pm-future-railway-en-vt":{prefix:"vt-railen-future"},"pm-current-bts-mrt-th-vt":{prefix:"vt-btsmrt-cur-th"},"pm-current-bts-mrt-en-vt":{prefix:"vt-btsmrt-cur-en"},"pm-future-bts-mrt-th-vt":{prefix:"vt-btsmrt-fut-th"},"pm-future-bts-mrt-en-vt":{prefix:"vt-btsmrt-fut-en"}};function se(r,e,t,o,i,n={}){const s=n.tileSize||256;return{id:r,name:e,ensure:a=>{if(!(a!=null&&a.getStyle()))return;const l=r.replace("-layer","-source");a.getSource(l)||a.addSource(l,{type:"raster",tiles:[ue(`${o}/data/${t}/{z}/{x}/{y}.png`,i)],tileSize:s,minzoom:8,maxzoom:16}),a.getLayer(r)||a.addLayer({id:r,type:"raster",source:l,paint:{"raster-opacity":1},layout:{visibility:"none"}})}}}function Ie({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}Round1`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}Round1`]=!0),l[`${i}Sprite`]||(await Ft(l,u,o.replace("/","_"),s),l[`${i}Sprite`]=!0),l[`${i}Round2`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol",base:n,apiKey:s}),l[`${i}Round2`]=!0)}}}function Ye({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}_Lines`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}_Lines`]=!0),l[`${i}_Sprite`]||(await Ft(l,u,o.replace("/","_"),s),l[`${i}_Sprite`]=!0),l[`${i}_Symbols`]||(await Le(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol"&&d["source-layer"]==="bts_mrt_station",base:n,apiKey:s}),l[`${i}_Symbols`]=!0)}}}class In{constructor(e){this.context=e,this.eventBus=e.eventBus,this.authManager=e.authManager;const t=this.authManager.getBaseUrl();this._base=wn(t),this._apiKey=e.options.mapApiKey,this._catalog=Mn(this._base,this._apiKey),this._ensured=new Set,this._layerState=new Map,e.options.maptilerKey&&(this._maptilerKey=e.options.maptilerKey),this.eventBus.on("mapLoaded",({map:o})=>{this._maptilerKey&&o&&(o.__pmMaptilerKey=this._maptilerKey),o.on("style.load",async()=>{for(const[i,n]of this._layerState.entries())try{const s=this._findItem(i);s&&await s.item.ensure(o),n.visible!==void 0&&this._setVisibility(i,n.visible),n.opacity!==void 0&&this.setOpacity(i,n.opacity)}catch(s){console.warn(`LayerManager: Failed to auto-restore layer ${i}`,s)}})})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}_findItem(e){for(const t of this._catalog){const o=t.items.find(i=>i.id===e);if(o)return{item:o,group:t}}return null}getCatalog(){return this._catalog.map(e=>({key:e.key,label:e.label,items:e.items.map(t=>({id:t.id,name:t.name,groupPrefix:t.groupPrefix||null}))}))}getGroup(e){const t=this._catalog.find(o=>o.key===e);return t?t.items.map(o=>({id:o.id,name:o.name})):null}getLayerState(e){var n;const t=this._getMap(),o=this._ensured.has(e);let i=null;if(t&&o){const s=ut[e];if(s)try{const a=(((n=t.getStyle())==null?void 0:n.layers)||[]).filter(l=>l.id.startsWith(s.prefix+"-"));i=a.length>0&&a.some(l=>t.getLayoutProperty(l.id,"visibility")==="visible")}catch{i=!1}else try{i=t.getLayoutProperty(e,"visibility")==="visible"}catch{i=!1}}return{loaded:o,visible:i}}async ensure(e){const t=this._getMap();if(!t)throw new w("Map is not ready. Call ensure() after mapLoaded event.",C.INVALID_PARAMETERS,"layers");const o=this._findItem(e);if(!o)throw new w(`Layer "${e}" not found in catalog. Use getCatalog() to see available layers.`,C.INVALID_PARAMETERS,"layers");try{await o.item.ensure(t),this._ensured.add(e),this.eventBus.emit("layerEnsured",{layerId:e,group:o.group.key})}catch(i){throw new w(`Failed to ensure layer "${e}": ${i.message}`,C.API_REQUEST_FAILED,"layers",{originalError:i})}}async show(e){this._ensured.has(e)||await this.ensure(e);const t=this._layerState.get(e)||{};t.visible=!0,this._layerState.set(e,t),this._setVisibility(e,!0),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!0})}hide(e){const t=this._layerState.get(e)||{};t.visible=!1,this._layerState.set(e,t),this._setVisibility(e,!1),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!1})}async toggle(e){const t=this.getLayerState(e);t.loaded?t.visible?this.hide(e):this.show(e):await this.show(e)}setOpacity(e,t){var s;const o=this._layerState.get(e)||{};o.opacity=t,this._layerState.set(e,o);const i=this._getMap();if(!i)return;const n=ut[e];if(n)try{const a=(((s=i.getStyle())==null?void 0:s.layers)||[]).filter(l=>l.id.startsWith(n.prefix+"-"));for(const l of a)try{l.type==="line"?i.setPaintProperty(l.id,"line-opacity",t):l.type==="symbol"?(i.setPaintProperty(l.id,"icon-opacity",t),i.setPaintProperty(l.id,"text-opacity",t)):l.type==="fill"&&i.setPaintProperty(l.id,"fill-opacity",t)}catch{}}catch{}else try{const a=i.getLayer(e);a&&(a.type==="raster"?i.setPaintProperty(e,"raster-opacity",t):a.type==="line"?i.setPaintProperty(e,"line-opacity",t):a.type==="fill"&&i.setPaintProperty(e,"fill-opacity",t))}catch{}}async showGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)await this.show(o.id)}hideGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)this.hide(o.id)}hideAll(){for(const e of this._catalog)for(const t of e.items)this.hide(t.id)}_setVisibility(e,t){const o=this._getMap();if(!o)return;const i=ut[e];if(i){const n=!!t;if(o.__pmDesiredVis=o.__pmDesiredVis||{},o.__pmDesiredVis[i.prefix]=n,lo(o,i.prefix,n),o.getLayer(e))try{o.setLayoutProperty(e,"visibility",n?"visible":"none")}catch{}else try{o.addLayer({id:e,type:"background",layout:{visibility:n?"visible":"none"},paint:{"background-opacity":0}})}catch{}return}if(o.getLayer(e))try{o.setLayoutProperty(e,"visibility",t?"visible":"none")}catch{}}}class kn{constructor(e){this.context=e,this.baseUrl="https://maps.powermap.live/api/v2/indoor",this._geojsonCache={}}setBaseUrl(e){return this.baseUrl=e.replace(/\/$/,""),this}async getVenues(){return this._fetchJSON("/venues")}async getBuildings(e){const t=e?`/buildings?venueId=${e}`:"/buildings";return this._fetchJSON(t)}async getFloors(e){if(!e)throw new Error("buildingId is required");return this._fetchJSON(`/floors?buildingId=${e}`)}async getFloorGeoJSON(e){if(!e)throw new Error("floorId is required");if(this._geojsonCache[e])return JSON.parse(JSON.stringify(this._geojsonCache[e]));const t=await this._fetchJSON(`/floors/${e}/geojson`);return this._geojsonCache[e]=JSON.parse(JSON.stringify(t)),t}async search(e,t={}){if(!e)throw new Error("Search query is required");if(!t.buildingId)throw new w("buildingId is required for indoor search",C.INVALID_PARAMETERS,"indoor");let o=`/search?q=${encodeURIComponent(e)}&buildingId=${t.buildingId}`;return t.category&&(o+=`&category=${t.category}`),t.limit&&(o+=`&limit=${t.limit}`),this._fetchJSON(o)}async _fetchJSON(e){const t=this.context.authManager;if(!t)throw new w("AuthManager not found in SDK context.",C.MAP_NOT_INITIALIZED,"indoor");const o=`${this.baseUrl}${e}`,i=await t.fetchWithAuth(o);if(!i.ok)throw new w(`API Request failed with status ${i.status}`,C.UNKNOWN,"indoor",{status:i.status});return await i.json()}}class Bn{constructor(e){var t,o;this.context=e,this.map=(t=this.context.mapManager)==null?void 0:t.getMap(),this.routeData=null,this.activeFloorId=null,this.markers={start:null,end:null},this.backendUrl=(o=this.context.options)!=null&&o.baseUrl?this.context.options.baseUrl+"/api/v2/indoor":"https://maps.powermap.live/api/v2/indoor"}_getMap(){var e;if(this.map)return this.map;if(this.context.mapManager)return this.context.mapManager.getMap();if(this.context.registry&&this.context.registry.get){const t=this.context.registry.get("map");return(t==null?void 0:t.map)||((e=t==null?void 0:t.getMap)==null?void 0:e.call(t))}return null}setMap(e){this.map=e}async calculateRoute(e,t,o,i,n){var a,l;const s=new URL(`${this.backendUrl}/route`);s.searchParams.set("buildingId",e),s.searchParams.set("startFloorId",t),s.searchParams.set("startLng",o[0]),s.searchParams.set("startLat",o[1]),s.searchParams.set("endFloorId",i),s.searchParams.set("endLng",n[0]),s.searchParams.set("endLat",n[1]);try{let c;if(this.context.authManager?c=await this.context.authManager.fetchWithAuth(s.toString(),{source:"indoor-route"}):c=await fetch(s.toString(),{headers:{"x-client-id":this.context.mapApiKey||((a=this.context.auth)==null?void 0:a.clientId),"x-client-secret":(l=this.context.auth)==null?void 0:l.clientSecret}}),!c.ok)throw new Error("Failed to fetch indoor route");const u=await c.json();this.routeData=u,this.activeFloorId=t,this.drawRoute(this.activeFloorId);let d=0,p=0,h=[],g=null;if(u&&u.type==="FeatureCollection"){const m=u.properties||(u.features.length>0?u.features[0].properties:{});d=m.distance||0,p=m.duration||Math.round(d/1.4),h=m.instructions||[],g=u.features.length>0?u.features[0].geometry:null;const y=u.features.flatMap(b=>{var E;return((E=b.geometry)==null?void 0:E.coordinates)||[]});if(y.length>1){const b=y.reduce((E,x)=>E.extend(x),new H.LngLatBounds(y[0],y[0]));this._getMap()&&this._getMap().fitBounds(b,{padding:60,duration:1e3})}}const f=h.map(m=>{var E;let y=null;(E=m.maneuver)!=null&&E.location?y=m.maneuver.location:m.interval&&coords.length>0&&(y=coords[m.interval[0]]);const b=m.maneuver||{type:"turn",instruction:m.text};return!b.location&&y&&(b.location=y),{distance:m.distance,duration:m.time?m.time/1e3:Math.round((m.distance||0)/1.4),name:m.street_name||"",floorId:m.floorId,maneuver:b}});return{distance:d,duration:p,steps:f,geometry:g,raw:u}}catch(c){throw console.error("PowerMap SDK: Indoor routing failed",c),this.clearRoute(),c}}setActiveFloor(e){this.activeFloorId=e,this.routeData&&this.drawRoute(e),this._updateMarkerVisibility()}clearRoute(){this.routeData=null,this._removeLayers(),this.markers.start&&this.markers.start.remove(),this.markers.end&&this.markers.end.remove(),this.markers={start:null,end:null}}drawRoute(e){const t=this._getMap();if(!t||!this.routeData)return;let o=this.routeData;o.type==="FeatureCollection"&&e&&(o={...o,features:o.features.filter(s=>{var a;return!((a=s.properties)!=null&&a.floorId)||String(s.properties.floorId)===String(e)})});const i="pm-indoor-route",n=t.getSource(i);n?n.setData(o):t.addSource(i,{type:"geojson",data:o}),this._ensureLayers(i)}_ensureLayers(e){const t=this._getMap();t&&(t.getLayer(`${e}-casing`)||t.addLayer({id:`${e}-casing`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#1d4ed8","line-width":8,"line-opacity":.3}}),t.getLayer(`${e}-line`)||t.addLayer({id:`${e}-line`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#3b82f6","line-width":5}}))}_removeLayers(){const e=this._getMap();if(!e)return;const t="pm-indoor-route";e.getLayer(`${t}-line`)&&e.removeLayer(`${t}-line`),e.getLayer(`${t}-casing`)&&e.removeLayer(`${t}-casing`),e.getSource(t)&&e.removeSource(t)}drawMarkers(e,t){const o=this._getMap();if(o){if(!e&&this.markers.start&&(this.markers.start.remove(),this.markers.start=null),!t&&this.markers.end&&(this.markers.end.remove(),this.markers.end=null),e){if(this.markers.start)this.markers.start.setLngLat([e.lng,e.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-start",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#10b981",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.start=new H.Marker({element:i}).setLngLat([e.lng,e.lat]).addTo(o)}this.markers.start.getElement().dataset.floorId=e.floorId}if(t){if(this.markers.end)this.markers.end.setLngLat([t.lng,t.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-end",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#ef4444",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.end=new H.Marker({element:i}).setLngLat([t.lng,t.lat]).addTo(o)}this.markers.end.getElement().dataset.floorId=t.floorId}this._updateMarkerVisibility()}}_updateMarkerVisibility(){if(this.markers.start){const e=this.markers.start.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}if(this.markers.end){const e=this.markers.end.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}}}class Sn{constructor(e){this.context=e,this.eventBus=e.eventBus,this.api=new kn(e),this.router=new Bn(e),this.currentFloor=0,this._isTransitioning=!1,this.layerGroups={poi:["pm-draw-special-point-inactive","pm-draw-special-point-active"],beacon:["pm-draw-special-point-inactive","pm-draw-special-point-active"],walkway:["pm-draw-line-active","pm-draw-line-static","pm-draw-point-vertex","pm-draw-point-mid"],obstacle:["pm-draw-polygon-fill","pm-draw-polygon-outline","pm-draw-polygon-fill-static","pm-draw-polygon-outline-static","pm-draw-point-vertex","pm-draw-point-mid","pm-user-3d-buildings-fill"],model3d:["three-glb-layer"]},this.eventBus.on("mapLoaded",()=>{this.currentFloor!==0&&this.setFloor(this.currentFloor)}),this.eventBus.on("layerVisibilityChanged",()=>{this._applyFilters()})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}async setFloor(e,t={}){var n;if(typeof e!="number")throw new w("Floor ordinal must be a number.",C.INVALID_PARAMETERS,"indoor");if(this._isTransitioning)return this;const o=t.animate!==!1,i=t.duration||300;if(o&&this.currentFloor!==e){this._isTransitioning=!0;const s=this._getMap(),a=(n=s==null?void 0:s.getContainer)==null?void 0:n.call(s);a&&(a.style.pointerEvents="none");try{await this._transitionOpacity(0,i/2),this.currentFloor=e,this._applyFilters(),await this._transitionOpacity(1,i/2)}finally{this._isTransitioning=!1,a&&(a.style.pointerEvents="auto")}}else this.currentFloor=e,this._applyFilters();return this.eventBus.emit("floorChanged",e),this}getAvailableFloors(){var i;const e=new Set,t=this.context.registry.get("geometry");t&&typeof t.getAvailableFloors=="function"&&t.getAvailableFloors().forEach(n=>e.add(n));const o=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;return o&&typeof o.getAvailableFloors=="function"&&o.getAvailableFloors().forEach(n=>e.add(n)),Array.from(e).sort((n,s)=>n-s)}getCurrentFloor(){return this.currentFloor}async _transitionOpacity(e,t){if(!this._getMap())return;const i=this.context.registry.get("geometry");return i&&typeof i.setMarkerOpacity=="function"&&i.setMarkerOpacity(e),this._getAllIndoorLayerIds().forEach(s=>{this._setLayerOpacity(s,e,t)}),new Promise(s=>setTimeout(s,t))}_setLayerOpacity(e,t,o=0){const i=this._getMap();if(!i||!i.getLayer(e))return;const n=i.getLayer(e).type,s=[];n==="fill"?s.push("fill-opacity"):n==="line"?s.push("line-opacity"):n==="circle"?s.push("circle-opacity","circle-stroke-opacity"):n==="symbol"?s.push("icon-opacity","text-opacity"):n==="raster"?s.push("raster-opacity"):n==="fill-extrusion"&&s.push("fill-extrusion-opacity"),s.forEach(a=>{i.setPaintProperty(e,`${a}-transition`,{duration:o,delay:0}),i.setPaintProperty(e,a,t)})}_getAllIndoorLayerIds(){return[...this.layerGroups.poi,...this.layerGroups.beacon,...this.layerGroups.walkway,...this.layerGroups.obstacle]}_applyFilters(){var i;const e=this._getMap();if(!e)return;const t=this.currentFloor;try{const n=this.context.registry.get("geometry");n&&typeof n.syncFloorVisibility=="function"&&n.syncFloorVisibility(t)}catch(n){console.warn("FloorManager: Failed to sync Draw features",n)}try{const n=this.context.registry.get("geometry");n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch(n){console.warn("FloorManager: Failed to filter DOM markers",n)}Object.entries(this.layerGroups).forEach(([n,s])=>{s.forEach(a=>{e.getLayer(a)&&(a.startsWith("pm-draw-")||e.setLayoutProperty(a,"visibility","visible"))})}),["pm-user-3d-buildings-fill"].forEach(n=>{if(e.getLayer(n))try{e.setLayoutProperty(n,"visibility","visible");const s=["all",["==",["coalesce",["get","user_floorOrdinal"],["get","floorOrdinal"],["get","user_ordinal"],["get","ordinal"],0],t],["!=",["get","user_isHidden"],!0]];e.setFilter(n,s)}catch(s){console.warn(`FloorManager: Failed to set filter on layer ${n}`,s)}});try{const n=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch{}}_setActiveVenue(e){this._activeVenue=e||null,e&&this.eventBus.emit("venueChanged",this.getVenueInfo())}getActiveVenue(){return this._activeVenue||null}getVenues(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("venue").toArray(),...e.query().byKind("floor").where("category","eq","venue").toArray(),...e.query().byKind("floor").where("feature_type","eq","venue").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"venue",feature:i}})}getVenueInfo(){var s,a;if(!this._activeVenue)return null;const e=this._activeVenue.properties||{},t=e.user_name||e.name,o=this.getAvailableFloors(),i=this.getBuildings();let n=null;try{const l=((s=this._activeVenue.geometry)==null?void 0:s.type)==="Polygon"?this._activeVenue.geometry.coordinates[0]:((a=this._activeVenue.geometry)==null?void 0:a.type)==="Point"?[this._activeVenue.geometry.coordinates]:[];if(l.length>0){let c=1/0,u=1/0,d=-1/0,p=-1/0;for(const h of l)h[0]<c&&(c=h[0]),h[1]<u&&(u=h[1]),h[0]>d&&(d=h[0]),h[1]>p&&(p=h[1]);n=[[c,u],[d,p]]}}catch{}return{id:e.user_id||this._activeVenue.id,name:typeof t=="object"?t==null?void 0:t.en:t||"",category:e.user_category||e.category||"venue",floors:o,bounds:n,buildingCount:i.length}}getFloorInfo(e){const t=this.context.registry.get("geometry");if(!t||!t.query)return null;const o=t.query().byKind("floor").where("feature_type","eq","level").byFloor(e).first()||t.query().byKind("floor").byFloor(e).first();if(!o)return null;const i=o.properties||{},n=i.user_name||i.name,s=t.query().byKind("poi").byFloor(e).count(),a=t.query().byKind("beacon").byFloor(e).count(),l=t.query().byKind("unit").byFloor(e).count()+t.query().byKind("obstacle").byFloor(e).count();return{id:i.user_id||o.id,name:typeof n=="object"?n==null?void 0:n.en:n||"",shortName:i.user_short_name||i.short_name||"",ordinal:e,outdoor:!!(i.user_outdoor||i.outdoor),unitCount:l,poiCount:s,beaconCount:a}}getBuildings(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("building").toArray(),...e.query().byKind("floor").where("category","eq","building").toArray(),...e.query().byKind("floor").where("feature_type","eq","building").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"building"}})}}class Ln{constructor(e={}){this.options=e,this.container=null,this.floors=[],this.activeFloorId=null,this._map=null}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl maplibregl-ctrl-group pm-indoor-floor-selector",this._render(),this.container}onRemove(){var e;(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setFloors(e){this.floors=e||[],this._render()}setActiveFloor(e){this.activeFloorId=e,this._updateActiveState()}_render(){if(this.container){if(this.container.innerHTML="",this.floors.length===0){this.container.style.display="none";return}this.container.style.display="flex",this.floors.forEach(e=>{const t=document.createElement("button");t.className="pm-indoor-floor-btn",t.type="button",t.textContent=e.name||e.id,t.setAttribute("data-floor-id",e.id),t.addEventListener("click",()=>{this.setActiveFloor(e.id),this.options.onChange&&this.options.onChange(e.id,e)}),this.container.appendChild(t)}),this._updateActiveState()}}_updateActiveState(){if(!this.container)return;this.container.querySelectorAll(".pm-indoor-floor-btn").forEach(t=>{t.getAttribute("data-floor-id")===String(this.activeFloorId)?t.classList.add("active"):t.classList.remove("active")})}}class Tn{constructor(e={}){this.options=e,this.buildingId=e.buildingId||null,this.router=e.router||null,this.container=null,this._map=null,this._mapInstance=null,this._focusMarker=null,this.origin=null,this.destination=null,this.routeResult=null,this._originSearchTimer=null,this._destSearchTimer=null,this._onMapClick=this._onMapClick.bind(this),this.activeInput=null,this._icons={depart:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>',arrive:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>',elevator:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 4v16M8 8l4-4 4 4M8 16l4 4 4-4"/></svg>',left:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 14l-4-4 4-4"/><path d="M5 10h11a4 4 0 0 1 4 4v4"/></svg>',right:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 14l4-4-4-4"/><path d="M19 10H8a4 4 0 0 0-4 4v4"/></svg>',straight:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',uturn:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 10l-4 4 4 4"/><path d="M5 14h10a4 4 0 0 0 4-4v-4"/></svg>'}}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl pm-indoor-routing-panel",this._render(),this._map&&this._map.on("click",this._onMapClick),this.container}onRemove(){var e;this._map&&this._map.off("click",this._onMapClick),(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setBuildingId(e){this.buildingId=e}setMapInstance(e){this._mapInstance=e}_render(){if(!this.container)return;this.container.innerHTML=`
|
|
356
356
|
<div class="pm-routing-panel-header">
|
|
357
357
|
<div class="pm-routing-inputs-container">
|
|
358
358
|
<div class="pm-routing-inputs">
|
|
@@ -380,7 +380,7 @@
|
|
|
380
380
|
<div id="pm-indoor-search-results" class="pm-search-results" style="display: none; position: static; box-shadow: none; border: none; border-radius: 0; width: 100%; max-height: none; padding: 0; margin: 0; flex: 1; overflow-y: auto;"></div>
|
|
381
381
|
<div class="pm-routing-summary" id="pm-routing-summary" style="display: none;"></div>
|
|
382
382
|
<div class="pm-routing-steps" id="pm-routing-steps" style="display: none;"></div>
|
|
383
|
-
`;const e=this.container.querySelector("#pm-route-origin"),t=this.container.querySelector("#pm-route-dest");e.addEventListener("input",i=>this._onSearchInput(i.target.value,"origin")),t.addEventListener("input",i=>this._onSearchInput(i.target.value,"destination")),e.addEventListener("focus",()=>{this.activeInput="origin"}),t.addEventListener("focus",()=>{this.activeInput="destination"}),document.addEventListener("click",i=>{this.container.contains(i.target)||(this._hideResults("origin"),this._hideResults("destination"))});const o=this.container.querySelector("#pm-route-swap");o&&o.addEventListener("click",()=>this._swapLocations())}_swapLocations(){const e=this.origin;this.origin=this.destination,this.destination=e;const t=this.container.querySelector("#pm-route-origin"),o=this.container.querySelector("#pm-route-dest"),i=t.value;t.value=o.value,o.value=i,this._tryCalculateRoute()}_onMapClick(e){var n;if(!this.activeInput||!this.buildingId)return;const t=e.lngLat;let o=((n=this.router)==null?void 0:n.activeFloorId)||null;const i={id:"custom-"+Date.now(),name:`Point (${t.lat.toFixed(4)}, ${t.lng.toFixed(4)})`,floorId:o,lng:t.lng,lat:t.lat};this._selectLocation(i,this.activeInput),this.activeInput=null}async _onSearchInput(e,t){if(t==="origin"&&clearTimeout(this._originSearchTimer),t==="destination"&&clearTimeout(this._destSearchTimer),!e||e.length<2){this._hideResults();return}const o=setTimeout(async()=>{var i;try{const n=this.router&&this.router.backendUrl?this.router.backendUrl:"https://maps.powermap.live/indoor
|
|
383
|
+
`;const e=this.container.querySelector("#pm-route-origin"),t=this.container.querySelector("#pm-route-dest");e.addEventListener("input",i=>this._onSearchInput(i.target.value,"origin")),t.addEventListener("input",i=>this._onSearchInput(i.target.value,"destination")),e.addEventListener("focus",()=>{this.activeInput="origin"}),t.addEventListener("focus",()=>{this.activeInput="destination"}),document.addEventListener("click",i=>{this.container.contains(i.target)||(this._hideResults("origin"),this._hideResults("destination"))});const o=this.container.querySelector("#pm-route-swap");o&&o.addEventListener("click",()=>this._swapLocations())}_swapLocations(){const e=this.origin;this.origin=this.destination,this.destination=e;const t=this.container.querySelector("#pm-route-origin"),o=this.container.querySelector("#pm-route-dest"),i=t.value;t.value=o.value,o.value=i,this._tryCalculateRoute()}_onMapClick(e){var n;if(!this.activeInput||!this.buildingId)return;const t=e.lngLat;let o=((n=this.router)==null?void 0:n.activeFloorId)||null;const i={id:"custom-"+Date.now(),name:`Point (${t.lat.toFixed(4)}, ${t.lng.toFixed(4)})`,floorId:o,lng:t.lng,lat:t.lat};this._selectLocation(i,this.activeInput),this.activeInput=null}async _onSearchInput(e,t){if(t==="origin"&&clearTimeout(this._originSearchTimer),t==="destination"&&clearTimeout(this._destSearchTimer),!e||e.length<2){this._hideResults();return}const o=setTimeout(async()=>{var i;try{const n=this.router&&this.router.backendUrl?this.router.backendUrl:"https://maps.powermap.live/api/v2/indoor",s=new URL(`${n}/search`);s.searchParams.set("q",e),this.buildingId&&s.searchParams.set("buildingId",this.buildingId);let a;const l=((i=this._map)==null?void 0:i.authManager)||this.router&&this.router.context&&this.router.context.authManager;if(l?a=await l.fetchWithAuth(s.toString(),{source:"indoor-search"}):a=await fetch(s.toString()),a&&a.ok){const c=await a.json();let u=[];Array.isArray(c)?u=c:c.hits&&Array.isArray(c.hits.hits)?u=c.hits.hits:Array.isArray(c.hits)?u=c.hits:Array.isArray(c.data)?u=c.data:Array.isArray(c.results)?u=c.results:Array.isArray(c.value)&&(u=c.value),this._renderResults(u,t)}}catch(n){console.error("PowerMap SDK: Indoor search failed",n)}},300);t==="origin"&&(this._originSearchTimer=o),t==="destination"&&(this._destSearchTimer=o)}_renderResults(e,t){const o=this.container.querySelector("#pm-indoor-search-results");if(o.innerHTML="",!e||e.length===0){this._hideResults();return}e.forEach(s=>{const a=document.createElement("div");a.className="pm-route-step";let l="-";s.floorNumber!==void 0?l=String(s.floorNumber):s.level!==void 0?l=String(s.level):s.ordinal!==void 0&&(l=String(s.ordinal)),a.innerHTML=`
|
|
384
384
|
<div class="pm-step-icon-col" style="display: flex; flex-direction: column; align-items: center; margin-right: 12px;">
|
|
385
385
|
<div class="pm-step-icon-bg" style="width: 32px; height: 32px; border-radius: 50%; background: rgba(242, 101, 34, 0.1); color: #F26522; display: flex; justify-content: center; align-items: center;">
|
|
386
386
|
<svg viewBox="0 0 24 24" fill="currentColor" style="width: 16px; height: 16px;"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
|
package/dist/powermap-web-sdk.js
CHANGED
|
@@ -9408,11 +9408,11 @@ class Os {
|
|
|
9408
9408
|
* @param {Object} context - Shared SDK context (needs authManager)
|
|
9409
9409
|
*/
|
|
9410
9410
|
constructor(e) {
|
|
9411
|
-
this.context = e, this.baseUrl = "
|
|
9411
|
+
this.context = e, this.baseUrl = "https://maps.powermap.live/api/v2/indoor", this._geojsonCache = {};
|
|
9412
9412
|
}
|
|
9413
9413
|
/**
|
|
9414
9414
|
* Set the base URL for the Indoor API.
|
|
9415
|
-
* @param {string} url - The base URL (e.g., 'https://maps.powermap.live/indoor
|
|
9415
|
+
* @param {string} url - The base URL (e.g., 'https://maps.powermap.live/api/v2/indoor')
|
|
9416
9416
|
*/
|
|
9417
9417
|
setBaseUrl(e) {
|
|
9418
9418
|
return this.baseUrl = e.replace(/\/$/, ""), this;
|
|
@@ -9487,7 +9487,7 @@ class Os {
|
|
|
9487
9487
|
class Rs {
|
|
9488
9488
|
constructor(e) {
|
|
9489
9489
|
var t, o;
|
|
9490
|
-
this.context = e, this.map = (t = this.context.mapManager) == null ? void 0 : t.getMap(), this.routeData = null, this.activeFloorId = null, this.markers = { start: null, end: null }, this.backendUrl = (o = this.context.options) != null && o.baseUrl ? this.context.options.baseUrl + "/indoor
|
|
9490
|
+
this.context = e, this.map = (t = this.context.mapManager) == null ? void 0 : t.getMap(), this.routeData = null, this.activeFloorId = null, this.markers = { start: null, end: null }, this.backendUrl = (o = this.context.options) != null && o.baseUrl ? this.context.options.baseUrl + "/api/v2/indoor" : "https://maps.powermap.live/api/v2/indoor";
|
|
9491
9491
|
}
|
|
9492
9492
|
_getMap() {
|
|
9493
9493
|
var e;
|
|
@@ -10101,7 +10101,7 @@ class Us {
|
|
|
10101
10101
|
const o = setTimeout(async () => {
|
|
10102
10102
|
var i;
|
|
10103
10103
|
try {
|
|
10104
|
-
const n = this.router && this.router.backendUrl ? this.router.backendUrl : "https://maps.powermap.live/indoor
|
|
10104
|
+
const n = this.router && this.router.backendUrl ? this.router.backendUrl : "https://maps.powermap.live/api/v2/indoor", s = new URL(`${n}/search`);
|
|
10105
10105
|
s.searchParams.set("q", e), this.buildingId && s.searchParams.set("buildingId", this.buildingId);
|
|
10106
10106
|
let a;
|
|
10107
10107
|
const l = ((i = this._map) == null ? void 0 : i.authManager) || this.router && this.router.context && this.router.context.authManager;
|
|
@@ -352,7 +352,7 @@
|
|
|
352
352
|
<div class="pm-draw-divider" data-for="settings" style="display: none;"></div>
|
|
353
353
|
<button class="pm-draw-btn" data-tool="settings" title="Settings" style="display: none;">${d}</button>
|
|
354
354
|
`:""}
|
|
355
|
-
`,this.toolbar.innerHTML=b,this.tooltip&&this.tooltip.attachToToolbar(this.toolbar)}_exportGeoJSON(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometryExported",{data:t,format:e});const o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),i=URL.createObjectURL(o),n=document.createElement("a");n.href=i,n.download=`powermap-export-${new Date().getTime()}.json`,n.click(),URL.revokeObjectURL(i)}catch(e){const t=e instanceof PowerMapError?e:new PowerMapError(`Failed to export data: ${e.message}`,ErrorCode.UNKNOWN,"editor",{originalError:e});this.eventBus.emit("error",t)}}_triggerImport(){const e=document.createElement("input");e.type="file",e.accept=".json,application/json",e.onchange=t=>{const o=t.target.files[0];if(!o)return;const i=new FileReader;i.onload=n=>{try{const s=JSON.parse(n.target.result),a=this.mode==="indoor"?"imdf":"standard";this.geometryManager.import(s,{format:a})}catch(s){const a=s instanceof PowerMapError?s:new PowerMapError(`Failed to parse or import GeoJSON: ${s.message}`,ErrorCode.INVALID_PARAMETERS,"editor",{originalError:s});this.eventBus.emit("error",a)}},i.onerror=()=>{const n=new PowerMapError("Failed to read the selected file.",ErrorCode.UNKNOWN,"editor");this.eventBus.emit("error",n)},i.readAsText(o)},e.click()}_triggerSave(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometrySaveRequested",{data:t,format:e})}catch(e){typeof PowerMapError<"u"&&e instanceof PowerMapError?this.eventBus.emit("error",e):console.error(e)}}}class pn{constructor(e){this.mapManager=e.registry.get("map"),this.geometryManager=e.registry.get("geometry"),this.eventBus=e.eventBus,this.isEnabled=!1,this.control=null,this.mode=e.mode||"standard"}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t){this.eventBus.on("mapLoaded",()=>this.enable(e));return}this.geometryManager.getDrawInstance()||this.geometryManager.initDraw(t);const o=e.position||"bottom-left";this.mode=e.mode||this.mode;try{this.control=new dn(this.geometryManager,this.eventBus,{mode:this.mode}),this.control.setMode&&this.control.setMode(this.mode),t.addControl(this.control,o),this.isEnabled=!0}catch(i){const n=new w(`Failed to enable editor: ${i.message}`,v.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}setMode(e){this.mode=e,this.control&&this.control.setMode&&this.control.setMode(e)}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&this.control&&e.removeControl(this.control),this.control=null,this.isEnabled=!1}attach(e){const t=typeof e=="object"?e.id:e;if(!t)throw new w("Feature ID is required to attach editor.",v.INVALID_PARAMETERS,"editor");const o=this.geometryManager.getDrawInstance();if(!o)throw new w("Cannot attach: Draw instance not initialized.",v.MAP_NOT_INITIALIZED,"editor");try{o.changeMode("direct_select",{featureId:t})}catch(i){const n=new w(`Could not attach to feature ${t}: ${i.message}`,v.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}detach(){const e=this.geometryManager.getDrawInstance();e&&e.changeMode("simple_select")}}class hn{constructor(e){this.mapManager=e.registry.get("map"),this.eventBus=e.eventBus,this.isEnabled=!1,this.panel=null,this.fps=0,this.frameCount=0,this.lastTime=performance.now(),this.lastFpsCalc=this.lastTime,this._onRender=this._onRender.bind(this),this._onMove=this._onMove.bind(this),this.showFps=!0,this.showCoord=!0}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t)throw new w("Cannot enable debug panel: Map is not initialized.",v.MAP_NOT_INITIALIZED,"debug");const o=e.position||"top-left";this.panel=document.createElement("div"),this.panel.className="pm-debug-panel",Object.assign(this.panel.style,{position:"absolute",background:"rgba(0, 0, 0, 0.7)",color:"#0f0",padding:"12px",fontFamily:'"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',fontSize:"13px",borderRadius:"8px",zIndex:"9999",pointerEvents:"none",lineHeight:"1.6",boxShadow:"0 4px 6px rgba(0,0,0,0.3)",border:"1px solid rgba(0,255,0,0.3)"}),o.includes("top")&&(this.panel.style.top="10px"),o.includes("bottom")&&(this.panel.style.bottom="40px"),o.includes("left")&&(this.panel.style.left="10px"),o.includes("right")&&(this.panel.style.right="10px"),t.getContainer().appendChild(this.panel),t.on("render",this._onRender),t.on("move",this._onMove),this.isEnabled=!0,this._updateUI()}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&(e.off("render",this._onRender),e.off("move",this._onMove)),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null,this.isEnabled=!1}showFPS(e=!0){this.showFps=e,this._updateUI()}showCoordinate(e=!0){this.showCoord=e,this._updateUI()}_onRender(){const e=performance.now();this.frameCount++,e>=this.lastFpsCalc+1e3&&(this.fps=Math.round(this.frameCount*1e3/(e-this.lastFpsCalc)),this.frameCount=0,this.lastFpsCalc=e,this._updateUI())}_onMove(){this._updateUI()}_updateUI(){if(!this.isEnabled||!this.panel)return;const e=this.mapManager.getMap();if(!e)return;let t="<strong>PowerMap Debug</strong><br/>";if(this.showFps){const o=this.fps<30?"red":this.fps<50?"orange":"#0f0";t+=`FPS: <span style="color:${o}">${this.fps}</span><br/>`}if(this.showCoord){const o=e.getCenter();t+=`Lng: ${o.lng.toFixed(5)}<br/>`,t+=`Lat: ${o.lat.toFixed(5)}<br/>`,t+=`Zoom: ${e.getZoom().toFixed(2)}<br/>`,t+=`Pitch: ${e.getPitch().toFixed(1)}°<br/>`,t+=`Bearing: ${e.getBearing().toFixed(1)}°<br/>`;const i=e.getBounds();t+='<div style="font-size:10px; color:#aaa; margin-top:8px;">',t+=`NE: ${i.getNorthEast().lng.toFixed(3)}, ${i.getNorthEast().lat.toFixed(3)}<br/>`,t+=`SW: ${i.getSouthWest().lng.toFixed(3)}, ${i.getSouthWest().lat.toFixed(3)}`,t+="</div>"}this.panel.innerHTML=t}}const Dt=new Map;async function gn(r){if(Dt.has(r))return Dt.get(r);const e=await fetch(r);if(!e.ok)throw new w(`Fetch style failed: ${r}`,v.API_REQUEST_FAILED,"layers");const t=await e.json();return Dt.set(r,t),t}function fn(r){return`${r}/api/v2/map/vtile`}function he(r,e){if(!e||r.includes("apikey="))return r;const t=r.includes("?")?"&":"?";return`${r}${t}apikey=${encodeURIComponent(e)}`}function mn(r,e,t){if(!r)return r;if(r.startsWith(e))return he(r,t);if(r.startsWith("mbtiles://")){const i=r.replace("mbtiles://","").replace(/\.mbtiles$/i,"");return he(`${e}/data/${i}.json`,t)}const o=r.match(/\/data\/([^/]+)\.json$/i);return o?he(`${e}/data/${o[1]}.json`,t):r}function An(r,e,t){if(!r)return r;if(r.startsWith(e))return he(r,t);const o=r.match(/^https?:\/\/[^/]+\/data\/([^/]+)\/\{z\}\/\{x\}\/\{y\}\.pbf(?:\?.*)?$/i);return o?he(`${e}/data/${o[1]}/{z}/{x}/{y}.pbf`,t):r}function yn(r,e,t,o,i,n=()=>!0){var s;try{if(!n()||!((s=r==null?void 0:r.getStyle)!=null&&s.call(r))||r.getSource(e))return;const a={type:"vector"};if(Array.isArray(t.tiles)&&t.tiles.length)a.tiles=t.tiles.map(l=>An(l,o,i));else if(t.url&&t.url.startsWith("mbtiles://")){const l=t.url.replace("mbtiles://","").replace(/\.mbtiles$/i,"");a.tiles=[he(`${o}/data/${l}/{z}/{x}/{y}.pbf`,i)]}else if(t.url){const l=t.url.match(/\/data\/([^/]+)\.json(?:\?.*)?$/i);l?a.tiles=[he(`${o}/data/${l[1]}/{z}/{x}/{y}.pbf`,i)]:a.url=mn(t.url,o,i)}if(!n())return;r.addSource(e,a)}catch{}}function bn(r){var e,t,o;try{return(o=(((t=(e=r==null?void 0:r.getStyle)==null?void 0:e.call(r))==null?void 0:t.layers)||[]).find(i=>i.type==="symbol"))==null?void 0:o.id}catch{return}}async function Se(r,e,{ns:t="rp",includeFn:o=()=>!0,defaultVis:i="none",beforeId:n=void 0,base:s,apiKey:a}={}){var g;if(!(r!=null&&r.getStyle))return;const l=r.__pmNonce,c=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==l?!1:!!r.getStyle()}catch{return!1}},u=f=>{try{return c()?r.getLayer(f):void 0}catch{return}};if(!c())return;let d=null;try{d=await gn(e)}catch{console.warn("fetchStyle failed:",e);return}if(!c())return;const p={};for(const[f,A]of Object.entries(d.sources||{})){if(!c())return;const y=`${t}-src-${f}`;yn(r,y,A,s,a,c),p[f]=y}for(const f of d.layers||[]){if(!o(f))continue;if(!c())return;const A=`${t}-${f.id}`;if(u(A))continue;const y=JSON.parse(JSON.stringify(f));y.id=A,p[y.source]&&(y.source=p[y.source]),y.layout=y.layout||{},y.layout.visibility=i;try{if(!c())return;r.addLayer(y,n)}catch{}}if(!c())return;const h=(g=r.__pmDesiredVis)==null?void 0:g[t];return typeof h=="boolean"&&no(r,t,h,c),{prefix:t}}function no(r,e,t,o=()=>!0){var i;try{if(!o())return;const n=t?"visible":"none",s=(((i=r.getStyle())==null?void 0:i.layers)||[]).filter(a=>a.id.startsWith(e+"-"));for(const a of s){if(!o())return;try{r.setLayoutProperty(a.id,"visibility",n)}catch{}}}catch{}}async function Nt(r,e,t=e,o){if(!(r!=null&&r.getStyle))return;const i=r.__pmNonce,n=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==i?!1:!!r.getStyle()}catch{return!1}},s=y=>{try{return n()?!!(r.hasImage&&r.hasImage(y)):!1}catch{return!1}};if(r.isStyleLoaded&&!r.isStyleLoaded()&&await new Promise(y=>{if(!n())return y();const b=()=>{x(),y()},x=()=>{try{r.off("styledata",b)}catch{}try{r.off("load",b)}catch{}};r.on("styledata",b),r.on("load",b),setTimeout(()=>{x(),y()},1500)}),!n()||(r.__pmSpriteLoaded=r.__pmSpriteLoaded||{},r.__pmSpriteLoaded[t]))return;const a=y=>he(y,o),c=(window.devicePixelRatio||1)>1.5?[a(`${e}@2x.json`),a(`${e}@2x.png`),a(`${e}.json`),a(`${e}.png`)]:[a(`${e}.json`),a(`${e}.png`),a(`${e}@2x.json`),a(`${e}@2x.png`)];let u,d,p=1;for(let y=0;y<c.length;y+=2){if(!n())return;try{const[b,x]=[c[y],c[y+1]],M=await fetch(b);if(!M.ok)throw 0;if(u=await M.json(),!n())return;const I=await fetch(x);if(!I.ok)throw 0;const P=await I.blob();if(!n())return;d="createImageBitmap"in window?await createImageBitmap(P):await A(P),p=b.includes("@2x")?2:1;break}catch{}}if(!n())return;if(!u||!d){console.warn("sprite load failed for",e);return}const h="createImageBitmap"in window&&d instanceof ImageBitmap,g=h?null:document.createElement("canvas"),f=g?g.getContext("2d"):null;for(const[y,b]of Object.entries(u)){if(!n())return;if(s(y))continue;const{x,y:M,width:I,height:P,sdf:k}=b;let G;if(h?G=await createImageBitmap(d,x,M,I,P):(g.width=I,g.height=P,f.clearRect(0,0,I,P),f.drawImage(d,x,M,I,P,0,0,I,P),G=g),!n())return;try{r.addImage(y,G,{pixelRatio:p,sdf:!!k})}catch{}}if(!n())return;r.__pmSpriteLoaded[t]=!0;function A(y){return new Promise((b,x)=>{const M=new Image;M.onload=()=>b(M),M.onerror=x,M.crossOrigin="anonymous",M.src=URL.createObjectURL(y)})}}function wn(r,e){const t=o=>he(o,e);return[{key:"city",label:"CITY PLAN",items:[ce("pm-bangkok-layer","Bangkok","PM_Bangkok",r,e),ce("pm-nakhon-pathom-layer","Nakhon Pathom","PM_Nakhon_Pathom",r,e),ce("pm-ayutthaya-layer","Ayutthaya","PM_Phra_Nakhon_Si_Ayutthaya",r,e),ce("pm-chonburi-layer","Chon Buri","PM_Chon_Buri",r,e),ce("pm-samutprakan-layer","Samut Prakan","PM_Samut_Prakan",r,e),ce("pm-rayong-layer","Rayong","PM_Rayong",r,e),ce("pm-samutsakhon-layer","Samut Sakhon","PM_Samut_Sakhon",r,e,{tileSize:128}),ce("pm-pathumthani-layer","Pathum Thani","PM_Pathumthani",r,e,{tileSize:128}),ce("pm-ubonratchathani-layer","Ubon Ratchathani","PM_Ubon_Ratchathani",r,e,{tileSize:128}),ce("pm-nonthaburi-layer","Nonthaburi","PM_Nonthaburi",r,e,{tileSize:128}),ce("pm-chachoengsao-layer","Chachoengsao","PM_Chachoengsao",r,e,{tileSize:128})]},{key:"transport",label:"TRANSPORT",items:[{id:"pm-road-vt",name:"Road",groupPrefix:"vt-road",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/road_poi/style.json`);o.__pmRoadVt||(await Se(o,i,{ns:"vt-road",defaultVis:"none",includeFn:n=>n?n.type==="line"?!0:n.type==="symbol"&&n.source==="road"?n["source-layer"]==="road_name":!1:!1,base:r,apiKey:e}),o.__pmRoadVt=!0)}},{id:"pm-post-elec-vt",name:"Post Election",groupPrefix:"vt-postelec",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/post_elec/style.json`),n=`${r}/transport/post_elec/sprite`;o.__pmGroupReady=o.__pmGroupReady||{},!o.__pmGroupReady["vt-postelec"]&&(await Nt(o,n,"post_elec",e),await Se(o,i,{ns:"vt-postelec",defaultVis:"none",includeFn:s=>(s==null?void 0:s.type)==="symbol",base:r,apiKey:e}),o.__pmGroupReady["vt-postelec"]=!0)}},Le({id:"pm-future-motorway-th-vt",name:"Future Motorway TH",ns:"vt-fmw-th",stylePath:"transport/future_motorway_th",flagPrefix:"__pmFutureMwTh",base:r,apiKey:e,tk:t}),Le({id:"pm-future-motorway-en-vt",name:"Future Motorway EN",ns:"vt-fmw-en",stylePath:"transport/future_motorway_en",flagPrefix:"__pmFutureMwEn",base:r,apiKey:e,tk:t}),Le({id:"pm-current-railway-th-vt",name:"Current Railway TH",ns:"vt-railth-cur",stylePath:"transport/current_railway_th",flagPrefix:"__pmRailTh",base:r,apiKey:e,tk:t}),Le({id:"pm-current-railway-en-vt",name:"Current Railway EN",ns:"vt-railen-cur",stylePath:"transport/current_railway_en",flagPrefix:"__pmRailEn",base:r,apiKey:e,tk:t}),Le({id:"pm-future-railway-th-vt",name:"Future Railway TH",ns:"vt-railth-future",stylePath:"transport/future_railway_th",flagPrefix:"__pmFRailTh",base:r,apiKey:e,tk:t}),Le({id:"pm-future-railway-en-vt",name:"Future Railway EN",ns:"vt-railen-future",stylePath:"transport/future_railway_en",flagPrefix:"__pmFRailEn",base:r,apiKey:e,tk:t}),tt({id:"pm-current-bts-mrt-th-vt",name:"Current BTS MRT TH",ns:"vt-btsmrt-cur-th",stylePath:"transport/current_bts_mrt_th",flagPrefix:"__pmBTSMRTTH",base:r,apiKey:e,tk:t}),tt({id:"pm-current-bts-mrt-en-vt",name:"Current BTS MRT EN",ns:"vt-btsmrt-cur-en",stylePath:"transport/current_bts_mrt_en",flagPrefix:"__pmBTSMRTEN",base:r,apiKey:e,tk:t}),tt({id:"pm-future-bts-mrt-th-vt",name:"Future BTS MRT TH",ns:"vt-btsmrt-fut-th",stylePath:"transport/future_bts_mrt_th",flagPrefix:"__pmBTSMRT_FUTTH",base:r,apiKey:e,tk:t}),tt({id:"pm-future-bts-mrt-en-vt",name:"Future BTS MRT EN",ns:"vt-btsmrt-fut-en",stylePath:"transport/future_bts_mrt_en",flagPrefix:"__pmBTSMRT_FUTEN",base:r,apiKey:e,tk:t})]},{key:"insight",label:"INSIGHT DATA",items:[{id:"pm-viirs-blackmarble-layer",name:"Night Lights",ensure:o=>{o!=null&&o.getStyle()&&(o.getSource("pm-viirs-blackmarble-source")||o.addSource("pm-viirs-blackmarble-source",{type:"raster",tiles:["https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/VIIRS_Black_Marble/default/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.png"],tileSize:256,minzoom:0,maxzoom:8}),o.getLayer("pm-viirs-blackmarble-layer")||o.addLayer({id:"pm-viirs-blackmarble-layer",type:"raster",source:"pm-viirs-blackmarble-source",paint:{"raster-opacity":.7},layout:{visibility:"none"}}))}},{id:"pm-maptiler-satellite-layer",name:"Satellite",ensure:o=>{if(!(o!=null&&o.getStyle()))return;const i=o.__pmMaptilerKey;if(!i){console.warn("PowerMap LayerManager: maptilerKey not provided, satellite layer skipped.");return}if(o.getSource("pm-maptiler-satellite-source")||o.addSource("pm-maptiler-satellite-source",{type:"raster",tiles:[`https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=${encodeURIComponent(i)}`],tileSize:256,minzoom:0,maxzoom:22}),!o.getLayer("pm-maptiler-satellite-layer")){const n=bn(o);o.addLayer({id:"pm-maptiler-satellite-layer",type:"raster",source:"pm-maptiler-satellite-source",paint:{"raster-opacity":1},layout:{visibility:"none"}},n)}}}]}]}const Ft={"pm-road-vt":{prefix:"vt-road"},"pm-road-poi-vt":{prefix:"vt-roadpoi"},"pm-post-elec-vt":{prefix:"vt-postelec"},"pm-future-motorway-th-vt":{prefix:"vt-fmw-th"},"pm-future-motorway-en-vt":{prefix:"vt-fmw-en"},"pm-current-railway-th-vt":{prefix:"vt-railth-cur"},"pm-current-railway-en-vt":{prefix:"vt-railen-cur"},"pm-future-railway-th-vt":{prefix:"vt-railth-future"},"pm-future-railway-en-vt":{prefix:"vt-railen-future"},"pm-current-bts-mrt-th-vt":{prefix:"vt-btsmrt-cur-th"},"pm-current-bts-mrt-en-vt":{prefix:"vt-btsmrt-cur-en"},"pm-future-bts-mrt-th-vt":{prefix:"vt-btsmrt-fut-th"},"pm-future-bts-mrt-en-vt":{prefix:"vt-btsmrt-fut-en"}};function ce(r,e,t,o,i,n={}){const s=n.tileSize||256;return{id:r,name:e,ensure:a=>{if(!(a!=null&&a.getStyle()))return;const l=r.replace("-layer","-source");a.getSource(l)||a.addSource(l,{type:"raster",tiles:[he(`${o}/data/${t}/{z}/{x}/{y}.png`,i)],tileSize:s,minzoom:8,maxzoom:16}),a.getLayer(r)||a.addLayer({id:r,type:"raster",source:l,paint:{"raster-opacity":1},layout:{visibility:"none"}})}}}function Le({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}Round1`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}Round1`]=!0),l[`${i}Sprite`]||(await Nt(l,u,o.replace("/","_"),s),l[`${i}Sprite`]=!0),l[`${i}Round2`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol",base:n,apiKey:s}),l[`${i}Round2`]=!0)}}}function tt({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}_Lines`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}_Lines`]=!0),l[`${i}_Sprite`]||(await Nt(l,u,o.replace("/","_"),s),l[`${i}_Sprite`]=!0),l[`${i}_Symbols`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol"&&d["source-layer"]==="bts_mrt_station",base:n,apiKey:s}),l[`${i}_Symbols`]=!0)}}}class vn{constructor(e){this.context=e,this.eventBus=e.eventBus,this.authManager=e.authManager;const t=this.authManager.getBaseUrl();this._base=fn(t),this._apiKey=e.options.mapApiKey,this._catalog=wn(this._base,this._apiKey),this._ensured=new Set,this._layerState=new Map,e.options.maptilerKey&&(this._maptilerKey=e.options.maptilerKey),this.eventBus.on("mapLoaded",({map:o})=>{this._maptilerKey&&o&&(o.__pmMaptilerKey=this._maptilerKey),o.on("style.load",async()=>{for(const[i,n]of this._layerState.entries())try{const s=this._findItem(i);s&&await s.item.ensure(o),n.visible!==void 0&&this._setVisibility(i,n.visible),n.opacity!==void 0&&this.setOpacity(i,n.opacity)}catch(s){console.warn(`LayerManager: Failed to auto-restore layer ${i}`,s)}})})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}_findItem(e){for(const t of this._catalog){const o=t.items.find(i=>i.id===e);if(o)return{item:o,group:t}}return null}getCatalog(){return this._catalog.map(e=>({key:e.key,label:e.label,items:e.items.map(t=>({id:t.id,name:t.name,groupPrefix:t.groupPrefix||null}))}))}getGroup(e){const t=this._catalog.find(o=>o.key===e);return t?t.items.map(o=>({id:o.id,name:o.name})):null}getLayerState(e){var n;const t=this._getMap(),o=this._ensured.has(e);let i=null;if(t&&o){const s=Ft[e];if(s)try{const a=(((n=t.getStyle())==null?void 0:n.layers)||[]).filter(l=>l.id.startsWith(s.prefix+"-"));i=a.length>0&&a.some(l=>t.getLayoutProperty(l.id,"visibility")==="visible")}catch{i=!1}else try{i=t.getLayoutProperty(e,"visibility")==="visible"}catch{i=!1}}return{loaded:o,visible:i}}async ensure(e){const t=this._getMap();if(!t)throw new w("Map is not ready. Call ensure() after mapLoaded event.",v.INVALID_PARAMETERS,"layers");const o=this._findItem(e);if(!o)throw new w(`Layer "${e}" not found in catalog. Use getCatalog() to see available layers.`,v.INVALID_PARAMETERS,"layers");try{await o.item.ensure(t),this._ensured.add(e),this.eventBus.emit("layerEnsured",{layerId:e,group:o.group.key})}catch(i){throw new w(`Failed to ensure layer "${e}": ${i.message}`,v.API_REQUEST_FAILED,"layers",{originalError:i})}}async show(e){this._ensured.has(e)||await this.ensure(e);const t=this._layerState.get(e)||{};t.visible=!0,this._layerState.set(e,t),this._setVisibility(e,!0),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!0})}hide(e){const t=this._layerState.get(e)||{};t.visible=!1,this._layerState.set(e,t),this._setVisibility(e,!1),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!1})}async toggle(e){const t=this.getLayerState(e);t.loaded?t.visible?this.hide(e):this.show(e):await this.show(e)}setOpacity(e,t){var s;const o=this._layerState.get(e)||{};o.opacity=t,this._layerState.set(e,o);const i=this._getMap();if(!i)return;const n=Ft[e];if(n)try{const a=(((s=i.getStyle())==null?void 0:s.layers)||[]).filter(l=>l.id.startsWith(n.prefix+"-"));for(const l of a)try{l.type==="line"?i.setPaintProperty(l.id,"line-opacity",t):l.type==="symbol"?(i.setPaintProperty(l.id,"icon-opacity",t),i.setPaintProperty(l.id,"text-opacity",t)):l.type==="fill"&&i.setPaintProperty(l.id,"fill-opacity",t)}catch{}}catch{}else try{const a=i.getLayer(e);a&&(a.type==="raster"?i.setPaintProperty(e,"raster-opacity",t):a.type==="line"?i.setPaintProperty(e,"line-opacity",t):a.type==="fill"&&i.setPaintProperty(e,"fill-opacity",t))}catch{}}async showGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)await this.show(o.id)}hideGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)this.hide(o.id)}hideAll(){for(const e of this._catalog)for(const t of e.items)this.hide(t.id)}_setVisibility(e,t){const o=this._getMap();if(!o)return;const i=Ft[e];if(i){const n=!!t;if(o.__pmDesiredVis=o.__pmDesiredVis||{},o.__pmDesiredVis[i.prefix]=n,no(o,i.prefix,n),o.getLayer(e))try{o.setLayoutProperty(e,"visibility",n?"visible":"none")}catch{}else try{o.addLayer({id:e,type:"background",layout:{visibility:n?"visible":"none"},paint:{"background-opacity":0}})}catch{}return}if(o.getLayer(e))try{o.setLayoutProperty(e,"visibility",t?"visible":"none")}catch{}}}class Cn{constructor(e){this.context=e,this.baseUrl="http://localhost:3000/indoor-api",this._geojsonCache={}}setBaseUrl(e){return this.baseUrl=e.replace(/\/$/,""),this}async getVenues(){return this._fetchJSON("/venues")}async getBuildings(e){const t=e?`/buildings?venueId=${e}`:"/buildings";return this._fetchJSON(t)}async getFloors(e){if(!e)throw new Error("buildingId is required");return this._fetchJSON(`/floors?buildingId=${e}`)}async getFloorGeoJSON(e){if(!e)throw new Error("floorId is required");if(this._geojsonCache[e])return JSON.parse(JSON.stringify(this._geojsonCache[e]));const t=await this._fetchJSON(`/floors/${e}/geojson`);return this._geojsonCache[e]=JSON.parse(JSON.stringify(t)),t}async search(e,t={}){if(!e)throw new Error("Search query is required");if(!t.buildingId)throw new w("buildingId is required for indoor search",v.INVALID_PARAMETERS,"indoor");let o=`/search?q=${encodeURIComponent(e)}&buildingId=${t.buildingId}`;return t.category&&(o+=`&category=${t.category}`),t.limit&&(o+=`&limit=${t.limit}`),this._fetchJSON(o)}async _fetchJSON(e){const t=this.context.authManager;if(!t)throw new w("AuthManager not found in SDK context.",v.MAP_NOT_INITIALIZED,"indoor");const o=`${this.baseUrl}${e}`,i=await t.fetchWithAuth(o);if(!i.ok)throw new w(`API Request failed with status ${i.status}`,v.UNKNOWN,"indoor",{status:i.status});return await i.json()}}class xn{constructor(e){var t,o;this.context=e,this.map=(t=this.context.mapManager)==null?void 0:t.getMap(),this.routeData=null,this.activeFloorId=null,this.markers={start:null,end:null},this.backendUrl=(o=this.context.options)!=null&&o.baseUrl?this.context.options.baseUrl+"/indoor-api":"https://maps.powermap.live/indoor-api"}_getMap(){var e;if(this.map)return this.map;if(this.context.mapManager)return this.context.mapManager.getMap();if(this.context.registry&&this.context.registry.get){const t=this.context.registry.get("map");return(t==null?void 0:t.map)||((e=t==null?void 0:t.getMap)==null?void 0:e.call(t))}return null}setMap(e){this.map=e}async calculateRoute(e,t,o,i,n){var a,l;const s=new URL(`${this.backendUrl}/route`);s.searchParams.set("buildingId",e),s.searchParams.set("startFloorId",t),s.searchParams.set("startLng",o[0]),s.searchParams.set("startLat",o[1]),s.searchParams.set("endFloorId",i),s.searchParams.set("endLng",n[0]),s.searchParams.set("endLat",n[1]);try{let c;if(this.context.authManager?c=await this.context.authManager.fetchWithAuth(s.toString(),{source:"indoor-route"}):c=await fetch(s.toString(),{headers:{"x-client-id":this.context.mapApiKey||((a=this.context.auth)==null?void 0:a.clientId),"x-client-secret":(l=this.context.auth)==null?void 0:l.clientSecret}}),!c.ok)throw new Error("Failed to fetch indoor route");const u=await c.json();this.routeData=u,this.activeFloorId=t,this.drawRoute(this.activeFloorId);let d=0,p=0,h=[],g=null;if(u&&u.type==="FeatureCollection"){const A=u.properties||(u.features.length>0?u.features[0].properties:{});d=A.distance||0,p=A.duration||Math.round(d/1.4),h=A.instructions||[],g=u.features.length>0?u.features[0].geometry:null;const y=u.features.flatMap(b=>{var x;return((x=b.geometry)==null?void 0:x.coordinates)||[]});if(y.length>1){const b=y.reduce((x,M)=>x.extend(M),new D.LngLatBounds(y[0],y[0]));this._getMap()&&this._getMap().fitBounds(b,{padding:60,duration:1e3})}}const f=h.map(A=>{var x;let y=null;(x=A.maneuver)!=null&&x.location?y=A.maneuver.location:A.interval&&coords.length>0&&(y=coords[A.interval[0]]);const b=A.maneuver||{type:"turn",instruction:A.text};return!b.location&&y&&(b.location=y),{distance:A.distance,duration:A.time?A.time/1e3:Math.round((A.distance||0)/1.4),name:A.street_name||"",floorId:A.floorId,maneuver:b}});return{distance:d,duration:p,steps:f,geometry:g,raw:u}}catch(c){throw console.error("PowerMap SDK: Indoor routing failed",c),this.clearRoute(),c}}setActiveFloor(e){this.activeFloorId=e,this.routeData&&this.drawRoute(e),this._updateMarkerVisibility()}clearRoute(){this.routeData=null,this._removeLayers(),this.markers.start&&this.markers.start.remove(),this.markers.end&&this.markers.end.remove(),this.markers={start:null,end:null}}drawRoute(e){const t=this._getMap();if(!t||!this.routeData)return;let o=this.routeData;o.type==="FeatureCollection"&&e&&(o={...o,features:o.features.filter(s=>{var a;return!((a=s.properties)!=null&&a.floorId)||String(s.properties.floorId)===String(e)})});const i="pm-indoor-route",n=t.getSource(i);n?n.setData(o):t.addSource(i,{type:"geojson",data:o}),this._ensureLayers(i)}_ensureLayers(e){const t=this._getMap();t&&(t.getLayer(`${e}-casing`)||t.addLayer({id:`${e}-casing`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#1d4ed8","line-width":8,"line-opacity":.3}}),t.getLayer(`${e}-line`)||t.addLayer({id:`${e}-line`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#3b82f6","line-width":5}}))}_removeLayers(){const e=this._getMap();if(!e)return;const t="pm-indoor-route";e.getLayer(`${t}-line`)&&e.removeLayer(`${t}-line`),e.getLayer(`${t}-casing`)&&e.removeLayer(`${t}-casing`),e.getSource(t)&&e.removeSource(t)}drawMarkers(e,t){const o=this._getMap();if(o){if(!e&&this.markers.start&&(this.markers.start.remove(),this.markers.start=null),!t&&this.markers.end&&(this.markers.end.remove(),this.markers.end=null),e){if(this.markers.start)this.markers.start.setLngLat([e.lng,e.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-start",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#10b981",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.start=new D.Marker({element:i}).setLngLat([e.lng,e.lat]).addTo(o)}this.markers.start.getElement().dataset.floorId=e.floorId}if(t){if(this.markers.end)this.markers.end.setLngLat([t.lng,t.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-end",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#ef4444",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.end=new D.Marker({element:i}).setLngLat([t.lng,t.lat]).addTo(o)}this.markers.end.getElement().dataset.floorId=t.floorId}this._updateMarkerVisibility()}}_updateMarkerVisibility(){if(this.markers.start){const e=this.markers.start.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}if(this.markers.end){const e=this.markers.end.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}}}class Mn{constructor(e){this.context=e,this.eventBus=e.eventBus,this.api=new Cn(e),this.router=new xn(e),this.currentFloor=0,this._isTransitioning=!1,this.layerGroups={poi:["pm-draw-special-point-inactive","pm-draw-special-point-active"],beacon:["pm-draw-special-point-inactive","pm-draw-special-point-active"],walkway:["pm-draw-line-active","pm-draw-line-static","pm-draw-point-vertex","pm-draw-point-mid"],obstacle:["pm-draw-polygon-fill","pm-draw-polygon-outline","pm-draw-polygon-fill-static","pm-draw-polygon-outline-static","pm-draw-point-vertex","pm-draw-point-mid","pm-user-3d-buildings-fill"],model3d:["three-glb-layer"]},this.eventBus.on("mapLoaded",()=>{this.currentFloor!==0&&this.setFloor(this.currentFloor)}),this.eventBus.on("layerVisibilityChanged",()=>{this._applyFilters()})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}async setFloor(e,t={}){var n;if(typeof e!="number")throw new w("Floor ordinal must be a number.",v.INVALID_PARAMETERS,"indoor");if(this._isTransitioning)return this;const o=t.animate!==!1,i=t.duration||300;if(o&&this.currentFloor!==e){this._isTransitioning=!0;const s=this._getMap(),a=(n=s==null?void 0:s.getContainer)==null?void 0:n.call(s);a&&(a.style.pointerEvents="none");try{await this._transitionOpacity(0,i/2),this.currentFloor=e,this._applyFilters(),await this._transitionOpacity(1,i/2)}finally{this._isTransitioning=!1,a&&(a.style.pointerEvents="auto")}}else this.currentFloor=e,this._applyFilters();return this.eventBus.emit("floorChanged",e),this}getAvailableFloors(){var i;const e=new Set,t=this.context.registry.get("geometry");t&&typeof t.getAvailableFloors=="function"&&t.getAvailableFloors().forEach(n=>e.add(n));const o=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;return o&&typeof o.getAvailableFloors=="function"&&o.getAvailableFloors().forEach(n=>e.add(n)),Array.from(e).sort((n,s)=>n-s)}getCurrentFloor(){return this.currentFloor}async _transitionOpacity(e,t){if(!this._getMap())return;const i=this.context.registry.get("geometry");return i&&typeof i.setMarkerOpacity=="function"&&i.setMarkerOpacity(e),this._getAllIndoorLayerIds().forEach(s=>{this._setLayerOpacity(s,e,t)}),new Promise(s=>setTimeout(s,t))}_setLayerOpacity(e,t,o=0){const i=this._getMap();if(!i||!i.getLayer(e))return;const n=i.getLayer(e).type,s=[];n==="fill"?s.push("fill-opacity"):n==="line"?s.push("line-opacity"):n==="circle"?s.push("circle-opacity","circle-stroke-opacity"):n==="symbol"?s.push("icon-opacity","text-opacity"):n==="raster"?s.push("raster-opacity"):n==="fill-extrusion"&&s.push("fill-extrusion-opacity"),s.forEach(a=>{i.setPaintProperty(e,`${a}-transition`,{duration:o,delay:0}),i.setPaintProperty(e,a,t)})}_getAllIndoorLayerIds(){return[...this.layerGroups.poi,...this.layerGroups.beacon,...this.layerGroups.walkway,...this.layerGroups.obstacle]}_applyFilters(){var i;const e=this._getMap();if(!e)return;const t=this.currentFloor;try{const n=this.context.registry.get("geometry");n&&typeof n.syncFloorVisibility=="function"&&n.syncFloorVisibility(t)}catch(n){console.warn("FloorManager: Failed to sync Draw features",n)}try{const n=this.context.registry.get("geometry");n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch(n){console.warn("FloorManager: Failed to filter DOM markers",n)}Object.entries(this.layerGroups).forEach(([n,s])=>{s.forEach(a=>{e.getLayer(a)&&(a.startsWith("pm-draw-")||e.setLayoutProperty(a,"visibility","visible"))})}),["pm-user-3d-buildings-fill"].forEach(n=>{if(e.getLayer(n))try{e.setLayoutProperty(n,"visibility","visible");const s=["all",["==",["coalesce",["get","user_floorOrdinal"],["get","floorOrdinal"],["get","user_ordinal"],["get","ordinal"],0],t],["!=",["get","user_isHidden"],!0]];e.setFilter(n,s)}catch(s){console.warn(`FloorManager: Failed to set filter on layer ${n}`,s)}});try{const n=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch{}}_setActiveVenue(e){this._activeVenue=e||null,e&&this.eventBus.emit("venueChanged",this.getVenueInfo())}getActiveVenue(){return this._activeVenue||null}getVenues(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("venue").toArray(),...e.query().byKind("floor").where("category","eq","venue").toArray(),...e.query().byKind("floor").where("feature_type","eq","venue").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"venue",feature:i}})}getVenueInfo(){var s,a;if(!this._activeVenue)return null;const e=this._activeVenue.properties||{},t=e.user_name||e.name,o=this.getAvailableFloors(),i=this.getBuildings();let n=null;try{const l=((s=this._activeVenue.geometry)==null?void 0:s.type)==="Polygon"?this._activeVenue.geometry.coordinates[0]:((a=this._activeVenue.geometry)==null?void 0:a.type)==="Point"?[this._activeVenue.geometry.coordinates]:[];if(l.length>0){let c=1/0,u=1/0,d=-1/0,p=-1/0;for(const h of l)h[0]<c&&(c=h[0]),h[1]<u&&(u=h[1]),h[0]>d&&(d=h[0]),h[1]>p&&(p=h[1]);n=[[c,u],[d,p]]}}catch{}return{id:e.user_id||this._activeVenue.id,name:typeof t=="object"?t==null?void 0:t.en:t||"",category:e.user_category||e.category||"venue",floors:o,bounds:n,buildingCount:i.length}}getFloorInfo(e){const t=this.context.registry.get("geometry");if(!t||!t.query)return null;const o=t.query().byKind("floor").where("feature_type","eq","level").byFloor(e).first()||t.query().byKind("floor").byFloor(e).first();if(!o)return null;const i=o.properties||{},n=i.user_name||i.name,s=t.query().byKind("poi").byFloor(e).count(),a=t.query().byKind("beacon").byFloor(e).count(),l=t.query().byKind("unit").byFloor(e).count()+t.query().byKind("obstacle").byFloor(e).count();return{id:i.user_id||o.id,name:typeof n=="object"?n==null?void 0:n.en:n||"",shortName:i.user_short_name||i.short_name||"",ordinal:e,outdoor:!!(i.user_outdoor||i.outdoor),unitCount:l,poiCount:s,beaconCount:a}}getBuildings(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("building").toArray(),...e.query().byKind("floor").where("category","eq","building").toArray(),...e.query().byKind("floor").where("feature_type","eq","building").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"building"}})}}class En{constructor(e={}){this.options=e,this.container=null,this.floors=[],this.activeFloorId=null,this._map=null}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl maplibregl-ctrl-group pm-indoor-floor-selector",this._render(),this.container}onRemove(){var e;(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setFloors(e){this.floors=e||[],this._render()}setActiveFloor(e){this.activeFloorId=e,this._updateActiveState()}_render(){if(this.container){if(this.container.innerHTML="",this.floors.length===0){this.container.style.display="none";return}this.container.style.display="flex",this.floors.forEach(e=>{const t=document.createElement("button");t.className="pm-indoor-floor-btn",t.type="button",t.textContent=e.name||e.id,t.setAttribute("data-floor-id",e.id),t.addEventListener("click",()=>{this.setActiveFloor(e.id),this.options.onChange&&this.options.onChange(e.id,e)}),this.container.appendChild(t)}),this._updateActiveState()}}_updateActiveState(){if(!this.container)return;this.container.querySelectorAll(".pm-indoor-floor-btn").forEach(t=>{t.getAttribute("data-floor-id")===String(this.activeFloorId)?t.classList.add("active"):t.classList.remove("active")})}}class In{constructor(e={}){this.options=e,this.buildingId=e.buildingId||null,this.router=e.router||null,this.container=null,this._map=null,this._mapInstance=null,this._focusMarker=null,this.origin=null,this.destination=null,this.routeResult=null,this._originSearchTimer=null,this._destSearchTimer=null,this._onMapClick=this._onMapClick.bind(this),this.activeInput=null,this._icons={depart:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>',arrive:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>',elevator:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 4v16M8 8l4-4 4 4M8 16l4 4 4-4"/></svg>',left:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 14l-4-4 4-4"/><path d="M5 10h11a4 4 0 0 1 4 4v4"/></svg>',right:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 14l4-4-4-4"/><path d="M19 10H8a4 4 0 0 0-4 4v4"/></svg>',straight:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',uturn:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 10l-4 4 4 4"/><path d="M5 14h10a4 4 0 0 0 4-4v-4"/></svg>'}}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl pm-indoor-routing-panel",this._render(),this._map&&this._map.on("click",this._onMapClick),this.container}onRemove(){var e;this._map&&this._map.off("click",this._onMapClick),(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setBuildingId(e){this.buildingId=e}setMapInstance(e){this._mapInstance=e}_render(){if(!this.container)return;this.container.innerHTML=`
|
|
355
|
+
`,this.toolbar.innerHTML=b,this.tooltip&&this.tooltip.attachToToolbar(this.toolbar)}_exportGeoJSON(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometryExported",{data:t,format:e});const o=new Blob([JSON.stringify(t,null,2)],{type:"application/json"}),i=URL.createObjectURL(o),n=document.createElement("a");n.href=i,n.download=`powermap-export-${new Date().getTime()}.json`,n.click(),URL.revokeObjectURL(i)}catch(e){const t=e instanceof PowerMapError?e:new PowerMapError(`Failed to export data: ${e.message}`,ErrorCode.UNKNOWN,"editor",{originalError:e});this.eventBus.emit("error",t)}}_triggerImport(){const e=document.createElement("input");e.type="file",e.accept=".json,application/json",e.onchange=t=>{const o=t.target.files[0];if(!o)return;const i=new FileReader;i.onload=n=>{try{const s=JSON.parse(n.target.result),a=this.mode==="indoor"?"imdf":"standard";this.geometryManager.import(s,{format:a})}catch(s){const a=s instanceof PowerMapError?s:new PowerMapError(`Failed to parse or import GeoJSON: ${s.message}`,ErrorCode.INVALID_PARAMETERS,"editor",{originalError:s});this.eventBus.emit("error",a)}},i.onerror=()=>{const n=new PowerMapError("Failed to read the selected file.",ErrorCode.UNKNOWN,"editor");this.eventBus.emit("error",n)},i.readAsText(o)},e.click()}_triggerSave(){try{const e=this.mode==="indoor"?"imdf":"standard",t=this.geometryManager.export({format:e});this.eventBus.emit("geometrySaveRequested",{data:t,format:e})}catch(e){typeof PowerMapError<"u"&&e instanceof PowerMapError?this.eventBus.emit("error",e):console.error(e)}}}class pn{constructor(e){this.mapManager=e.registry.get("map"),this.geometryManager=e.registry.get("geometry"),this.eventBus=e.eventBus,this.isEnabled=!1,this.control=null,this.mode=e.mode||"standard"}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t){this.eventBus.on("mapLoaded",()=>this.enable(e));return}this.geometryManager.getDrawInstance()||this.geometryManager.initDraw(t);const o=e.position||"bottom-left";this.mode=e.mode||this.mode;try{this.control=new dn(this.geometryManager,this.eventBus,{mode:this.mode}),this.control.setMode&&this.control.setMode(this.mode),t.addControl(this.control,o),this.isEnabled=!0}catch(i){const n=new w(`Failed to enable editor: ${i.message}`,v.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}setMode(e){this.mode=e,this.control&&this.control.setMode&&this.control.setMode(e)}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&this.control&&e.removeControl(this.control),this.control=null,this.isEnabled=!1}attach(e){const t=typeof e=="object"?e.id:e;if(!t)throw new w("Feature ID is required to attach editor.",v.INVALID_PARAMETERS,"editor");const o=this.geometryManager.getDrawInstance();if(!o)throw new w("Cannot attach: Draw instance not initialized.",v.MAP_NOT_INITIALIZED,"editor");try{o.changeMode("direct_select",{featureId:t})}catch(i){const n=new w(`Could not attach to feature ${t}: ${i.message}`,v.UNKNOWN,"editor",{originalError:i});throw this.eventBus.emit("error",n),n}}detach(){const e=this.geometryManager.getDrawInstance();e&&e.changeMode("simple_select")}}class hn{constructor(e){this.mapManager=e.registry.get("map"),this.eventBus=e.eventBus,this.isEnabled=!1,this.panel=null,this.fps=0,this.frameCount=0,this.lastTime=performance.now(),this.lastFpsCalc=this.lastTime,this._onRender=this._onRender.bind(this),this._onMove=this._onMove.bind(this),this.showFps=!0,this.showCoord=!0}enable(e={}){if(this.isEnabled)return;const t=this.mapManager.getMap();if(!t)throw new w("Cannot enable debug panel: Map is not initialized.",v.MAP_NOT_INITIALIZED,"debug");const o=e.position||"top-left";this.panel=document.createElement("div"),this.panel.className="pm-debug-panel",Object.assign(this.panel.style,{position:"absolute",background:"rgba(0, 0, 0, 0.7)",color:"#0f0",padding:"12px",fontFamily:'"SFMono-Regular", Consolas, "Liberation Mono", Menlo, Courier, monospace',fontSize:"13px",borderRadius:"8px",zIndex:"9999",pointerEvents:"none",lineHeight:"1.6",boxShadow:"0 4px 6px rgba(0,0,0,0.3)",border:"1px solid rgba(0,255,0,0.3)"}),o.includes("top")&&(this.panel.style.top="10px"),o.includes("bottom")&&(this.panel.style.bottom="40px"),o.includes("left")&&(this.panel.style.left="10px"),o.includes("right")&&(this.panel.style.right="10px"),t.getContainer().appendChild(this.panel),t.on("render",this._onRender),t.on("move",this._onMove),this.isEnabled=!0,this._updateUI()}disable(){if(!this.isEnabled)return;const e=this.mapManager.getMap();e&&(e.off("render",this._onRender),e.off("move",this._onMove)),this.panel&&this.panel.parentNode&&this.panel.parentNode.removeChild(this.panel),this.panel=null,this.isEnabled=!1}showFPS(e=!0){this.showFps=e,this._updateUI()}showCoordinate(e=!0){this.showCoord=e,this._updateUI()}_onRender(){const e=performance.now();this.frameCount++,e>=this.lastFpsCalc+1e3&&(this.fps=Math.round(this.frameCount*1e3/(e-this.lastFpsCalc)),this.frameCount=0,this.lastFpsCalc=e,this._updateUI())}_onMove(){this._updateUI()}_updateUI(){if(!this.isEnabled||!this.panel)return;const e=this.mapManager.getMap();if(!e)return;let t="<strong>PowerMap Debug</strong><br/>";if(this.showFps){const o=this.fps<30?"red":this.fps<50?"orange":"#0f0";t+=`FPS: <span style="color:${o}">${this.fps}</span><br/>`}if(this.showCoord){const o=e.getCenter();t+=`Lng: ${o.lng.toFixed(5)}<br/>`,t+=`Lat: ${o.lat.toFixed(5)}<br/>`,t+=`Zoom: ${e.getZoom().toFixed(2)}<br/>`,t+=`Pitch: ${e.getPitch().toFixed(1)}°<br/>`,t+=`Bearing: ${e.getBearing().toFixed(1)}°<br/>`;const i=e.getBounds();t+='<div style="font-size:10px; color:#aaa; margin-top:8px;">',t+=`NE: ${i.getNorthEast().lng.toFixed(3)}, ${i.getNorthEast().lat.toFixed(3)}<br/>`,t+=`SW: ${i.getSouthWest().lng.toFixed(3)}, ${i.getSouthWest().lat.toFixed(3)}`,t+="</div>"}this.panel.innerHTML=t}}const Dt=new Map;async function gn(r){if(Dt.has(r))return Dt.get(r);const e=await fetch(r);if(!e.ok)throw new w(`Fetch style failed: ${r}`,v.API_REQUEST_FAILED,"layers");const t=await e.json();return Dt.set(r,t),t}function fn(r){return`${r}/api/v2/map/vtile`}function he(r,e){if(!e||r.includes("apikey="))return r;const t=r.includes("?")?"&":"?";return`${r}${t}apikey=${encodeURIComponent(e)}`}function mn(r,e,t){if(!r)return r;if(r.startsWith(e))return he(r,t);if(r.startsWith("mbtiles://")){const i=r.replace("mbtiles://","").replace(/\.mbtiles$/i,"");return he(`${e}/data/${i}.json`,t)}const o=r.match(/\/data\/([^/]+)\.json$/i);return o?he(`${e}/data/${o[1]}.json`,t):r}function An(r,e,t){if(!r)return r;if(r.startsWith(e))return he(r,t);const o=r.match(/^https?:\/\/[^/]+\/data\/([^/]+)\/\{z\}\/\{x\}\/\{y\}\.pbf(?:\?.*)?$/i);return o?he(`${e}/data/${o[1]}/{z}/{x}/{y}.pbf`,t):r}function yn(r,e,t,o,i,n=()=>!0){var s;try{if(!n()||!((s=r==null?void 0:r.getStyle)!=null&&s.call(r))||r.getSource(e))return;const a={type:"vector"};if(Array.isArray(t.tiles)&&t.tiles.length)a.tiles=t.tiles.map(l=>An(l,o,i));else if(t.url&&t.url.startsWith("mbtiles://")){const l=t.url.replace("mbtiles://","").replace(/\.mbtiles$/i,"");a.tiles=[he(`${o}/data/${l}/{z}/{x}/{y}.pbf`,i)]}else if(t.url){const l=t.url.match(/\/data\/([^/]+)\.json(?:\?.*)?$/i);l?a.tiles=[he(`${o}/data/${l[1]}/{z}/{x}/{y}.pbf`,i)]:a.url=mn(t.url,o,i)}if(!n())return;r.addSource(e,a)}catch{}}function bn(r){var e,t,o;try{return(o=(((t=(e=r==null?void 0:r.getStyle)==null?void 0:e.call(r))==null?void 0:t.layers)||[]).find(i=>i.type==="symbol"))==null?void 0:o.id}catch{return}}async function Se(r,e,{ns:t="rp",includeFn:o=()=>!0,defaultVis:i="none",beforeId:n=void 0,base:s,apiKey:a}={}){var g;if(!(r!=null&&r.getStyle))return;const l=r.__pmNonce,c=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==l?!1:!!r.getStyle()}catch{return!1}},u=f=>{try{return c()?r.getLayer(f):void 0}catch{return}};if(!c())return;let d=null;try{d=await gn(e)}catch{console.warn("fetchStyle failed:",e);return}if(!c())return;const p={};for(const[f,A]of Object.entries(d.sources||{})){if(!c())return;const y=`${t}-src-${f}`;yn(r,y,A,s,a,c),p[f]=y}for(const f of d.layers||[]){if(!o(f))continue;if(!c())return;const A=`${t}-${f.id}`;if(u(A))continue;const y=JSON.parse(JSON.stringify(f));y.id=A,p[y.source]&&(y.source=p[y.source]),y.layout=y.layout||{},y.layout.visibility=i;try{if(!c())return;r.addLayer(y,n)}catch{}}if(!c())return;const h=(g=r.__pmDesiredVis)==null?void 0:g[t];return typeof h=="boolean"&&no(r,t,h,c),{prefix:t}}function no(r,e,t,o=()=>!0){var i;try{if(!o())return;const n=t?"visible":"none",s=(((i=r.getStyle())==null?void 0:i.layers)||[]).filter(a=>a.id.startsWith(e+"-"));for(const a of s){if(!o())return;try{r.setLayoutProperty(a.id,"visibility",n)}catch{}}}catch{}}async function Nt(r,e,t=e,o){if(!(r!=null&&r.getStyle))return;const i=r.__pmNonce,n=()=>{try{return!r||r.__pmDestroyed||r._removed||r.__pmNonce!==i?!1:!!r.getStyle()}catch{return!1}},s=y=>{try{return n()?!!(r.hasImage&&r.hasImage(y)):!1}catch{return!1}};if(r.isStyleLoaded&&!r.isStyleLoaded()&&await new Promise(y=>{if(!n())return y();const b=()=>{x(),y()},x=()=>{try{r.off("styledata",b)}catch{}try{r.off("load",b)}catch{}};r.on("styledata",b),r.on("load",b),setTimeout(()=>{x(),y()},1500)}),!n()||(r.__pmSpriteLoaded=r.__pmSpriteLoaded||{},r.__pmSpriteLoaded[t]))return;const a=y=>he(y,o),c=(window.devicePixelRatio||1)>1.5?[a(`${e}@2x.json`),a(`${e}@2x.png`),a(`${e}.json`),a(`${e}.png`)]:[a(`${e}.json`),a(`${e}.png`),a(`${e}@2x.json`),a(`${e}@2x.png`)];let u,d,p=1;for(let y=0;y<c.length;y+=2){if(!n())return;try{const[b,x]=[c[y],c[y+1]],M=await fetch(b);if(!M.ok)throw 0;if(u=await M.json(),!n())return;const I=await fetch(x);if(!I.ok)throw 0;const P=await I.blob();if(!n())return;d="createImageBitmap"in window?await createImageBitmap(P):await A(P),p=b.includes("@2x")?2:1;break}catch{}}if(!n())return;if(!u||!d){console.warn("sprite load failed for",e);return}const h="createImageBitmap"in window&&d instanceof ImageBitmap,g=h?null:document.createElement("canvas"),f=g?g.getContext("2d"):null;for(const[y,b]of Object.entries(u)){if(!n())return;if(s(y))continue;const{x,y:M,width:I,height:P,sdf:k}=b;let G;if(h?G=await createImageBitmap(d,x,M,I,P):(g.width=I,g.height=P,f.clearRect(0,0,I,P),f.drawImage(d,x,M,I,P,0,0,I,P),G=g),!n())return;try{r.addImage(y,G,{pixelRatio:p,sdf:!!k})}catch{}}if(!n())return;r.__pmSpriteLoaded[t]=!0;function A(y){return new Promise((b,x)=>{const M=new Image;M.onload=()=>b(M),M.onerror=x,M.crossOrigin="anonymous",M.src=URL.createObjectURL(y)})}}function wn(r,e){const t=o=>he(o,e);return[{key:"city",label:"CITY PLAN",items:[ce("pm-bangkok-layer","Bangkok","PM_Bangkok",r,e),ce("pm-nakhon-pathom-layer","Nakhon Pathom","PM_Nakhon_Pathom",r,e),ce("pm-ayutthaya-layer","Ayutthaya","PM_Phra_Nakhon_Si_Ayutthaya",r,e),ce("pm-chonburi-layer","Chon Buri","PM_Chon_Buri",r,e),ce("pm-samutprakan-layer","Samut Prakan","PM_Samut_Prakan",r,e),ce("pm-rayong-layer","Rayong","PM_Rayong",r,e),ce("pm-samutsakhon-layer","Samut Sakhon","PM_Samut_Sakhon",r,e,{tileSize:128}),ce("pm-pathumthani-layer","Pathum Thani","PM_Pathumthani",r,e,{tileSize:128}),ce("pm-ubonratchathani-layer","Ubon Ratchathani","PM_Ubon_Ratchathani",r,e,{tileSize:128}),ce("pm-nonthaburi-layer","Nonthaburi","PM_Nonthaburi",r,e,{tileSize:128}),ce("pm-chachoengsao-layer","Chachoengsao","PM_Chachoengsao",r,e,{tileSize:128})]},{key:"transport",label:"TRANSPORT",items:[{id:"pm-road-vt",name:"Road",groupPrefix:"vt-road",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/road_poi/style.json`);o.__pmRoadVt||(await Se(o,i,{ns:"vt-road",defaultVis:"none",includeFn:n=>n?n.type==="line"?!0:n.type==="symbol"&&n.source==="road"?n["source-layer"]==="road_name":!1:!1,base:r,apiKey:e}),o.__pmRoadVt=!0)}},{id:"pm-post-elec-vt",name:"Post Election",groupPrefix:"vt-postelec",ensure:async o=>{if(!(o!=null&&o.getStyle()))return;const i=t(`${r}/transport/post_elec/style.json`),n=`${r}/transport/post_elec/sprite`;o.__pmGroupReady=o.__pmGroupReady||{},!o.__pmGroupReady["vt-postelec"]&&(await Nt(o,n,"post_elec",e),await Se(o,i,{ns:"vt-postelec",defaultVis:"none",includeFn:s=>(s==null?void 0:s.type)==="symbol",base:r,apiKey:e}),o.__pmGroupReady["vt-postelec"]=!0)}},Le({id:"pm-future-motorway-th-vt",name:"Future Motorway TH",ns:"vt-fmw-th",stylePath:"transport/future_motorway_th",flagPrefix:"__pmFutureMwTh",base:r,apiKey:e,tk:t}),Le({id:"pm-future-motorway-en-vt",name:"Future Motorway EN",ns:"vt-fmw-en",stylePath:"transport/future_motorway_en",flagPrefix:"__pmFutureMwEn",base:r,apiKey:e,tk:t}),Le({id:"pm-current-railway-th-vt",name:"Current Railway TH",ns:"vt-railth-cur",stylePath:"transport/current_railway_th",flagPrefix:"__pmRailTh",base:r,apiKey:e,tk:t}),Le({id:"pm-current-railway-en-vt",name:"Current Railway EN",ns:"vt-railen-cur",stylePath:"transport/current_railway_en",flagPrefix:"__pmRailEn",base:r,apiKey:e,tk:t}),Le({id:"pm-future-railway-th-vt",name:"Future Railway TH",ns:"vt-railth-future",stylePath:"transport/future_railway_th",flagPrefix:"__pmFRailTh",base:r,apiKey:e,tk:t}),Le({id:"pm-future-railway-en-vt",name:"Future Railway EN",ns:"vt-railen-future",stylePath:"transport/future_railway_en",flagPrefix:"__pmFRailEn",base:r,apiKey:e,tk:t}),tt({id:"pm-current-bts-mrt-th-vt",name:"Current BTS MRT TH",ns:"vt-btsmrt-cur-th",stylePath:"transport/current_bts_mrt_th",flagPrefix:"__pmBTSMRTTH",base:r,apiKey:e,tk:t}),tt({id:"pm-current-bts-mrt-en-vt",name:"Current BTS MRT EN",ns:"vt-btsmrt-cur-en",stylePath:"transport/current_bts_mrt_en",flagPrefix:"__pmBTSMRTEN",base:r,apiKey:e,tk:t}),tt({id:"pm-future-bts-mrt-th-vt",name:"Future BTS MRT TH",ns:"vt-btsmrt-fut-th",stylePath:"transport/future_bts_mrt_th",flagPrefix:"__pmBTSMRT_FUTTH",base:r,apiKey:e,tk:t}),tt({id:"pm-future-bts-mrt-en-vt",name:"Future BTS MRT EN",ns:"vt-btsmrt-fut-en",stylePath:"transport/future_bts_mrt_en",flagPrefix:"__pmBTSMRT_FUTEN",base:r,apiKey:e,tk:t})]},{key:"insight",label:"INSIGHT DATA",items:[{id:"pm-viirs-blackmarble-layer",name:"Night Lights",ensure:o=>{o!=null&&o.getStyle()&&(o.getSource("pm-viirs-blackmarble-source")||o.addSource("pm-viirs-blackmarble-source",{type:"raster",tiles:["https://gibs.earthdata.nasa.gov/wmts/epsg3857/best/VIIRS_Black_Marble/default/default/GoogleMapsCompatible_Level8/{z}/{y}/{x}.png"],tileSize:256,minzoom:0,maxzoom:8}),o.getLayer("pm-viirs-blackmarble-layer")||o.addLayer({id:"pm-viirs-blackmarble-layer",type:"raster",source:"pm-viirs-blackmarble-source",paint:{"raster-opacity":.7},layout:{visibility:"none"}}))}},{id:"pm-maptiler-satellite-layer",name:"Satellite",ensure:o=>{if(!(o!=null&&o.getStyle()))return;const i=o.__pmMaptilerKey;if(!i){console.warn("PowerMap LayerManager: maptilerKey not provided, satellite layer skipped.");return}if(o.getSource("pm-maptiler-satellite-source")||o.addSource("pm-maptiler-satellite-source",{type:"raster",tiles:[`https://api.maptiler.com/tiles/satellite-v2/{z}/{x}/{y}.jpg?key=${encodeURIComponent(i)}`],tileSize:256,minzoom:0,maxzoom:22}),!o.getLayer("pm-maptiler-satellite-layer")){const n=bn(o);o.addLayer({id:"pm-maptiler-satellite-layer",type:"raster",source:"pm-maptiler-satellite-source",paint:{"raster-opacity":1},layout:{visibility:"none"}},n)}}}]}]}const Ft={"pm-road-vt":{prefix:"vt-road"},"pm-road-poi-vt":{prefix:"vt-roadpoi"},"pm-post-elec-vt":{prefix:"vt-postelec"},"pm-future-motorway-th-vt":{prefix:"vt-fmw-th"},"pm-future-motorway-en-vt":{prefix:"vt-fmw-en"},"pm-current-railway-th-vt":{prefix:"vt-railth-cur"},"pm-current-railway-en-vt":{prefix:"vt-railen-cur"},"pm-future-railway-th-vt":{prefix:"vt-railth-future"},"pm-future-railway-en-vt":{prefix:"vt-railen-future"},"pm-current-bts-mrt-th-vt":{prefix:"vt-btsmrt-cur-th"},"pm-current-bts-mrt-en-vt":{prefix:"vt-btsmrt-cur-en"},"pm-future-bts-mrt-th-vt":{prefix:"vt-btsmrt-fut-th"},"pm-future-bts-mrt-en-vt":{prefix:"vt-btsmrt-fut-en"}};function ce(r,e,t,o,i,n={}){const s=n.tileSize||256;return{id:r,name:e,ensure:a=>{if(!(a!=null&&a.getStyle()))return;const l=r.replace("-layer","-source");a.getSource(l)||a.addSource(l,{type:"raster",tiles:[he(`${o}/data/${t}/{z}/{x}/{y}.png`,i)],tileSize:s,minzoom:8,maxzoom:16}),a.getLayer(r)||a.addLayer({id:r,type:"raster",source:l,paint:{"raster-opacity":1},layout:{visibility:"none"}})}}}function Le({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}Round1`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}Round1`]=!0),l[`${i}Sprite`]||(await Nt(l,u,o.replace("/","_"),s),l[`${i}Sprite`]=!0),l[`${i}Round2`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol",base:n,apiKey:s}),l[`${i}Round2`]=!0)}}}function tt({id:r,name:e,ns:t,stylePath:o,flagPrefix:i,base:n,apiKey:s,tk:a}){return{id:r,name:e,groupPrefix:t,ensure:async l=>{if(!(l!=null&&l.getStyle()))return;const c=a(`${n}/${o}/style.json`),u=`${n}/${o}/sprite`;l[`${i}_Lines`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="line",base:n,apiKey:s}),l[`${i}_Lines`]=!0),l[`${i}_Sprite`]||(await Nt(l,u,o.replace("/","_"),s),l[`${i}_Sprite`]=!0),l[`${i}_Symbols`]||(await Se(l,c,{ns:t,defaultVis:"none",includeFn:d=>(d==null?void 0:d.type)==="symbol"&&d["source-layer"]==="bts_mrt_station",base:n,apiKey:s}),l[`${i}_Symbols`]=!0)}}}class vn{constructor(e){this.context=e,this.eventBus=e.eventBus,this.authManager=e.authManager;const t=this.authManager.getBaseUrl();this._base=fn(t),this._apiKey=e.options.mapApiKey,this._catalog=wn(this._base,this._apiKey),this._ensured=new Set,this._layerState=new Map,e.options.maptilerKey&&(this._maptilerKey=e.options.maptilerKey),this.eventBus.on("mapLoaded",({map:o})=>{this._maptilerKey&&o&&(o.__pmMaptilerKey=this._maptilerKey),o.on("style.load",async()=>{for(const[i,n]of this._layerState.entries())try{const s=this._findItem(i);s&&await s.item.ensure(o),n.visible!==void 0&&this._setVisibility(i,n.visible),n.opacity!==void 0&&this.setOpacity(i,n.opacity)}catch(s){console.warn(`LayerManager: Failed to auto-restore layer ${i}`,s)}})})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}_findItem(e){for(const t of this._catalog){const o=t.items.find(i=>i.id===e);if(o)return{item:o,group:t}}return null}getCatalog(){return this._catalog.map(e=>({key:e.key,label:e.label,items:e.items.map(t=>({id:t.id,name:t.name,groupPrefix:t.groupPrefix||null}))}))}getGroup(e){const t=this._catalog.find(o=>o.key===e);return t?t.items.map(o=>({id:o.id,name:o.name})):null}getLayerState(e){var n;const t=this._getMap(),o=this._ensured.has(e);let i=null;if(t&&o){const s=Ft[e];if(s)try{const a=(((n=t.getStyle())==null?void 0:n.layers)||[]).filter(l=>l.id.startsWith(s.prefix+"-"));i=a.length>0&&a.some(l=>t.getLayoutProperty(l.id,"visibility")==="visible")}catch{i=!1}else try{i=t.getLayoutProperty(e,"visibility")==="visible"}catch{i=!1}}return{loaded:o,visible:i}}async ensure(e){const t=this._getMap();if(!t)throw new w("Map is not ready. Call ensure() after mapLoaded event.",v.INVALID_PARAMETERS,"layers");const o=this._findItem(e);if(!o)throw new w(`Layer "${e}" not found in catalog. Use getCatalog() to see available layers.`,v.INVALID_PARAMETERS,"layers");try{await o.item.ensure(t),this._ensured.add(e),this.eventBus.emit("layerEnsured",{layerId:e,group:o.group.key})}catch(i){throw new w(`Failed to ensure layer "${e}": ${i.message}`,v.API_REQUEST_FAILED,"layers",{originalError:i})}}async show(e){this._ensured.has(e)||await this.ensure(e);const t=this._layerState.get(e)||{};t.visible=!0,this._layerState.set(e,t),this._setVisibility(e,!0),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!0})}hide(e){const t=this._layerState.get(e)||{};t.visible=!1,this._layerState.set(e,t),this._setVisibility(e,!1),this.eventBus.emit("layerVisibilityChanged",{layerId:e,visible:!1})}async toggle(e){const t=this.getLayerState(e);t.loaded?t.visible?this.hide(e):this.show(e):await this.show(e)}setOpacity(e,t){var s;const o=this._layerState.get(e)||{};o.opacity=t,this._layerState.set(e,o);const i=this._getMap();if(!i)return;const n=Ft[e];if(n)try{const a=(((s=i.getStyle())==null?void 0:s.layers)||[]).filter(l=>l.id.startsWith(n.prefix+"-"));for(const l of a)try{l.type==="line"?i.setPaintProperty(l.id,"line-opacity",t):l.type==="symbol"?(i.setPaintProperty(l.id,"icon-opacity",t),i.setPaintProperty(l.id,"text-opacity",t)):l.type==="fill"&&i.setPaintProperty(l.id,"fill-opacity",t)}catch{}}catch{}else try{const a=i.getLayer(e);a&&(a.type==="raster"?i.setPaintProperty(e,"raster-opacity",t):a.type==="line"?i.setPaintProperty(e,"line-opacity",t):a.type==="fill"&&i.setPaintProperty(e,"fill-opacity",t))}catch{}}async showGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)await this.show(o.id)}hideGroup(e){const t=this._catalog.find(o=>o.key===e);if(t)for(const o of t.items)this.hide(o.id)}hideAll(){for(const e of this._catalog)for(const t of e.items)this.hide(t.id)}_setVisibility(e,t){const o=this._getMap();if(!o)return;const i=Ft[e];if(i){const n=!!t;if(o.__pmDesiredVis=o.__pmDesiredVis||{},o.__pmDesiredVis[i.prefix]=n,no(o,i.prefix,n),o.getLayer(e))try{o.setLayoutProperty(e,"visibility",n?"visible":"none")}catch{}else try{o.addLayer({id:e,type:"background",layout:{visibility:n?"visible":"none"},paint:{"background-opacity":0}})}catch{}return}if(o.getLayer(e))try{o.setLayoutProperty(e,"visibility",t?"visible":"none")}catch{}}}class Cn{constructor(e){this.context=e,this.baseUrl="https://maps.powermap.live/api/v2/indoor",this._geojsonCache={}}setBaseUrl(e){return this.baseUrl=e.replace(/\/$/,""),this}async getVenues(){return this._fetchJSON("/venues")}async getBuildings(e){const t=e?`/buildings?venueId=${e}`:"/buildings";return this._fetchJSON(t)}async getFloors(e){if(!e)throw new Error("buildingId is required");return this._fetchJSON(`/floors?buildingId=${e}`)}async getFloorGeoJSON(e){if(!e)throw new Error("floorId is required");if(this._geojsonCache[e])return JSON.parse(JSON.stringify(this._geojsonCache[e]));const t=await this._fetchJSON(`/floors/${e}/geojson`);return this._geojsonCache[e]=JSON.parse(JSON.stringify(t)),t}async search(e,t={}){if(!e)throw new Error("Search query is required");if(!t.buildingId)throw new w("buildingId is required for indoor search",v.INVALID_PARAMETERS,"indoor");let o=`/search?q=${encodeURIComponent(e)}&buildingId=${t.buildingId}`;return t.category&&(o+=`&category=${t.category}`),t.limit&&(o+=`&limit=${t.limit}`),this._fetchJSON(o)}async _fetchJSON(e){const t=this.context.authManager;if(!t)throw new w("AuthManager not found in SDK context.",v.MAP_NOT_INITIALIZED,"indoor");const o=`${this.baseUrl}${e}`,i=await t.fetchWithAuth(o);if(!i.ok)throw new w(`API Request failed with status ${i.status}`,v.UNKNOWN,"indoor",{status:i.status});return await i.json()}}class xn{constructor(e){var t,o;this.context=e,this.map=(t=this.context.mapManager)==null?void 0:t.getMap(),this.routeData=null,this.activeFloorId=null,this.markers={start:null,end:null},this.backendUrl=(o=this.context.options)!=null&&o.baseUrl?this.context.options.baseUrl+"/api/v2/indoor":"https://maps.powermap.live/api/v2/indoor"}_getMap(){var e;if(this.map)return this.map;if(this.context.mapManager)return this.context.mapManager.getMap();if(this.context.registry&&this.context.registry.get){const t=this.context.registry.get("map");return(t==null?void 0:t.map)||((e=t==null?void 0:t.getMap)==null?void 0:e.call(t))}return null}setMap(e){this.map=e}async calculateRoute(e,t,o,i,n){var a,l;const s=new URL(`${this.backendUrl}/route`);s.searchParams.set("buildingId",e),s.searchParams.set("startFloorId",t),s.searchParams.set("startLng",o[0]),s.searchParams.set("startLat",o[1]),s.searchParams.set("endFloorId",i),s.searchParams.set("endLng",n[0]),s.searchParams.set("endLat",n[1]);try{let c;if(this.context.authManager?c=await this.context.authManager.fetchWithAuth(s.toString(),{source:"indoor-route"}):c=await fetch(s.toString(),{headers:{"x-client-id":this.context.mapApiKey||((a=this.context.auth)==null?void 0:a.clientId),"x-client-secret":(l=this.context.auth)==null?void 0:l.clientSecret}}),!c.ok)throw new Error("Failed to fetch indoor route");const u=await c.json();this.routeData=u,this.activeFloorId=t,this.drawRoute(this.activeFloorId);let d=0,p=0,h=[],g=null;if(u&&u.type==="FeatureCollection"){const A=u.properties||(u.features.length>0?u.features[0].properties:{});d=A.distance||0,p=A.duration||Math.round(d/1.4),h=A.instructions||[],g=u.features.length>0?u.features[0].geometry:null;const y=u.features.flatMap(b=>{var x;return((x=b.geometry)==null?void 0:x.coordinates)||[]});if(y.length>1){const b=y.reduce((x,M)=>x.extend(M),new D.LngLatBounds(y[0],y[0]));this._getMap()&&this._getMap().fitBounds(b,{padding:60,duration:1e3})}}const f=h.map(A=>{var x;let y=null;(x=A.maneuver)!=null&&x.location?y=A.maneuver.location:A.interval&&coords.length>0&&(y=coords[A.interval[0]]);const b=A.maneuver||{type:"turn",instruction:A.text};return!b.location&&y&&(b.location=y),{distance:A.distance,duration:A.time?A.time/1e3:Math.round((A.distance||0)/1.4),name:A.street_name||"",floorId:A.floorId,maneuver:b}});return{distance:d,duration:p,steps:f,geometry:g,raw:u}}catch(c){throw console.error("PowerMap SDK: Indoor routing failed",c),this.clearRoute(),c}}setActiveFloor(e){this.activeFloorId=e,this.routeData&&this.drawRoute(e),this._updateMarkerVisibility()}clearRoute(){this.routeData=null,this._removeLayers(),this.markers.start&&this.markers.start.remove(),this.markers.end&&this.markers.end.remove(),this.markers={start:null,end:null}}drawRoute(e){const t=this._getMap();if(!t||!this.routeData)return;let o=this.routeData;o.type==="FeatureCollection"&&e&&(o={...o,features:o.features.filter(s=>{var a;return!((a=s.properties)!=null&&a.floorId)||String(s.properties.floorId)===String(e)})});const i="pm-indoor-route",n=t.getSource(i);n?n.setData(o):t.addSource(i,{type:"geojson",data:o}),this._ensureLayers(i)}_ensureLayers(e){const t=this._getMap();t&&(t.getLayer(`${e}-casing`)||t.addLayer({id:`${e}-casing`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#1d4ed8","line-width":8,"line-opacity":.3}}),t.getLayer(`${e}-line`)||t.addLayer({id:`${e}-line`,type:"line",source:e,layout:{"line-join":"round","line-cap":"round"},paint:{"line-color":"#3b82f6","line-width":5}}))}_removeLayers(){const e=this._getMap();if(!e)return;const t="pm-indoor-route";e.getLayer(`${t}-line`)&&e.removeLayer(`${t}-line`),e.getLayer(`${t}-casing`)&&e.removeLayer(`${t}-casing`),e.getSource(t)&&e.removeSource(t)}drawMarkers(e,t){const o=this._getMap();if(o){if(!e&&this.markers.start&&(this.markers.start.remove(),this.markers.start=null),!t&&this.markers.end&&(this.markers.end.remove(),this.markers.end=null),e){if(this.markers.start)this.markers.start.setLngLat([e.lng,e.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-start",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#10b981",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.start=new D.Marker({element:i}).setLngLat([e.lng,e.lat]).addTo(o)}this.markers.start.getElement().dataset.floorId=e.floorId}if(t){if(this.markers.end)this.markers.end.setLngLat([t.lng,t.lat]);else{const i=document.createElement("div");i.className="pm-routing-marker pm-routing-marker-end",i.style.width="24px",i.style.height="24px",i.style.backgroundColor="#ef4444",i.style.borderRadius="50%",i.style.border="3px solid white",i.style.boxShadow="0 2px 4px rgba(0,0,0,0.3)",i.style.zIndex="1",this.markers.end=new D.Marker({element:i}).setLngLat([t.lng,t.lat]).addTo(o)}this.markers.end.getElement().dataset.floorId=t.floorId}this._updateMarkerVisibility()}}_updateMarkerVisibility(){if(this.markers.start){const e=this.markers.start.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}if(this.markers.end){const e=this.markers.end.getElement();e.style.display=!e.dataset.floorId||String(e.dataset.floorId)===String(this.activeFloorId)?"block":"none"}}}class Mn{constructor(e){this.context=e,this.eventBus=e.eventBus,this.api=new Cn(e),this.router=new xn(e),this.currentFloor=0,this._isTransitioning=!1,this.layerGroups={poi:["pm-draw-special-point-inactive","pm-draw-special-point-active"],beacon:["pm-draw-special-point-inactive","pm-draw-special-point-active"],walkway:["pm-draw-line-active","pm-draw-line-static","pm-draw-point-vertex","pm-draw-point-mid"],obstacle:["pm-draw-polygon-fill","pm-draw-polygon-outline","pm-draw-polygon-fill-static","pm-draw-polygon-outline-static","pm-draw-point-vertex","pm-draw-point-mid","pm-user-3d-buildings-fill"],model3d:["three-glb-layer"]},this.eventBus.on("mapLoaded",()=>{this.currentFloor!==0&&this.setFloor(this.currentFloor)}),this.eventBus.on("layerVisibilityChanged",()=>{this._applyFilters()})}_getMap(){var t;const e=this.context.registry.get("map");return(e==null?void 0:e.map)||((t=e==null?void 0:e.getMap)==null?void 0:t.call(e))}async setFloor(e,t={}){var n;if(typeof e!="number")throw new w("Floor ordinal must be a number.",v.INVALID_PARAMETERS,"indoor");if(this._isTransitioning)return this;const o=t.animate!==!1,i=t.duration||300;if(o&&this.currentFloor!==e){this._isTransitioning=!0;const s=this._getMap(),a=(n=s==null?void 0:s.getContainer)==null?void 0:n.call(s);a&&(a.style.pointerEvents="none");try{await this._transitionOpacity(0,i/2),this.currentFloor=e,this._applyFilters(),await this._transitionOpacity(1,i/2)}finally{this._isTransitioning=!1,a&&(a.style.pointerEvents="auto")}}else this.currentFloor=e,this._applyFilters();return this.eventBus.emit("floorChanged",e),this}getAvailableFloors(){var i;const e=new Set,t=this.context.registry.get("geometry");t&&typeof t.getAvailableFloors=="function"&&t.getAvailableFloors().forEach(n=>e.add(n));const o=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;return o&&typeof o.getAvailableFloors=="function"&&o.getAvailableFloors().forEach(n=>e.add(n)),Array.from(e).sort((n,s)=>n-s)}getCurrentFloor(){return this.currentFloor}async _transitionOpacity(e,t){if(!this._getMap())return;const i=this.context.registry.get("geometry");return i&&typeof i.setMarkerOpacity=="function"&&i.setMarkerOpacity(e),this._getAllIndoorLayerIds().forEach(s=>{this._setLayerOpacity(s,e,t)}),new Promise(s=>setTimeout(s,t))}_setLayerOpacity(e,t,o=0){const i=this._getMap();if(!i||!i.getLayer(e))return;const n=i.getLayer(e).type,s=[];n==="fill"?s.push("fill-opacity"):n==="line"?s.push("line-opacity"):n==="circle"?s.push("circle-opacity","circle-stroke-opacity"):n==="symbol"?s.push("icon-opacity","text-opacity"):n==="raster"?s.push("raster-opacity"):n==="fill-extrusion"&&s.push("fill-extrusion-opacity"),s.forEach(a=>{i.setPaintProperty(e,`${a}-transition`,{duration:o,delay:0}),i.setPaintProperty(e,a,t)})}_getAllIndoorLayerIds(){return[...this.layerGroups.poi,...this.layerGroups.beacon,...this.layerGroups.walkway,...this.layerGroups.obstacle]}_applyFilters(){var i;const e=this._getMap();if(!e)return;const t=this.currentFloor;try{const n=this.context.registry.get("geometry");n&&typeof n.syncFloorVisibility=="function"&&n.syncFloorVisibility(t)}catch(n){console.warn("FloorManager: Failed to sync Draw features",n)}try{const n=this.context.registry.get("geometry");n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch(n){console.warn("FloorManager: Failed to filter DOM markers",n)}Object.entries(this.layerGroups).forEach(([n,s])=>{s.forEach(a=>{e.getLayer(a)&&(a.startsWith("pm-draw-")||e.setLayoutProperty(a,"visibility","visible"))})}),["pm-user-3d-buildings-fill"].forEach(n=>{if(e.getLayer(n))try{e.setLayoutProperty(n,"visibility","visible");const s=["all",["==",["coalesce",["get","user_floorOrdinal"],["get","floorOrdinal"],["get","user_ordinal"],["get","ordinal"],0],t],["!=",["get","user_isHidden"],!0]];e.setFilter(n,s)}catch(s){console.warn(`FloorManager: Failed to set filter on layer ${n}`,s)}});try{const n=(i=this.context.registry.get("map"))==null?void 0:i.threeLayer;n&&typeof n.setFloorFilter=="function"&&n.setFloorFilter(t)}catch{}}_setActiveVenue(e){this._activeVenue=e||null,e&&this.eventBus.emit("venueChanged",this.getVenueInfo())}getActiveVenue(){return this._activeVenue||null}getVenues(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("venue").toArray(),...e.query().byKind("floor").where("category","eq","venue").toArray(),...e.query().byKind("floor").where("feature_type","eq","venue").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"venue",feature:i}})}getVenueInfo(){var s,a;if(!this._activeVenue)return null;const e=this._activeVenue.properties||{},t=e.user_name||e.name,o=this.getAvailableFloors(),i=this.getBuildings();let n=null;try{const l=((s=this._activeVenue.geometry)==null?void 0:s.type)==="Polygon"?this._activeVenue.geometry.coordinates[0]:((a=this._activeVenue.geometry)==null?void 0:a.type)==="Point"?[this._activeVenue.geometry.coordinates]:[];if(l.length>0){let c=1/0,u=1/0,d=-1/0,p=-1/0;for(const h of l)h[0]<c&&(c=h[0]),h[1]<u&&(u=h[1]),h[0]>d&&(d=h[0]),h[1]>p&&(p=h[1]);n=[[c,u],[d,p]]}}catch{}return{id:e.user_id||this._activeVenue.id,name:typeof t=="object"?t==null?void 0:t.en:t||"",category:e.user_category||e.category||"venue",floors:o,bounds:n,buildingCount:i.length}}getFloorInfo(e){const t=this.context.registry.get("geometry");if(!t||!t.query)return null;const o=t.query().byKind("floor").where("feature_type","eq","level").byFloor(e).first()||t.query().byKind("floor").byFloor(e).first();if(!o)return null;const i=o.properties||{},n=i.user_name||i.name,s=t.query().byKind("poi").byFloor(e).count(),a=t.query().byKind("beacon").byFloor(e).count(),l=t.query().byKind("unit").byFloor(e).count()+t.query().byKind("obstacle").byFloor(e).count();return{id:i.user_id||o.id,name:typeof n=="object"?n==null?void 0:n.en:n||"",shortName:i.user_short_name||i.short_name||"",ordinal:e,outdoor:!!(i.user_outdoor||i.outdoor),unitCount:l,poiCount:s,beaconCount:a}}getBuildings(){const e=this.context.registry.get("geometry");if(!e||!e.query)return[];const t=[...e.query().byKind("building").toArray(),...e.query().byKind("floor").where("category","eq","building").toArray(),...e.query().byKind("floor").where("feature_type","eq","building").toArray()],o=new Set;return t.filter(i=>{var s;const n=((s=i.properties)==null?void 0:s.user_id)||i.id;return o.has(n)?!1:(o.add(n),!0)}).map(i=>{const n=i.properties||{},s=n.user_name||n.name;return{id:n.user_id||i.id,name:typeof s=="object"?s==null?void 0:s.en:s||"",category:n.user_category||n.category||"building"}})}}class En{constructor(e={}){this.options=e,this.container=null,this.floors=[],this.activeFloorId=null,this._map=null}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl maplibregl-ctrl-group pm-indoor-floor-selector",this._render(),this.container}onRemove(){var e;(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setFloors(e){this.floors=e||[],this._render()}setActiveFloor(e){this.activeFloorId=e,this._updateActiveState()}_render(){if(this.container){if(this.container.innerHTML="",this.floors.length===0){this.container.style.display="none";return}this.container.style.display="flex",this.floors.forEach(e=>{const t=document.createElement("button");t.className="pm-indoor-floor-btn",t.type="button",t.textContent=e.name||e.id,t.setAttribute("data-floor-id",e.id),t.addEventListener("click",()=>{this.setActiveFloor(e.id),this.options.onChange&&this.options.onChange(e.id,e)}),this.container.appendChild(t)}),this._updateActiveState()}}_updateActiveState(){if(!this.container)return;this.container.querySelectorAll(".pm-indoor-floor-btn").forEach(t=>{t.getAttribute("data-floor-id")===String(this.activeFloorId)?t.classList.add("active"):t.classList.remove("active")})}}class In{constructor(e={}){this.options=e,this.buildingId=e.buildingId||null,this.router=e.router||null,this.container=null,this._map=null,this._mapInstance=null,this._focusMarker=null,this.origin=null,this.destination=null,this.routeResult=null,this._originSearchTimer=null,this._destSearchTimer=null,this._onMapClick=this._onMapClick.bind(this),this.activeInput=null,this._icons={depart:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><circle cx="12" cy="12" r="3"/></svg>',arrive:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 10c0 7-9 13-9 13s-9-6-9-13a9 9 0 0 1 18 0z"></path><circle cx="12" cy="10" r="3"></circle></svg>',elevator:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 4v16M8 8l4-4 4 4M8 16l4 4 4-4"/></svg>',left:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 14l-4-4 4-4"/><path d="M5 10h11a4 4 0 0 1 4 4v4"/></svg>',right:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M15 14l4-4-4-4"/><path d="M19 10H8a4 4 0 0 0-4 4v4"/></svg>',straight:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 19V5M5 12l7-7 7 7"/></svg>',uturn:'<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 10l-4 4 4 4"/><path d="M5 14h10a4 4 0 0 0 4-4v-4"/></svg>'}}onAdd(e){return this._map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl pm-indoor-routing-panel",this._render(),this._map&&this._map.on("click",this._onMapClick),this.container}onRemove(){var e;this._map&&this._map.off("click",this._onMapClick),(e=this.container.parentNode)==null||e.removeChild(this.container),this._map=null}setBuildingId(e){this.buildingId=e}setMapInstance(e){this._mapInstance=e}_render(){if(!this.container)return;this.container.innerHTML=`
|
|
356
356
|
<div class="pm-routing-panel-header">
|
|
357
357
|
<div class="pm-routing-inputs-container">
|
|
358
358
|
<div class="pm-routing-inputs">
|
|
@@ -380,7 +380,7 @@
|
|
|
380
380
|
<div id="pm-indoor-search-results" class="pm-search-results" style="display: none; position: static; box-shadow: none; border: none; border-radius: 0; width: 100%; max-height: none; padding: 0; margin: 0; flex: 1; overflow-y: auto;"></div>
|
|
381
381
|
<div class="pm-routing-summary" id="pm-routing-summary" style="display: none;"></div>
|
|
382
382
|
<div class="pm-routing-steps" id="pm-routing-steps" style="display: none;"></div>
|
|
383
|
-
`;const e=this.container.querySelector("#pm-route-origin"),t=this.container.querySelector("#pm-route-dest");e.addEventListener("input",i=>this._onSearchInput(i.target.value,"origin")),t.addEventListener("input",i=>this._onSearchInput(i.target.value,"destination")),e.addEventListener("focus",()=>{this.activeInput="origin"}),t.addEventListener("focus",()=>{this.activeInput="destination"}),document.addEventListener("click",i=>{this.container.contains(i.target)||(this._hideResults("origin"),this._hideResults("destination"))});const o=this.container.querySelector("#pm-route-swap");o&&o.addEventListener("click",()=>this._swapLocations())}_swapLocations(){const e=this.origin;this.origin=this.destination,this.destination=e;const t=this.container.querySelector("#pm-route-origin"),o=this.container.querySelector("#pm-route-dest"),i=t.value;t.value=o.value,o.value=i,this._tryCalculateRoute()}_onMapClick(e){var n;if(!this.activeInput||!this.buildingId)return;const t=e.lngLat;let o=((n=this.router)==null?void 0:n.activeFloorId)||null;const i={id:"custom-"+Date.now(),name:`Point (${t.lat.toFixed(4)}, ${t.lng.toFixed(4)})`,floorId:o,lng:t.lng,lat:t.lat};this._selectLocation(i,this.activeInput),this.activeInput=null}async _onSearchInput(e,t){if(t==="origin"&&clearTimeout(this._originSearchTimer),t==="destination"&&clearTimeout(this._destSearchTimer),!e||e.length<2){this._hideResults();return}const o=setTimeout(async()=>{var i;try{const n=this.router&&this.router.backendUrl?this.router.backendUrl:"https://maps.powermap.live/indoor
|
|
383
|
+
`;const e=this.container.querySelector("#pm-route-origin"),t=this.container.querySelector("#pm-route-dest");e.addEventListener("input",i=>this._onSearchInput(i.target.value,"origin")),t.addEventListener("input",i=>this._onSearchInput(i.target.value,"destination")),e.addEventListener("focus",()=>{this.activeInput="origin"}),t.addEventListener("focus",()=>{this.activeInput="destination"}),document.addEventListener("click",i=>{this.container.contains(i.target)||(this._hideResults("origin"),this._hideResults("destination"))});const o=this.container.querySelector("#pm-route-swap");o&&o.addEventListener("click",()=>this._swapLocations())}_swapLocations(){const e=this.origin;this.origin=this.destination,this.destination=e;const t=this.container.querySelector("#pm-route-origin"),o=this.container.querySelector("#pm-route-dest"),i=t.value;t.value=o.value,o.value=i,this._tryCalculateRoute()}_onMapClick(e){var n;if(!this.activeInput||!this.buildingId)return;const t=e.lngLat;let o=((n=this.router)==null?void 0:n.activeFloorId)||null;const i={id:"custom-"+Date.now(),name:`Point (${t.lat.toFixed(4)}, ${t.lng.toFixed(4)})`,floorId:o,lng:t.lng,lat:t.lat};this._selectLocation(i,this.activeInput),this.activeInput=null}async _onSearchInput(e,t){if(t==="origin"&&clearTimeout(this._originSearchTimer),t==="destination"&&clearTimeout(this._destSearchTimer),!e||e.length<2){this._hideResults();return}const o=setTimeout(async()=>{var i;try{const n=this.router&&this.router.backendUrl?this.router.backendUrl:"https://maps.powermap.live/api/v2/indoor",s=new URL(`${n}/search`);s.searchParams.set("q",e),this.buildingId&&s.searchParams.set("buildingId",this.buildingId);let a;const l=((i=this._map)==null?void 0:i.authManager)||this.router&&this.router.context&&this.router.context.authManager;if(l?a=await l.fetchWithAuth(s.toString(),{source:"indoor-search"}):a=await fetch(s.toString()),a&&a.ok){const c=await a.json();let u=[];Array.isArray(c)?u=c:c.hits&&Array.isArray(c.hits.hits)?u=c.hits.hits:Array.isArray(c.hits)?u=c.hits:Array.isArray(c.data)?u=c.data:Array.isArray(c.results)?u=c.results:Array.isArray(c.value)&&(u=c.value),this._renderResults(u,t)}}catch(n){console.error("PowerMap SDK: Indoor search failed",n)}},300);t==="origin"&&(this._originSearchTimer=o),t==="destination"&&(this._destSearchTimer=o)}_renderResults(e,t){const o=this.container.querySelector("#pm-indoor-search-results");if(o.innerHTML="",!e||e.length===0){this._hideResults();return}e.forEach(s=>{const a=document.createElement("div");a.className="pm-route-step";let l="-";s.floorNumber!==void 0?l=String(s.floorNumber):s.level!==void 0?l=String(s.level):s.ordinal!==void 0&&(l=String(s.ordinal)),a.innerHTML=`
|
|
384
384
|
<div class="pm-step-icon-col" style="display: flex; flex-direction: column; align-items: center; margin-right: 12px;">
|
|
385
385
|
<div class="pm-step-icon-bg" style="width: 32px; height: 32px; border-radius: 50%; background: rgba(242, 101, 34, 0.1); color: #F26522; display: flex; justify-content: center; align-items: center;">
|
|
386
386
|
<svg viewBox="0 0 24 24" fill="currentColor" style="width: 16px; height: 16px;"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>
|