@drecchia/maplibre-layerlibre 2.2.0 → 2.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.
@@ -1 +1 @@
1
- class BoundsHelper{static calculateBounds(e,t=0){if(!e||!Array.isArray(e)||0===e.length)throw new Error("Points array is required and must not be empty");let i=1/0,s=1/0,a=-1/0,r=-1/0;for(var[o,n]of e)i=Math.min(i,o),a=Math.max(a,o),s=Math.min(s,n),r=Math.max(r,n);let l,h,c,v;return"number"==typeof t?l=h=c=v=t:"object"==typeof t&&null!==t?(l=t.top||0,h=t.bottom||0,c=t.left||0,v=t.right||0):l=h=c=v=0,[[i-c,s-h],[a+v,r+l]]}static calculateBoundsCenter(e){var t,i;if(e&&Array.isArray(e)&&2===e.length)return t=e[0][0],i=e[0][1],[(t+e[1][0])/2,(i+e[1][1])/2];throw new Error("Bounds must be an array with two coordinate pairs")}static calculateBoundsZoom(e,t,i=.5){if(!e||!Array.isArray(e)||2!==e.length)throw new Error("Bounds must be an array with two coordinate pairs");var s,a,r;if(t&&"number"==typeof t.width&&"number"==typeof t.height)return r=e[0][0],s=e[0][1],a=e[1][0],e=e[1][1]-s,s=Math.log2(360*t.width/(512*(a-r))),a=Math.log2(180*t.height/(512*e)),r=Math.min(s,a)-i,Math.max(1,Math.min(20,r));throw new Error("Container must have numeric width and height properties")}static calculatePanCenter(t){try{if(t.deckLayers&&0<t.deckLayers.length){var e=t.deckLayers[0];if(e.props&&e.props.data&&0<e.props.data.length){var i=e.props.data[0];if(i.position)return i.position}}}catch(e){console.error(`Failed to calculate pan center for overlay ${t.id}:`,e)}return null}}class EventEmitter{constructor(){this._events=new Map}on(e,t){if("function"!=typeof t)throw new TypeError("Handler must be a function");return this._events.has(e)||this._events.set(e,new Set),this._events.get(e).add(t),this}off(e,t){var i=this._events.get(e);return i&&(i.delete(t),0===i.size)&&this._events.delete(e),this}emit(t,e){var i=this._events.get(t);if(i)for(var s of Array.from(i))try{s(e)}catch(e){console.error(`EventEmitter: error in "${t}" handler:`,e)}}once(t,i){let s=e=>{this.off(t,s),i(e)};return this.on(t,s)}removeAllListeners(e){return e?this._events.delete(e):this._events.clear(),this}}class StateService{constructor(e,t){this.eventEmitter=e,this.persistenceKey=t||null,this._debounceTimer=null,this._state={base:null,overlays:{},groups:{},layerOrder:[],viewport:{center:null,zoom:null,bearing:0,pitch:0}},this._loadPersisted()}get(e){return this._state[e]}getCurrentBase(){return this._state.base}getOverlayStates(){return this._state.overlays}getGroupStates(){return this._state.groups}getViewport(){return this._state.viewport||{}}getAll(){return JSON.parse(JSON.stringify(this._state))}initOverlay(e,t){this._state.overlays[e]||(this._state.overlays[e]={visible:!0===t.defaultVisible,opacity:void 0!==t.defaultOpacity?t.defaultOpacity:1})}setBase(e){var t=this._state.base;this._state.base=e,this._schedulePersist(),t!==e&&(this.eventEmitter.emit("basechange",{id:e}),this.eventEmitter.emit("change",{type:"basechange",id:e}))}setOverlayVisibility(e,t){this._state.overlays[e]||(this._state.overlays[e]={visible:!1,opacity:1}),this._state.overlays[e].visible=t,this._schedulePersist()}setOverlayOpacity(e,t){this._state.overlays[e]||(this._state.overlays[e]={visible:!1,opacity:1}),this._state.overlays[e].opacity=Math.max(0,Math.min(1,parseFloat(t)||0)),this._schedulePersist()}setGroupVisibility(e,t){this._state.groups[e]||(this._state.groups[e]={visible:!1,opacity:1}),this._state.groups[e].visible=t,this._schedulePersist()}setGroupOpacity(e,t){this._state.groups[e]||(this._state.groups[e]={visible:!1,opacity:1}),this._state.groups[e].opacity=Math.max(0,Math.min(1,parseFloat(t)||0)),this._schedulePersist()}setViewport(e){this._state.viewport={...this._state.viewport||{},...e},this._schedulePersist(),this.eventEmitter.emit("viewportchange",{...this._state.viewport}),this.eventEmitter.emit("change",{type:"viewportchange",...this._state.viewport})}reorderLayers(e){this._state.layerOrder=[...e],this._schedulePersist()}removeOverlay(e){delete this._state.overlays[e];e=this._state.layerOrder.indexOf(e);-1<e&&this._state.layerOrder.splice(e,1),this._schedulePersist()}clearPersisted(){if(!this.persistenceKey)return!1;try{return localStorage.removeItem(this.persistenceKey),this.eventEmitter.emit("memorycleared",{}),this.eventEmitter.emit("change",{type:"memorycleared"}),!0}catch(e){return console.error("StateService: failed to clear persisted state:",e),!1}}destroy(){this._debounceTimer&&(clearTimeout(this._debounceTimer),this._debounceTimer=null)}_schedulePersist(){this.persistenceKey&&(clearTimeout(this._debounceTimer),this._debounceTimer=setTimeout(()=>this._persist(),300))}_persist(){if(this.persistenceKey)try{localStorage.setItem(this.persistenceKey,JSON.stringify(this._state))}catch(e){console.warn("StateService: failed to persist state:",e)}}_loadPersisted(){if(this.persistenceKey)try{var e,t=localStorage.getItem(this.persistenceKey);t&&(void 0!==(e=JSON.parse(t)).base&&(this._state.base=e.base),e.overlays&&(this._state.overlays={...e.overlays}),e.groups&&(this._state.groups={...e.groups}),Array.isArray(e.layerOrder)&&(this._state.layerOrder=e.layerOrder),e.viewport)&&(this._state.viewport={...this._state.viewport,...e.viewport})}catch(e){console.warn("StateService: failed to load persisted state:",e)}}}class MapService{constructor(e){this.eventEmitter=e,this.map=null}setMap(e){this.map=e}getMap(){return this.map}getCurrentViewport(){var e;return this.map?{center:{lng:(e=this.map.getCenter()).lng,lat:e.lat},zoom:this.map.getZoom(),bearing:this.map.getBearing(),pitch:this.map.getPitch()}:null}destroy(){this.map=null}}class UIManager{constructor(e,t,i){if(!e)throw new Error("UIManager requires stateService");if(!i)throw new Error("UIManager requires eventEmitter");this.stateService=e,this.mapService=t||null,this.eventEmitter=i,this.businessLogicService=null,this.options={},this.map=null,this.container=null,this.deckOverlay=null,this.toggle=null,this.panel=null,this.isOpen=!1,this.deckLayers=new Map,this.overlayToLayerIds=new Map,this.loadingStates=new Map,this.errorStates=new Map,this.zoomFilteredOverlays=new Set,this.overlayCache=new Map,this._handleToggleClick=this._handleToggleClick.bind(this),this._handleDocumentClick=this._handleDocumentClick.bind(this),this._onZoomEnd=this._onZoomEnd.bind(this)}setOptions(e){this.options=e||{}}setBusinessLogicService(e){this.businessLogicService=e}setMap(e){this.map=e,this.mapService&&this.mapService.setMap(e),e&&(this._initializeDeckOverlay(),e.on("zoomend",this._onZoomEnd))}setContainer(e){this.container=e}render(){this.container&&(this.container.innerHTML="",this.toggle=document.createElement("button"),this.toggle.className="layers-control__toggle",this.toggle.setAttribute("aria-label","Toggle layers"),this.toggle.textContent=this.options.icon||"☰",this.toggle.addEventListener("click",this._handleToggleClick),this.panel=document.createElement("div"),this.panel.className="layers-control__panel",this.panel.style.display="none",this.container.appendChild(this.toggle),this.container.appendChild(this.panel),this._renderPanelContent(),this._setupEventDelegation())}destroy(){if(this.map&&this.map.off("zoomend",this._onZoomEnd),this.options&&this.options.autoClose&&document.removeEventListener("click",this._handleDocumentClick),this.deckOverlay&&this.map)try{this.map.removeControl(this.deckOverlay)}catch(e){}this.deckLayers.clear(),this.overlayToLayerIds.clear(),this.loadingStates.clear(),this.errorStates.clear(),this.zoomFilteredOverlays.clear(),this.overlayCache.clear(),this.map=null,this.container=null,this.deckOverlay=null,this.panel=null,this.toggle=null}updateOverlays(){this._renderPanelContent()}updateBaseStyles(){this._renderPanelContent()}updateBaseUI(){let s=this.stateService.getCurrentBase();this.panel&&this.panel.querySelectorAll(".layers-control__base-item").forEach(e=>{var t,i=e.querySelector('input[type="radio"]');i&&(t=i.value===s,e.classList.toggle("layers-control__base-item--active",i.checked=t))})}updateOverlayUI(e){this._updateOverlayUI(e)}updateGroupUI(e){this._updateGroupUI(e)}setLoadingState(e,t){this._setLoadingState(e,t)}setErrorState(e,t){t?this.errorStates.set(e,t):this.errorStates.delete(e),this._updateOverlayUI(e)}async activateOverlay(e,t=!1){return this._activateOverlay(e,t)}deactivateOverlay(e){this._deactivateOverlay(e),this._updateOverlayUI(e)}updateOverlayOpacity(e,t){var i;this._updateOverlayOpacity(e,t),this.panel&&(e=this.panel.querySelector(`[data-overlay-id="${e}"]`))&&(i=e.querySelector(".layers-control__opacity-slider"),e=e.querySelector(".layers-control__opacity-label"),i&&(i.value=t),e)&&(e.textContent=Math.round(100*t)+"%")}clearAll(){this.deckLayers.clear(),this.overlayToLayerIds.clear(),this._updateDeckOverlay(),this.loadingStates.clear(),this.errorStates.clear(),this.zoomFilteredOverlays.clear(),this.overlayCache.clear()}applyBaseStyle(e){this._applyBaseToMap(e)}_renderPanelContent(){this.panel&&(this.panel.innerHTML="",this.options.baseStyles&&0<this.options.baseStyles.length&&this.panel.appendChild(this._createBaseSection()),this.options.overlays)&&0<this.options.overlays.length&&this.panel.appendChild(this._createOverlaysSection())}_createBaseSection(){var e=document.createElement("div"),t=(e.className="layers-control__base-section",document.createElement("h3"));t.className="layers-control__section-title",t.textContent=this.options.i18n&&this.options.i18n.baseHeader?this.options.i18n.baseHeader:"Base Layers";let a=document.createElement("div"),r=(a.className="layers-control__base-list",this.stateService.getCurrentBase());return(this.options.baseStyles||[]).forEach(e=>{var t=document.createElement("label");t.className="layers-control__base-item",e.id===r&&t.classList.add("layers-control__base-item--active");let i=document.createElement("input");i.type="radio",i.name="base-layer",i.value=e.id,i.checked=e.id===r,i.addEventListener("change",()=>{i.checked&&this._handleBaseChange(e.id)});var s=document.createElement("span");s.textContent=e.label||e.id,t.appendChild(i),t.appendChild(s),a.appendChild(t)}),e.appendChild(t),e.appendChild(a),e}_createOverlaysSection(){var e=document.createElement("div"),t=(e.className="layers-control__overlays-section",document.createElement("h3"));t.className="layers-control__section-title",t.textContent=this.options.i18n&&this.options.i18n.overlaysHeader?this.options.i18n.overlaysHeader:"Overlays";let i=document.createElement("div"),s=(i.className="layers-control__overlays-list",new Map),a=[];return(this.options.overlays||[]).forEach(e=>{(e.group?(s.has(e.group)||s.set(e.group,[]),s.get(e.group)):a).push(e)}),s.forEach((e,t)=>{i.appendChild(this._createGroupElement(t,e))}),a.forEach(e=>{i.appendChild(this._createOverlayElement(e))}),e.appendChild(t),e.appendChild(i),e}_createGroupElement(t,e){var i=document.createElement("div"),s=(i.className="layers-control__group",document.createElement("div")),a=(s.className="layers-control__group-header",document.createElement("label")),r=(a.className="layers-control__group-toggle",document.createElement("input")),o=(r.type="checkbox",r.value=t,this.stateService.getGroupStates()[t]),o=(r.checked=!!o&&o.visible,r.addEventListener("change",()=>this._handleToggleGroup(t)),(this.options.groups||[]).find(e=>e.id===t)),n=document.createElement("span");n.textContent=o&&o.label?o.label:t,a.appendChild(r),a.appendChild(n),s.appendChild(a);let l=document.createElement("div");return l.className="layers-control__group-overlays",e.forEach(e=>{l.appendChild(this._createOverlayElement(e))}),i.appendChild(s),i.appendChild(l),i}_createOverlayElement(e){var t=document.createElement("div"),i=(t.className="layers-control__overlay-item",t.dataset.overlayId=e.id,document.createElement("label")),s=(i.className="layers-control__overlay-toggle",document.createElement("input")),a=(s.type="checkbox",s.value=e.id,this.stateService.getOverlayStates()[e.id]),r=(s.checked=!!a&&a.visible,s.addEventListener("change",()=>this._handleToggleOverlay(e.id)),document.createElement("span")),o=(r.className="layers-control__label",r.textContent=e.label||e.id,document.createElement("span"));return o.className="layers-control__loading",o.style.display="none",i.appendChild(s),i.appendChild(r),i.appendChild(o),t.appendChild(i),!1!==this.options.showOpacity&&e.opacityControls&&(s=a?a.opacity:1,t.appendChild(this._createOpacitySlider(e.id,s))),t}_createOpacitySlider(t,e){var i=document.createElement("div"),s=(i.className="layers-control__opacity-control",document.createElement("input"));s.type="range",s.className="layers-control__opacity-slider",s.min="0",s.max="1",s.step="0.01",s.value=e;let a=document.createElement("span");return a.className="layers-control__opacity-label",a.textContent=Math.round(100*e)+"%",s.addEventListener("input",e=>{e=parseFloat(e.target.value);a.textContent=Math.round(100*e)+"%",this._handleOpacitySlider(t,e,!1)}),i.appendChild(s),i.appendChild(a),i}_setupEventDelegation(){this.options.autoClose&&document.addEventListener("click",this._handleDocumentClick)}_handleToggleClick(e){e.stopPropagation(),this.isOpen=!this.isOpen,this.panel&&(this.panel.style.display=this.isOpen?"block":"none",this.panel.classList.toggle("layers-control__panel--open",this.isOpen))}_handleDocumentClick(e){this.container&&!this.container.contains(e.target)&&(this.isOpen=!1,this.panel)&&(this.panel.style.display="none",this.panel.classList.remove("layers-control__panel--open"))}_handleBaseChange(e){this.businessLogicService&&this.businessLogicService.setBaseLayer(e)}_handleToggleOverlay(e){var t;this.businessLogicService&&(!((t=this.stateService.getOverlayStates()[e])&&t.visible)?this.businessLogicService.showOverlay(e,!0):this.businessLogicService.hideOverlay(e,!0))}_handleToggleGroup(e){var t;this.businessLogicService&&(t=!((t=this.stateService.getGroupStates()[e])&&t.visible),this.businessLogicService.setGroupVisibility(e,t))}_handleOpacitySlider(e,t,i){this.businessLogicService&&(i?this.businessLogicService.setGroupOpacity(e,t):this.businessLogicService.setOverlayOpacity(e,t))}_onZoomEnd(){this.updateAllZoomFiltering()}updateAllZoomFiltering(){if(this.map){let a=this.stateService.getOverlayStates();Object.keys(a).forEach(t=>{var e,i,s=a[t];s&&s.visible&&(s=(this.options.overlays||[]).find(e=>e.id===t))&&(e=this._checkZoomConstraints(s),i=this.zoomFilteredOverlays.has(t),e&&i?(this.zoomFilteredOverlays.delete(t),this._showOverlayLayers(s),this._updateOverlayUI(t),this.eventEmitter.emit("zoomfilter",{id:t,filtered:!1})):e||i||(this.zoomFilteredOverlays.add(t),this._hideOverlayLayers(s),this._updateOverlayUI(t),this.eventEmitter.emit("zoomfilter",{id:t,filtered:!0})))})}}_checkZoomConstraints(e){var t;return!(this.map&&(t=this.map.getZoom(),void 0!==(e=this._getFilterConfig(e)).minZoom&&t<e.minZoom||void 0!==e.maxZoom&&t>=e.maxZoom))}_getFilterConfig(e){var t=e.filter||{};return{minZoom:void 0!==t.minZoom?t.minZoom:e.minZoomLevel,maxZoom:void 0!==t.maxZoom?t.maxZoom:e.maxZoomLevel}}_updateZoomFiltering(t){var e=(this.options.overlays||[]).find(e=>e.id===t);return!e||((e=this._checkZoomConstraints(e))?this.zoomFilteredOverlays.delete(t):this.zoomFilteredOverlays.add(t),e)}_getViewportConfig(e){var t=e.viewport||{};return e.viewport||e.fitBounds||e.forcedCenter||void 0!==e.panZoom||void 0!==e.forcedBearing||void 0!==e.forcedPitch?{fitBounds:t.fitBounds||e.fitBounds,center:t.center||e.forcedCenter,zoom:void 0!==t.zoom?t.zoom:e.panZoom,bearing:void 0!==t.bearing?t.bearing:e.forcedBearing,pitch:void 0!==t.pitch?t.pitch:e.forcedPitch}:null}_applyViewportConfig(e){if(this.map&&e){var t={};if(e.fitBounds)try{var i=BoundsHelper.calculateBoundsCenter(e.fitBounds),s=this.map.getContainer(),a=BoundsHelper.calculateBoundsZoom(e.fitBounds,{width:s.offsetWidth,height:s.offsetHeight});t.center=i,t.zoom=a}catch(e){console.warn("UIManager: fitBounds calculation failed:",e)}else void 0!==e.center&&(t.center=e.center),void 0!==e.zoom&&(t.zoom=e.zoom);void 0!==e.bearing&&(t.bearing=e.bearing),void 0!==e.pitch&&(t.pitch=e.pitch),0<Object.keys(t).length&&(t.duration=1e3,this.map.flyTo(t))}}_applyBaseToMap(t){if(this.map){var e=(this.options.baseStyles||[]).find(e=>e.id===t);if(e&&e.style){if(this.deckOverlay){try{this.map.removeControl(this.deckOverlay)}catch(e){}this.deckOverlay=null}this.deckLayers.clear(),this.overlayToLayerIds.clear(),this.map.setStyle(e.style),this.map.once("styledata",()=>{setTimeout(()=>{this._initializeDeckOverlay();let i=this.stateService.getOverlayStates();Object.keys(i).forEach(e=>{var t=i[e];t&&t.visible&&this._activateOverlay(e,!1)}),this.eventEmitter.emit("styleload",{baseId:t}),this.eventEmitter.emit("change",{type:"styleload",baseId:t})},50)})}}}_initializeDeckOverlay(){this.map&&!this.deckOverlay&&("undefined"==typeof deck?console.warn("UIManager: deck.gl not found on window.deck"):(this.deckOverlay=new deck.MapboxOverlay({interleaved:!0,pickingRadius:10,controller:!1,getTooltip:this._getTooltip.bind(this)}),this.map.addControl(this.deckOverlay)))}async _activateOverlay(t,i=!1){if(this.map&&(this.deckOverlay||this._initializeDeckOverlay(),this.deckOverlay)){let e=(this.options.overlays||[]).find(e=>e.id===t);if(e){this._setLoadingState(t,!0);try{var s,a;if(i&&e.forcedBaseLayerId)if(this.stateService.getCurrentBase()!==e.forcedBaseLayerId)return(s=this._getViewportConfig(e))&&this._applyViewportConfig(s),this.businessLogicService&&this.businessLogicService.setBaseLayer(e.forcedBaseLayerId),void this._setLoadingState(t,!1);i&&(a=this._getViewportConfig(e))&&this._applyViewportConfig(a),this._updateZoomFiltering(t)?(e.onChecked&&(await this._executeOnChecked(t,e,i),e=(this.options.overlays||[]).find(e=>e.id===t)),e&&e.deckLayers&&this._createAndStoreDeckLayers(t,e),this._setLoadingState(t,!1),this.errorStates.delete(t),this._updateOverlayUI(t)):(this._setLoadingState(t,!1),this._updateOverlayUI(t),this.eventEmitter.emit("zoomfilter",{id:t,filtered:!0}))}catch(e){console.error(`UIManager: error activating overlay "${t}":`,e),this._setLoadingState(t,!1),this.errorStates.set(t,e.message||String(e)),this._updateOverlayUI(t),this.eventEmitter.emit("error",{id:t,error:e.message||String(e)})}}}}async _executeOnChecked(a,e,t){this.eventEmitter.emit("loading",{id:a});t={map:this.map,overlayManager:this,stateManager:this.stateService,stateService:this.stateService,overlayId:a,overlay:e,isUserInteraction:t,deckOverlay:this.deckOverlay,getCurrentViewport:()=>{var e=this.map.getCenter();return{center:[e.lng,e.lat],zoom:this.map.getZoom(),bearing:this.map.getBearing(),pitch:this.map.getPitch()}},getOverlayState:e=>this.stateService.getOverlayStates()[e],getAllOverlayStates:()=>this.stateService.getOverlayStates(),getOverlayConfig:()=>(this.options.overlays||[]).find(e=>e.id===a),setOverlayConfig:(e,t={})=>{var i,s=(this.options.overlays||[]).findIndex(e=>e.id===a);-1!==s&&(Object.assign(this.options.overlays[s],e),t.applyViewport&&(t=this.options.overlays[s],s=this._getViewportConfig(t))&&this._applyViewportConfig(s),e.label)&&this.panel&&(i=this.panel.querySelector(`[data-overlay-id="${a}"] .layers-control__label`))&&(i.textContent=e.label)},getCache:()=>this.overlayCache.get(a),setCache:e=>this.overlayCache.set(a,e),clearCache:()=>this.overlayCache.delete(a)};try{await Promise.resolve(e.onChecked(t)),this.eventEmitter.emit("success",{id:a})}catch(e){throw this.eventEmitter.emit("error",{id:a,error:e.message||String(e)}),e}}_deactivateOverlay(e){var t=this.overlayToLayerIds.get(e);t&&(t.forEach(e=>this.deckLayers.delete(e)),this.overlayToLayerIds.delete(e)),this.zoomFilteredOverlays.delete(e),this._setLoadingState(e,!1),this._updateDeckOverlay()}_createAndStoreDeckLayers(e,t){(this.overlayToLayerIds.get(e)||[]).forEach(e=>this.deckLayers.delete(e));var i=this.stateService.getOverlayStates()[e];let s=i?i.opacity:1,a=[];t.deckLayers.forEach(e=>{var t=this._createDeckLayer(e,s);t&&(this.deckLayers.set(e.id,t),a.push(e.id))}),this.overlayToLayerIds.set(e,a),this._updateDeckOverlay()}_createDeckLayer(t,e){if("undefined"==typeof deck)return null;try{var i=deck[t.type];return i?new i({id:t.id,opacity:void 0!==e?e:1,...t.props}):(console.error(`UIManager: unknown deck.gl layer type "${t.type}"`),null)}catch(e){return console.error(`UIManager: failed to create deck.gl layer "${t.id}":`,e),null}}_showOverlayLayers(e){if(e&&e.deckLayers){var t=this.stateService.getOverlayStates()[e.id];let i=t?t.opacity:1;e.deckLayers.forEach(e=>{var t=this._createDeckLayer(e,i);t&&this.deckLayers.set(e.id,t)}),this._updateDeckOverlay()}}_hideOverlayLayers(e){e&&e.deckLayers&&(e.deckLayers.forEach(e=>this.deckLayers.delete(e.id)),this._updateDeckOverlay())}_updateOverlayOpacity(e,i){e=this.overlayToLayerIds.get(e);e&&(e.forEach(e=>{var t=this.deckLayers.get(e);t&&(t=t.clone({opacity:i}),this.deckLayers.set(e,t))}),this._updateDeckOverlay())}_updateDeckOverlay(){this.deckOverlay&&this.deckOverlay.setProps({layers:Array.from(this.deckLayers.values())})}_setLoadingState(e,t){this.loadingStates.set(e,t),this._updateOverlayUI(e)}_updateOverlayUI(t){if(this.panel){var i=this.panel.querySelector(`[data-overlay-id="${t}"]`);if(i){var s=this.stateService.getOverlayStates()[t],a=i.querySelector('input[type="checkbox"]'),a=(a&&(a.checked=!!s&&s.visible),this.loadingStates.get(t)),s=this.errorStates.has(t),r=this.zoomFilteredOverlays.has(t);let e="ok";a?e="loading":s?e="error":r&&(e="zoomfiltered");var o=i.querySelector(".layers-control__loading");if(o)switch(e){case"loading":o.textContent="↻",o.style.display="inline",o.classList.add("loadingRotate"),o.title="Loading...";break;case"error":o.textContent="🚨",o.style.display="inline",o.classList.remove("loadingRotate"),o.title=this.errorStates.get(t)||"Error loading overlay";break;case"zoomfiltered":o.textContent="🔍",o.style.display="inline",o.classList.remove("loadingRotate"),o.title="Hidden due to zoom level";break;default:o.style.display="none",o.classList.remove("loadingRotate"),o.title=""}i.classList.toggle("layers-control__overlay-item--loading","loading"===e),i.classList.toggle("layers-control__overlay-item--error","error"===e),i.classList.toggle("layers-control__overlay-item--filtered","zoomfiltered"===e)}}}_updateGroupUI(e){var t;this.panel&&(t=this.panel.querySelector(`.layers-control__group-toggle input[value="${e}"]`))&&(e=this.stateService.getGroupStates()[e],t.checked=!!e&&e.visible)}_getTooltip(e){if(!e||!e.object||!e.layer)return null;var t=e.layer.id,i=e.object,t=this._findOverlayByLayerId(t);if(!t)return null;if(t.getTooltip&&"function"==typeof t.getTooltip){try{var s=t.getTooltip(i,e);if(s)return{html:s.html||this._formatDefaultTooltip(s),style:s.style||this._defaultTooltipStyle()}}catch(e){console.error("UIManager: error in getTooltip:",e)}return null}return t.tooltip?{html:this._formatTooltipFromConfig(t.tooltip,i),style:this._defaultTooltipStyle()}:null}_findOverlayByLayerId(e){for(var t of this.options.overlays||[])if(t.deckLayers)for(var i of t.deckLayers)if(i.id===e)return t;return null}_formatTooltipFromConfig(e,i){var t;if("string"==typeof e)return`<div class="tooltip-content">${""!==(t=this._getNestedValue(i,e))?t:"No data"}</div>`;if("object"!=typeof e||null===e)return'<div class="tooltip-content">No data</div>';{let t='<div class="tooltip-content">';return e.title&&(t+=`<div class="tooltip-title">${this._getNestedValue(i,e.title)}</div>`),e.fields&&Array.isArray(e.fields)&&(t+='<div class="tooltip-body"><div class="tooltip-fields">',e.fields.forEach(e=>{"string"==typeof e?t+=`<div class="tooltip-field"><strong>${e}:</strong> ${this._getNestedValue(i,e)}</div>`:e.label&&e.property&&(t+=`<div class="tooltip-field"><strong>${e.label}:</strong> ${this._getNestedValue(i,e.property)}</div>`)}),t+="</div></div>"),t+="</div>"}}_formatDefaultTooltip(t){if("string"==typeof t)return`<div class="tooltip-content">${t}</div>`;if(t&&(t.title||t.content)){let e='<div class="tooltip-content">';return t.title&&(e+=`<div class="tooltip-title">${t.title}</div>`),t.content&&(e+=`<div class="tooltip-body">${t.content}</div>`),e+="</div>"}return`<div class="tooltip-content">${JSON.stringify(t)}</div>`}_getNestedValue(e,t){if(!t||null==e)return"";var i;let s=e;for(i of t.split(".")){if(null==s||"object"!=typeof s)return"";s=s[i]}return null!=s?String(s):""}_defaultTooltipStyle(){return{backgroundColor:"rgba(0,0,0,0.8)",color:"white",padding:"8px 12px",borderRadius:"4px",fontSize:"12px",fontFamily:"Arial, sans-serif",maxWidth:"300px",boxShadow:"0 2px 8px rgba(0,0,0,0.3)",pointerEvents:"none",zIndex:1e3}}_updateOverlayLayers(t){var e=(this.options.overlays||[]).find(e=>e.id===t);e&&(e.deckLayers?this._createAndStoreDeckLayers(t,e):((this.overlayToLayerIds.get(t)||[]).forEach(e=>this.deckLayers.delete(e)),this.overlayToLayerIds.delete(t),this._updateDeckOverlay()))}}let UIService=UIManager;class BusinessLogicService{constructor(e,t){if(!e)throw new Error("BusinessLogicService requires stateService");if(!t)throw new Error("BusinessLogicService requires eventEmitter");this.stateService=e,this.eventEmitter=t,this.map=null,this.uiManager=null,this.mapService=null,this.options=null}initialize(e){this.map=e.map,this.uiManager=e.uiService,this.mapService=e.mapService,e.options&&(this.options=e.options)}setBaseLayer(t){return(this.options.baseStyles||[]).find(e=>e.id===t)?(this.stateService.setBase(t),this.uiManager&&(this.uiManager.applyBaseStyle(t),this.uiManager.updateBaseUI()),!0):(console.warn(`BusinessLogicService: base style "${t}" not found`),!1)}updateBaseStyles(e){this.options&&(this.options.baseStyles=e),this.uiManager&&this.uiManager.updateBaseStyles()}async showOverlay(e,t=!1){var i=this.stateService.getOverlayStates();return i[e]&&i[e].visible||(this.stateService.setOverlayVisibility(e,!0),this.uiManager&&await this.uiManager.activateOverlay(e,t),t&&(t=(i=this.stateService.getOverlayStates()[e])?i.opacity:1,this.eventEmitter.emit("overlaychange",{id:e,visible:!0,opacity:t}),this.eventEmitter.emit("change",{type:"overlaychange",id:e,visible:!0,opacity:t}))),!0}hideOverlay(e,t=!1){var i=this.stateService.getOverlayStates();return i[e]&&i[e].visible&&(this.stateService.setOverlayVisibility(e,!1),this.uiManager&&this.uiManager.deactivateOverlay(e),t)&&(t=(i=this.stateService.getOverlayStates()[e])?i.opacity:1,this.eventEmitter.emit("overlaychange",{id:e,visible:!1,opacity:t}),this.eventEmitter.emit("change",{type:"overlaychange",id:e,visible:!1,opacity:t})),!0}async activateOverlay(e,t=!1){this.uiManager&&await this.uiManager.activateOverlay(e,t)}setOverlayOpacity(e,t){var t=Math.max(0,Math.min(1,parseFloat(t)||0)),i=(this.stateService.setOverlayOpacity(e,t),this.stateService.getOverlayStates()[e]);return this.uiManager&&i&&i.visible&&this.uiManager.updateOverlayOpacity(e,t),this.eventEmitter.emit("overlaychange",{id:e,visible:!!i&&i.visible,opacity:t}),this.eventEmitter.emit("change",{type:"overlaychange",id:e,visible:!!i&&i.visible,opacity:t}),!0}addOverlay(e,t=!1){this.stateService.initOverlay(e.id,e);var i=this.stateService.getOverlayStates()[e.id];return this.uiManager&&i&&i.visible&&this.uiManager.activateOverlay(e.id,!1),t&&this.eventEmitter.emit("overlaychange",{id:e.id,visible:!!i&&i.visible,opacity:i?i.opacity:1}),!0}removeOverlay(e,t=!1){return this.uiManager&&(this.uiManager.deactivateOverlay(e),this.uiManager.setLoadingState(e,!1),this.uiManager.setErrorState(e,null)),this.stateService.removeOverlay(e),t&&this.eventEmitter.emit("overlaychange",{id:e,visible:!1,opacity:1}),!0}removeAllOverlays(){return this.options&&this.options.overlays&&this.options.overlays.forEach(e=>{this.uiManager&&this.uiManager.deactivateOverlay(e.id),this.stateService.removeOverlay(e.id)}),this.uiManager&&this.uiManager.clearAll(),!0}setGroupVisibility(t,e){this.stateService.setGroupVisibility(t,e);var s=(this.options&&this.options.overlays||[]).filter(e=>e.group===t);if(e){let i=s.some(e=>{e=this.stateService.getOverlayStates()[e.id];return e&&e.visible});s.forEach(e=>{i||this.stateService.setOverlayVisibility(e.id,!0);var t=this.stateService.getOverlayStates()[e.id];this.uiManager&&t&&t.visible&&this.uiManager.activateOverlay(e.id,!1),this.uiManager&&this.uiManager.updateOverlayUI(e.id)})}else s.forEach(e=>{this.stateService.setOverlayVisibility(e.id,!1),this.uiManager&&this.uiManager.deactivateOverlay(e.id)});return this.uiManager&&this.uiManager.updateGroupUI(t),this.eventEmitter.emit("overlaygroupchange",{id:t,visible:e}),this.eventEmitter.emit("change",{type:"overlaygroupchange",id:t,visible:e}),!0}setGroupOpacity(t,e){let i=Math.max(0,Math.min(1,parseFloat(e)||0));return this.stateService.setGroupOpacity(t,i),(this.options&&this.options.overlays||[]).filter(e=>e.group===t).forEach(e=>{this.stateService.setOverlayOpacity(e.id,i);var t=this.stateService.getOverlayStates()[e.id];this.uiManager&&t&&t.visible&&this.uiManager.updateOverlayOpacity(e.id,i)}),!0}destroy(){this.map=null,this.uiManager=null,this.mapService=null,this.options=null}}class LayersControl{constructor(e={},t={}){if(!t.stateService)throw new Error("LayersControl requires stateService");if(!t.uiService)throw new Error("LayersControl requires uiService");if(!t.mapService)throw new Error("LayersControl requires mapService");if(!t.businessLogicService)throw new Error("LayersControl requires businessLogicService");if(!t.eventEmitter)throw new Error("LayersControl requires eventEmitter");if(!e.baseStyles||!Array.isArray(e.baseStyles))throw new Error("LayersControl requires a baseStyles array");if(!e.overlays||!Array.isArray(e.overlays))throw new Error("LayersControl requires an overlays array");this.options={showOpacity:!0,autoClose:!1,icon:"☰",i18n:{baseHeader:"Base Layers",overlaysHeader:"Overlays"},...e,i18n:{baseHeader:"Base Layers",overlaysHeader:"Overlays",...e.i18n||{}}},this.stateService=t.stateService,this.uiService=t.uiService,this.mapService=t.mapService,this.businessLogicService=t.businessLogicService,this.eventEmitter=t.eventEmitter,this.map=null,this.container=null,this._viewportSaveTimeout=null,this._mapEventHandlers=new Map,this._setupPublicEventForwarding()}onAdd(e){var t;return this.map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl maplibregl-ctrl-group layers-control-container",this.mapService.setMap(e),this.uiService.setOptions(this.options),this.uiService.setMap(e),this.uiService.setContainer(this.container),this.options.overlays.forEach(e=>{this.stateService.initOverlay(e.id,e)}),this.stateService.getCurrentBase()||(t=this.options.defaultBaseId||(0<this.options.baseStyles.length?this.options.baseStyles[0].id:null))&&this.stateService.setBase(t),this.businessLogicService.initialize({map:e,stateService:this.stateService,uiService:this.uiService,mapService:this.mapService,eventEmitter:this.eventEmitter,options:this.options}),this.uiService.setBusinessLogicService(this.businessLogicService),this.uiService.render(),this._setupMapEventListeners(),this._restoreMapState(),this.container}onRemove(){this._cleanupMapEventListeners(),this.mapService.setMap(null),this.uiService.setMap(null),this.uiService.setContainer(null),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.map=null,this.container=null}destroy(){if(this.removeAllOverlays(),this._cleanupMapEventListeners(),this.map&&this.container)try{this.map.removeControl(this)}catch(e){}return this.businessLogicService.destroy(),this.uiService.destroy(),this.mapService.destroy(),this.stateService.destroy(),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.map=null,this.container=null,this.stateService=null,this.uiService=null,this.mapService=null,this.businessLogicService=null,this.eventEmitter=null,this.options=null,this._mapEventHandlers.clear(),this._viewportSaveTimeout&&(clearTimeout(this._viewportSaveTimeout),this._viewportSaveTimeout=null),!0}setBaseLayer(t){return this.options.baseStyles.find(e=>e.id===t)?(this.businessLogicService.setBaseLayer(t),!0):(console.warn(`LayersControl.setBaseLayer: base style "${t}" not found`),!1)}setBase(e){return this.setBaseLayer(e)}addBaseStyle(t){var e;if(t&&t.id)return-1<(e=this.options.baseStyles.findIndex(e=>e.id===t.id))?this.options.baseStyles[e]={...this.options.baseStyles[e],...t}:this.options.baseStyles.push(t),this.businessLogicService.updateBaseStyles(this.options.baseStyles),!0;throw new Error("Base style must have an id")}removeBaseStyle(t){var e,i;return!!t&&(-1===(i=this.options.baseStyles.findIndex(e=>e.id===t))?(console.warn(`LayersControl.removeBaseStyle: "${t}" not found`),!1):(e=this.stateService.getCurrentBase()===t,this.options.baseStyles.splice(i,1),e&&0<this.options.baseStyles.length&&(i=this.options.baseStyles.find(e=>e.id===this.options.defaultBaseId)||this.options.baseStyles[0],this.businessLogicService.setBaseLayer(i.id)),this.businessLogicService.updateBaseStyles(this.options.baseStyles),!0))}getBaseLayers(){let t=this.stateService.getCurrentBase();return this.options.baseStyles.map(e=>({...e,active:e.id===t}))}addOverlay(t,e=!1){var i;if(t&&t.id)return-1<(i=this.options.overlays.findIndex(e=>e.id===t.id))?this.options.overlays[i]={...this.options.overlays[i],...t}:this.options.overlays.push(t),this.businessLogicService.addOverlay(t,e),this.uiService.updateOverlays(),!0;throw new Error("Overlay config must have an id")}removeOverlay(t,e=!1){var i=this.options.overlays.findIndex(e=>e.id===t);return-1===i?(console.warn(`LayersControl.removeOverlay: "${t}" not found`),!1):(this.businessLogicService.removeOverlay(t,e),this.options.overlays.splice(i,1),this.uiService.updateOverlays(),!0)}removeAllOverlays(){return this.businessLogicService.removeAllOverlays(),this.options.overlays=[],this.uiService.updateOverlays(),!0}showOverlay(t,e=!1){return this.options.overlays.find(e=>e.id===t)?(this.businessLogicService.showOverlay(t,e),!0):(console.warn(`LayersControl.showOverlay: "${t}" not found`),!1)}hideOverlay(t,e=!1){return this.options.overlays.find(e=>e.id===t)?(this.businessLogicService.hideOverlay(t,e),!0):(console.warn(`LayersControl.hideOverlay: "${t}" not found`),!1)}setOverlayOpacity(t,e){return this.options.overlays.find(e=>e.id===t)?(this.businessLogicService.setOverlayOpacity(t,e),!0):(console.warn(`LayersControl.setOverlayOpacity: "${t}" not found`),!1)}getOverlays(){let t=this.stateService.getOverlayStates();return this.options.overlays.map(e=>({...e,visible:!!t[e.id]&&t[e.id].visible,opacity:t[e.id]?t[e.id].opacity:1}))}showGroup(t){return this.options.overlays.some(e=>e.group===t)?(this.businessLogicService.setGroupVisibility(t,!0),!0):(console.warn(`LayersControl.showGroup: group "${t}" not found`),!1)}hideGroup(t){return this.options.overlays.some(e=>e.group===t)?(this.businessLogicService.setGroupVisibility(t,!1),!0):(console.warn(`LayersControl.hideGroup: group "${t}" not found`),!1)}setGroupOpacity(t,e){return this.options.overlays.some(e=>e.group===t)?(this.businessLogicService.setGroupOpacity(t,e),!0):(console.warn(`LayersControl.setGroupOpacity: group "${t}" not found`),!1)}getGroups(){let i=this.stateService.getGroupStates(),s=new Map;return this.options.overlays.forEach(t=>{var e;t.group&&!s.has(t.group)&&(e=(this.options.groups||[]).find(e=>e.id===t.group),s.set(t.group,{id:t.group,label:e?e.label:t.group,visible:!!i[t.group]&&i[t.group].visible,opacity:i[t.group]?i[t.group].opacity:1,overlays:[]}))}),this.options.overlays.forEach(e=>{e.group&&s.has(e.group)&&s.get(e.group).overlays.push(e.id)}),Array.from(s.values())}saveCurrentViewport(){var e;return!!this.map&&(e=this.map.getCenter(),this.stateService.setViewport({center:{lng:e.lng,lat:e.lat},zoom:this.map.getZoom(),bearing:this.map.getBearing(),pitch:this.map.getPitch()}),!0)}applySavedViewport(){var e;return!!this.map&&!(!(e=this.stateService.getViewport())||!e.center||(this.map.jumpTo({center:e.center,zoom:e.zoom||0,bearing:e.bearing||0,pitch:e.pitch||0}),0))}clearPersistedData(){return this.stateService.clearPersisted()}on(e,t){return this.eventEmitter.on(e,t),this}off(e,t){return this.eventEmitter.off(e,t),this}getCurrentState(){return this.stateService.getAll()}_setupPublicEventForwarding(){}_setupMapEventListeners(){var e;this.map&&(this._mapEventHandlers.set("moveend",e=()=>{clearTimeout(this._viewportSaveTimeout),this._viewportSaveTimeout=setTimeout(()=>{this.saveCurrentViewport()},500)}),this.map.on("moveend",e))}_cleanupMapEventListeners(){this.map&&(this._mapEventHandlers.forEach((e,t)=>{this.map.off(t,e)}),this._mapEventHandlers.clear(),this._viewportSaveTimeout)&&(clearTimeout(this._viewportSaveTimeout),this._viewportSaveTimeout=null)}_restoreMapState(){if(this.map){let t=this.stateService.getCurrentBase(),e=!1;t&&(this.options.baseStyles.find(e=>e.id===t)?(this.businessLogicService.setBaseLayer(t),e=!0):(i=this.options.baseStyles.find(e=>e.id===this.options.defaultBaseId)||this.options.baseStyles[0])&&(this.stateService.setBase(i.id),this.uiService.updateBaseUI()));var i=this.stateService.getViewport();i&&i.center&&setTimeout(()=>this.applySavedViewport(),e?400:100),e||(i=this.stateService.getOverlayStates(),Object.entries(i).forEach(([e,t])=>{t&&t.visible&&setTimeout(()=>{this.businessLogicService.activateOverlay(e,!1)},200)}))}}}
1
+ class BoundsHelper{static calculateBounds(e,t=0){if(!e||!Array.isArray(e)||0===e.length)throw new Error("Points array is required and must not be empty");let i=1/0,s=1/0,r=-1/0,a=-1/0;for(var[o,n]of e)i=Math.min(i,o),r=Math.max(r,o),s=Math.min(s,n),a=Math.max(a,n);let l,h,c,v;return"number"==typeof t?l=h=c=v=t:"object"==typeof t&&null!==t?(l=t.top||0,h=t.bottom||0,c=t.left||0,v=t.right||0):l=h=c=v=0,[[i-c,s-h],[r+v,a+l]]}static calculateBoundsCenter(e){var t,i;if(e&&Array.isArray(e)&&2===e.length)return t=e[0][0],i=e[0][1],[(t+e[1][0])/2,(i+e[1][1])/2];throw new Error("Bounds must be an array with two coordinate pairs")}static calculateBoundsZoom(e,t,i=.5){if(!e||!Array.isArray(e)||2!==e.length)throw new Error("Bounds must be an array with two coordinate pairs");var s,r,a;if(t&&"number"==typeof t.width&&"number"==typeof t.height)return a=e[0][0],s=e[0][1],r=e[1][0],e=e[1][1]-s,s=Math.log2(360*t.width/(512*(r-a))),r=Math.log2(180*t.height/(512*e)),a=Math.min(s,r)-i,Math.max(1,Math.min(20,a));throw new Error("Container must have numeric width and height properties")}static calculatePanCenter(t){try{if(t.deckLayers&&0<t.deckLayers.length){var e=t.deckLayers[0];if(e.props&&e.props.data&&0<e.props.data.length){var i=e.props.data[0];if(i.position)return i.position}}}catch(e){console.error(`Failed to calculate pan center for overlay ${t.id}:`,e)}return null}}class EventEmitter{constructor(){this._events=new Map}on(e,t){if("function"!=typeof t)throw new TypeError("Handler must be a function");return this._events.has(e)||this._events.set(e,new Set),this._events.get(e).add(t),this}off(e,t){var i=this._events.get(e);return i&&(i.delete(t),0===i.size)&&this._events.delete(e),this}emit(t,e){var i=this._events.get(t);if(i)for(var s of Array.from(i))try{s(e)}catch(e){console.error(`EventEmitter: error in "${t}" handler:`,e)}}once(t,i){let s=e=>{this.off(t,s),i(e)};return this.on(t,s)}removeAllListeners(e){return e?this._events.delete(e):this._events.clear(),this}}class StateService{constructor(e,t){this.eventEmitter=e,this.persistenceKey=t||null,this._debounceTimer=null,this._state={base:null,overlays:{},groups:{},layerOrder:[],viewport:{center:null,zoom:null,bearing:0,pitch:0}},this._loadPersisted()}get(e){return this._state[e]}getCurrentBase(){return this._state.base}getOverlayStates(){return this._state.overlays}getGroupStates(){return this._state.groups}getViewport(){return this._state.viewport||{}}getAll(){return JSON.parse(JSON.stringify(this._state))}initOverlay(e,t){var i;this._state.overlays[e]||(i=!0===t.defaultVisible,this._state.overlays[e]={visible:i,opacity:void 0!==t.defaultOpacity?t.defaultOpacity:1},i&&t.group&&!this._state.groups[t.group]&&(this._state.groups[t.group]={visible:!0,opacity:1}))}setBase(e){var t=this._state.base;this._state.base=e,this._schedulePersist(),t!==e&&(this.eventEmitter.emit("basechange",{id:e}),this.eventEmitter.emit("change",{type:"basechange",id:e}))}setOverlayVisibility(e,t){this._state.overlays[e]||(this._state.overlays[e]={visible:!1,opacity:1}),this._state.overlays[e].visible=t,this._schedulePersist()}setOverlayOpacity(e,t){this._state.overlays[e]||(this._state.overlays[e]={visible:!1,opacity:1}),this._state.overlays[e].opacity=Math.max(0,Math.min(1,parseFloat(t)||0)),this._schedulePersist()}setGroupVisibility(e,t){this._state.groups[e]||(this._state.groups[e]={visible:!1,opacity:1}),this._state.groups[e].visible=t,this._schedulePersist()}setGroupOpacity(e,t){this._state.groups[e]||(this._state.groups[e]={visible:!1,opacity:1}),this._state.groups[e].opacity=Math.max(0,Math.min(1,parseFloat(t)||0)),this._schedulePersist()}setViewport(e){this._state.viewport={...this._state.viewport||{},...e},this._schedulePersist(),this.eventEmitter.emit("viewportchange",{...this._state.viewport}),this.eventEmitter.emit("change",{type:"viewportchange",...this._state.viewport})}reorderLayers(e){this._state.layerOrder=[...e],this._schedulePersist()}removeOverlay(e){delete this._state.overlays[e];e=this._state.layerOrder.indexOf(e);-1<e&&this._state.layerOrder.splice(e,1),this._schedulePersist()}clearPersisted(){if(!this.persistenceKey)return!1;try{return localStorage.removeItem(this.persistenceKey),this.eventEmitter.emit("memorycleared",{}),this.eventEmitter.emit("change",{type:"memorycleared"}),!0}catch(e){return console.error("StateService: failed to clear persisted state:",e),!1}}destroy(){this._debounceTimer&&(clearTimeout(this._debounceTimer),this._debounceTimer=null)}_schedulePersist(){this.persistenceKey&&(clearTimeout(this._debounceTimer),this._debounceTimer=setTimeout(()=>this._persist(),300))}_persist(){if(this.persistenceKey)try{localStorage.setItem(this.persistenceKey,JSON.stringify(this._state))}catch(e){console.warn("StateService: failed to persist state:",e)}}_loadPersisted(){if(this.persistenceKey)try{var e,t=localStorage.getItem(this.persistenceKey);t&&(void 0!==(e=JSON.parse(t)).base&&(this._state.base=e.base),e.overlays&&(this._state.overlays={...e.overlays}),e.groups&&(this._state.groups={...e.groups}),Array.isArray(e.layerOrder)&&(this._state.layerOrder=e.layerOrder),e.viewport)&&(this._state.viewport={...this._state.viewport,...e.viewport})}catch(e){console.warn("StateService: failed to load persisted state:",e)}}}class MapService{constructor(e){this.eventEmitter=e,this.map=null}setMap(e){this.map=e}getMap(){return this.map}getCurrentViewport(){var e;return this.map?{center:{lng:(e=this.map.getCenter()).lng,lat:e.lat},zoom:this.map.getZoom(),bearing:this.map.getBearing(),pitch:this.map.getPitch()}:null}destroy(){this.map=null}}class UIManager{constructor(e,t,i){if(!e)throw new Error("UIManager requires stateService");if(!i)throw new Error("UIManager requires eventEmitter");this.stateService=e,this.mapService=t||null,this.eventEmitter=i,this.businessLogicService=null,this.options={},this.map=null,this.container=null,this.deckOverlay=null,this.toggle=null,this.panel=null,this.isOpen=!1,this.deckLayers=new Map,this.overlayToLayerIds=new Map,this.loadingStates=new Map,this.errorStates=new Map,this.zoomFilteredOverlays=new Set,this.overlayCache=new Map,this._handleToggleClick=this._handleToggleClick.bind(this),this._handleDocumentClick=this._handleDocumentClick.bind(this),this._onZoomEnd=this._onZoomEnd.bind(this)}setOptions(e){this.options=e||{}}setBusinessLogicService(e){this.businessLogicService=e}setMap(e){this.map=e,this.mapService&&this.mapService.setMap(e),e&&(this._initializeDeckOverlay(),e.on("zoomend",this._onZoomEnd))}setContainer(e){this.container=e}render(){this.container&&(this.container.innerHTML="",this.toggle=document.createElement("button"),this.toggle.className="layers-control__toggle",this.toggle.setAttribute("aria-label","Toggle layers"),this.toggle.innerHTML=this.options.icon||"☰",this.toggle.addEventListener("click",this._handleToggleClick),this.panel=document.createElement("div"),this.panel.className="layers-control__panel",this.panel.style.display="none",this.container.appendChild(this.toggle),this.container.appendChild(this.panel),this._renderPanelContent(),this._setupEventDelegation())}destroy(){if(this.map&&this.map.off("zoomend",this._onZoomEnd),this.options&&this.options.autoClose&&document.removeEventListener("click",this._handleDocumentClick),this.deckOverlay&&this.map)try{this.map.removeControl(this.deckOverlay)}catch(e){}this.deckLayers.clear(),this.overlayToLayerIds.clear(),this.loadingStates.clear(),this.errorStates.clear(),this.zoomFilteredOverlays.clear(),this.overlayCache.clear(),this.map=null,this.container=null,this.deckOverlay=null,this.panel=null,this.toggle=null}updateOverlays(){this._renderPanelContent()}updateBaseStyles(){this._renderPanelContent()}updateBaseUI(){let s=this.stateService.getCurrentBase();this.panel&&this.panel.querySelectorAll(".layers-control__base-item").forEach(e=>{var t,i=e.querySelector('input[type="radio"]');i&&(t=i.value===s,e.classList.toggle("layers-control__base-item--active",i.checked=t))})}updateOverlayUI(e){this._updateOverlayUI(e)}updateGroupUI(e){this._updateGroupUI(e)}setLoadingState(e,t){this._setLoadingState(e,t)}setErrorState(e,t){t?this.errorStates.set(e,t):this.errorStates.delete(e),this._updateOverlayUI(e)}async activateOverlay(e,t=!1){return this._activateOverlay(e,t)}deactivateOverlay(e){this._deactivateOverlay(e),this._updateOverlayUI(e)}updateOverlayOpacity(e,t){var i;this._updateOverlayOpacity(e,t),this.panel&&(e=this.panel.querySelector(`[data-overlay-id="${e}"]`))&&(i=e.querySelector(".layers-control__opacity-slider"),e=e.querySelector(".layers-control__opacity-label"),i&&(i.value=t),e)&&(e.textContent=Math.round(100*t)+"%")}clearAll(){this.deckLayers.clear(),this.overlayToLayerIds.clear(),this._updateDeckOverlay(),this.loadingStates.clear(),this.errorStates.clear(),this.zoomFilteredOverlays.clear(),this.overlayCache.clear()}applyBaseStyle(e){this._applyBaseToMap(e)}_renderPanelContent(){this.panel&&(this.panel.innerHTML="",this.options.baseStyles&&0<this.options.baseStyles.length&&this.panel.appendChild(this._createBaseSection()),this.options.overlays)&&0<this.options.overlays.length&&this.panel.appendChild(this._createOverlaysSection())}_createBaseSection(){var e=document.createElement("div"),t=(e.className="layers-control__base-section",document.createElement("h3"));t.className="layers-control__section-title",t.textContent=this.options.i18n&&this.options.i18n.baseHeader?this.options.i18n.baseHeader:"Base Layers";let r=document.createElement("div"),a=(r.className="layers-control__base-list",this.stateService.getCurrentBase());return(this.options.baseStyles||[]).forEach(e=>{var t=document.createElement("label");t.className="layers-control__base-item",e.id===a&&t.classList.add("layers-control__base-item--active");let i=document.createElement("input");i.type="radio",i.name="base-layer",i.value=e.id,i.checked=e.id===a,i.addEventListener("change",()=>{i.checked&&this._handleBaseChange(e.id)});var s=document.createElement("span");s.textContent=e.label||e.id,t.appendChild(i),t.appendChild(s),r.appendChild(t)}),e.appendChild(t),e.appendChild(r),e}_createOverlaysSection(){var e=document.createElement("div"),t=(e.className="layers-control__overlays-section",document.createElement("h3"));t.className="layers-control__section-title",t.textContent=this.options.i18n&&this.options.i18n.overlaysHeader?this.options.i18n.overlaysHeader:"Overlays";let i=document.createElement("div"),s=(i.className="layers-control__overlays-list",new Map),r=[];return(this.options.overlays||[]).forEach(e=>{(e.group?(s.has(e.group)||s.set(e.group,[]),s.get(e.group)):r).push(e)}),s.forEach((e,t)=>{i.appendChild(this._createGroupElement(t,e))}),r.forEach(e=>{i.appendChild(this._createOverlayElement(e))}),e.appendChild(t),e.appendChild(i),e}_createGroupElement(t,e){var i=document.createElement("div"),s=(i.className="layers-control__group",document.createElement("div")),r=(s.className="layers-control__group-header",document.createElement("label")),a=(r.className="layers-control__group-toggle",document.createElement("input")),o=(a.type="checkbox",a.value=t,this.stateService.getGroupStates()[t]),o=(a.checked=!!o&&o.visible,a.addEventListener("change",()=>this._handleToggleGroup(t)),(this.options.groups||[]).find(e=>e.id===t)),n=document.createElement("span");n.textContent=o&&o.label?o.label:t,r.appendChild(a),r.appendChild(n),s.appendChild(r);let l=document.createElement("div");return l.className="layers-control__group-overlays",e.forEach(e=>{l.appendChild(this._createOverlayElement(e))}),i.appendChild(s),i.appendChild(l),i}_createOverlayElement(e){var t=document.createElement("div"),i=(t.className="layers-control__overlay-item",t.dataset.overlayId=e.id,document.createElement("label")),s=(i.className="layers-control__overlay-toggle",document.createElement("input")),r=(s.type="checkbox",s.value=e.id,this.stateService.getOverlayStates()[e.id]),a=(s.checked=!!r&&r.visible,s.addEventListener("change",()=>this._handleToggleOverlay(e.id)),document.createElement("span")),o=(a.className="layers-control__label",a.textContent=e.label||e.id,document.createElement("span"));return o.className="layers-control__loading",o.style.display="none",i.appendChild(s),i.appendChild(a),i.appendChild(o),t.appendChild(i),!1!==this.options.showOpacity&&e.opacityControls&&(s=r?r.opacity:1,t.appendChild(this._createOpacitySlider(e.id,s))),t}_createOpacitySlider(t,e){var i=document.createElement("div"),s=(i.className="layers-control__opacity-control",document.createElement("input"));s.type="range",s.className="layers-control__opacity-slider",s.min="0",s.max="1",s.step="0.01",s.value=e;let r=document.createElement("span");return r.className="layers-control__opacity-label",r.textContent=Math.round(100*e)+"%",s.addEventListener("input",e=>{e=parseFloat(e.target.value);r.textContent=Math.round(100*e)+"%",this._handleOpacitySlider(t,e,!1)}),i.appendChild(s),i.appendChild(r),i}_setupEventDelegation(){this.options.autoClose&&document.addEventListener("click",this._handleDocumentClick)}_handleToggleClick(e){e.stopPropagation(),this.isOpen=!this.isOpen,this.panel&&(this.panel.style.display=this.isOpen?"block":"none",this.panel.classList.toggle("layers-control__panel--open",this.isOpen))}_handleDocumentClick(e){this.container&&!this.container.contains(e.target)&&(this.isOpen=!1,this.panel)&&(this.panel.style.display="none",this.panel.classList.remove("layers-control__panel--open"))}_handleBaseChange(e){this.businessLogicService&&this.businessLogicService.setBaseLayer(e)}_handleToggleOverlay(e){var t;this.businessLogicService&&(!((t=this.stateService.getOverlayStates()[e])&&t.visible)?this.businessLogicService.showOverlay(e,!0):this.businessLogicService.hideOverlay(e,!0))}_handleToggleGroup(e){var t;this.businessLogicService&&(t=!((t=this.stateService.getGroupStates()[e])&&t.visible),this.businessLogicService.setGroupVisibility(e,t))}_handleOpacitySlider(e,t,i){this.businessLogicService&&(i?this.businessLogicService.setGroupOpacity(e,t):this.businessLogicService.setOverlayOpacity(e,t))}_onZoomEnd(){this.updateAllZoomFiltering()}updateAllZoomFiltering(){if(this.map){let r=this.stateService.getOverlayStates();Object.keys(r).forEach(t=>{var e,i,s=r[t];s&&s.visible&&(s=(this.options.overlays||[]).find(e=>e.id===t))&&(e=this._checkZoomConstraints(s),i=this.zoomFilteredOverlays.has(t),e&&i?(this.zoomFilteredOverlays.delete(t),this._showOverlayLayers(s),this._updateOverlayUI(t),this.eventEmitter.emit("zoomfilter",{id:t,filtered:!1})):e||i||(this.zoomFilteredOverlays.add(t),this._hideOverlayLayers(s),this._updateOverlayUI(t),this.eventEmitter.emit("zoomfilter",{id:t,filtered:!0})))})}}_checkZoomConstraints(e){var t;return!(this.map&&(t=this.map.getZoom(),void 0!==(e=this._getFilterConfig(e)).minZoom&&t<e.minZoom||void 0!==e.maxZoom&&t>=e.maxZoom))}_getFilterConfig(e){var t=e.filter||{};return{minZoom:void 0!==t.minZoom?t.minZoom:e.minZoomLevel,maxZoom:void 0!==t.maxZoom?t.maxZoom:e.maxZoomLevel}}_updateZoomFiltering(t){var e=(this.options.overlays||[]).find(e=>e.id===t);return!e||((e=this._checkZoomConstraints(e))?this.zoomFilteredOverlays.delete(t):this.zoomFilteredOverlays.add(t),e)}_getViewportConfig(e){var t=e.viewport||{};return e.viewport||e.fitBounds||e.forcedCenter||void 0!==e.panZoom||void 0!==e.forcedBearing||void 0!==e.forcedPitch?{fitBounds:t.fitBounds||e.fitBounds,center:t.center||e.forcedCenter,zoom:void 0!==t.zoom?t.zoom:e.panZoom,bearing:void 0!==t.bearing?t.bearing:e.forcedBearing,pitch:void 0!==t.pitch?t.pitch:e.forcedPitch}:null}_applyViewportConfig(e){if(this.map&&e){var t={};if(e.fitBounds)try{var i=BoundsHelper.calculateBoundsCenter(e.fitBounds),s=this.map.getContainer(),r=BoundsHelper.calculateBoundsZoom(e.fitBounds,{width:s.offsetWidth,height:s.offsetHeight});t.center=i,t.zoom=r}catch(e){console.warn("UIManager: fitBounds calculation failed:",e)}else void 0!==e.center&&(t.center=e.center),void 0!==e.zoom&&(t.zoom=e.zoom);void 0!==e.bearing&&(t.bearing=e.bearing),void 0!==e.pitch&&(t.pitch=e.pitch),0<Object.keys(t).length&&(t.duration=1e3,this.map.flyTo(t))}}_applyBaseToMap(t){if(this.map){var e=(this.options.baseStyles||[]).find(e=>e.id===t);if(e&&e.style){if(this.deckOverlay){try{this.map.removeControl(this.deckOverlay)}catch(e){}this.deckOverlay=null}this.deckLayers.clear(),this.overlayToLayerIds.clear(),this.map.setStyle(e.style),this.map.once("styledata",()=>{setTimeout(()=>{this._initializeDeckOverlay();let i=this.stateService.getOverlayStates();Object.keys(i).forEach(e=>{var t=i[e];t&&t.visible&&this._activateOverlay(e,!1)}),this.eventEmitter.emit("styleload",{baseId:t}),this.eventEmitter.emit("change",{type:"styleload",baseId:t})},50)})}}}_initializeDeckOverlay(){this.map&&!this.deckOverlay&&("undefined"==typeof deck?console.warn("UIManager: deck.gl not found on window.deck"):(this.deckOverlay=new deck.MapboxOverlay({interleaved:!0,pickingRadius:10,controller:!1,getTooltip:this._getTooltip.bind(this)}),this.map.addControl(this.deckOverlay)))}async _activateOverlay(t,i=!1){if(this.map&&(this.deckOverlay||this._initializeDeckOverlay(),this.deckOverlay)){let e=(this.options.overlays||[]).find(e=>e.id===t);if(e){this._setLoadingState(t,!0);try{var s,r;if(i&&e.forcedBaseLayerId)if(this.stateService.getCurrentBase()!==e.forcedBaseLayerId)return(s=this._getViewportConfig(e))&&this._applyViewportConfig(s),this.businessLogicService&&this.businessLogicService.setBaseLayer(e.forcedBaseLayerId),void this._setLoadingState(t,!1);i&&(r=this._getViewportConfig(e))&&this._applyViewportConfig(r),this._updateZoomFiltering(t)?(e.onChecked&&(await this._executeOnChecked(t,e,i),e=(this.options.overlays||[]).find(e=>e.id===t)),e&&e.deckLayers&&this._createAndStoreDeckLayers(t,e),this._setLoadingState(t,!1),this.errorStates.delete(t),this._updateOverlayUI(t)):(this._setLoadingState(t,!1),this._updateOverlayUI(t),this.eventEmitter.emit("zoomfilter",{id:t,filtered:!0}))}catch(e){console.error(`UIManager: error activating overlay "${t}":`,e),this._setLoadingState(t,!1),this.errorStates.set(t,e.message||String(e)),this._updateOverlayUI(t),this.eventEmitter.emit("error",{id:t,error:e.message||String(e)})}}}}async _executeOnChecked(r,e,t){this.eventEmitter.emit("loading",{id:r});t={map:this.map,overlayManager:this,stateManager:this.stateService,stateService:this.stateService,overlayId:r,overlay:e,isUserInteraction:t,deckOverlay:this.deckOverlay,getCurrentViewport:()=>{var e=this.map.getCenter();return{center:[e.lng,e.lat],zoom:this.map.getZoom(),bearing:this.map.getBearing(),pitch:this.map.getPitch()}},getOverlayState:e=>this.stateService.getOverlayStates()[e],getAllOverlayStates:()=>this.stateService.getOverlayStates(),getOverlayConfig:()=>(this.options.overlays||[]).find(e=>e.id===r),setOverlayConfig:(e,t={})=>{var i,s=(this.options.overlays||[]).findIndex(e=>e.id===r);-1!==s&&(Object.assign(this.options.overlays[s],e),t.applyViewport&&(t=this.options.overlays[s],s=this._getViewportConfig(t))&&this._applyViewportConfig(s),e.label)&&this.panel&&(i=this.panel.querySelector(`[data-overlay-id="${r}"] .layers-control__label`))&&(i.textContent=e.label)},getCache:()=>this.overlayCache.get(r),setCache:e=>this.overlayCache.set(r,e),clearCache:()=>this.overlayCache.delete(r)};try{await Promise.resolve(e.onChecked(t)),this.eventEmitter.emit("success",{id:r})}catch(e){throw this.eventEmitter.emit("error",{id:r,error:e.message||String(e)}),e}}_deactivateOverlay(e){var t=this.overlayToLayerIds.get(e);t&&(t.forEach(e=>this.deckLayers.delete(e)),this.overlayToLayerIds.delete(e)),this.zoomFilteredOverlays.delete(e),this._setLoadingState(e,!1),this._updateDeckOverlay()}_createAndStoreDeckLayers(e,t){(this.overlayToLayerIds.get(e)||[]).forEach(e=>this.deckLayers.delete(e));var i=this.stateService.getOverlayStates()[e];let s=i?i.opacity:1,r=[];t.deckLayers.forEach(e=>{var t=this._createDeckLayer(e,s);t&&(this.deckLayers.set(e.id,t),r.push(e.id))}),this.overlayToLayerIds.set(e,r),this._updateDeckOverlay()}_createDeckLayer(t,e){if("undefined"==typeof deck)return null;try{var i=deck[t.type];return i?new i({id:t.id,opacity:void 0!==e?e:1,...t.props}):(console.error(`UIManager: unknown deck.gl layer type "${t.type}"`),null)}catch(e){return console.error(`UIManager: failed to create deck.gl layer "${t.id}":`,e),null}}_showOverlayLayers(e){if(e&&e.deckLayers){var t=this.stateService.getOverlayStates()[e.id];let i=t?t.opacity:1;e.deckLayers.forEach(e=>{var t=this._createDeckLayer(e,i);t&&this.deckLayers.set(e.id,t)}),this._updateDeckOverlay()}}_hideOverlayLayers(e){e&&e.deckLayers&&(e.deckLayers.forEach(e=>this.deckLayers.delete(e.id)),this._updateDeckOverlay())}_updateOverlayOpacity(e,i){e=this.overlayToLayerIds.get(e);e&&(e.forEach(e=>{var t=this.deckLayers.get(e);t&&(t=t.clone({opacity:i}),this.deckLayers.set(e,t))}),this._updateDeckOverlay())}_updateDeckOverlay(){this.deckOverlay&&this.deckOverlay.setProps({layers:Array.from(this.deckLayers.values())})}_setLoadingState(e,t){this.loadingStates.set(e,t),this._updateOverlayUI(e)}_updateOverlayUI(t){if(this.panel){var i=this.panel.querySelector(`[data-overlay-id="${t}"]`);if(i){var s=this.stateService.getOverlayStates()[t],r=i.querySelector('input[type="checkbox"]'),r=(r&&(r.checked=!!s&&s.visible),this.loadingStates.get(t)),s=this.errorStates.has(t),a=this.zoomFilteredOverlays.has(t);let e="ok";r?e="loading":s?e="error":a&&(e="zoomfiltered");var o=i.querySelector(".layers-control__loading");if(o)switch(e){case"loading":o.textContent="↻",o.style.display="inline",o.classList.add("loadingRotate"),o.title="Loading...";break;case"error":o.textContent="🚨",o.style.display="inline",o.classList.remove("loadingRotate"),o.title=this.errorStates.get(t)||"Error loading overlay";break;case"zoomfiltered":o.textContent="🔍",o.style.display="inline",o.classList.remove("loadingRotate"),o.title="Hidden due to zoom level";break;default:o.style.display="none",o.classList.remove("loadingRotate"),o.title=""}i.classList.toggle("layers-control__overlay-item--loading","loading"===e),i.classList.toggle("layers-control__overlay-item--error","error"===e),i.classList.toggle("layers-control__overlay-item--filtered","zoomfiltered"===e)}}}_updateGroupUI(e){var t;this.panel&&(t=this.panel.querySelector(`.layers-control__group-toggle input[value="${e}"]`))&&(e=this.stateService.getGroupStates()[e],t.checked=!!e&&e.visible)}_getTooltip(e){if(!e||!e.object||!e.layer)return null;var t=e.layer.id,i=e.object,t=this._findOverlayByLayerId(t);if(!t)return null;if(t.getTooltip&&"function"==typeof t.getTooltip){try{var s=t.getTooltip(i,e);if(s)return{html:s.html||this._formatDefaultTooltip(s),style:s.style||this._defaultTooltipStyle()}}catch(e){console.error("UIManager: error in getTooltip:",e)}return null}return t.tooltip?{html:this._formatTooltipFromConfig(t.tooltip,i),style:this._defaultTooltipStyle()}:null}_findOverlayByLayerId(e){for(var t of this.options.overlays||[])if(t.deckLayers)for(var i of t.deckLayers)if(i.id===e)return t;return null}_formatTooltipFromConfig(e,i){var t;if("string"==typeof e)return`<div class="tooltip-content">${""!==(t=this._getNestedValue(i,e))?t:"No data"}</div>`;if("object"!=typeof e||null===e)return'<div class="tooltip-content">No data</div>';{let t='<div class="tooltip-content">';return e.title&&(t+=`<div class="tooltip-title">${this._getNestedValue(i,e.title)}</div>`),e.fields&&Array.isArray(e.fields)&&(t+='<div class="tooltip-body"><div class="tooltip-fields">',e.fields.forEach(e=>{"string"==typeof e?t+=`<div class="tooltip-field"><strong>${e}:</strong> ${this._getNestedValue(i,e)}</div>`:e.label&&e.property&&(t+=`<div class="tooltip-field"><strong>${e.label}:</strong> ${this._getNestedValue(i,e.property)}</div>`)}),t+="</div></div>"),t+="</div>"}}_formatDefaultTooltip(t){if("string"==typeof t)return`<div class="tooltip-content">${t}</div>`;if(t&&(t.title||t.content)){let e='<div class="tooltip-content">';return t.title&&(e+=`<div class="tooltip-title">${t.title}</div>`),t.content&&(e+=`<div class="tooltip-body">${t.content}</div>`),e+="</div>"}return`<div class="tooltip-content">${JSON.stringify(t)}</div>`}_getNestedValue(e,t){if(!t||null==e)return"";var i;let s=e;for(i of t.split(".")){if(null==s||"object"!=typeof s)return"";s=s[i]}return null!=s?String(s):""}_defaultTooltipStyle(){return{backgroundColor:"rgba(0,0,0,0.8)",color:"white",padding:"8px 12px",borderRadius:"4px",fontSize:"12px",fontFamily:"Arial, sans-serif",maxWidth:"300px",boxShadow:"0 2px 8px rgba(0,0,0,0.3)",pointerEvents:"none",zIndex:1e3}}_updateOverlayLayers(t){var e=(this.options.overlays||[]).find(e=>e.id===t);e&&(e.deckLayers?this._createAndStoreDeckLayers(t,e):((this.overlayToLayerIds.get(t)||[]).forEach(e=>this.deckLayers.delete(e)),this.overlayToLayerIds.delete(t),this._updateDeckOverlay()))}}let UIService=UIManager;class BusinessLogicService{constructor(e,t){if(!e)throw new Error("BusinessLogicService requires stateService");if(!t)throw new Error("BusinessLogicService requires eventEmitter");this.stateService=e,this.eventEmitter=t,this.map=null,this.uiManager=null,this.mapService=null,this.options=null}initialize(e){this.map=e.map,this.uiManager=e.uiService,this.mapService=e.mapService,e.options&&(this.options=e.options)}setBaseLayer(t){return(this.options.baseStyles||[]).find(e=>e.id===t)?(this.stateService.setBase(t),this.uiManager&&(this.uiManager.applyBaseStyle(t),this.uiManager.updateBaseUI()),!0):(console.warn(`BusinessLogicService: base style "${t}" not found`),!1)}updateBaseStyles(e){this.options&&(this.options.baseStyles=e),this.uiManager&&this.uiManager.updateBaseStyles()}async showOverlay(e,t=!1){var i=this.stateService.getOverlayStates();return i[e]&&i[e].visible||(this.stateService.setOverlayVisibility(e,!0),this.uiManager&&await this.uiManager.activateOverlay(e,t),t&&(t=(i=this.stateService.getOverlayStates()[e])?i.opacity:1,this.eventEmitter.emit("overlaychange",{id:e,visible:!0,opacity:t}),this.eventEmitter.emit("change",{type:"overlaychange",id:e,visible:!0,opacity:t}))),!0}hideOverlay(e,t=!1){var i=this.stateService.getOverlayStates();return i[e]&&i[e].visible&&(this.stateService.setOverlayVisibility(e,!1),this.uiManager&&this.uiManager.deactivateOverlay(e),t)&&(t=(i=this.stateService.getOverlayStates()[e])?i.opacity:1,this.eventEmitter.emit("overlaychange",{id:e,visible:!1,opacity:t}),this.eventEmitter.emit("change",{type:"overlaychange",id:e,visible:!1,opacity:t})),!0}async activateOverlay(e,t=!1){this.uiManager&&await this.uiManager.activateOverlay(e,t)}setOverlayOpacity(e,t){var t=Math.max(0,Math.min(1,parseFloat(t)||0)),i=(this.stateService.setOverlayOpacity(e,t),this.stateService.getOverlayStates()[e]);return this.uiManager&&i&&i.visible&&this.uiManager.updateOverlayOpacity(e,t),this.eventEmitter.emit("overlaychange",{id:e,visible:!!i&&i.visible,opacity:t}),this.eventEmitter.emit("change",{type:"overlaychange",id:e,visible:!!i&&i.visible,opacity:t}),!0}addOverlay(e,t=!1){this.stateService.initOverlay(e.id,e);var i=this.stateService.getOverlayStates()[e.id];return this.uiManager&&i&&i.visible&&this.uiManager.activateOverlay(e.id,!1),t&&this.eventEmitter.emit("overlaychange",{id:e.id,visible:!!i&&i.visible,opacity:i?i.opacity:1}),!0}removeOverlay(e,t=!1){return this.uiManager&&(this.uiManager.deactivateOverlay(e),this.uiManager.setLoadingState(e,!1),this.uiManager.setErrorState(e,null)),this.stateService.removeOverlay(e),t&&this.eventEmitter.emit("overlaychange",{id:e,visible:!1,opacity:1}),!0}removeAllOverlays(){return this.options&&this.options.overlays&&this.options.overlays.forEach(e=>{this.uiManager&&this.uiManager.deactivateOverlay(e.id),this.stateService.removeOverlay(e.id)}),this.uiManager&&this.uiManager.clearAll(),!0}setGroupVisibility(t,e){this.stateService.setGroupVisibility(t,e);var s=(this.options&&this.options.overlays||[]).filter(e=>e.group===t);if(e){let i=s.some(e=>{e=this.stateService.getOverlayStates()[e.id];return e&&e.visible});s.forEach(e=>{i||this.stateService.setOverlayVisibility(e.id,!0);var t=this.stateService.getOverlayStates()[e.id];this.uiManager&&t&&t.visible&&this.uiManager.activateOverlay(e.id,!1),this.uiManager&&this.uiManager.updateOverlayUI(e.id)})}else s.forEach(e=>{this.stateService.setOverlayVisibility(e.id,!1),this.uiManager&&this.uiManager.deactivateOverlay(e.id)});return this.uiManager&&this.uiManager.updateGroupUI(t),this.eventEmitter.emit("overlaygroupchange",{id:t,visible:e}),this.eventEmitter.emit("change",{type:"overlaygroupchange",id:t,visible:e}),!0}setGroupOpacity(t,e){let i=Math.max(0,Math.min(1,parseFloat(e)||0));return this.stateService.setGroupOpacity(t,i),(this.options&&this.options.overlays||[]).filter(e=>e.group===t).forEach(e=>{this.stateService.setOverlayOpacity(e.id,i);var t=this.stateService.getOverlayStates()[e.id];this.uiManager&&t&&t.visible&&this.uiManager.updateOverlayOpacity(e.id,i)}),!0}destroy(){this.map=null,this.uiManager=null,this.mapService=null,this.options=null}}class LayersControl{constructor(e={},t={}){if(!t.stateService)throw new Error("LayersControl requires stateService");if(!t.uiService)throw new Error("LayersControl requires uiService");if(!t.mapService)throw new Error("LayersControl requires mapService");if(!t.businessLogicService)throw new Error("LayersControl requires businessLogicService");if(!t.eventEmitter)throw new Error("LayersControl requires eventEmitter");if(!e.baseStyles||!Array.isArray(e.baseStyles))throw new Error("LayersControl requires a baseStyles array");if(!e.overlays||!Array.isArray(e.overlays))throw new Error("LayersControl requires an overlays array");this.options={showOpacity:!0,autoClose:!1,icon:"☰",i18n:{baseHeader:"Base Layers",overlaysHeader:"Overlays"},...e,i18n:{baseHeader:"Base Layers",overlaysHeader:"Overlays",...e.i18n||{}}},this.stateService=t.stateService,this.uiService=t.uiService,this.mapService=t.mapService,this.businessLogicService=t.businessLogicService,this.eventEmitter=t.eventEmitter,this.map=null,this.container=null,this._viewportSaveTimeout=null,this._mapEventHandlers=new Map,this._setupPublicEventForwarding()}onAdd(e){var t;return this.map=e,this.container=document.createElement("div"),this.container.className="maplibregl-ctrl maplibregl-ctrl-group layers-control-container",this.mapService.setMap(e),this.uiService.setOptions(this.options),this.uiService.setMap(e),this.uiService.setContainer(this.container),this.options.overlays.forEach(e=>{this.stateService.initOverlay(e.id,e)}),this.stateService.getCurrentBase()||(t=this.options.defaultBaseId||(0<this.options.baseStyles.length?this.options.baseStyles[0].id:null))&&this.stateService.setBase(t),this.businessLogicService.initialize({map:e,stateService:this.stateService,uiService:this.uiService,mapService:this.mapService,eventEmitter:this.eventEmitter,options:this.options}),this.uiService.setBusinessLogicService(this.businessLogicService),this.uiService.render(),this._setupMapEventListeners(),this._restoreMapState(),this.container}onRemove(){this._cleanupMapEventListeners(),this.mapService.setMap(null),this.uiService.setMap(null),this.uiService.setContainer(null),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.map=null,this.container=null}destroy(){if(this.removeAllOverlays(),this._cleanupMapEventListeners(),this.map&&this.container)try{this.map.removeControl(this)}catch(e){}return this.businessLogicService.destroy(),this.uiService.destroy(),this.mapService.destroy(),this.stateService.destroy(),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container),this.map=null,this.container=null,this.stateService=null,this.uiService=null,this.mapService=null,this.businessLogicService=null,this.eventEmitter=null,this.options=null,this._mapEventHandlers.clear(),this._viewportSaveTimeout&&(clearTimeout(this._viewportSaveTimeout),this._viewportSaveTimeout=null),!0}setBaseLayer(t){return this.options.baseStyles.find(e=>e.id===t)?(this.businessLogicService.setBaseLayer(t),!0):(console.warn(`LayersControl.setBaseLayer: base style "${t}" not found`),!1)}setBase(e){return this.setBaseLayer(e)}addBaseStyle(t){var e;if(t&&t.id)return-1<(e=this.options.baseStyles.findIndex(e=>e.id===t.id))?this.options.baseStyles[e]={...this.options.baseStyles[e],...t}:this.options.baseStyles.push(t),this.businessLogicService.updateBaseStyles(this.options.baseStyles),!0;throw new Error("Base style must have an id")}removeBaseStyle(t){var e,i;return!!t&&(-1===(i=this.options.baseStyles.findIndex(e=>e.id===t))?(console.warn(`LayersControl.removeBaseStyle: "${t}" not found`),!1):(e=this.stateService.getCurrentBase()===t,this.options.baseStyles.splice(i,1),e&&0<this.options.baseStyles.length&&(i=this.options.baseStyles.find(e=>e.id===this.options.defaultBaseId)||this.options.baseStyles[0],this.businessLogicService.setBaseLayer(i.id)),this.businessLogicService.updateBaseStyles(this.options.baseStyles),!0))}getBaseLayers(){let t=this.stateService.getCurrentBase();return this.options.baseStyles.map(e=>({...e,active:e.id===t}))}addOverlay(t,e=!1){var i;if(t&&t.id)return-1<(i=this.options.overlays.findIndex(e=>e.id===t.id))?this.options.overlays[i]={...this.options.overlays[i],...t}:this.options.overlays.push(t),this.businessLogicService.addOverlay(t,e),this.uiService.updateOverlays(),!0;throw new Error("Overlay config must have an id")}removeOverlay(t,e=!1){var i=this.options.overlays.findIndex(e=>e.id===t);return-1===i?(console.warn(`LayersControl.removeOverlay: "${t}" not found`),!1):(this.businessLogicService.removeOverlay(t,e),this.options.overlays.splice(i,1),this.uiService.updateOverlays(),!0)}removeAllOverlays(){return this.businessLogicService.removeAllOverlays(),this.options.overlays=[],this.uiService.updateOverlays(),!0}showOverlay(t,e=!1){return this.options.overlays.find(e=>e.id===t)?(this.businessLogicService.showOverlay(t,e),!0):(console.warn(`LayersControl.showOverlay: "${t}" not found`),!1)}hideOverlay(t,e=!1){return this.options.overlays.find(e=>e.id===t)?(this.businessLogicService.hideOverlay(t,e),!0):(console.warn(`LayersControl.hideOverlay: "${t}" not found`),!1)}setOverlayOpacity(t,e){return this.options.overlays.find(e=>e.id===t)?(this.businessLogicService.setOverlayOpacity(t,e),!0):(console.warn(`LayersControl.setOverlayOpacity: "${t}" not found`),!1)}getOverlays(){let t=this.stateService.getOverlayStates();return this.options.overlays.map(e=>({...e,visible:!!t[e.id]&&t[e.id].visible,opacity:t[e.id]?t[e.id].opacity:1}))}showGroup(t){return this.options.overlays.some(e=>e.group===t)?(this.businessLogicService.setGroupVisibility(t,!0),!0):(console.warn(`LayersControl.showGroup: group "${t}" not found`),!1)}hideGroup(t){return this.options.overlays.some(e=>e.group===t)?(this.businessLogicService.setGroupVisibility(t,!1),!0):(console.warn(`LayersControl.hideGroup: group "${t}" not found`),!1)}setGroupOpacity(t,e){return this.options.overlays.some(e=>e.group===t)?(this.businessLogicService.setGroupOpacity(t,e),!0):(console.warn(`LayersControl.setGroupOpacity: group "${t}" not found`),!1)}getGroups(){let i=this.stateService.getGroupStates(),s=new Map;return this.options.overlays.forEach(t=>{var e;t.group&&!s.has(t.group)&&(e=(this.options.groups||[]).find(e=>e.id===t.group),s.set(t.group,{id:t.group,label:e?e.label:t.group,visible:!!i[t.group]&&i[t.group].visible,opacity:i[t.group]?i[t.group].opacity:1,overlays:[]}))}),this.options.overlays.forEach(e=>{e.group&&s.has(e.group)&&s.get(e.group).overlays.push(e.id)}),Array.from(s.values())}saveCurrentViewport(){var e;return!!this.map&&(e=this.map.getCenter(),this.stateService.setViewport({center:{lng:e.lng,lat:e.lat},zoom:this.map.getZoom(),bearing:this.map.getBearing(),pitch:this.map.getPitch()}),!0)}applySavedViewport(){var e;return!!this.map&&!(!(e=this.stateService.getViewport())||!e.center||(this.map.jumpTo({center:e.center,zoom:e.zoom||0,bearing:e.bearing||0,pitch:e.pitch||0}),0))}clearPersistedData(){return this.stateService.clearPersisted()}on(e,t){return this.eventEmitter.on(e,t),this}off(e,t){return this.eventEmitter.off(e,t),this}getCurrentState(){return this.stateService.getAll()}_setupPublicEventForwarding(){}_setupMapEventListeners(){var e;this.map&&(this._mapEventHandlers.set("moveend",e=()=>{clearTimeout(this._viewportSaveTimeout),this._viewportSaveTimeout=setTimeout(()=>{this.saveCurrentViewport()},500)}),this.map.on("moveend",e))}_cleanupMapEventListeners(){this.map&&(this._mapEventHandlers.forEach((e,t)=>{this.map.off(t,e)}),this._mapEventHandlers.clear(),this._viewportSaveTimeout)&&(clearTimeout(this._viewportSaveTimeout),this._viewportSaveTimeout=null)}_restoreMapState(){if(this.map){let t=this.stateService.getCurrentBase(),e=!1;t&&(this.options.baseStyles.find(e=>e.id===t)?(this.businessLogicService.setBaseLayer(t),e=!0):(i=this.options.baseStyles.find(e=>e.id===this.options.defaultBaseId)||this.options.baseStyles[0])&&(this.stateService.setBase(i.id),this.uiService.updateBaseUI()));var i=this.stateService.getViewport();i&&i.center&&setTimeout(()=>this.applySavedViewport(),e?400:100),e||(i=this.stateService.getOverlayStates(),Object.entries(i).forEach(([e,t])=>{t&&t.visible&&setTimeout(()=>{this.businessLogicService.activateOverlay(e,!1)},200)}))}}}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drecchia/maplibre-layerlibre",
3
- "version": "2.2.0",
3
+ "version": "2.2.1",
4
4
  "author": "Danilo T Recchia",
5
5
  "main": "dist/js/all.min.js",
6
6
  "files": [