web-mojo 2.1.1043 → 2.1.1087

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.
Files changed (119) hide show
  1. package/README.md +19 -16
  2. package/dist/admin.cjs.js +1 -1
  3. package/dist/admin.cjs.js.map +1 -1
  4. package/dist/admin.es.js +16 -14
  5. package/dist/admin.es.js.map +1 -1
  6. package/dist/auth.cjs.js +1 -1
  7. package/dist/auth.cjs.js.map +1 -1
  8. package/dist/auth.css +305 -266
  9. package/dist/auth.es.js +537 -2175
  10. package/dist/auth.es.js.map +1 -1
  11. package/dist/charts.cjs.js +1 -1
  12. package/dist/charts.cjs.js.map +1 -1
  13. package/dist/charts.css +319 -0
  14. package/dist/charts.es.js +555 -2
  15. package/dist/charts.es.js.map +1 -1
  16. package/dist/chunks/ChatView-BnC15uoD.js +2 -0
  17. package/dist/chunks/{ChatView-CGBaudUc.js.map → ChatView-BnC15uoD.js.map} +1 -1
  18. package/dist/chunks/{ChatView-DguKw-gR.js → ChatView-D-5lHZ5H.js} +7 -8
  19. package/dist/chunks/{ChatView-DguKw-gR.js.map → ChatView-D-5lHZ5H.js.map} +1 -1
  20. package/dist/chunks/{Collection-DD1_31eh.js → Collection-B64LJ92k.js} +2 -2
  21. package/dist/chunks/{Collection-DD1_31eh.js.map → Collection-B64LJ92k.js.map} +1 -1
  22. package/dist/chunks/{Collection-YRfGoT73.js → Collection-CsAk0UhA.js} +2 -2
  23. package/dist/chunks/{Collection-YRfGoT73.js.map → Collection-CsAk0UhA.js.map} +1 -1
  24. package/dist/chunks/ContextMenu-CfMAB33c.js +3 -0
  25. package/dist/chunks/ContextMenu-CfMAB33c.js.map +1 -0
  26. package/dist/chunks/{ContextMenu-B4_YS0G8.js → ContextMenu-Cvls3QC_.js} +350 -3
  27. package/dist/chunks/ContextMenu-Cvls3QC_.js.map +1 -0
  28. package/dist/chunks/DataView-DESqBxT-.js +2 -0
  29. package/dist/chunks/DataView-DESqBxT-.js.map +1 -0
  30. package/dist/chunks/{DataView-OUqaLmGB.js → DataView-QXyfcg2M.js} +3 -2
  31. package/dist/chunks/DataView-QXyfcg2M.js.map +1 -0
  32. package/dist/chunks/Dialog-BfXN-fFA.js +2 -0
  33. package/dist/chunks/Dialog-BfXN-fFA.js.map +1 -0
  34. package/dist/chunks/{Dialog-BiVgKzSK.js → Dialog-DHUsZ92-.js} +1375 -7
  35. package/dist/chunks/Dialog-DHUsZ92-.js.map +1 -0
  36. package/dist/chunks/{FormView-BClEkzmE.js → FormView-DGRmcKUG.js} +282 -123
  37. package/dist/chunks/FormView-DGRmcKUG.js.map +1 -0
  38. package/dist/chunks/FormView-KGvr68ju.js +3 -0
  39. package/dist/chunks/FormView-KGvr68ju.js.map +1 -0
  40. package/dist/chunks/{ListView-BMNhd5-B.js → ListView-BGJG4GYH.js} +3 -3
  41. package/dist/chunks/{ListView-BMNhd5-B.js.map → ListView-BGJG4GYH.js.map} +1 -1
  42. package/dist/chunks/{ListView-BRGiITfD.js → ListView-BpGEatee.js} +2 -2
  43. package/dist/chunks/{ListView-BRGiITfD.js.map → ListView-BpGEatee.js.map} +1 -1
  44. package/dist/chunks/{MetricsMiniChartWidget-CCroU6BZ.js → MetricsMiniChartWidget-BKbFGvXG.js} +4 -4
  45. package/dist/chunks/{MetricsMiniChartWidget-CCroU6BZ.js.map → MetricsMiniChartWidget-BKbFGvXG.js.map} +1 -1
  46. package/dist/chunks/MetricsMiniChartWidget-BNdGuSZV.js +2 -0
  47. package/dist/chunks/{MetricsMiniChartWidget-Esvv-lFp.js.map → MetricsMiniChartWidget-BNdGuSZV.js.map} +1 -1
  48. package/dist/chunks/{PDFViewer-NeL91Gon.js → PDFViewer-BIBNhuWY.js} +3 -3
  49. package/dist/chunks/{PDFViewer-NeL91Gon.js.map → PDFViewer-BIBNhuWY.js.map} +1 -1
  50. package/dist/chunks/{PDFViewer-D4uo3oiA.js → PDFViewer-nZAQQScE.js} +2 -2
  51. package/dist/chunks/{PDFViewer-D4uo3oiA.js.map → PDFViewer-nZAQQScE.js.map} +1 -1
  52. package/dist/chunks/Rest-BpDyhFfG.js +2 -0
  53. package/dist/chunks/Rest-BpDyhFfG.js.map +1 -0
  54. package/dist/chunks/{Rest-CS4jRCAs.js → Rest-DpbPbmra.js} +96 -5
  55. package/dist/chunks/Rest-DpbPbmra.js.map +1 -0
  56. package/dist/chunks/TokenManager-BWc_pRpg.js +2 -0
  57. package/dist/chunks/TokenManager-BWc_pRpg.js.map +1 -0
  58. package/dist/chunks/{TopNav-DC8oGpHp.js → TokenManager-N3e5wDu1.js} +369 -6
  59. package/dist/chunks/TokenManager-N3e5wDu1.js.map +1 -0
  60. package/dist/chunks/{WebSocketClient-D-5DJoMX.js → WebSocketClient-DghNkEyO.js} +2 -2
  61. package/dist/chunks/{WebSocketClient-D-5DJoMX.js.map → WebSocketClient-DghNkEyO.js.map} +1 -1
  62. package/dist/chunks/{WebSocketClient-DzcqAmho.js → WebSocketClient-E08hfP5f.js} +2 -2
  63. package/dist/chunks/{WebSocketClient-DzcqAmho.js.map → WebSocketClient-E08hfP5f.js.map} +1 -1
  64. package/dist/chunks/version-CKPqwcQJ.js +2 -0
  65. package/dist/chunks/version-CKPqwcQJ.js.map +1 -0
  66. package/dist/chunks/version-Dtwh-YkD.js +38 -0
  67. package/dist/chunks/version-Dtwh-YkD.js.map +1 -0
  68. package/dist/css/web-mojo.css +1 -17
  69. package/dist/docit.cjs.js +1 -1
  70. package/dist/docit.cjs.js.map +1 -1
  71. package/dist/docit.es.js +6 -8
  72. package/dist/docit.es.js.map +1 -1
  73. package/dist/index.cjs.js +1 -1
  74. package/dist/index.cjs.js.map +1 -1
  75. package/dist/index.es.js +34 -36
  76. package/dist/index.es.js.map +1 -1
  77. package/dist/lightbox.cjs.js +1 -1
  78. package/dist/lightbox.cjs.js.map +1 -1
  79. package/dist/lightbox.es.js +5 -4
  80. package/dist/lightbox.es.js.map +1 -1
  81. package/dist/map.cjs.js +1 -1
  82. package/dist/map.cjs.js.map +1 -1
  83. package/dist/map.es.js +82 -3
  84. package/dist/map.es.js.map +1 -1
  85. package/dist/timeline.cjs.js +1 -1
  86. package/dist/timeline.es.js +4 -4
  87. package/package.json +1 -1
  88. package/dist/chunks/ChatView-CGBaudUc.js +0 -2
  89. package/dist/chunks/ContextMenu-B4_YS0G8.js.map +0 -1
  90. package/dist/chunks/ContextMenu-DcLhcYMp.js +0 -3
  91. package/dist/chunks/ContextMenu-DcLhcYMp.js.map +0 -1
  92. package/dist/chunks/DataView-CdDY9ijM.js +0 -2
  93. package/dist/chunks/DataView-CdDY9ijM.js.map +0 -1
  94. package/dist/chunks/DataView-OUqaLmGB.js.map +0 -1
  95. package/dist/chunks/Dialog-BiVgKzSK.js.map +0 -1
  96. package/dist/chunks/Dialog-DmIPK_Bi.js +0 -2
  97. package/dist/chunks/Dialog-DmIPK_Bi.js.map +0 -1
  98. package/dist/chunks/FormView-BClEkzmE.js.map +0 -1
  99. package/dist/chunks/FormView-nulck4nL.js +0 -3
  100. package/dist/chunks/FormView-nulck4nL.js.map +0 -1
  101. package/dist/chunks/MetricsMiniChartWidget-Esvv-lFp.js +0 -2
  102. package/dist/chunks/Page-CvbwEoLv.js +0 -2
  103. package/dist/chunks/Page-CvbwEoLv.js.map +0 -1
  104. package/dist/chunks/Page-Deq4y2Kq.js +0 -351
  105. package/dist/chunks/Page-Deq4y2Kq.js.map +0 -1
  106. package/dist/chunks/Rest-BNYqGlnP.js +0 -2
  107. package/dist/chunks/Rest-BNYqGlnP.js.map +0 -1
  108. package/dist/chunks/Rest-CS4jRCAs.js.map +0 -1
  109. package/dist/chunks/TokenManager-CAZNcCMs.js +0 -366
  110. package/dist/chunks/TokenManager-CAZNcCMs.js.map +0 -1
  111. package/dist/chunks/TokenManager-CJBYcVqs.js +0 -2
  112. package/dist/chunks/TokenManager-CJBYcVqs.js.map +0 -1
  113. package/dist/chunks/TopNav-23B5R-dl.js +0 -2
  114. package/dist/chunks/TopNav-23B5R-dl.js.map +0 -1
  115. package/dist/chunks/TopNav-DC8oGpHp.js.map +0 -1
  116. package/dist/chunks/WebApp-C1vcdSuu.js +0 -1388
  117. package/dist/chunks/WebApp-C1vcdSuu.js.map +0 -1
  118. package/dist/chunks/WebApp-CpxtmTk0.js +0 -2
  119. package/dist/chunks/WebApp-CpxtmTk0.js.map +0 -1
package/dist/map.cjs.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/Rest-BNYqGlnP.js"),e=require("./chunks/Collection-DD1_31eh.js");class MapView extends t.View{constructor(t={}){super({className:"map-view",...t}),this.markers=t.markers||[],this.center=t.center||null,this.zoom=t.zoom||13,this.height=t.height||400,this.showZoomControl=!1!==t.showZoomControl,this.tileLayer=t.tileLayer||"osm",this.map=null,this.leafletMarkers=[],this.template='\n <div class="map-container">\n <div id="map-{{id}}" style="height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;"></div>\n </div>\n '}async onAfterRender(){await this.loadLeaflet(),await this.initializeMap()}async loadLeaflet(){if(window.L)return;const t=new Promise(t=>{const e=document.createElement("link");e.rel="stylesheet",e.href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css",e.onload=t,e.onerror=t,document.head.appendChild(e)}),e=new Promise((t,e)=>{const r=document.createElement("script");r.src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js",r.onload=t,r.onerror=e,document.head.appendChild(r)});await Promise.all([t,e])}getTileLayerUrl(){const t={osm:{url:"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",attribution:"© OpenStreetMap contributors",maxZoom:19},satellite:{url:"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",attribution:"© Esri",maxZoom:19},terrain:{url:"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",attribution:"© OpenTopoMap contributors",maxZoom:17},dark:{url:"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20},light:{url:"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20},watercolor:{url:"https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg",attribution:"© Stadia Maps © Stamen Design © OpenStreetMap contributors",maxZoom:16},bw:{url:"https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20},streets:{url:"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20}};return t[this.tileLayer]||t.osm}async initializeMap(){const t=this.element.querySelector(`#map-${this.id}`);if(!t||!window.L)return;let e=this.center;!e&&this.markers.length>0&&(e=[this.markers[0].lat,this.markers[0].lng]),e||(e=[0,0]),this.map=window.L.map(t,{center:e,zoom:this.zoom,zoomControl:this.showZoomControl});const r=this.getTileLayerUrl();window.L.tileLayer(r.url,{attribution:r.attribution,maxZoom:r.maxZoom}).addTo(this.map),this.addMarkers(this.markers),this.markers.length>1&&this.fitBounds(),setTimeout(()=>{this.map&&this.map.invalidateSize()},300)}addMarkers(t){this.map&&Array.isArray(t)&&t.forEach(t=>{const{lat:e,lng:r,popup:s,icon:o}=t;if(!e||!r)return;const a={};o&&(a.icon=window.L.icon(o));const i=window.L.marker([e,r],a).addTo(this.map);s&&i.bindPopup(s),this.leafletMarkers.push(i)})}fitBounds(){if(!this.map||0===this.leafletMarkers.length)return;const t=new window.L.featureGroup(this.leafletMarkers);this.map.fitBounds(t.getBounds().pad(.1))}updateMarkers(t){this.clearMarkers(),this.markers=t,this.addMarkers(t),t.length>1?this.fitBounds():1===t.length&&this.map.setView([t[0].lat,t[0].lng],this.zoom)}clearMarkers(){this.leafletMarkers.forEach(t=>{this.map.removeLayer(t)}),this.leafletMarkers=[]}setView(t,e,r=null){this.map&&this.map.setView([t,e],r||this.zoom)}setZoom(t){this.map&&this.map.setZoom(t)}async onBeforeDestroy(){this.map&&(this.map.remove(),this.map=null),await super.onBeforeDestroy()}}exports.View=t.View,exports.Collection=e.Collection,exports.Model=e.Model,exports.MapView=MapView;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/Rest-BpDyhFfG.js"),e=require("./chunks/Collection-B64LJ92k.js");class MapView extends t.View{constructor(t={}){super({className:"map-view",...t}),this.markers=t.markers||[],this.center=t.center||null,this.zoom=t.zoom||13,this.height=t.height||400,this.showZoomControl=!1!==t.showZoomControl,this.tileLayer=t.tileLayer||"osm",this.showLeafletBranding=!0===t.showLeafletBranding,this.showLayerControl=!0===t.showLayerControl,this.layerOptions=t.layerOptions||{osm:"OSM",satellite:"Satellite",terrain:"Terrain",dark:"Dark",light:"Light",watercolor:"Watercolor",bw:"B/W",streets:"Streets"},this.map=null,this.leafletMarkers=[],this._tileLayer=null,this.template='\n <div class="map-container">\n <div id="map-{{id}}" style="height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;"></div>\n </div>\n '}async onAfterRender(){await this.loadLeaflet(),await this.initializeMap()}async loadLeaflet(){if(window.L)return;const t=new Promise(t=>{const e=document.createElement("link");e.rel="stylesheet",e.href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css",e.onload=t,e.onerror=t,document.head.appendChild(e)}),e=new Promise((t,e)=>{const i=document.createElement("script");i.src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js",i.onload=t,i.onerror=e,document.head.appendChild(i)});await Promise.all([t,e])}getTileLayerUrl(){const t={osm:{url:"https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",attribution:"© OpenStreetMap contributors",maxZoom:19},satellite:{url:"https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",attribution:"© Esri",maxZoom:19},terrain:{url:"https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",attribution:"© OpenTopoMap contributors",maxZoom:17},dark:{url:"https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20},light:{url:"https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20},watercolor:{url:"https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg",attribution:"© Stadia Maps © Stamen Design © OpenStreetMap contributors",maxZoom:16},bw:{url:"https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20},streets:{url:"https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png",attribution:"© OpenStreetMap contributors © CARTO",maxZoom:20}};return t[this.tileLayer]||t.osm}async initializeMap(){const t=this.element.querySelector(`#map-${this.id}`);if(!t||!window.L)return;let e=this.center;if(!e&&this.markers.length>0&&(e=[this.markers[0].lat,this.markers[0].lng]),e||(e=[0,0]),this.map=window.L.map(t,{center:e,zoom:this.zoom,zoomControl:this.showZoomControl}),this.map&&this.map.attributionControl&&!1===this.showLeafletBranding)try{this.map.attributionControl.setPrefix("")}catch(s){}const i=this.getTileLayerUrl();if(this._tileLayer=window.L.tileLayer(i.url,{attribution:i.attribution,maxZoom:i.maxZoom}).addTo(this.map),this.showLayerControl){const e=t.parentElement||this.element.querySelector(".map-container");if(e){e.style.position=e.style.position||"relative";const t=document.createElement("select");t.className="form-select form-select-sm",t.style.position="absolute",t.style.top="8px",t.style.right="8px",t.style.zIndex="1000",t.style.maxWidth="180px",t.setAttribute("aria-label","Map tile layer"),Object.entries(this.layerOptions||{}).forEach(([e,i])=>{const s=document.createElement("option");s.value=e,s.textContent=i,e===this.tileLayer&&(s.selected=!0),t.appendChild(s)}),t.addEventListener("change",()=>this.setTileLayer(t.value)),e.appendChild(t)}}this.addMarkers(this.markers),this.markers.length>1&&this.fitBounds(),setTimeout(()=>{this.map&&this.map.invalidateSize()},300)}addMarkers(t){this.map&&Array.isArray(t)&&t.forEach(t=>{const{lat:e,lng:i,popup:s,icon:r}=t;if(!e||!i)return;const a={};r&&(a.icon=window.L.icon(r));const o=window.L.marker([e,i],a).addTo(this.map);s&&o.bindPopup(s),this.leafletMarkers.push(o)})}fitBounds(){if(!this.map||0===this.leafletMarkers.length)return;const t=new window.L.featureGroup(this.leafletMarkers);this.map.fitBounds(t.getBounds().pad(.1))}updateMarkers(t){this.clearMarkers(),this.markers=t,this.addMarkers(t),t.length>1?this.fitBounds():1===t.length&&this.map.setView([t[0].lat,t[0].lng],this.zoom)}clearMarkers(){this.leafletMarkers.forEach(t=>{this.map.removeLayer(t)}),this.leafletMarkers=[]}setView(t,e,i=null){this.map&&this.map.setView([t,e],i||this.zoom)}setZoom(t){this.map&&this.map.setZoom(t)}setTileLayer(t){if(!this.map)return;const e=this.tileLayer;this.tileLayer=t||this.tileLayer;const i=this.getTileLayerUrl();try{this._tileLayer&&this.map.removeLayer(this._tileLayer)}catch(s){}this._tileLayer=window.L.tileLayer(i.url,{attribution:i.attribution,maxZoom:i.maxZoom}).addTo(this.map),this.tileLayer=t||e,setTimeout(()=>{try{this.map.invalidateSize()}catch(s){}},150)}async onBeforeDestroy(){this.map&&(this.map.remove(),this.map=null),await super.onBeforeDestroy()}static async showAsDialog(t={}){const e=new MapView(t),i={title:"Map View",header:!0,body:e,size:"lg",centered:!1,...t.dialogOptions||{}};await e.init(),await e.getApp().showDialog(i)}}exports.View=t.View,exports.Collection=e.Collection,exports.Model=e.Model,exports.MapView=MapView;
2
2
  //# sourceMappingURL=map.cjs.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"map.cjs.js","sources":["../src/extensions/map/MapView.js"],"sourcesContent":["/**\n * MapView - Interactive map component using Leaflet\n * \n * Features:\n * - Display single or multiple markers\n * - Auto-zoom to fit markers\n * - Customizable marker popups\n * - Support for different tile layers\n * \n * @example\n * const mapView = new MapView({\n * markers: [\n * { lat: 37.422, lng: -122.084, popup: 'Mountain View, CA' }\n * ],\n * zoom: 10,\n * height: 400\n * });\n */\n\nimport View from '@core/View.js';\n\nclass MapView extends View {\n constructor(options = {}) {\n super({\n className: 'map-view',\n ...options\n });\n\n this.markers = options.markers || [];\n this.center = options.center || null;\n this.zoom = options.zoom || 13;\n this.height = options.height || 400;\n this.showZoomControl = options.showZoomControl !== false;\n this.tileLayer = options.tileLayer || 'osm'; // 'osm', 'satellite', 'terrain'\n \n this.map = null;\n this.leafletMarkers = [];\n\n this.template = `\n <div class=\"map-container\">\n <div id=\"map-{{id}}\" style=\"height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;\"></div>\n </div>\n `;\n }\n\n async onAfterRender() {\n await this.loadLeaflet();\n await this.initializeMap();\n }\n\n async loadLeaflet() {\n // Check if Leaflet is already loaded\n if (window.L) return;\n\n // Load Leaflet CSS and wait for it\n const cssLoaded = new Promise((resolve) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';\n link.onload = resolve;\n link.onerror = resolve; // Continue even if CSS fails\n document.head.appendChild(link);\n });\n\n // Load Leaflet JS\n const jsLoaded = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';\n script.onload = resolve;\n script.onerror = reject;\n document.head.appendChild(script);\n });\n\n // Wait for both CSS and JS to load\n await Promise.all([cssLoaded, jsLoaded]);\n }\n\n getTileLayerUrl() {\n const tileLayers = {\n // Standard street maps\n osm: {\n url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution: '© OpenStreetMap contributors',\n maxZoom: 19\n },\n \n // Satellite imagery\n satellite: {\n url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n attribution: '© Esri',\n maxZoom: 19\n },\n \n // Terrain and topographic\n terrain: {\n url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',\n attribution: '© OpenTopoMap contributors',\n maxZoom: 17\n },\n \n // Dark mode styles\n dark: {\n url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n \n // Light/minimal styles\n light: {\n url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n \n // Watercolor artistic style\n watercolor: {\n url: 'https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg',\n attribution: '© Stadia Maps © Stamen Design © OpenStreetMap contributors',\n maxZoom: 16\n },\n \n // Black and white\n bw: {\n url: 'https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n \n // Streets with labels\n streets: {\n url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n }\n };\n\n return tileLayers[this.tileLayer] || tileLayers.osm;\n }\n\n async initializeMap() {\n const mapElement = this.element.querySelector(`#map-${this.id}`);\n if (!mapElement || !window.L) return;\n\n // Determine map center\n let mapCenter = this.center;\n if (!mapCenter && this.markers.length > 0) {\n // Use first marker as center\n mapCenter = [this.markers[0].lat, this.markers[0].lng];\n }\n if (!mapCenter) {\n // Default to world view\n mapCenter = [0, 0];\n }\n\n // Create map\n this.map = window.L.map(mapElement, {\n center: mapCenter,\n zoom: this.zoom,\n zoomControl: this.showZoomControl\n });\n\n // Add tile layer\n const tileConfig = this.getTileLayerUrl();\n window.L.tileLayer(tileConfig.url, {\n attribution: tileConfig.attribution,\n maxZoom: tileConfig.maxZoom\n }).addTo(this.map);\n\n // Add markers\n this.addMarkers(this.markers);\n\n // Auto-fit bounds if multiple markers\n if (this.markers.length > 1) {\n this.fitBounds();\n }\n\n // Fix tile rendering issues by invalidating size after a delay\n // This ensures the container has proper dimensions and CSS is applied\n setTimeout(() => {\n if (this.map) {\n this.map.invalidateSize();\n }\n }, 300);\n }\n\n addMarkers(markers) {\n if (!this.map || !Array.isArray(markers)) return;\n\n markers.forEach(markerData => {\n const { lat, lng, popup, icon } = markerData;\n \n if (!lat || !lng) return;\n\n const markerOptions = {};\n \n // Custom icon if provided\n if (icon) {\n markerOptions.icon = window.L.icon(icon);\n }\n\n const marker = window.L.marker([lat, lng], markerOptions).addTo(this.map);\n\n // Add popup if provided\n if (popup) {\n marker.bindPopup(popup);\n }\n\n this.leafletMarkers.push(marker);\n });\n }\n\n fitBounds() {\n if (!this.map || this.leafletMarkers.length === 0) return;\n\n const group = new window.L.featureGroup(this.leafletMarkers);\n this.map.fitBounds(group.getBounds().pad(0.1));\n }\n\n updateMarkers(newMarkers) {\n // Clear existing markers\n this.clearMarkers();\n \n // Add new markers\n this.markers = newMarkers;\n this.addMarkers(newMarkers);\n \n // Fit bounds if multiple markers\n if (newMarkers.length > 1) {\n this.fitBounds();\n } else if (newMarkers.length === 1) {\n this.map.setView([newMarkers[0].lat, newMarkers[0].lng], this.zoom);\n }\n }\n\n clearMarkers() {\n this.leafletMarkers.forEach(marker => {\n this.map.removeLayer(marker);\n });\n this.leafletMarkers = [];\n }\n\n setView(lat, lng, zoom = null) {\n if (!this.map) return;\n this.map.setView([lat, lng], zoom || this.zoom);\n }\n\n setZoom(zoom) {\n if (!this.map) return;\n this.map.setZoom(zoom);\n }\n\n async onBeforeDestroy() {\n if (this.map) {\n this.map.remove();\n this.map = null;\n }\n await super.onBeforeDestroy();\n }\n}\n\nexport default MapView;\n"],"names":["MapView","View","constructor","options","super","className","this","markers","center","zoom","height","showZoomControl","tileLayer","map","leafletMarkers","template","onAfterRender","loadLeaflet","initializeMap","window","L","cssLoaded","Promise","resolve","link","document","createElement","rel","href","onload","onerror","head","appendChild","jsLoaded","reject","script","src","all","getTileLayerUrl","tileLayers","osm","url","attribution","maxZoom","satellite","terrain","dark","light","watercolor","bw","streets","mapElement","element","querySelector","id","mapCenter","length","lat","lng","zoomControl","tileConfig","addTo","addMarkers","fitBounds","setTimeout","invalidateSize","Array","isArray","forEach","markerData","popup","icon","markerOptions","marker","bindPopup","push","group","featureGroup","getBounds","pad","updateMarkers","newMarkers","clearMarkers","setView","removeLayer","setZoom","onBeforeDestroy","remove"],"mappings":"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"}
1
+ {"version":3,"file":"map.cjs.js","sources":["../src/extensions/map/MapView.js"],"sourcesContent":["/**\n * MapView - Interactive map component using Leaflet\n *\n * Features:\n * - Display single or multiple markers\n * - Auto-zoom to fit markers\n * - Customizable marker popups\n * - Support for different tile layers\n *\n * @example\n * const mapView = new MapView({\n * markers: [\n * { lat: 37.422, lng: -122.084, popup: 'Mountain View, CA' }\n * ],\n * zoom: 10,\n * height: 400\n * });\n */\n\nimport View from '@core/View.js';\n\nclass MapView extends View {\n constructor(options = {}) {\n super({\n className: 'map-view',\n ...options\n });\n\n this.markers = options.markers || [];\n this.center = options.center || null;\n this.zoom = options.zoom || 13;\n this.height = options.height || 400;\n this.showZoomControl = options.showZoomControl !== false;\n this.tileLayer = options.tileLayer || 'osm'; // 'osm', 'satellite', 'terrain'\n this.showLeafletBranding = options.showLeafletBranding === true;\n this.showLayerControl = options.showLayerControl === true;\n this.layerOptions = options.layerOptions || {\n osm: 'OSM',\n satellite: 'Satellite',\n terrain: 'Terrain',\n dark: 'Dark',\n light: 'Light',\n watercolor: 'Watercolor',\n bw: 'B/W',\n streets: 'Streets'\n };\n\n this.map = null;\n this.leafletMarkers = [];\n this._tileLayer = null;\n\n this.template = `\n <div class=\"map-container\">\n <div id=\"map-{{id}}\" style=\"height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;\"></div>\n </div>\n `;\n }\n\n async onAfterRender() {\n await this.loadLeaflet();\n await this.initializeMap();\n }\n\n async loadLeaflet() {\n // Check if Leaflet is already loaded\n if (window.L) return;\n\n // Load Leaflet CSS and wait for it\n const cssLoaded = new Promise((resolve) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';\n link.onload = resolve;\n link.onerror = resolve; // Continue even if CSS fails\n document.head.appendChild(link);\n });\n\n // Load Leaflet JS\n const jsLoaded = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';\n script.onload = resolve;\n script.onerror = reject;\n document.head.appendChild(script);\n });\n\n // Wait for both CSS and JS to load\n await Promise.all([cssLoaded, jsLoaded]);\n }\n\n getTileLayerUrl() {\n const tileLayers = {\n // Standard street maps\n osm: {\n url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution: '© OpenStreetMap contributors',\n maxZoom: 19\n },\n\n // Satellite imagery\n satellite: {\n url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n attribution: '© Esri',\n maxZoom: 19\n },\n\n // Terrain and topographic\n terrain: {\n url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',\n attribution: '© OpenTopoMap contributors',\n maxZoom: 17\n },\n\n // Dark mode styles\n dark: {\n url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n\n // Light/minimal styles\n light: {\n url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n\n // Watercolor artistic style\n watercolor: {\n url: 'https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg',\n attribution: '© Stadia Maps © Stamen Design © OpenStreetMap contributors',\n maxZoom: 16\n },\n\n // Black and white\n bw: {\n url: 'https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n\n // Streets with labels\n streets: {\n url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n }\n };\n\n return tileLayers[this.tileLayer] || tileLayers.osm;\n }\n\n async initializeMap() {\n const mapElement = this.element.querySelector(`#map-${this.id}`);\n if (!mapElement || !window.L) return;\n\n // Determine map center\n let mapCenter = this.center;\n if (!mapCenter && this.markers.length > 0) {\n // Use first marker as center\n mapCenter = [this.markers[0].lat, this.markers[0].lng];\n }\n if (!mapCenter) {\n // Default to world view\n mapCenter = [0, 0];\n }\n\n // Create map\n this.map = window.L.map(mapElement, {\n center: mapCenter,\n zoom: this.zoom,\n zoomControl: this.showZoomControl\n });\n // Optionally hide Leaflet branding/prefix (removes Leaflet link/flag in attribution control)\n if (this.map && this.map.attributionControl && this.showLeafletBranding === false) {\n try { this.map.attributionControl.setPrefix(''); } catch (e) {}\n }\n\n // Add tile layer\n const tileConfig = this.getTileLayerUrl();\n this._tileLayer = window.L.tileLayer(tileConfig.url, {\n attribution: tileConfig.attribution,\n maxZoom: tileConfig.maxZoom\n }).addTo(this.map);\n\n // Optional built-in tile layer selector UI\n if (this.showLayerControl) {\n const container = mapElement.parentElement || this.element.querySelector('.map-container');\n if (container) {\n container.style.position = container.style.position || 'relative';\n const selector = document.createElement('select');\n selector.className = 'form-select form-select-sm';\n selector.style.position = 'absolute';\n selector.style.top = '8px';\n selector.style.right = '8px';\n selector.style.zIndex = '1000';\n selector.style.maxWidth = '180px';\n selector.setAttribute('aria-label', 'Map tile layer');\n\n // Populate options\n Object.entries(this.layerOptions || {}).forEach(([key, label]) => {\n const opt = document.createElement('option');\n opt.value = key;\n opt.textContent = label;\n if (key === this.tileLayer) opt.selected = true;\n selector.appendChild(opt);\n });\n\n selector.addEventListener('change', () => this.setTileLayer(selector.value));\n container.appendChild(selector);\n }\n }\n\n // Add markers\n this.addMarkers(this.markers);\n\n // Auto-fit bounds if multiple markers\n if (this.markers.length > 1) {\n this.fitBounds();\n }\n\n // Fix tile rendering issues by invalidating size after a delay\n // This ensures the container has proper dimensions and CSS is applied\n setTimeout(() => {\n if (this.map) {\n this.map.invalidateSize();\n }\n }, 300);\n }\n\n addMarkers(markers) {\n if (!this.map || !Array.isArray(markers)) return;\n\n markers.forEach(markerData => {\n const { lat, lng, popup, icon } = markerData;\n\n if (!lat || !lng) return;\n\n const markerOptions = {};\n\n // Custom icon if provided\n if (icon) {\n markerOptions.icon = window.L.icon(icon);\n }\n\n const marker = window.L.marker([lat, lng], markerOptions).addTo(this.map);\n\n // Add popup if provided\n if (popup) {\n marker.bindPopup(popup);\n }\n\n this.leafletMarkers.push(marker);\n });\n }\n\n fitBounds() {\n if (!this.map || this.leafletMarkers.length === 0) return;\n\n const group = new window.L.featureGroup(this.leafletMarkers);\n this.map.fitBounds(group.getBounds().pad(0.1));\n }\n\n updateMarkers(newMarkers) {\n // Clear existing markers\n this.clearMarkers();\n\n // Add new markers\n this.markers = newMarkers;\n this.addMarkers(newMarkers);\n\n // Fit bounds if multiple markers\n if (newMarkers.length > 1) {\n this.fitBounds();\n } else if (newMarkers.length === 1) {\n this.map.setView([newMarkers[0].lat, newMarkers[0].lng], this.zoom);\n }\n }\n\n clearMarkers() {\n this.leafletMarkers.forEach(marker => {\n this.map.removeLayer(marker);\n });\n this.leafletMarkers = [];\n }\n\n setView(lat, lng, zoom = null) {\n if (!this.map) return;\n this.map.setView([lat, lng], zoom || this.zoom);\n }\n\n setZoom(zoom) {\n if (!this.map) return;\n this.map.setZoom(zoom);\n }\n\n setTileLayer(key) {\n if (!this.map) return;\n // Resolve tile layer config using the same logic as getTileLayerUrl\n const original = this.tileLayer;\n this.tileLayer = key || this.tileLayer;\n const tileConfig = this.getTileLayerUrl();\n try {\n if (this._tileLayer) {\n this.map.removeLayer(this._tileLayer);\n }\n } catch (e) {\n // ignore if layer already removed\n }\n this._tileLayer = window.L.tileLayer(tileConfig.url, {\n attribution: tileConfig.attribution,\n maxZoom: tileConfig.maxZoom\n }).addTo(this.map);\n // Keep property in sync\n this.tileLayer = key || original;\n\n // Nudge map to ensure proper redraw\n setTimeout(() => {\n try { this.map.invalidateSize(); } catch (e) {}\n }, 150);\n }\n\n async onBeforeDestroy() {\n if (this.map) {\n this.map.remove();\n this.map = null;\n }\n await super.onBeforeDestroy();\n }\n\n static async showAsDialog(options = {}) {\n const view = new MapView(options);\n const dopts = options.dialogOptions || {};\n const dialogOptions = {\n title: \"Map View\",\n header: true,\n body: view,\n size: 'lg',\n centered: false,\n ...dopts\n }\n await view.init();\n await view.getApp().showDialog(dialogOptions);\n }\n}\n\nexport default MapView;\n"],"names":["MapView","View","constructor","options","super","className","this","markers","center","zoom","height","showZoomControl","tileLayer","showLeafletBranding","showLayerControl","layerOptions","osm","satellite","terrain","dark","light","watercolor","bw","streets","map","leafletMarkers","_tileLayer","template","onAfterRender","loadLeaflet","initializeMap","window","L","cssLoaded","Promise","resolve","link","document","createElement","rel","href","onload","onerror","head","appendChild","jsLoaded","reject","script","src","all","getTileLayerUrl","tileLayers","url","attribution","maxZoom","mapElement","element","querySelector","id","mapCenter","length","lat","lng","zoomControl","attributionControl","setPrefix","e","tileConfig","addTo","container","parentElement","style","position","selector","top","right","zIndex","maxWidth","setAttribute","Object","entries","forEach","key","label","opt","value","textContent","selected","addEventListener","setTileLayer","addMarkers","fitBounds","setTimeout","invalidateSize","Array","isArray","markerData","popup","icon","markerOptions","marker","bindPopup","push","group","featureGroup","getBounds","pad","updateMarkers","newMarkers","clearMarkers","setView","removeLayer","setZoom","original","onBeforeDestroy","remove","showAsDialog","view","dialogOptions","title","header","body","size","centered","init","getApp","showDialog"],"mappings":"0KAqBA,MAAMA,gBAAgBC,EAAAA,KAClB,WAAAC,CAAYC,EAAU,IAClBC,MAAM,CACFC,UAAW,cACRF,IAGPG,KAAKC,QAAUJ,EAAQI,SAAW,GAClCD,KAAKE,OAASL,EAAQK,QAAU,KAChCF,KAAKG,KAAON,EAAQM,MAAQ,GAC5BH,KAAKI,OAASP,EAAQO,QAAU,IAChCJ,KAAKK,iBAA8C,IAA5BR,EAAQQ,gBAC/BL,KAAKM,UAAYT,EAAQS,WAAa,MACtCN,KAAKO,qBAAsD,IAAhCV,EAAQU,oBACnCP,KAAKQ,kBAAgD,IAA7BX,EAAQW,iBAChCR,KAAKS,aAAeZ,EAAQY,cAAgB,CACxCC,IAAK,MACLC,UAAW,YACXC,QAAS,UACTC,KAAM,OACNC,MAAO,QACPC,WAAY,aACZC,GAAI,MACJC,QAAS,WAGbjB,KAAKkB,IAAM,KACXlB,KAAKmB,eAAiB,GACtBnB,KAAKoB,WAAa,KAElBpB,KAAKqB,SAAW,qNAKpB,CAEA,mBAAMC,SACItB,KAAKuB,oBACLvB,KAAKwB,eACf,CAEA,iBAAMD,GAEF,GAAIE,OAAOC,EAAG,OAGd,MAAMC,EAAY,IAAIC,QAASC,IAC3B,MAAMC,EAAOC,SAASC,cAAc,QACpCF,EAAKG,IAAM,aACXH,EAAKI,KAAO,mDACZJ,EAAKK,OAASN,EACdC,EAAKM,QAAUP,EACfE,SAASM,KAAKC,YAAYR,KAIxBS,EAAW,IAAIX,QAAQ,CAACC,EAASW,KACnC,MAAMC,EAASV,SAASC,cAAc,UACtCS,EAAOC,IAAM,kDACbD,EAAON,OAASN,EAChBY,EAAOL,QAAUI,EACjBT,SAASM,KAAKC,YAAYG,WAIxBb,QAAQe,IAAI,CAAChB,EAAWY,GAClC,CAEA,eAAAK,GACI,MAAMC,EAAa,CAEfnC,IAAK,CACDoC,IAAK,qDACLC,YAAa,+BACbC,QAAS,IAIbrC,UAAW,CACPmC,IAAK,gGACLC,YAAa,SACbC,QAAS,IAIbpC,QAAS,CACLkC,IAAK,mDACLC,YAAa,6BACbC,QAAS,IAIbnC,KAAM,CACFiC,IAAK,gEACLC,YAAa,uCACbC,QAAS,IAIblC,MAAO,CACHgC,IAAK,iEACLC,YAAa,uCACbC,QAAS,IAIbjC,WAAY,CACR+B,IAAK,uEACLC,YAAa,6DACbC,QAAS,IAIbhC,GAAI,CACA8B,IAAK,sEACLC,YAAa,uCACbC,QAAS,IAIb/B,QAAS,CACL6B,IAAK,2EACLC,YAAa,uCACbC,QAAS,KAIjB,OAAOH,EAAW7C,KAAKM,YAAcuC,EAAWnC,GACpD,CAEA,mBAAMc,GACF,MAAMyB,EAAajD,KAAKkD,QAAQC,cAAc,QAAQnD,KAAKoD,MAC3D,IAAKH,IAAexB,OAAOC,EAAG,OAG9B,IAAI2B,EAAYrD,KAAKE,OAiBrB,IAhBKmD,GAAarD,KAAKC,QAAQqD,OAAS,IAEpCD,EAAY,CAACrD,KAAKC,QAAQ,GAAGsD,IAAKvD,KAAKC,QAAQ,GAAGuD,MAEjDH,IAEDA,EAAY,CAAC,EAAG,IAIpBrD,KAAKkB,IAAMO,OAAOC,EAAER,IAAI+B,EAAY,CAChC/C,OAAQmD,EACRlD,KAAMH,KAAKG,KACXsD,YAAazD,KAAKK,kBAGlBL,KAAKkB,KAAOlB,KAAKkB,IAAIwC,qBAAmD,IAA7B1D,KAAKO,oBAChD,IAAMP,KAAKkB,IAAIwC,mBAAmBC,UAAU,GAAK,OAASC,GAAI,CAIlE,MAAMC,EAAa7D,KAAK4C,kBAOxB,GANA5C,KAAKoB,WAAaK,OAAOC,EAAEpB,UAAUuD,EAAWf,IAAK,CACjDC,YAAac,EAAWd,YACxBC,QAASa,EAAWb,UACrBc,MAAM9D,KAAKkB,KAGVlB,KAAKQ,iBAAkB,CACvB,MAAMuD,EAAYd,EAAWe,eAAiBhE,KAAKkD,QAAQC,cAAc,kBACzE,GAAIY,EAAW,CACXA,EAAUE,MAAMC,SAAWH,EAAUE,MAAMC,UAAY,WACvD,MAAMC,EAAWpC,SAASC,cAAc,UACxCmC,EAASpE,UAAY,6BACrBoE,EAASF,MAAMC,SAAW,WAC1BC,EAASF,MAAMG,IAAM,MACrBD,EAASF,MAAMI,MAAQ,MACvBF,EAASF,MAAMK,OAAS,OACxBH,EAASF,MAAMM,SAAW,QAC1BJ,EAASK,aAAa,aAAc,kBAGpCC,OAAOC,QAAQ1E,KAAKS,cAAgB,CAAA,GAAIkE,QAAQ,EAAEC,EAAKC,MACnD,MAAMC,EAAM/C,SAASC,cAAc,UACnC8C,EAAIC,MAAQH,EACZE,EAAIE,YAAcH,EACdD,IAAQ5E,KAAKM,YAAWwE,EAAIG,UAAW,GAC3Cd,EAAS7B,YAAYwC,KAGzBX,EAASe,iBAAiB,SAAU,IAAMlF,KAAKmF,aAAahB,EAASY,QACrEhB,EAAUzB,YAAY6B,EAC1B,CACJ,CAGAnE,KAAKoF,WAAWpF,KAAKC,SAGjBD,KAAKC,QAAQqD,OAAS,GACtBtD,KAAKqF,YAKTC,WAAW,KACHtF,KAAKkB,KACLlB,KAAKkB,IAAIqE,kBAEd,IACP,CAEA,UAAAH,CAAWnF,GACFD,KAAKkB,KAAQsE,MAAMC,QAAQxF,IAEhCA,EAAQ0E,QAAQe,IACZ,MAAMnC,IAAEA,EAAAC,IAAKA,EAAAmC,MAAKA,EAAAC,KAAOA,GAASF,EAElC,IAAKnC,IAAQC,EAAK,OAElB,MAAMqC,EAAgB,CAAA,EAGlBD,IACAC,EAAcD,KAAOnE,OAAOC,EAAEkE,KAAKA,IAGvC,MAAME,EAASrE,OAAOC,EAAEoE,OAAO,CAACvC,EAAKC,GAAMqC,GAAe/B,MAAM9D,KAAKkB,KAGjEyE,GACAG,EAAOC,UAAUJ,GAGrB3F,KAAKmB,eAAe6E,KAAKF,IAEjC,CAEA,SAAAT,GACI,IAAKrF,KAAKkB,KAAsC,IAA/BlB,KAAKmB,eAAemC,OAAc,OAEnD,MAAM2C,EAAQ,IAAIxE,OAAOC,EAAEwE,aAAalG,KAAKmB,gBAC7CnB,KAAKkB,IAAImE,UAAUY,EAAME,YAAYC,IAAI,IAC7C,CAEA,aAAAC,CAAcC,GAEVtG,KAAKuG,eAGLvG,KAAKC,QAAUqG,EACftG,KAAKoF,WAAWkB,GAGZA,EAAWhD,OAAS,EACpBtD,KAAKqF,YACwB,IAAtBiB,EAAWhD,QAClBtD,KAAKkB,IAAIsF,QAAQ,CAACF,EAAW,GAAG/C,IAAK+C,EAAW,GAAG9C,KAAMxD,KAAKG,KAEtE,CAEA,YAAAoG,GACIvG,KAAKmB,eAAewD,QAAQmB,IACxB9F,KAAKkB,IAAIuF,YAAYX,KAEzB9F,KAAKmB,eAAiB,EAC1B,CAEA,OAAAqF,CAAQjD,EAAKC,EAAKrD,EAAO,MAChBH,KAAKkB,KACVlB,KAAKkB,IAAIsF,QAAQ,CAACjD,EAAKC,GAAMrD,GAAQH,KAAKG,KAC9C,CAEA,OAAAuG,CAAQvG,GACCH,KAAKkB,KACVlB,KAAKkB,IAAIwF,QAAQvG,EACrB,CAEA,YAAAgF,CAAaP,GACT,IAAK5E,KAAKkB,IAAK,OAEf,MAAMyF,EAAW3G,KAAKM,UACtBN,KAAKM,UAAYsE,GAAO5E,KAAKM,UAC7B,MAAMuD,EAAa7D,KAAK4C,kBACxB,IACQ5C,KAAKoB,YACLpB,KAAKkB,IAAIuF,YAAYzG,KAAKoB,WAElC,OAASwC,GAET,CACA5D,KAAKoB,WAAaK,OAAOC,EAAEpB,UAAUuD,EAAWf,IAAK,CACjDC,YAAac,EAAWd,YACxBC,QAASa,EAAWb,UACrBc,MAAM9D,KAAKkB,KAEdlB,KAAKM,UAAYsE,GAAO+B,EAGxBrB,WAAW,KACP,IAAMtF,KAAKkB,IAAIqE,gBAAkB,OAAS3B,GAAI,GAC/C,IACP,CAEA,qBAAMgD,GACE5G,KAAKkB,MACLlB,KAAKkB,IAAI2F,SACT7G,KAAKkB,IAAM,YAETpB,MAAM8G,iBAChB,CAEA,yBAAaE,CAAajH,EAAU,IAChC,MAAMkH,EAAO,IAAIrH,QAAQG,GAEnBmH,EAAgB,CAClBC,MAAO,WACPC,QAAQ,EACRC,KAAMJ,EACNK,KAAM,KACNC,UAAU,KANAxH,EAAQmH,eAAiB,CAAA,SASjCD,EAAKO,aACLP,EAAKQ,SAASC,WAAWR,EACnC"}
package/dist/map.es.js CHANGED
@@ -1,5 +1,5 @@
1
- import { V as View } from "./chunks/Rest-CS4jRCAs.js";
2
- import { C, M } from "./chunks/Collection-YRfGoT73.js";
1
+ import { V as View } from "./chunks/Rest-DpbPbmra.js";
2
+ import { C, M } from "./chunks/Collection-CsAk0UhA.js";
3
3
  class MapView extends View {
4
4
  constructor(options = {}) {
5
5
  super({
@@ -12,8 +12,21 @@ class MapView extends View {
12
12
  this.height = options.height || 400;
13
13
  this.showZoomControl = options.showZoomControl !== false;
14
14
  this.tileLayer = options.tileLayer || "osm";
15
+ this.showLeafletBranding = options.showLeafletBranding === true;
16
+ this.showLayerControl = options.showLayerControl === true;
17
+ this.layerOptions = options.layerOptions || {
18
+ osm: "OSM",
19
+ satellite: "Satellite",
20
+ terrain: "Terrain",
21
+ dark: "Dark",
22
+ light: "Light",
23
+ watercolor: "Watercolor",
24
+ bw: "B/W",
25
+ streets: "Streets"
26
+ };
15
27
  this.map = null;
16
28
  this.leafletMarkers = [];
29
+ this._tileLayer = null;
17
30
  this.template = `
18
31
  <div class="map-container">
19
32
  <div id="map-{{id}}" style="height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;"></div>
@@ -111,11 +124,40 @@ class MapView extends View {
111
124
  zoom: this.zoom,
112
125
  zoomControl: this.showZoomControl
113
126
  });
127
+ if (this.map && this.map.attributionControl && this.showLeafletBranding === false) {
128
+ try {
129
+ this.map.attributionControl.setPrefix("");
130
+ } catch (e) {
131
+ }
132
+ }
114
133
  const tileConfig = this.getTileLayerUrl();
115
- window.L.tileLayer(tileConfig.url, {
134
+ this._tileLayer = window.L.tileLayer(tileConfig.url, {
116
135
  attribution: tileConfig.attribution,
117
136
  maxZoom: tileConfig.maxZoom
118
137
  }).addTo(this.map);
138
+ if (this.showLayerControl) {
139
+ const container = mapElement.parentElement || this.element.querySelector(".map-container");
140
+ if (container) {
141
+ container.style.position = container.style.position || "relative";
142
+ const selector = document.createElement("select");
143
+ selector.className = "form-select form-select-sm";
144
+ selector.style.position = "absolute";
145
+ selector.style.top = "8px";
146
+ selector.style.right = "8px";
147
+ selector.style.zIndex = "1000";
148
+ selector.style.maxWidth = "180px";
149
+ selector.setAttribute("aria-label", "Map tile layer");
150
+ Object.entries(this.layerOptions || {}).forEach(([key, label]) => {
151
+ const opt = document.createElement("option");
152
+ opt.value = key;
153
+ opt.textContent = label;
154
+ if (key === this.tileLayer) opt.selected = true;
155
+ selector.appendChild(opt);
156
+ });
157
+ selector.addEventListener("change", () => this.setTileLayer(selector.value));
158
+ container.appendChild(selector);
159
+ }
160
+ }
119
161
  this.addMarkers(this.markers);
120
162
  if (this.markers.length > 1) {
121
163
  this.fitBounds();
@@ -171,6 +213,29 @@ class MapView extends View {
171
213
  if (!this.map) return;
172
214
  this.map.setZoom(zoom);
173
215
  }
216
+ setTileLayer(key) {
217
+ if (!this.map) return;
218
+ const original = this.tileLayer;
219
+ this.tileLayer = key || this.tileLayer;
220
+ const tileConfig = this.getTileLayerUrl();
221
+ try {
222
+ if (this._tileLayer) {
223
+ this.map.removeLayer(this._tileLayer);
224
+ }
225
+ } catch (e) {
226
+ }
227
+ this._tileLayer = window.L.tileLayer(tileConfig.url, {
228
+ attribution: tileConfig.attribution,
229
+ maxZoom: tileConfig.maxZoom
230
+ }).addTo(this.map);
231
+ this.tileLayer = key || original;
232
+ setTimeout(() => {
233
+ try {
234
+ this.map.invalidateSize();
235
+ } catch (e) {
236
+ }
237
+ }, 150);
238
+ }
174
239
  async onBeforeDestroy() {
175
240
  if (this.map) {
176
241
  this.map.remove();
@@ -178,6 +243,20 @@ class MapView extends View {
178
243
  }
179
244
  await super.onBeforeDestroy();
180
245
  }
246
+ static async showAsDialog(options = {}) {
247
+ const view = new MapView(options);
248
+ const dopts = options.dialogOptions || {};
249
+ const dialogOptions = {
250
+ title: "Map View",
251
+ header: true,
252
+ body: view,
253
+ size: "lg",
254
+ centered: false,
255
+ ...dopts
256
+ };
257
+ await view.init();
258
+ await view.getApp().showDialog(dialogOptions);
259
+ }
181
260
  }
182
261
  export {
183
262
  C as Collection,
@@ -1 +1 @@
1
- {"version":3,"file":"map.es.js","sources":["../src/extensions/map/MapView.js"],"sourcesContent":["/**\n * MapView - Interactive map component using Leaflet\n * \n * Features:\n * - Display single or multiple markers\n * - Auto-zoom to fit markers\n * - Customizable marker popups\n * - Support for different tile layers\n * \n * @example\n * const mapView = new MapView({\n * markers: [\n * { lat: 37.422, lng: -122.084, popup: 'Mountain View, CA' }\n * ],\n * zoom: 10,\n * height: 400\n * });\n */\n\nimport View from '@core/View.js';\n\nclass MapView extends View {\n constructor(options = {}) {\n super({\n className: 'map-view',\n ...options\n });\n\n this.markers = options.markers || [];\n this.center = options.center || null;\n this.zoom = options.zoom || 13;\n this.height = options.height || 400;\n this.showZoomControl = options.showZoomControl !== false;\n this.tileLayer = options.tileLayer || 'osm'; // 'osm', 'satellite', 'terrain'\n \n this.map = null;\n this.leafletMarkers = [];\n\n this.template = `\n <div class=\"map-container\">\n <div id=\"map-{{id}}\" style=\"height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;\"></div>\n </div>\n `;\n }\n\n async onAfterRender() {\n await this.loadLeaflet();\n await this.initializeMap();\n }\n\n async loadLeaflet() {\n // Check if Leaflet is already loaded\n if (window.L) return;\n\n // Load Leaflet CSS and wait for it\n const cssLoaded = new Promise((resolve) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';\n link.onload = resolve;\n link.onerror = resolve; // Continue even if CSS fails\n document.head.appendChild(link);\n });\n\n // Load Leaflet JS\n const jsLoaded = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';\n script.onload = resolve;\n script.onerror = reject;\n document.head.appendChild(script);\n });\n\n // Wait for both CSS and JS to load\n await Promise.all([cssLoaded, jsLoaded]);\n }\n\n getTileLayerUrl() {\n const tileLayers = {\n // Standard street maps\n osm: {\n url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution: '© OpenStreetMap contributors',\n maxZoom: 19\n },\n \n // Satellite imagery\n satellite: {\n url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n attribution: '© Esri',\n maxZoom: 19\n },\n \n // Terrain and topographic\n terrain: {\n url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',\n attribution: '© OpenTopoMap contributors',\n maxZoom: 17\n },\n \n // Dark mode styles\n dark: {\n url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n \n // Light/minimal styles\n light: {\n url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n \n // Watercolor artistic style\n watercolor: {\n url: 'https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg',\n attribution: '© Stadia Maps © Stamen Design © OpenStreetMap contributors',\n maxZoom: 16\n },\n \n // Black and white\n bw: {\n url: 'https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n \n // Streets with labels\n streets: {\n url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n }\n };\n\n return tileLayers[this.tileLayer] || tileLayers.osm;\n }\n\n async initializeMap() {\n const mapElement = this.element.querySelector(`#map-${this.id}`);\n if (!mapElement || !window.L) return;\n\n // Determine map center\n let mapCenter = this.center;\n if (!mapCenter && this.markers.length > 0) {\n // Use first marker as center\n mapCenter = [this.markers[0].lat, this.markers[0].lng];\n }\n if (!mapCenter) {\n // Default to world view\n mapCenter = [0, 0];\n }\n\n // Create map\n this.map = window.L.map(mapElement, {\n center: mapCenter,\n zoom: this.zoom,\n zoomControl: this.showZoomControl\n });\n\n // Add tile layer\n const tileConfig = this.getTileLayerUrl();\n window.L.tileLayer(tileConfig.url, {\n attribution: tileConfig.attribution,\n maxZoom: tileConfig.maxZoom\n }).addTo(this.map);\n\n // Add markers\n this.addMarkers(this.markers);\n\n // Auto-fit bounds if multiple markers\n if (this.markers.length > 1) {\n this.fitBounds();\n }\n\n // Fix tile rendering issues by invalidating size after a delay\n // This ensures the container has proper dimensions and CSS is applied\n setTimeout(() => {\n if (this.map) {\n this.map.invalidateSize();\n }\n }, 300);\n }\n\n addMarkers(markers) {\n if (!this.map || !Array.isArray(markers)) return;\n\n markers.forEach(markerData => {\n const { lat, lng, popup, icon } = markerData;\n \n if (!lat || !lng) return;\n\n const markerOptions = {};\n \n // Custom icon if provided\n if (icon) {\n markerOptions.icon = window.L.icon(icon);\n }\n\n const marker = window.L.marker([lat, lng], markerOptions).addTo(this.map);\n\n // Add popup if provided\n if (popup) {\n marker.bindPopup(popup);\n }\n\n this.leafletMarkers.push(marker);\n });\n }\n\n fitBounds() {\n if (!this.map || this.leafletMarkers.length === 0) return;\n\n const group = new window.L.featureGroup(this.leafletMarkers);\n this.map.fitBounds(group.getBounds().pad(0.1));\n }\n\n updateMarkers(newMarkers) {\n // Clear existing markers\n this.clearMarkers();\n \n // Add new markers\n this.markers = newMarkers;\n this.addMarkers(newMarkers);\n \n // Fit bounds if multiple markers\n if (newMarkers.length > 1) {\n this.fitBounds();\n } else if (newMarkers.length === 1) {\n this.map.setView([newMarkers[0].lat, newMarkers[0].lng], this.zoom);\n }\n }\n\n clearMarkers() {\n this.leafletMarkers.forEach(marker => {\n this.map.removeLayer(marker);\n });\n this.leafletMarkers = [];\n }\n\n setView(lat, lng, zoom = null) {\n if (!this.map) return;\n this.map.setView([lat, lng], zoom || this.zoom);\n }\n\n setZoom(zoom) {\n if (!this.map) return;\n this.map.setZoom(zoom);\n }\n\n async onBeforeDestroy() {\n if (this.map) {\n this.map.remove();\n this.map = null;\n }\n await super.onBeforeDestroy();\n }\n}\n\nexport default MapView;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"map.es.js","sources":["../src/extensions/map/MapView.js"],"sourcesContent":["/**\n * MapView - Interactive map component using Leaflet\n *\n * Features:\n * - Display single or multiple markers\n * - Auto-zoom to fit markers\n * - Customizable marker popups\n * - Support for different tile layers\n *\n * @example\n * const mapView = new MapView({\n * markers: [\n * { lat: 37.422, lng: -122.084, popup: 'Mountain View, CA' }\n * ],\n * zoom: 10,\n * height: 400\n * });\n */\n\nimport View from '@core/View.js';\n\nclass MapView extends View {\n constructor(options = {}) {\n super({\n className: 'map-view',\n ...options\n });\n\n this.markers = options.markers || [];\n this.center = options.center || null;\n this.zoom = options.zoom || 13;\n this.height = options.height || 400;\n this.showZoomControl = options.showZoomControl !== false;\n this.tileLayer = options.tileLayer || 'osm'; // 'osm', 'satellite', 'terrain'\n this.showLeafletBranding = options.showLeafletBranding === true;\n this.showLayerControl = options.showLayerControl === true;\n this.layerOptions = options.layerOptions || {\n osm: 'OSM',\n satellite: 'Satellite',\n terrain: 'Terrain',\n dark: 'Dark',\n light: 'Light',\n watercolor: 'Watercolor',\n bw: 'B/W',\n streets: 'Streets'\n };\n\n this.map = null;\n this.leafletMarkers = [];\n this._tileLayer = null;\n\n this.template = `\n <div class=\"map-container\">\n <div id=\"map-{{id}}\" style=\"height: {{height}}px; width: 100%; border-radius: 0.375rem; border: 1px solid #dee2e6;\"></div>\n </div>\n `;\n }\n\n async onAfterRender() {\n await this.loadLeaflet();\n await this.initializeMap();\n }\n\n async loadLeaflet() {\n // Check if Leaflet is already loaded\n if (window.L) return;\n\n // Load Leaflet CSS and wait for it\n const cssLoaded = new Promise((resolve) => {\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.css';\n link.onload = resolve;\n link.onerror = resolve; // Continue even if CSS fails\n document.head.appendChild(link);\n });\n\n // Load Leaflet JS\n const jsLoaded = new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://unpkg.com/leaflet@1.9.4/dist/leaflet.js';\n script.onload = resolve;\n script.onerror = reject;\n document.head.appendChild(script);\n });\n\n // Wait for both CSS and JS to load\n await Promise.all([cssLoaded, jsLoaded]);\n }\n\n getTileLayerUrl() {\n const tileLayers = {\n // Standard street maps\n osm: {\n url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',\n attribution: '© OpenStreetMap contributors',\n maxZoom: 19\n },\n\n // Satellite imagery\n satellite: {\n url: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}',\n attribution: '© Esri',\n maxZoom: 19\n },\n\n // Terrain and topographic\n terrain: {\n url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png',\n attribution: '© OpenTopoMap contributors',\n maxZoom: 17\n },\n\n // Dark mode styles\n dark: {\n url: 'https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n\n // Light/minimal styles\n light: {\n url: 'https://{s}.basemaps.cartocdn.com/light_all/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n\n // Watercolor artistic style\n watercolor: {\n url: 'https://tiles.stadiamaps.com/tiles/stamen_watercolor/{z}/{x}/{y}.jpg',\n attribution: '© Stadia Maps © Stamen Design © OpenStreetMap contributors',\n maxZoom: 16\n },\n\n // Black and white\n bw: {\n url: 'https://{s}.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n },\n\n // Streets with labels\n streets: {\n url: 'https://{s}.basemaps.cartocdn.com/rastertiles/voyager/{z}/{x}/{y}{r}.png',\n attribution: '© OpenStreetMap contributors © CARTO',\n maxZoom: 20\n }\n };\n\n return tileLayers[this.tileLayer] || tileLayers.osm;\n }\n\n async initializeMap() {\n const mapElement = this.element.querySelector(`#map-${this.id}`);\n if (!mapElement || !window.L) return;\n\n // Determine map center\n let mapCenter = this.center;\n if (!mapCenter && this.markers.length > 0) {\n // Use first marker as center\n mapCenter = [this.markers[0].lat, this.markers[0].lng];\n }\n if (!mapCenter) {\n // Default to world view\n mapCenter = [0, 0];\n }\n\n // Create map\n this.map = window.L.map(mapElement, {\n center: mapCenter,\n zoom: this.zoom,\n zoomControl: this.showZoomControl\n });\n // Optionally hide Leaflet branding/prefix (removes Leaflet link/flag in attribution control)\n if (this.map && this.map.attributionControl && this.showLeafletBranding === false) {\n try { this.map.attributionControl.setPrefix(''); } catch (e) {}\n }\n\n // Add tile layer\n const tileConfig = this.getTileLayerUrl();\n this._tileLayer = window.L.tileLayer(tileConfig.url, {\n attribution: tileConfig.attribution,\n maxZoom: tileConfig.maxZoom\n }).addTo(this.map);\n\n // Optional built-in tile layer selector UI\n if (this.showLayerControl) {\n const container = mapElement.parentElement || this.element.querySelector('.map-container');\n if (container) {\n container.style.position = container.style.position || 'relative';\n const selector = document.createElement('select');\n selector.className = 'form-select form-select-sm';\n selector.style.position = 'absolute';\n selector.style.top = '8px';\n selector.style.right = '8px';\n selector.style.zIndex = '1000';\n selector.style.maxWidth = '180px';\n selector.setAttribute('aria-label', 'Map tile layer');\n\n // Populate options\n Object.entries(this.layerOptions || {}).forEach(([key, label]) => {\n const opt = document.createElement('option');\n opt.value = key;\n opt.textContent = label;\n if (key === this.tileLayer) opt.selected = true;\n selector.appendChild(opt);\n });\n\n selector.addEventListener('change', () => this.setTileLayer(selector.value));\n container.appendChild(selector);\n }\n }\n\n // Add markers\n this.addMarkers(this.markers);\n\n // Auto-fit bounds if multiple markers\n if (this.markers.length > 1) {\n this.fitBounds();\n }\n\n // Fix tile rendering issues by invalidating size after a delay\n // This ensures the container has proper dimensions and CSS is applied\n setTimeout(() => {\n if (this.map) {\n this.map.invalidateSize();\n }\n }, 300);\n }\n\n addMarkers(markers) {\n if (!this.map || !Array.isArray(markers)) return;\n\n markers.forEach(markerData => {\n const { lat, lng, popup, icon } = markerData;\n\n if (!lat || !lng) return;\n\n const markerOptions = {};\n\n // Custom icon if provided\n if (icon) {\n markerOptions.icon = window.L.icon(icon);\n }\n\n const marker = window.L.marker([lat, lng], markerOptions).addTo(this.map);\n\n // Add popup if provided\n if (popup) {\n marker.bindPopup(popup);\n }\n\n this.leafletMarkers.push(marker);\n });\n }\n\n fitBounds() {\n if (!this.map || this.leafletMarkers.length === 0) return;\n\n const group = new window.L.featureGroup(this.leafletMarkers);\n this.map.fitBounds(group.getBounds().pad(0.1));\n }\n\n updateMarkers(newMarkers) {\n // Clear existing markers\n this.clearMarkers();\n\n // Add new markers\n this.markers = newMarkers;\n this.addMarkers(newMarkers);\n\n // Fit bounds if multiple markers\n if (newMarkers.length > 1) {\n this.fitBounds();\n } else if (newMarkers.length === 1) {\n this.map.setView([newMarkers[0].lat, newMarkers[0].lng], this.zoom);\n }\n }\n\n clearMarkers() {\n this.leafletMarkers.forEach(marker => {\n this.map.removeLayer(marker);\n });\n this.leafletMarkers = [];\n }\n\n setView(lat, lng, zoom = null) {\n if (!this.map) return;\n this.map.setView([lat, lng], zoom || this.zoom);\n }\n\n setZoom(zoom) {\n if (!this.map) return;\n this.map.setZoom(zoom);\n }\n\n setTileLayer(key) {\n if (!this.map) return;\n // Resolve tile layer config using the same logic as getTileLayerUrl\n const original = this.tileLayer;\n this.tileLayer = key || this.tileLayer;\n const tileConfig = this.getTileLayerUrl();\n try {\n if (this._tileLayer) {\n this.map.removeLayer(this._tileLayer);\n }\n } catch (e) {\n // ignore if layer already removed\n }\n this._tileLayer = window.L.tileLayer(tileConfig.url, {\n attribution: tileConfig.attribution,\n maxZoom: tileConfig.maxZoom\n }).addTo(this.map);\n // Keep property in sync\n this.tileLayer = key || original;\n\n // Nudge map to ensure proper redraw\n setTimeout(() => {\n try { this.map.invalidateSize(); } catch (e) {}\n }, 150);\n }\n\n async onBeforeDestroy() {\n if (this.map) {\n this.map.remove();\n this.map = null;\n }\n await super.onBeforeDestroy();\n }\n\n static async showAsDialog(options = {}) {\n const view = new MapView(options);\n const dopts = options.dialogOptions || {};\n const dialogOptions = {\n title: \"Map View\",\n header: true,\n body: view,\n size: 'lg',\n centered: false,\n ...dopts\n }\n await view.init();\n await view.getApp().showDialog(dialogOptions);\n }\n}\n\nexport default MapView;\n"],"names":[],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/ListView-BRGiITfD.js"),e=require("./chunks/Rest-BNYqGlnP.js"),i=require("./chunks/Collection-DD1_31eh.js");class TimelineViewItem extends t.ListViewItem{constructor(t={}){super({className:"timeline-item",...t}),this.dateFormat=t.dateFormat||"date",this.dotStyle=t.dotStyle||"solid",this.showDate=!1!==t.showDate,this.theme=t.theme||"primary",this.template||(this.template='\n <div class="timeline-marker timeline-marker-{{markerType}}">\n {{#hasIcon}}\n <i class="bi {{model.icon}} text-{{displayColor}}"></i>\n {{/hasIcon}}\n {{^hasIcon}}\n <div class="timeline-dot bg-{{displayColor}}"></div>\n {{/hasIcon}}\n </div>\n \n <div class="timeline-content">\n {{#showDate}}\n <div class="timeline-date text-muted small">\n {{formattedDate}}\n </div>\n {{/showDate}}\n \n <div class="timeline-card">\n {{#model.title}}\n <h6 class="timeline-title mb-1">{{model.title}}</h6>\n {{/model.title}}\n \n {{#model.description}}\n <p class="timeline-description mb-0">{{model.description}}</p>\n {{/model.description}}\n \n {{#model.meta}}\n <div class="timeline-meta mt-2 text-muted small">\n {{model.meta}}\n </div>\n {{/model.meta}}\n </div>\n </div>\n ')}async onInit(){await super.onInit(),this.processItemData()}processItemData(){this.displayColor=this.model?.get?.("color")||this.model?.color||this.theme;const t=!(!this.model?.get?.("icon")&&!this.model?.icon)&&"icon"===this.dotStyle;this.hasIcon=t,this.markerType=t?"icon":this.dotStyle;const e=this.model?.get?.("date")||this.model?.date;this.formattedDate=this.formatDate(e)}formatDate(t){if(!t)return"";switch(this.dateFormat){case"datetime":return e.dataFormatter.pipe(t,"datetime");case"relative":return e.dataFormatter.pipe(t,"timeago");default:return e.dataFormatter.pipe(t,"date")}}async onActionSelect(t,e){t.stopPropagation(),this.emit("item:click",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model})}}class TimelineView extends t.ListView{constructor(t={}){super({className:"timeline-view",itemClass:t.itemClass||TimelineViewItem,selectionMode:"none",emptyMessage:t.emptyMessage||"No timeline events to display",template:'\n <div class="timeline-container timeline-{{position}}">\n {{#loading}}\n <div class="timeline-loading text-center py-4">\n <div class="spinner-border spinner-border-sm" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n <span class="ms-2 text-muted">Loading timeline...</span>\n </div>\n {{/loading}}\n {{^loading}}\n {{#isEmpty}}\n <div class="timeline-empty text-center text-muted py-4">\n <i class="bi bi-clock-history fs-1 d-block mb-2"></i>\n <p>{{emptyMessage}}</p>\n </div>\n {{/isEmpty}}\n {{^isEmpty}}\n <div class="timeline" data-container="items"></div>\n {{/isEmpty}}\n {{/loading}}\n </div>\n ',...t}),this.position=t.position||"left",this.dateFormat=t.dateFormat||"date",this.dotStyle=t.dotStyle||"solid",this.showDate=!1!==t.showDate,this.theme=t.theme||"primary",this.groupBy=t.groupBy||"none"}_createItemView(t,e){if(this.itemViews.has(t.id))return;const i=new this.itemClass({model:t,index:e,listView:this,template:this.itemTemplate,dateFormat:this.dateFormat,dotStyle:this.dotStyle,showDate:this.showDate,theme:this.theme});return this.itemViews.set(t.id,i),i.on("item:click",this._onItemClick.bind(this)),i}_onItemClick(t){this.emit("item:click",t)}setPosition(t){return"left"!==t&&"center"!==t?(console.warn('Invalid position. Use "left" or "center"'),this):(this.position=t,this.isMounted()&&this.render(),this)}setDateFormat(t){return this.dateFormat=t,this.forEachItem(e=>{e.dateFormat=t,e.processItemData(),e.isMounted()&&e.render()}),this}setDotStyle(t){return this.dotStyle=t,this.forEachItem(e=>{e.dotStyle=t,e.processItemData(),e.isMounted()&&e.render()}),this}toggleDates(t=null){return this.showDate=null!==t?t:!this.showDate,this.forEachItem(t=>{t.showDate=this.showDate,t.isMounted()&&t.render()}),this}}exports.ListView=t.ListView,exports.ListViewItem=t.ListViewItem,exports.View=e.View,exports.Collection=i.Collection,exports.Model=i.Model,exports.TimelineView=TimelineView,exports.TimelineViewItem=TimelineViewItem;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("./chunks/ListView-BpGEatee.js"),e=require("./chunks/Rest-BpDyhFfG.js"),i=require("./chunks/Collection-B64LJ92k.js");class TimelineViewItem extends t.ListViewItem{constructor(t={}){super({className:"timeline-item",...t}),this.dateFormat=t.dateFormat||"date",this.dotStyle=t.dotStyle||"solid",this.showDate=!1!==t.showDate,this.theme=t.theme||"primary",this.template||(this.template='\n <div class="timeline-marker timeline-marker-{{markerType}}">\n {{#hasIcon}}\n <i class="bi {{model.icon}} text-{{displayColor}}"></i>\n {{/hasIcon}}\n {{^hasIcon}}\n <div class="timeline-dot bg-{{displayColor}}"></div>\n {{/hasIcon}}\n </div>\n \n <div class="timeline-content">\n {{#showDate}}\n <div class="timeline-date text-muted small">\n {{formattedDate}}\n </div>\n {{/showDate}}\n \n <div class="timeline-card">\n {{#model.title}}\n <h6 class="timeline-title mb-1">{{model.title}}</h6>\n {{/model.title}}\n \n {{#model.description}}\n <p class="timeline-description mb-0">{{model.description}}</p>\n {{/model.description}}\n \n {{#model.meta}}\n <div class="timeline-meta mt-2 text-muted small">\n {{model.meta}}\n </div>\n {{/model.meta}}\n </div>\n </div>\n ')}async onInit(){await super.onInit(),this.processItemData()}processItemData(){this.displayColor=this.model?.get?.("color")||this.model?.color||this.theme;const t=!(!this.model?.get?.("icon")&&!this.model?.icon)&&"icon"===this.dotStyle;this.hasIcon=t,this.markerType=t?"icon":this.dotStyle;const e=this.model?.get?.("date")||this.model?.date;this.formattedDate=this.formatDate(e)}formatDate(t){if(!t)return"";switch(this.dateFormat){case"datetime":return e.dataFormatter.pipe(t,"datetime");case"relative":return e.dataFormatter.pipe(t,"timeago");default:return e.dataFormatter.pipe(t,"date")}}async onActionSelect(t,e){t.stopPropagation(),this.emit("item:click",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model}),this.listView&&this.listView.emit("item:click",{item:this,model:this.model,index:this.index,data:this.model?.toJSON?this.model.toJSON():this.model})}}class TimelineView extends t.ListView{constructor(t={}){super({className:"timeline-view",itemClass:t.itemClass||TimelineViewItem,selectionMode:"none",emptyMessage:t.emptyMessage||"No timeline events to display",template:'\n <div class="timeline-container timeline-{{position}}">\n {{#loading}}\n <div class="timeline-loading text-center py-4">\n <div class="spinner-border spinner-border-sm" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n <span class="ms-2 text-muted">Loading timeline...</span>\n </div>\n {{/loading}}\n {{^loading}}\n {{#isEmpty}}\n <div class="timeline-empty text-center text-muted py-4">\n <i class="bi bi-clock-history fs-1 d-block mb-2"></i>\n <p>{{emptyMessage}}</p>\n </div>\n {{/isEmpty}}\n {{^isEmpty}}\n <div class="timeline" data-container="items"></div>\n {{/isEmpty}}\n {{/loading}}\n </div>\n ',...t}),this.position=t.position||"left",this.dateFormat=t.dateFormat||"date",this.dotStyle=t.dotStyle||"solid",this.showDate=!1!==t.showDate,this.theme=t.theme||"primary",this.groupBy=t.groupBy||"none"}_createItemView(t,e){if(this.itemViews.has(t.id))return;const i=new this.itemClass({model:t,index:e,listView:this,template:this.itemTemplate,dateFormat:this.dateFormat,dotStyle:this.dotStyle,showDate:this.showDate,theme:this.theme});return this.itemViews.set(t.id,i),i.on("item:click",this._onItemClick.bind(this)),i}_onItemClick(t){this.emit("item:click",t)}setPosition(t){return"left"!==t&&"center"!==t?(console.warn('Invalid position. Use "left" or "center"'),this):(this.position=t,this.isMounted()&&this.render(),this)}setDateFormat(t){return this.dateFormat=t,this.forEachItem(e=>{e.dateFormat=t,e.processItemData(),e.isMounted()&&e.render()}),this}setDotStyle(t){return this.dotStyle=t,this.forEachItem(e=>{e.dotStyle=t,e.processItemData(),e.isMounted()&&e.render()}),this}toggleDates(t=null){return this.showDate=null!==t?t:!this.showDate,this.forEachItem(t=>{t.showDate=this.showDate,t.isMounted()&&t.render()}),this}}exports.ListView=t.ListView,exports.ListViewItem=t.ListViewItem,exports.View=e.View,exports.Collection=i.Collection,exports.Model=i.Model,exports.TimelineView=TimelineView,exports.TimelineViewItem=TimelineViewItem;
2
2
  //# sourceMappingURL=timeline.cjs.js.map
@@ -1,7 +1,7 @@
1
- import { L as ListViewItem, a as ListView } from "./chunks/ListView-BMNhd5-B.js";
2
- import { d as dataFormatter } from "./chunks/Rest-CS4jRCAs.js";
3
- import { V } from "./chunks/Rest-CS4jRCAs.js";
4
- import { C, M } from "./chunks/Collection-YRfGoT73.js";
1
+ import { L as ListViewItem, a as ListView } from "./chunks/ListView-BGJG4GYH.js";
2
+ import { d as dataFormatter } from "./chunks/Rest-DpbPbmra.js";
3
+ import { V } from "./chunks/Rest-DpbPbmra.js";
4
+ import { C, M } from "./chunks/Collection-CsAk0UhA.js";
5
5
  class TimelineViewItem extends ListViewItem {
6
6
  constructor(options = {}) {
7
7
  super({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "web-mojo",
3
- "version": "2.1.1043",
3
+ "version": "2.1.1087",
4
4
  "description": "WEB-MOJO - A lightweight JavaScript framework for building data-driven web applications",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs.js",