web-mojo 2.4.6 → 2.4.9
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.
- package/dist/admin-models.cjs.js +1 -1
- package/dist/admin-models.cjs.js.map +1 -1
- package/dist/admin-models.es.js +1 -1
- package/dist/admin-models.es.js.map +1 -1
- package/dist/admin.cjs.js +1 -1
- package/dist/admin.cjs.js.map +1 -1
- package/dist/admin.es.js +1 -1
- package/dist/admin.es.js.map +1 -1
- package/dist/auth.cjs.js +1 -1
- package/dist/auth.es.js +1 -1
- package/dist/charts.cjs.js +1 -1
- package/dist/charts.es.js +1 -1
- package/dist/chunks/{ChatView-D2WOSxPu.js → ChatView-C_2dRLAY.js} +2 -2
- package/dist/chunks/{ChatView-D2WOSxPu.js.map → ChatView-C_2dRLAY.js.map} +1 -1
- package/dist/chunks/{ChatView-kWguc444.js → ChatView-DVb2Ufq_.js} +2 -2
- package/dist/chunks/{ChatView-kWguc444.js.map → ChatView-DVb2Ufq_.js.map} +1 -1
- package/dist/chunks/{Collection-DNmr743A.js → Collection-Bq_EMAqK.js} +2 -2
- package/dist/chunks/{Collection-DNmr743A.js.map → Collection-Bq_EMAqK.js.map} +1 -1
- package/dist/chunks/{Collection-C0pHSKDH.js → Collection-tgvDhyz_.js} +2 -2
- package/dist/chunks/{Collection-C0pHSKDH.js.map → Collection-tgvDhyz_.js.map} +1 -1
- package/dist/chunks/{ContextMenu-T3yDdsIe.js → ContextMenu-BL_sdgIw.js} +2 -2
- package/dist/chunks/{ContextMenu-T3yDdsIe.js.map → ContextMenu-BL_sdgIw.js.map} +1 -1
- package/dist/chunks/{ContextMenu-BeveGkJr.js → ContextMenu-fIy3upEy.js} +2 -2
- package/dist/chunks/{ContextMenu-BeveGkJr.js.map → ContextMenu-fIy3upEy.js.map} +1 -1
- package/dist/chunks/{DataView-VZIXSsZa.js → DataView-DRQ2yFRz.js} +2 -2
- package/dist/chunks/{DataView-VZIXSsZa.js.map → DataView-DRQ2yFRz.js.map} +1 -1
- package/dist/chunks/{DataView-z2rxXk4L.js → DataView-DW_ufpQo.js} +2 -2
- package/dist/chunks/{DataView-z2rxXk4L.js.map → DataView-DW_ufpQo.js.map} +1 -1
- package/dist/chunks/{FormView-COIPtbrd.js → FormView-eWUWw8oL.js} +2 -2
- package/dist/chunks/{FormView-COIPtbrd.js.map → FormView-eWUWw8oL.js.map} +1 -1
- package/dist/chunks/{FormView-DUXQruUZ.js → FormView-xl_w506t.js} +2 -2
- package/dist/chunks/{FormView-DUXQruUZ.js.map → FormView-xl_w506t.js.map} +1 -1
- package/dist/chunks/{ListView-BjsNHuZ1.js → ListView-Bj4ONQFG.js} +2 -2
- package/dist/chunks/{ListView-BjsNHuZ1.js.map → ListView-Bj4ONQFG.js.map} +1 -1
- package/dist/chunks/{ListView-BxcxIwC3.js → ListView-jyIVhCN3.js} +2 -2
- package/dist/chunks/{ListView-BxcxIwC3.js.map → ListView-jyIVhCN3.js.map} +1 -1
- package/dist/chunks/MetricsCountryMapView-D_666qlW.js +2 -0
- package/dist/chunks/MetricsCountryMapView-D_666qlW.js.map +1 -0
- package/dist/chunks/MetricsCountryMapView-U3xr0QXD.js +2 -0
- package/dist/chunks/MetricsCountryMapView-U3xr0QXD.js.map +1 -0
- package/dist/chunks/Modal-CCVJefEX.js +3 -0
- package/dist/chunks/{Modal-Bm1OQ8Ou.js.map → Modal-CCVJefEX.js.map} +1 -1
- package/dist/chunks/Modal-Uwt-GBgJ.js +3 -0
- package/dist/chunks/{Modal-KnJhNZ1E.js.map → Modal-Uwt-GBgJ.js.map} +1 -1
- package/dist/chunks/Passkeys-DScGUF6p.js +2 -0
- package/dist/chunks/{Passkeys-BlHx11-5.js.map → Passkeys-DScGUF6p.js.map} +1 -1
- package/dist/chunks/{Passkeys-B1-Z4-16.js → Passkeys-c4amXO03.js} +2 -2
- package/dist/chunks/{Passkeys-B1-Z4-16.js.map → Passkeys-c4amXO03.js.map} +1 -1
- package/dist/chunks/{TokenManager-CiNtJclo.js → TokenManager-BRx2U5w4.js} +2 -2
- package/dist/chunks/{TokenManager-CiNtJclo.js.map → TokenManager-BRx2U5w4.js.map} +1 -1
- package/dist/chunks/{TokenManager-6atX9uKB.js → TokenManager-DZP2Lcnz.js} +2 -2
- package/dist/chunks/{TokenManager-6atX9uKB.js.map → TokenManager-DZP2Lcnz.js.map} +1 -1
- package/dist/chunks/{User-9qvKV7G6.js → User-DR-2VJcv.js} +2 -2
- package/dist/chunks/{User-9qvKV7G6.js.map → User-DR-2VJcv.js.map} +1 -1
- package/dist/chunks/{User-BM76Ughk.js → User-e9aOjdHv.js} +2 -2
- package/dist/chunks/{User-BM76Ughk.js.map → User-e9aOjdHv.js.map} +1 -1
- package/dist/chunks/{UserProfileView-DDflzpTa.js → UserProfileView-CCNcNT-M.js} +2 -2
- package/dist/chunks/{UserProfileView-DDflzpTa.js.map → UserProfileView-CCNcNT-M.js.map} +1 -1
- package/dist/chunks/{UserProfileView-cUF8ED9n.js → UserProfileView-PmerV2tC.js} +2 -2
- package/dist/chunks/{UserProfileView-cUF8ED9n.js.map → UserProfileView-PmerV2tC.js.map} +1 -1
- package/dist/chunks/{View-CPWwS19u.js → View-CLWMWXbO.js} +2 -2
- package/dist/chunks/{View-CPWwS19u.js.map → View-CLWMWXbO.js.map} +1 -1
- package/dist/chunks/{View-BxlKR1IW.js → View-DADtcBcb.js} +2 -2
- package/dist/chunks/{View-BxlKR1IW.js.map → View-DADtcBcb.js.map} +1 -1
- package/dist/chunks/{WebApp-BdxhRnnT.js → WebApp-BBrvjnnH.js} +2 -2
- package/dist/chunks/{WebApp-BdxhRnnT.js.map → WebApp-BBrvjnnH.js.map} +1 -1
- package/dist/chunks/{WebApp-Bo_egO0c.js → WebApp-wMWf0qkm.js} +2 -2
- package/dist/chunks/{WebApp-Bo_egO0c.js.map → WebApp-wMWf0qkm.js.map} +1 -1
- package/dist/chunks/exportChart-BszC9qir.js +2 -0
- package/dist/chunks/{exportChart-BTrEOM9j.js.map → exportChart-BszC9qir.js.map} +1 -1
- package/dist/chunks/exportChart-CnAGJjyS.js +2 -0
- package/dist/chunks/{exportChart-BfzZUb1j.js.map → exportChart-CnAGJjyS.js.map} +1 -1
- package/dist/chunks/{index-DsID1QpB.js → index-B312g4f-.js} +2 -2
- package/dist/chunks/{index-DsID1QpB.js.map → index-B312g4f-.js.map} +1 -1
- package/dist/chunks/{index-Cxffar1o.js → index-D7ITRVln.js} +2 -2
- package/dist/chunks/{index-Cxffar1o.js.map → index-D7ITRVln.js.map} +1 -1
- package/dist/chunks/{version-BxLEknar.js → version-Cz_nlYsB.js} +2 -2
- package/dist/chunks/{version-BxLEknar.js.map → version-Cz_nlYsB.js.map} +1 -1
- package/dist/chunks/{version-BYy2UAT0.js → version-D2vRYNuT.js} +2 -2
- package/dist/chunks/{version-BYy2UAT0.js.map → version-D2vRYNuT.js.map} +1 -1
- package/dist/docit.cjs.js +1 -1
- package/dist/docit.es.js +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.es.js +1 -1
- package/dist/lightbox.cjs.js +1 -1
- package/dist/lightbox.es.js +1 -1
- package/dist/map.cjs.js +1 -1
- package/dist/map.es.js +1 -1
- package/dist/timeline.cjs.js +1 -1
- package/dist/timeline.es.js +1 -1
- package/dist/user-profile.cjs.js +1 -1
- package/dist/user-profile.es.js +1 -1
- package/package.json +1 -1
- package/dist/chunks/AssistantPanelView-CkQEcaFk.js +0 -2
- package/dist/chunks/AssistantPanelView-CkQEcaFk.js.map +0 -1
- package/dist/chunks/AssistantPanelView-D1wEbgtM.js +0 -2
- package/dist/chunks/AssistantPanelView-D1wEbgtM.js.map +0 -1
- package/dist/chunks/MetricsCountryMapView-Bp3qoVHp.js +0 -2
- package/dist/chunks/MetricsCountryMapView-Bp3qoVHp.js.map +0 -1
- package/dist/chunks/MetricsCountryMapView-CWjIEBJB.js +0 -2
- package/dist/chunks/MetricsCountryMapView-CWjIEBJB.js.map +0 -1
- package/dist/chunks/Modal-Bm1OQ8Ou.js +0 -3
- package/dist/chunks/Modal-KnJhNZ1E.js +0 -3
- package/dist/chunks/Passkeys-BlHx11-5.js +0 -2
- package/dist/chunks/TicketPanelView-DVePzWyJ.js +0 -2
- package/dist/chunks/TicketPanelView-DVePzWyJ.js.map +0 -1
- package/dist/chunks/TicketPanelView-TYh5iZiR.js +0 -2
- package/dist/chunks/TicketPanelView-TYh5iZiR.js.map +0 -1
- package/dist/chunks/admin-CHPo4iDn.js +0 -2
- package/dist/chunks/admin-CHPo4iDn.js.map +0 -1
- package/dist/chunks/admin-CucHFXfD.js +0 -2
- package/dist/chunks/admin-CucHFXfD.js.map +0 -1
- package/dist/chunks/admin-models-CkHjtMHf.js +0 -2
- package/dist/chunks/admin-models-CkHjtMHf.js.map +0 -1
- package/dist/chunks/admin-models-DLtFboxy.js +0 -2
- package/dist/chunks/admin-models-DLtFboxy.js.map +0 -1
- package/dist/chunks/exportChart-BTrEOM9j.js +0 -2
- package/dist/chunks/exportChart-BfzZUb1j.js +0 -2
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"MetricsCountryMapView-CWjIEBJB.js","sources":["../../src/extensions/map/MapView.js","../../src/extensions/map/MapLibreView.js","../../src/extensions/map/countryCentroids.js","../../src/extensions/map/MetricsCountryMapView.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 // Interaction toggles. `interactive` is the master switch; granular\n // flags override individual handlers when set.\n const interactive = options.interactive !== false;\n this.interactive = interactive;\n this.scrollZoom = options.scrollZoom !== undefined ? !!options.scrollZoom : interactive;\n this.dragPan = options.dragPan !== undefined ? !!options.dragPan : interactive;\n this.doubleClickZoom = options.doubleClickZoom !== undefined ? !!options.doubleClickZoom : interactive;\n this.keyboard = options.keyboard !== undefined ? !!options.keyboard : interactive;\n this.touchZoom = options.touchZoom !== undefined ? !!options.touchZoom : interactive;\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 scrollWheelZoom: this.scrollZoom,\n dragging: this.dragPan,\n doubleClickZoom: this.doubleClickZoom,\n keyboard: this.keyboard,\n touchZoom: this.touchZoom,\n boxZoom: this.interactive,\n tap: this.interactive\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","/**\n * MapLibreView - Interactive vector map component using MapLibre GL JS\n * \n * MapLibre GL is better for:\n * - Vector tiles and custom styling\n * - 3D terrain and buildings\n * - High-performance rendering\n * - Heat maps and data visualizations\n * - Complex animations\n * \n * Use MapView (Leaflet) for simple marker maps.\n * Use MapLibreView for advanced visualizations.\n * \n * @example\n * const mapView = new MapLibreView({\n * markers: [\n * { lng: -122.084, lat: 37.422, popup: 'Mountain View, CA' }\n * ],\n * style: 'streets', // 'streets', 'satellite', 'dark', 'light'\n * zoom: 10,\n * height: 400\n * });\n */\n\nimport View from '@core/View.js';\n\nclass MapLibreView extends View {\n constructor(options = {}) {\n super({\n className: 'maplibre-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.pitch = options.pitch || 0; // 0-60 degrees (3D tilt)\n this.bearing = options.bearing || 0; // 0-360 degrees (rotation)\n this.mapStyle = options.style || 'streets'; // 'streets', 'satellite', 'dark', 'light', 'terrain'\n this.showNavigationControl = options.showNavigationControl !== false;\n this.autoFitBounds = options.autoFitBounds !== false;\n\n // Interaction toggles. `interactive` is the master switch; granular\n // flags override individual handlers when set.\n const interactive = options.interactive !== false;\n this.interactive = interactive;\n this.scrollZoom = options.scrollZoom !== undefined ? !!options.scrollZoom : interactive;\n this.dragPan = options.dragPan !== undefined ? !!options.dragPan : interactive;\n this.doubleClickZoom = options.doubleClickZoom !== undefined ? !!options.doubleClickZoom : interactive;\n this.keyboard = options.keyboard !== undefined ? !!options.keyboard : interactive;\n this.touchZoom = options.touchZoom !== undefined ? !!options.touchZoom : interactive;\n \n this.map = null;\n this.mapMarkers = [];\n this.pendingMarkers = [...this.markers];\n this.lineSources = options.lineSources || [];\n this.pendingLineData = new Map();\n\n this.template = `\n <div class=\"maplibre-container\">\n <div id=\"maplibre-{{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.loadMapLibre();\n await this.initializeMap();\n }\n\n async loadMapLibre() {\n // Check if MapLibre is already loaded\n if (window.maplibregl) return;\n\n // Load MapLibre CSS\n const link = document.createElement('link');\n link.rel = 'stylesheet';\n link.href = 'https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.css';\n document.head.appendChild(link);\n\n // Load MapLibre JS\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.src = 'https://unpkg.com/maplibre-gl@4.7.1/dist/maplibre-gl.js';\n script.onload = resolve;\n script.onerror = reject;\n document.head.appendChild(script);\n });\n }\n\n getMapStyle() {\n const styles = {\n streets: 'https://demotiles.maplibre.org/style.json',\n dark: {\n version: 8,\n sources: {\n osm: {\n type: 'raster',\n tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],\n tileSize: 256,\n attribution: '© OpenStreetMap contributors'\n }\n },\n layers: [{\n id: 'osm',\n type: 'raster',\n source: 'osm'\n }],\n glyphs: 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf'\n },\n light: {\n version: 8,\n sources: {\n osm: {\n type: 'raster',\n tiles: ['https://a.tile.openstreetmap.org/{z}/{x}/{y}.png'],\n tileSize: 256,\n attribution: '© OpenStreetMap contributors'\n }\n },\n layers: [{\n id: 'osm',\n type: 'raster',\n source: 'osm'\n }],\n glyphs: 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf'\n },\n satellite: {\n version: 8,\n sources: {\n satellite: {\n type: 'raster',\n tiles: ['https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'],\n tileSize: 256,\n attribution: '© Esri'\n }\n },\n layers: [{\n id: 'satellite',\n type: 'raster',\n source: 'satellite'\n }],\n glyphs: 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf'\n },\n terrain: {\n version: 8,\n sources: {\n terrain: {\n type: 'raster',\n tiles: ['https://a.tile.opentopomap.org/{z}/{x}/{y}.png'],\n tileSize: 256,\n attribution: '© OpenTopoMap contributors'\n }\n },\n layers: [{\n id: 'terrain',\n type: 'raster',\n source: 'terrain'\n }],\n glyphs: 'https://demotiles.maplibre.org/font/{fontstack}/{range}.pbf'\n }\n };\n\n return styles[this.mapStyle] || styles.streets;\n }\n\n async initializeMap() {\n const mapElement = this.element.querySelector(`#maplibre-${this.id}`);\n if (!mapElement || !window.maplibregl) return;\n\n // Determine map center\n let mapCenter = this.center;\n if (!mapCenter && this.markers.length > 0) {\n // Use first marker as center (MapLibre uses [lng, lat])\n mapCenter = [this.markers[0].lng, this.markers[0].lat];\n }\n if (!mapCenter) {\n // Default to world view\n mapCenter = [0, 0];\n }\n\n // Create map\n this.map = new window.maplibregl.Map({\n container: mapElement,\n style: this.getMapStyle(),\n center: mapCenter,\n zoom: this.zoom,\n pitch: this.pitch,\n bearing: this.bearing,\n interactive: this.interactive,\n scrollZoom: this.scrollZoom,\n dragPan: this.dragPan,\n doubleClickZoom: this.doubleClickZoom,\n keyboard: this.keyboard,\n touchZoomRotate: this.touchZoom\n });\n\n // Add navigation control\n if (this.showNavigationControl) {\n this.map.addControl(new window.maplibregl.NavigationControl(), 'top-right');\n }\n\n // Wait for map to load before adding markers\n this.map.on('load', () => {\n const initialMarkers = this.pendingMarkers.length ? this.pendingMarkers : this.markers;\n this.updateMarkers(initialMarkers);\n this.lineSources.forEach(source => this.addLineSource(source));\n this.pendingLineData.forEach(source => this.addLineSource(source));\n this.pendingLineData.clear();\n });\n }\n\n addMarkers(markers) {\n if (!this.map || !Array.isArray(markers)) {\n this.pendingMarkers = Array.isArray(markers) ? markers : [];\n return;\n }\n\n markers.forEach(markerData => {\n const { lng, lat, popup, color, icon, size } = markerData;\n \n if (!lng || !lat) return;\n\n // Create marker element\n const el = document.createElement('div');\n el.className = 'maplibre-marker';\n const markerSize = Number(size) || 30;\n el.style.width = `${markerSize}px`;\n el.style.height = `${markerSize}px`;\n el.style.borderRadius = '50%';\n el.style.backgroundColor = color || '#3b82f6';\n el.style.border = '3px solid white';\n el.style.boxShadow = '0 2px 4px rgba(0,0,0,0.3)';\n el.style.cursor = 'pointer';\n el.style.display = 'flex';\n el.style.alignItems = 'center';\n el.style.justifyContent = 'center';\n\n // Optional icon\n if (icon) {\n el.innerHTML = `<i class=\"${icon}\" style=\"color: white;\"></i>`;\n }\n\n // Create marker\n const marker = new window.maplibregl.Marker({ element: el })\n .setLngLat([lng, lat])\n .addTo(this.map);\n\n // Add popup if provided\n if (popup) {\n const mapPopup = new window.maplibregl.Popup({ offset: 25 })\n .setHTML(popup);\n marker.setPopup(mapPopup);\n }\n\n this.mapMarkers.push(marker);\n });\n }\n\n fitBounds() {\n if (!this.map || this.markers.length === 0) return;\n\n const bounds = new window.maplibregl.LngLatBounds();\n \n this.markers.forEach(marker => {\n bounds.extend([marker.lng, marker.lat]);\n });\n\n this.map.fitBounds(bounds, {\n padding: 50,\n maxZoom: 15\n });\n }\n\n updateMarkers(newMarkers) {\n const markers = Array.isArray(newMarkers) ? newMarkers : [];\n this.markers = markers;\n this.pendingMarkers = markers;\n if (!this.map) return;\n\n this.clearMarkers();\n this.addMarkers(markers);\n\n if (this.autoFitBounds && markers.length > 1) {\n this.fitBounds();\n } else if (markers.length === 1 && this.map) {\n this.map.flyTo({\n center: [markers[0].lng, markers[0].lat],\n zoom: this.zoom\n });\n }\n }\n\n clearMarkers() {\n this.mapMarkers.forEach(marker => {\n marker.remove();\n });\n this.mapMarkers = [];\n }\n\n addLineSource({ id, data, paint, layout }) {\n if (!id || !data) return;\n\n const sourceId = `${id}-source`;\n\n if (!this.map) {\n this.pendingLineData.set(id, { id, data, paint, layout });\n return;\n }\n\n if (this.map.getLayer(id)) {\n this.map.removeLayer(id);\n }\n if (this.map.getSource(sourceId)) {\n this.map.removeSource(sourceId);\n }\n\n this.map.addSource(sourceId, {\n type: 'geojson',\n data\n });\n\n this.map.addLayer({\n id,\n type: 'line',\n source: sourceId,\n paint: {\n 'line-color': '#3b82f6',\n 'line-width': 2,\n 'line-opacity': 0.6,\n ...paint\n },\n layout: {\n 'line-cap': 'round',\n 'line-join': 'round',\n ...layout\n }\n });\n }\n\n updateLineSource(id, { data, paint, layout } = {}) {\n if (!id || !data) return;\n const sourceId = `${id}-source`;\n if (!this.map) {\n this.pendingLineData.set(id, { id, data, paint, layout });\n return;\n }\n if (this.map.getSource(sourceId)) {\n this.map.getSource(sourceId).setData(data);\n if (paint || layout) {\n if (paint) {\n Object.entries(paint).forEach(([key, value]) => {\n this.map.setPaintProperty(id, key, value);\n });\n }\n if (layout) {\n Object.entries(layout).forEach(([key, value]) => {\n this.map.setLayoutProperty(id, key, value);\n });\n }\n }\n } else {\n this.addLineSource({ id, data, paint, layout });\n }\n }\n\n setView(lng, lat, zoom = null) {\n if (!this.map) return;\n this.map.flyTo({\n center: [lng, lat],\n zoom: zoom || this.zoom\n });\n }\n\n setZoom(zoom) {\n if (!this.map) return;\n this.map.setZoom(zoom);\n }\n\n setPitch(pitch) {\n if (!this.map) return;\n this.map.setPitch(pitch);\n }\n\n setBearing(bearing) {\n if (!this.map) return;\n this.map.setBearing(bearing);\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 MapLibreView;\n","// Auto-generated from countries.geojson - do not edit manually.\nexport const COUNTRY_CENTROIDS = {\n \"AD\": { name: \"Andorra\", lat: 42.54859834854764, lng: 1.5802243611232873 },\n \"AE\": { name: \"United Arab Emirates\", lat: 24.18250292309135, lng: 54.27920525789581 },\n \"AF\": { name: \"Afghanistan\", lat: 34.13402601376932, lng: 66.59216131095278 },\n \"AG\": { name: \"Antigua and Barbuda\", lat: 17.07146759372967, lng: -61.78530823226373 },\n \"AI\": { name: \"Anguilla\", lat: 18.222874004219086, lng: -63.06008343771806 },\n \"AL\": { name: \"Albania\", lat: 41.14165894891656, lng: 20.061082767269493 },\n \"AM\": { name: \"Armenia\", lat: 40.17841274230679, lng: 45.05490831965259 },\n \"AO\": { name: \"Angola\", lat: -12.167424062667942, lng: 17.651768783079 },\n \"AQ\": { name: \"Antarctica\", lat: -77.16987521415838, lng: -177.56451613408842 },\n \"AR\": { name: \"Argentina\", lat: -35.697270518120085, lng: -64.53238503843076 },\n \"AS\": { name: \"American Samoa\", lat: -14.305711987770538, lng: -170.7007316174498 },\n \"AT\": { name: \"Austria\", lat: 47.631858269895794, lng: 13.797778364631036 },\n \"AU\": { name: \"Australia\", lat: -25.697337673983082, lng: 134.02277170916162 },\n \"AW\": { name: \"Aruba\", lat: 12.515625722992898, lng: -69.97564014284046 },\n \"AZ\": { name: \"Azerbaijan\", lat: 40.3920509942049, lng: 48.634592670644324 },\n \"BA\": { name: \"Bosnia and Herzegovina\", lat: 44.14415356126429, lng: 17.83467240787538 },\n \"BB\": { name: \"Barbados\", lat: 13.183219369337529, lng: -59.557383949150285 },\n \"BD\": { name: \"Bangladesh\", lat: 23.673728665121, lng: 90.43212562608613 },\n \"BE\": { name: \"Belgium\", lat: 50.6182138854095, lng: 4.675010154696485 },\n \"BF\": { name: \"Burkina Faso\", lat: 12.108709036312737, lng: -1.6932816211842325 },\n \"BG\": { name: \"Bulgaria\", lat: 42.82043677302438, lng: 25.251739122561908 },\n \"BH\": { name: \"Bahrain\", lat: 26.04798501537066, lng: 50.540695402276775 },\n \"BI\": { name: \"Burundi\", lat: -3.261251993278643, lng: 29.88518227845293 },\n \"BJ\": { name: \"Benin\", lat: 9.503013199615893, lng: 2.305714528830206 },\n \"BL\": { name: \"Saint Barthelemy\", lat: 17.90561691241738, lng: -62.83051610005156 },\n \"BM\": { name: \"Bermuda\", lat: 32.315067430740726, lng: -64.7458500599169 },\n \"BN\": { name: \"Brunei Darussalam\", lat: 4.543205889917609, lng: 114.6430958360464 },\n \"BO\": { name: \"Bolivia\", lat: -16.7312488393574, lng: -64.45209597511206 },\n \"BQ\": { name: \"Bonaire\", lat: 12.180844982440338, lng: -68.29350445958761 },\n \"BQ\": { name: \"Saba\", lat: 17.632512616389718, lng: -63.23739481909494 },\n \"BQ\": { name: \"Saint Eustatius\", lat: 17.4919042294197, lng: -62.978230589445026 },\n \"BR\": { name: \"Brazil\", lat: -11.524630416426652, lng: -54.355206608256424 },\n \"BS\": { name: \"Bahamas\", lat: 24.72162633646784, lng: -78.07275370060313 },\n \"BT\": { name: \"Bhutan\", lat: 27.42163933959824, lng: 90.46716647173861 },\n \"BV\": { name: \"Bouvet Island\", lat: -54.42316679395248, lng: 3.411969465057627 },\n \"BW\": { name: \"Botswana\", lat: -22.236609002062902, lng: 23.85779956995608 },\n \"BY\": { name: \"Belarus\", lat: 53.46791374543163, lng: 27.964252054715104 },\n \"BZ\": { name: \"Belize\", lat: 17.24252476647155, lng: -88.68273510023441 },\n \"CA\": { name: \"Canada\", lat: 57.550480044655636, lng: -98.41680517868062 },\n \"CC\": { name: \"Cocos Islands\", lat: -12.171249450199545, lng: 96.83688767323002 },\n \"CD\": { name: \"Congo DRC\", lat: -3.338629596207896, lng: 23.419827574282188 },\n \"CF\": { name: \"Central African Republic\", lat: 6.331390033944319, lng: 20.520743419397256 },\n \"CG\": { name: \"Congo\", lat: -0.7294391595233845, lng: 14.879732849491393 },\n \"CH\": { name: \"Switzerland\", lat: 46.73678128684938, lng: 8.286928794895285 },\n \"CI\": { name: \"Côte d'Ivoire\", lat: 7.536779279421307, lng: -5.571710194917734 },\n \"CK\": { name: \"Cook Islands\", lat: -21.222613253399842, lng: -159.78768870952257 },\n \"CL\": { name: \"Chile\", lat: -37.82938283049967, lng: -70.76863431739216 },\n \"CM\": { name: \"Cameroon\", lat: 6.294168487480992, lng: 12.948474142398263 },\n \"CN\": { name: \"China\", lat: 38.07325481105728, lng: 104.69113855849604 },\n \"CO\": { name: \"Colombia\", lat: 4.187753877352739, lng: -72.6445066243485 },\n \"CR\": { name: \"Costa Rica\", lat: 9.863467407406214, lng: -84.14673625701816 },\n \"CU\": { name: \"Cuba\", lat: 21.476176522869448, lng: -79.69817857618705 },\n \"CV\": { name: \"Cabo Verde\", lat: 15.076411518651643, lng: -23.63401005900474 },\n \"CW\": { name: \"Curacao\", lat: 12.199996647939832, lng: -68.96939768599042 },\n \"CX\": { name: \"Christmas Island\", lat: -10.446440802183416, lng: 105.70209512200549 },\n \"CY\": { name: \"Cyprus\", lat: 35.11700416345239, lng: 33.375346009199205 },\n \"CZ\": { name: \"Czech Republic\", lat: 49.74917370930982, lng: 15.383273292023533 },\n \"DE\": { name: \"Germany\", lat: 51.08304539800482, lng: 10.426171427430804 },\n \"DJ\": { name: \"Djibouti\", lat: 11.750235727618804, lng: 42.613496898789506 },\n \"DK\": { name: \"Denmark\", lat: 56.00118817971057, lng: 9.378670542409406 },\n \"DM\": { name: \"Dominica\", lat: 15.429269860940513, lng: -61.360471946942994 },\n \"DO\": { name: \"Dominican Republic\", lat: 18.77954818522993, lng: -70.43495198520012 },\n \"DZ\": { name: \"Algeria\", lat: 28.350969744889056, lng: 2.6558464719769135 },\n \"EC\": { name: \"Ecuador\", lat: -1.5642721388853116, lng: -78.4630326109714 },\n \"EE\": { name: \"Estonia\", lat: 58.648108311231034, lng: 25.916870250633806 },\n \"EG\": { name: \"Egypt\", lat: 26.60517034450628, lng: 30.240135435012338 },\n \"ER\": { name: \"Eritrea\", lat: 15.005533147667684, lng: 39.2672401449901 },\n \"ES\": { name: \"Spain\", lat: 40.365008336683836, lng: -3.6516251409956983 },\n \"ES\": { name: \"Canarias\", lat: 28.297665106525546, lng: -16.53799441021647 },\n \"ET\": { name: \"Ethiopia\", lat: 8.729389557048396, lng: 39.914902886544276 },\n \"FI\": { name: \"Finland\", lat: 65.01578959749911, lng: 25.65738433454702 },\n \"FJ\": { name: \"Fiji\", lat: -17.822470952336204, lng: 177.98144613732626 },\n \"FK\": { name: \"Falkland Islands\", lat: -51.75901312766726, lng: -58.746646363799854 },\n \"FM\": { name: \"Micronesia\", lat: 6.8789448129255435, lng: 158.2291899444527 },\n \"FO\": { name: \"Faroe Islands\", lat: 62.130896281495346, lng: -6.9811060913122835 },\n \"FR\": { name: \"France\", lat: 46.6423682169416, lng: 2.1940236627886227 },\n \"GA\": { name: \"Gabon\", lat: -0.628448459921234, lng: 11.839410898545754 },\n \"GB\": { name: \"United Kingdom\", lat: 53.97844735080214, lng: -2.852943909329258 },\n \"GD\": { name: \"Grenada\", lat: 12.112926656338907, lng: -61.67937937204098 },\n \"GE\": { name: \"Georgia\", lat: 42.17986277737226, lng: 43.378866534112234 },\n \"GF\": { name: \"French Guiana\", lat: 3.857429742497078, lng: -53.32232307156624 },\n \"GG\": { name: \"Guernsey\", lat: 49.45870771378872, lng: -2.576392582891568 },\n \"GH\": { name: \"Ghana\", lat: 7.94530467243628, lng: -1.219233362526581 },\n \"GI\": { name: \"Gibraltar\", lat: 36.14022671336082, lng: -5.345549484594358 },\n \"GL\": { name: \"Greenland\", lat: 74.16847218965994, lng: -42.07567788066985 },\n \"GM\": { name: \"Gambia\", lat: 13.428617959189328, lng: -15.383380385869662 },\n \"GN\": { name: \"Guinea\", lat: 10.255986541378112, lng: -10.986948848040218 },\n \"GP\": { name: \"Guadeloupe\", lat: 16.24420002705553, lng: -61.54382262282755 },\n \"GQ\": { name: \"Equatorial Guinea\", lat: 1.5954643936590733, lng: 10.425456672353823 },\n \"GR\": { name: \"Greece\", lat: 39.42012261727978, lng: 23.110368936161876 },\n \"GS\": { name: \"South Georgia and South Sandwich Islands\", lat: -54.37666443862139, lng: -36.77509575898928 },\n \"GT\": { name: \"Guatemala\", lat: 15.820878515352684, lng: -90.31219349119617 },\n \"GU\": { name: \"Guam\", lat: 13.445430479945276, lng: 144.78024458298802 },\n \"GW\": { name: \"Guinea-Bissau\", lat: 11.980075324820504, lng: -14.980186756910847 },\n \"GY\": { name: \"Guyana\", lat: 4.68211981385056, lng: -58.91352612754667 },\n \"HM\": { name: \"Heard Island and McDonald Islands\", lat: -53.084170035513736, lng: 73.49298560844045 },\n \"HN\": { name: \"Honduras\", lat: 14.740370695750006, lng: -86.49251679006962 },\n \"HR\": { name: \"Croatia\", lat: 44.91192100856702, lng: 16.625761129583374 },\n \"HT\": { name: \"Haiti\", lat: 18.883520486983567, lng: -72.89291379842 },\n \"HU\": { name: \"Hungary\", lat: 47.22527332486294, lng: 19.39620048366142 },\n \"ID\": { name: \"Indonesia\", lat: 0.15591979959037652, lng: 113.96538246847302 },\n \"IE\": { name: \"Ireland\", lat: 53.30489539816495, lng: -8.241128545554096 },\n \"IL\": { name: \"Israel\", lat: 31.513542220043195, lng: 35.027923472437024 },\n \"IM\": { name: \"Isle of Man\", lat: 54.22855301008011, lng: -4.532995055468449 },\n \"IN\": { name: \"India\", lat: 23.586300567746722, lng: 81.17300408530181 },\n \"IO\": { name: \"British Indian Ocean Territory\", lat: -7.323548444385743, lng: 72.43501618476016 },\n \"IQ\": { name: \"Iraq\", lat: 33.105075667527906, lng: 43.832529181056884 },\n \"IR\": { name: \"Iran\", lat: 32.906023742890056, lng: 54.237077001065444 },\n \"IS\": { name: \"Iceland\", lat: 65.12360920205514, lng: -19.05682967106099 },\n \"IT\": { name: \"Italy\", lat: 42.98201127614267, lng: 12.763657166123137 },\n \"JE\": { name: \"Jersey\", lat: 49.215396925724306, lng: -2.1291601162653575 },\n \"JM\": { name: \"Jamaica\", lat: 18.12207889341651, lng: -77.30358894542778 },\n \"JO\": { name: \"Jordan\", lat: 31.387064884449156, lng: 36.95728884547246 },\n \"JP\": { name: \"Japan\", lat: 36.76738832597829, lng: 137.46934234351835 },\n \"KE\": { name: \"Kenya\", lat: 0.6899182318376179, lng: 37.95309411262371 },\n \"KG\": { name: \"Kyrgyzstan\", lat: 41.35698905438358, lng: 74.17532903468319 },\n \"KH\": { name: \"Cambodia\", lat: 12.699186865507775, lng: 105.03973078680701 },\n \"KI\": { name: \"Kiribati\", lat: 1.8676673749241066, lng: -157.39024189323504 },\n \"KM\": { name: \"Comoros\", lat: -11.658861474508491, lng: 43.34826587429403 },\n \"KN\": { name: \"Saint Kitts and Nevis\", lat: 17.314736299587768, lng: -62.74560385895787 },\n \"KP\": { name: \"North Korea\", lat: 40.19198091470839, lng: 127.3379805653744 },\n \"KR\": { name: \"South Korea\", lat: 36.402386712544114, lng: 127.76224551357649 },\n \"KW\": { name: \"Kuwait\", lat: 29.281360965443092, lng: 47.56311109320184 },\n \"KY\": { name: \"Cayman Islands\", lat: 19.311231805620288, lng: -81.25203208977878 },\n \"KZ\": { name: \"Kazakhstan\", lat: 47.641465195176835, lng: 66.3759193479301 },\n \"LA\": { name: \"Laos\", lat: 18.117282736873282, lng: 103.76375899026448 },\n \"LB\": { name: \"Lebanon\", lat: 33.91160170722086, lng: 35.89651946324749 },\n \"LC\": { name: \"Saint Lucia\", lat: 13.895749185129906, lng: -60.9689510935251 },\n \"LI\": { name: \"Liechtenstein\", lat: 47.14627562133036, lng: 9.547674672376376 },\n \"LK\": { name: \"Sri Lanka\", lat: 7.696630939329944, lng: 80.66931169770622 },\n \"LR\": { name: \"Liberia\", lat: 6.52012979398834, lng: -9.258988935497618 },\n \"LS\": { name: \"Lesotho\", lat: -29.60168116924817, lng: 28.24475317864227 },\n \"LT\": { name: \"Lithuania\", lat: 55.29437393417175, lng: 23.946021605013534 },\n \"LU\": { name: \"Luxembourg\", lat: 49.77523454542369, lng: 6.103230338458876 },\n \"LV\": { name: \"Latvia\", lat: 56.813853047554154, lng: 24.693671325654403 },\n \"LY\": { name: \"Libya\", lat: 27.202915771690794, lng: 17.91133392454237 },\n \"MA\": { name: \"Morocco\", lat: 28.687598134979325, lng: -8.817212587250811 },\n \"MC\": { name: \"Monaco\", lat: 43.74798224995656, lng: 7.412820873271196 },\n \"MD\": { name: \"Moldova\", lat: 47.0725674580696, lng: 28.391111865941348 },\n \"ME\": { name: \"Montenegro\", lat: 42.73694835210454, lng: 19.29505087156758 },\n \"MF\": { name: \"Saint Martin\", lat: 18.078012113224464, lng: -63.06678525361946 },\n \"MG\": { name: \"Madagascar\", lat: -19.04163612493041, lng: 46.68493466832544 },\n \"MH\": { name: \"Marshall Islands\", lat: 7.307929900994344, lng: 168.72016025351076 },\n \"MK\": { name: \"North Macedonia\", lat: 41.59402890143112, lng: 21.70998923872772 },\n \"ML\": { name: \"Mali\", lat: 17.168146208584837, lng: -4.346399841781153 },\n \"MM\": { name: \"Myanmar\", lat: 19.901227931399873, lng: 97.08892285397344 },\n \"MN\": { name: \"Mongolia\", lat: 47.08644454604851, lng: 103.3987360327455 },\n \"MP\": { name: \"Northern Mariana Islands\", lat: 15.178063516432115, lng: 145.74119737203134 },\n \"MQ\": { name: \"Martinique\", lat: 14.642697353597645, lng: -61.01432380875083 },\n \"MR\": { name: \"Mauritania\", lat: 20.466731212820022, lng: -10.495079045035716 },\n \"MS\": { name: \"Montserrat\", lat: 16.735363391460357, lng: -62.18693281256255 },\n \"MT\": { name: \"Malta\", lat: 35.890522650899314, lng: 14.441922442508494 },\n \"MU\": { name: \"Mauritius\", lat: -20.28142317475198, lng: 57.56415671066546 },\n \"MV\": { name: \"Maldives\", lat: -0.6065577168009924, lng: 73.10076245140479 },\n \"MW\": { name: \"Malawi\", lat: -13.128986464184024, lng: 34.23441182298881 },\n \"MX\": { name: \"Mexico\", lat: 23.87436068093592, lng: -101.55399731630118 },\n \"MY\": { name: \"Malaysia\", lat: 3.6716608556387857, lng: 114.63330303992869 },\n \"MZ\": { name: \"Mozambique\", lat: -17.525230309488748, lng: 35.208577031290176 },\n \"NA\": { name: \"Namibia\", lat: -21.90858163281473, lng: 18.16451345845268 },\n \"NC\": { name: \"New Caledonia\", lat: -21.33003372660827, lng: 165.50767040438612 },\n \"NE\": { name: \"Niger\", lat: 17.08105392407292, lng: 8.86863247002646 },\n \"NF\": { name: \"Norfolk Island\", lat: -29.037654445046282, lng: 167.95259597483337 },\n \"NG\": { name: \"Nigeria\", lat: 9.61029352034213, lng: 8.147714845256194 },\n \"NI\": { name: \"Nicaragua\", lat: 12.893566631930554, lng: -85.016088327669 },\n \"NL\": { name: \"Netherlands\", lat: 52.134054128923886, lng: 5.554136426128487 },\n \"NO\": { name: \"Norway\", lat: 64.97775882947745, lng: 16.670259272390894 },\n \"NP\": { name: \"Nepal\", lat: 28.300920699755657, lng: 84.1338898313567 },\n \"NR\": { name: \"Nauru\", lat: -0.5221021440668993, lng: 166.92937633139178 },\n \"NU\": { name: \"Niue\", lat: -19.05230921680393, lng: -169.86878106699083 },\n \"NZ\": { name: \"New Zealand\", lat: -43.82765432544426, lng: 170.69035541428696 },\n \"OM\": { name: \"Oman\", lat: 20.7242833183209, lng: 55.841088119829 },\n \"PA\": { name: \"Panama\", lat: 8.439536749576892, lng: -80.14428761482796 },\n \"PE\": { name: \"Peru\", lat: -8.522717984240291, lng: -74.11416196781884 },\n \"PF\": { name: \"French Polynesia\", lat: -17.674684080120677, lng: -149.40041671099763 },\n \"PG\": { name: \"Papua New Guinea\", lat: -7.156912819152135, lng: 144.8348942994695 },\n \"PH\": { name: \"Philippines\", lat: 15.586542251094242, lng: 121.82208941416745 },\n \"PK\": { name: \"Pakistan\", lat: 30.116188371410882, lng: 69.08835090769651 },\n \"PL\": { name: \"Poland\", lat: 52.06848055692473, lng: 19.43573279234468 },\n \"PM\": { name: \"Saint Pierre and Miquelon\", lat: 46.95153913615198, lng: -56.32465353437558 },\n \"PN\": { name: \"Pitcairn\", lat: -24.366121747565458, lng: -128.3149848627581 },\n \"PR\": { name: \"Puerto Rico\", lat: 18.216224086610914, lng: -66.49425339593509 },\n \"PS\": { name: \"Palestinian Territory\", lat: 31.930818736453883, lng: 35.24251184154588 },\n \"PT\": { name: \"Portugal\", lat: 39.67529214702138, lng: -7.933662183874006 },\n \"PW\": { name: \"Palau\", lat: 7.534775852547396, lng: 134.57965086721052 },\n \"PY\": { name: \"Paraguay\", lat: -23.42190559259428, lng: -58.38906357428651 },\n \"QA\": { name: \"Qatar\", lat: 25.318528486425386, lng: 51.19794918743203 },\n \"RE\": { name: \"Réunion\", lat: -21.119825460665105, lng: 55.54393506194689 },\n \"RO\": { name: \"Romania\", lat: 45.82454894397586, lng: 25.094158201563292 },\n \"RS\": { name: \"Serbia\", lat: 44.02679870131969, lng: 20.85677444395745 },\n \"RU\": { name: \"Russian Federation\", lat: 59.039434214106194, lng: 98.6704990698032 },\n \"RW\": { name: \"Rwanda\", lat: -2.014687460047154, lng: 29.919439681764082 },\n \"SA\": { name: \"Saudi Arabia\", lat: 24.136038144757897, lng: 44.600958178225596 },\n \"SB\": { name: \"Solomon Islands\", lat: -9.613104734596515, lng: 160.16475795033884 },\n \"SC\": { name: \"Seychelles\", lat: -4.660002318822744, lng: 55.47250789595527 },\n \"SD\": { name: \"Sudan\", lat: 15.67060230984256, lng: 29.951458283594064 },\n \"SE\": { name: \"Sweden\", lat: 62.73420986108448, lng: 17.062431988004956 },\n \"SG\": { name: \"Singapore\", lat: 1.3528251890006349, lng: 103.81025757634053 },\n \"SH\": { name: \"Saint Helena\", lat: -15.962963318340398, lng: -5.717391620813109 },\n \"SI\": { name: \"Slovenia\", lat: 46.13759229564504, lng: 14.890636899973781 },\n \"SJ\": { name: \"Svalbard\", lat: 78.57318936469626, lng: 16.036378851505283 },\n \"SK\": { name: \"Slovakia\", lat: 48.69808390520484, lng: 19.581015362490966 },\n \"SL\": { name: \"Sierra Leone\", lat: 8.561330384750587, lng: -11.78656695731115 },\n \"SM\": { name: \"San Marino\", lat: 43.942820729097896, lng: 12.461278349581722 },\n \"SN\": { name: \"Senegal\", lat: 14.228861491763402, lng: -14.610875368352305 },\n \"SO\": { name: \"Somalia\", lat: 6.524534573103924, lng: 45.40037867243972 },\n \"SR\": { name: \"Suriname\", lat: 4.098723595920171, lng: -55.855514311561286 },\n \"SS\": { name: \"South Sudan\", lat: 7.657782041763295, lng: 30.3851856901788 },\n \"ST\": { name: \"Sao Tome and Principe\", lat: 0.22744704294793774, lng: 6.606158796857607 },\n \"SV\": { name: \"El Salvador\", lat: 13.758041517055418, lng: -88.85911489238985 },\n \"SX\": { name: \"Sint Maarten\", lat: 18.03942608463078, lng: -63.06883135915303 },\n \"SY\": { name: \"Syria\", lat: 35.09751106058316, lng: 38.5117323139514 },\n \"SZ\": { name: \"Eswatini\", lat: -26.562540935608702, lng: 31.510685746082007 },\n \"TC\": { name: \"Turks and Caicos Islands\", lat: 21.799865427483745, lng: -71.74058946811508 },\n \"TD\": { name: \"Chad\", lat: 15.283493546654503, lng: 18.427113900363025 },\n \"TF\": { name: \"Juan De Nova Island\", lat: -17.06449193630804, lng: 42.74374761089645 },\n \"TF\": { name: \"French Southern Territories\", lat: -49.26329687105643, lng: 69.54686984724839 },\n \"TF\": { name: \"Glorioso Islands\", lat: -11.566224871643417, lng: 47.290948081543384 },\n \"TG\": { name: \"Togo\", lat: 8.660743037717811, lng: 0.8990857571109684 },\n \"TH\": { name: \"Thailand\", lat: 13.66222784745538, lng: 101.08675116214552 },\n \"TJ\": { name: \"Tajikistan\", lat: 38.56933138382972, lng: 70.94215281065698 },\n \"TK\": { name: \"Tokelau\", lat: -9.195174767256544, lng: -171.85265950722743 },\n \"TL\": { name: \"Timor-Leste\", lat: -8.809894630601962, lng: 125.95024049562659 },\n \"TM\": { name: \"Turkmenistan\", lat: 39.06069118001429, lng: 58.4577357627054 },\n \"TN\": { name: \"Tunisia\", lat: 34.08636179565723, lng: 9.65587551697984 },\n \"TO\": { name: \"Tonga\", lat: -21.15927212823853, lng: -175.20415878511247 },\n \"TR\": { name: \"Turkey\", lat: 38.93207363123396, lng: 35.56886764076691 },\n \"TT\": { name: \"Trinidad and Tobago\", lat: 10.415515638298093, lng: -61.37236579976247 },\n \"TV\": { name: \"Tuvalu\", lat: -8.514701506447222, lng: 179.217833977593 },\n \"TZ\": { name: \"Tanzania\", lat: -6.355794440041147, lng: 34.81832206060381 },\n \"UA\": { name: \"Ukraine\", lat: 48.657532515563794, lng: 31.27377208442636 },\n \"UG\": { name: \"Uganda\", lat: 1.2821729218416205, lng: 32.34371768463123 },\n \"UM\": { name: \"United States Minor Outlying Islands\", lat: 19.302045812215958, lng: 166.63800339749642 },\n \"US\": { name: \"United States\", lat: 38.8208089190304, lng: -96.33161660829639 },\n \"UY\": { name: \"Uruguay\", lat: -32.78195043831093, lng: -56.01919523458085 },\n \"UZ\": { name: \"Uzbekistan\", lat: 41.4879065244633, lng: 63.8548297593985 },\n \"VA\": { name: \"Vatican City\", lat: 41.90402351316735, lng: 12.451312917026133 },\n \"VC\": { name: \"Saint Vincent and the Grenadines\", lat: 13.254808122970651, lng: -61.193766354393034 },\n \"VE\": { name: \"Venezuela\", lat: 7.148324760507107, lng: -66.36492135985132 },\n \"VG\": { name: \"British Virgin Islands\", lat: 18.42195819619707, lng: -64.62406519257699 },\n \"VI\": { name: \"US Virgin Islands\", lat: 17.738009708772523, lng: -64.76155341409797 },\n \"VN\": { name: \"Vietnam\", lat: 16.517347170839393, lng: 105.91338832758704 },\n \"VU\": { name: \"Vanuatu\", lat: -15.189132121699332, lng: 166.84912735669738 },\n \"WF\": { name: \"Wallis and Futuna\", lat: -14.283442307826677, lng: -178.12735555777184 },\n \"WS\": { name: \"Samoa\", lat: -13.634252953274622, lng: -172.44107655740137 },\n \"YE\": { name: \"Yemen\", lat: 16.001392616307445, lng: 47.46815793206386 },\n \"YT\": { name: \"Mayotte\", lat: -12.824468416301052, lng: 45.128142327031064 },\n \"ZA\": { name: \"South Africa\", lat: -28.55361930679731, lng: 24.75252746489084 },\n \"ZM\": { name: \"Zambia\", lat: -13.162832953186246, lng: 27.75521363430896 },\n \"ZW\": { name: \"Zimbabwe\", lat: -18.92700121981475, lng: 29.717829640720844 },\n};\n\nexport function getCountryCentroid(code) {\n if (!code) return null;\n return COUNTRY_CENTROIDS[code.toUpperCase()] || null;\n}\n\nexport function getCountryCentroids() {\n return COUNTRY_CENTROIDS;\n}","import View from '@core/View.js';\nimport MapLibreView from './MapLibreView.js';\nimport { COUNTRY_CENTROIDS } from './countryCentroids.js';\n\nclass MetricsCountryMapView extends View {\n constructor(options = {}) {\n const mapHeight = options.height || 320;\n super({\n className: 'metrics-country-map-view',\n ...options\n });\n\n this.endpoint = options.endpoint || '/api/metrics/fetch';\n this.account = options.account || 'global';\n this.category = options.category || null;\n this.slugs = options.slugs || null;\n this.granularity = options.granularity || 'days';\n this.maxCountries = options.maxCountries || 12;\n this.metricLabel = options.metricLabel || 'Events';\n this.height = mapHeight;\n this.mapStyle = options.mapStyle || 'dark';\n this.mapOptions = options.mapOptions || {};\n this.showRoutes = options.showRoutes !== false;\n this.routeOrigin = options.routeOrigin || { lng: -77.346, lat: 38.958, name: 'Reston, VA' };\n this._refreshing = false;\n }\n\n async getTemplate() {\n return `\n <div class=\"metrics-country-map\">\n <div class=\"map-container mb-3\" data-container=\"${this.id}-map\" style=\"height:${this.height}px\"></div>\n <div class=\"map-legend small\" data-region=\"legend\"></div>\n </div>\n `;\n }\n\n async onInit() {\n this.statusEl = document.createElement('div');\n this.statusEl.className = 'text-muted small px-3 pb-2';\n this.element.appendChild(this.statusEl);\n\n this.mapView = new MapLibreView({\n containerId: `${this.id}-map`,\n height: this.height,\n style: this.mapStyle,\n zoom: this.mapOptions.zoom ?? 1.3,\n center: this.mapOptions.center || [10, 20],\n pitch: this.mapOptions.pitch ?? 20,\n bearing: this.mapOptions.bearing ?? 0,\n showNavigationControl: this.mapOptions.showNavigationControl ?? true,\n autoFitBounds: this.mapOptions.autoFitBounds ?? false,\n interactive: this.mapOptions.interactive,\n scrollZoom: this.mapOptions.scrollZoom,\n dragPan: this.mapOptions.dragPan,\n doubleClickZoom: this.mapOptions.doubleClickZoom,\n keyboard: this.mapOptions.keyboard,\n touchZoom: this.mapOptions.touchZoom\n });\n this.addChild(this.mapView);\n await this.refresh();\n }\n\n async refresh() {\n if (this._refreshing) return;\n this._refreshing = true;\n this.setStatus('Loading hotspots…');\n try {\n const metrics = await this.fetchMetrics();\n await this.applyMetrics(metrics);\n this.setStatus('');\n } catch (error) {\n console.error('MetricsCountryMapView refresh error', error);\n this.setStatus('Unable to load country metrics.');\n } finally {\n this._refreshing = false;\n }\n }\n\n async fetchMetrics() {\n const rest = this.getApp()?.rest;\n if (!rest) {\n throw new Error('REST client unavailable');\n }\n const params = {\n account: this.account,\n granularity: this.granularity,\n with_labels: true\n };\n if (this.category) params.category = this.category;\n if (this.slugs) {\n const slugsArray = Array.isArray(this.slugs) ? this.slugs : [this.slugs];\n params['slugs[]'] = slugsArray;\n }\n\n const response = await rest.GET(this.endpoint, params);\n if (!response.success || !response.data?.status) {\n throw new Error(response.data?.error || 'Metrics API error');\n }\n return response.data.data;\n }\n\n async applyMetrics(data) {\n const metrics = data?.data || {};\n const labels = data?.labels || [];\n const entries = [];\n\n Object.entries(metrics).forEach(([iso, series]) => {\n const total = series.reduce((sum, value) => sum + (Number(value) || 0), 0);\n if (!total) return;\n const centroid = COUNTRY_CENTROIDS[iso.toUpperCase()];\n if (!centroid) return;\n entries.push({\n code: iso.toUpperCase(),\n total,\n values: series,\n centroid\n });\n });\n\n if (!entries.length) {\n this.mapView.updateMarkers([]);\n this.renderLegend([]);\n this.setStatus('No country data available for the selected range.');\n return;\n }\n\n entries.sort((a, b) => b.total - a.total);\n const topEntries = entries.slice(0, this.maxCountries);\n const maxValue = topEntries[0]?.total || 1;\n\n const markers = topEntries.map(entry => {\n const intensity = entry.total / maxValue;\n const markerSize = Math.round(18 + intensity * 24);\n return {\n lng: entry.centroid.lng,\n lat: entry.centroid.lat,\n size: markerSize,\n color: this.getMarkerColor(intensity),\n popup: `\n <div class=\"text-center\">\n <strong>${entry.centroid.name}</strong><br/>\n <span class=\"text-muted\">${entry.total.toLocaleString()} ${this.metricLabel}</span>\n </div>\n `\n };\n });\n\n if (this.showRoutes && this.routeOrigin?.lng && this.routeOrigin?.lat) {\n markers.push({\n lng: this.routeOrigin.lng,\n lat: this.routeOrigin.lat,\n size: 26,\n color: '#0d6efd',\n icon: 'bi bi-broadcast-pin',\n popup: `\n <div class=\"text-center\">\n <strong>${this.routeOrigin.name || 'Operations Hub'}</strong><br/>\n <span class=\"text-muted\">Origin</span>\n </div>\n `\n });\n }\n\n this.mapView.updateMarkers(markers);\n this.renderLegend(topEntries, labels);\n if (this.showRoutes) {\n this.renderRoutes(topEntries, maxValue);\n }\n }\n\n getMarkerColor(intensity) {\n const start = [32, 201, 151]; // teal\n const end = [255, 193, 7]; // amber\n const mix = start.map((value, idx) =>\n Math.round(value + (end[idx] - value) * intensity)\n );\n return `rgba(${mix[0]}, ${mix[1]}, ${mix[2]}, 0.9)`;\n }\n\n renderLegend(entries) {\n const legendEl = this.element.querySelector('[data-region=\"legend\"]');\n if (!legendEl) return;\n if (!entries.length) {\n legendEl.innerHTML = '';\n return;\n }\n\n const maxValue = entries[0]?.total || 1;\n const rows = entries.map(entry => {\n const percent = ((entry.total / maxValue) * 100).toFixed(0);\n return `\n <div class=\"d-flex justify-content-between align-items-center py-1 border-top\">\n <div>\n <span class=\"fw-semibold\">${entry.centroid.name}</span>\n <span class=\"text-muted ms-1\">(${entry.code})</span>\n </div>\n <div class=\"text-end\">\n <div class=\"fw-semibold\">${entry.total.toLocaleString()}</div>\n <small class=\"text-muted\">${percent}% of top</small>\n </div>\n </div>\n `;\n }).join('');\n\n legendEl.innerHTML = rows;\n }\n\n renderRoutes(entries, maxValue) {\n const origin = this.routeOrigin || null;\n if (!origin || !origin.lng || !origin.lat || !this.mapView) return;\n\n const features = entries.map(entry => ({\n type: 'Feature',\n geometry: {\n type: 'LineString',\n coordinates: [\n [origin.lng, origin.lat],\n [entry.centroid.lng, entry.centroid.lat]\n ]\n },\n properties: {\n total: entry.total,\n intensity: entry.total / maxValue\n }\n }));\n\n const geojson = {\n type: 'FeatureCollection',\n features\n };\n\n const paint = {\n 'line-color': [\n 'interpolate',\n ['linear'],\n ['get', 'intensity'],\n 0,\n 'rgba(32, 201, 151, 0.6)',\n 1,\n 'rgba(255, 193, 7, 0.95)'\n ],\n 'line-width': [\n 'interpolate',\n ['linear'],\n ['get', 'intensity'],\n 0,\n 1.75,\n 1,\n 6\n ],\n 'line-opacity': [\n 'interpolate',\n ['linear'],\n ['get', 'intensity'],\n 0,\n 0.45,\n 1,\n 0.95\n ]\n };\n\n this.mapView.lineSources = this.mapView.lineSources.filter(src => src.id !== `${this.id}-routes`);\n this.mapView.updateLineSource(`${this.id}-routes`, {\n data: geojson,\n paint\n });\n }\n\n setStatus(message) {\n if (!this.statusEl) return;\n this.statusEl.textContent = message || '';\n this.statusEl.style.display = message ? 'block' : 'none';\n }\n\n}\n\nexport default MetricsCountryMapView;\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","interactive","scrollZoom","dragPan","doubleClickZoom","keyboard","touchZoom","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","scrollWheelZoom","dragging","boxZoom","tap","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","MapLibreView","pitch","bearing","mapStyle","showNavigationControl","autoFitBounds","mapMarkers","pendingMarkers","lineSources","pendingLineData","Map","loadMapLibre","maplibregl","getMapStyle","styles","version","sources","type","tiles","tileSize","layers","source","glyphs","touchZoomRotate","addControl","NavigationControl","on","initialMarkers","addLineSource","clear","color","el","markerSize","Number","width","borderRadius","backgroundColor","border","boxShadow","cursor","display","alignItems","justifyContent","innerHTML","Marker","setLngLat","mapPopup","Popup","offset","setHTML","setPopup","bounds","LngLatBounds","extend","padding","flyTo","data","paint","layout","sourceId","getLayer","getSource","removeSource","addSource","addLayer","set","updateLineSource","setData","setPaintProperty","setLayoutProperty","setPitch","setBearing","COUNTRY_CENTROIDS","AD","name","AE","AF","AG","AI","AL","AM","AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ","BL","BM","BN","BO","BQ","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF","CG","CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CW","CX","CY","CZ","DE","DJ","DK","DM","DO","DZ","EC","EE","EG","ER","ES","ET","FI","FJ","FK","FM","FO","FR","GA","GB","GD","GE","GF","GG","GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HM","HN","HR","HT","HU","ID","IE","IL","IM","IN","IO","IQ","IR","IS","IT","JE","JM","JO","JP","KE","KG","KH","KI","KM","KN","KP","KR","KW","KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","ME","MF","MG","MH","MK","ML","MM","MN","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY","QA","RE","RO","RS","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO","SR","SS","ST","SV","SX","SY","SZ","TC","TD","TF","TG","TH","TJ","TK","TL","TM","TN","TO","TR","TT","TV","TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE","YT","ZA","ZM","ZW","MetricsCountryMapView","mapHeight","endpoint","account","category","slugs","granularity","maxCountries","metricLabel","mapOptions","showRoutes","routeOrigin","_refreshing","getTemplate","onInit","statusEl","mapView","containerId","addChild","refresh","setStatus","metrics","fetchMetrics","applyMetrics","error","console","rest","Error","params","with_labels","slugsArray","response","GET","success","status","labels","iso","series","total","reduce","sum","centroid","toUpperCase","code","values","renderLegend","sort","a","b","topEntries","slice","maxValue","entry","intensity","Math","round","getMarkerColor","toLocaleString","renderRoutes","end","mix","idx","legendEl","rows","percent","toFixed","join","origin","geojson","features","geometry","coordinates","properties","filter","message"],"mappings":"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"}
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
"use strict";const e=require("./View-CPWwS19u.js"),t=require("./Collection-C0pHSKDH.js"),i=require("./User-9qvKV7G6.js");class ToastService{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=/* @__PURE__ */new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",i={}){this.enforceMaxToasts();const o="toast-"+ ++this.toastCounter,s={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...i},n=this.createToastElement(o,e,t,s);if(this.container.appendChild(n),"undefined"==typeof bootstrap)throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:s.autohide,delay:s.delay});return this.toasts.set(o,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(o)}),a.show(),{id:o,hide:()=>{try{a.hide()}catch(e){console.warn("Error hiding toast:",e)}},dispose:()=>this.cleanup(o),updateProgress:i.updateProgress||null}}showView(e,t="info",i={}){this.enforceMaxToasts();const o="toast-"+ ++this.toastCounter,s={title:i.title||this.getDefaultTitle(t),icon:i.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...i},n=this.createViewToastElement(o,e,t,s);if(this.container.appendChild(n),"undefined"==typeof bootstrap)throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:s.autohide,delay:s.delay});this.toasts.set(o,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(o)});const r=n.querySelector(".toast-view-body");return r&&e&&e.render(!0,r),a.show(),{id:o,view:e,hide:()=>{try{a.hide()}catch(e){console.warn("Error hiding view toast:",e)}},dispose:()=>this.cleanupView(o),updateProgress:t=>{e&&"function"==typeof e.updateProgress&&e.updateProgress(t)}}}createToastElement(e,t,i,o){const s=document.createElement("div");s.id=e,s.className=`toast toast-service-${i}${o.size?` toast-${o.size}`:""}`,s.setAttribute("role","alert"),s.setAttribute("aria-live","assertive"),s.setAttribute("aria-atomic","true");const n=o.title||o.icon?this.createToastHeader(o,i):"",a=this.createToastBody(t,o.icon&&!o.title);return s.innerHTML=`\n ${n}\n ${a}\n `,s}createViewToastElement(e,t,i,o){const s=document.createElement("div");s.id=e,s.className=`toast toast-service-${i}${o.size?` toast-${o.size}`:""}`,s.setAttribute("role","alert"),s.setAttribute("aria-live","assertive"),s.setAttribute("aria-atomic","true");const n=o.title||o.icon?this.createToastHeader(o,i):"",a=this.createViewToastBody();return s.innerHTML=`\n ${n}\n ${a}\n `,s}createViewToastBody(){return'\n <div class="toast-body p-0">\n <div class="toast-view-body p-3"></div>\n </div>\n '}createToastHeader(e,t){const i=e.icon?`<i class="${e.icon} toast-service-icon me-2"></i>`:"",o=e.title?`<strong class="me-auto">${i}${this.escapeHtml(e.title)}</strong>`:"",s=e.showTime?`<small class="text-muted">${this.getTimeString()}</small>`:"",n=e.dismissible?'<button type="button" class="btn-close toast-service-close" data-bs-dismiss="toast" aria-label="Close"></button>':"";return o||s||n?`\n <div class="toast-header">\n ${o}\n ${s}\n ${n}\n </div>\n `:""}createToastBody(e,t=!1){return`\n <div class="toast-body d-flex align-items-center">\n ${t?`<i class="${this.getDefaultIcon("info")} toast-service-icon me-2"></i>`:""}\n <span>${this.escapeHtml(e)}</span>\n </div>\n `}getDefaultTitle(e){return{success:"Success",error:"Error",warning:"Warning",info:"Information",plain:""}[e]||"Notification"}getDefaultIcon(e){return{success:"bi-check-circle-fill",error:"bi-exclamation-triangle-fill",warning:"bi-exclamation-triangle-fill",info:"bi-info-circle-fill",plain:""}[e]||"bi-info-circle-fill"}enforceMaxToasts(){if(Array.from(this.toasts.values()).length>=this.options.maxToasts){const e=this.toasts.keys().next().value,t=this.toasts.get(e);t&&t.bootstrap.hide()}}cleanup(e){const t=this.toasts.get(e);if(t){try{t.bootstrap.dispose()}catch(i){console.warn("Error disposing toast:",i)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}cleanupView(e){const t=this.toasts.get(e);if(t){if(t.view&&"function"==typeof t.view.dispose)try{t.view.dispose()}catch(i){console.warn("Error disposing view in toast:",i)}try{t.bootstrap.dispose()}catch(i){console.warn("Error disposing toast:",i)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}hideAll(){this.toasts.forEach((e,t)=>{e.bootstrap.hide()})}clearAll(){this.toasts.forEach((e,t)=>{this.cleanup(t)})}getTimeString(){/* @__PURE__ */
|
|
2
|
-
return(new Date).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}dispose(){this.clearAll(),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container)}getStats(){const e={total:this.toasts.size,byType:{}};return this.toasts.forEach(t=>{e.byType[t.type]=(e.byType[t.type]||0)+1}),e}setOptions(e){this.options={...this.options,...e},e.position&&this.container&&(this.container.className=`toast-container position-fixed ${this.getPositionClasses()}`)}}class ProgressView extends e.View{constructor(e={}){super({template:"progress-view-template",...e}),this.filename=e.filename||"Unknown file",this.filesize=e.filesize||0,this.filesizeFormatted=t.dataFormatter.pipe(this.filesize,"filesize"),this.progress=0,this.percentage=0,this.loaded=0,this.total=this.filesize,this.loadedFormatted="0 B",this.totalFormatted=this.filesizeFormatted,this.status="Starting upload...",this.showCancel=!1!==e.showCancel,this.onCancel=e.onCancel||null,this.cancelled=!1,this.completed=!1}getTemplate(){return'\n <div class="progress-view">\n <div class="d-flex justify-content-between align-items-start mb-2">\n <div class="flex-grow-1 min-width-0">\n <div class="fw-medium text-truncate" title="{{filename}}">\n <i class="bi bi-file-earmark me-1"></i>\n {{filename}}\n </div>\n <small class="text-muted">{{status}}</small>\n </div>\n {{#showCancel}}\n <button type="button" \n class="btn btn-sm btn-outline-secondary ms-2" \n data-action="cancel"\n {{#cancelled}}disabled{{/cancelled}}>\n <i class="bi bi-x"></i>\n </button>\n {{/showCancel}}\n </div>\n \n <div class="progress mb-2" style="height: 8px;">\n <div class="progress-bar" \n role="progressbar" \n style="width: {{percentage}}%"\n aria-valuenow="{{percentage}}" \n aria-valuemin="0" \n aria-valuemax="100">\n </div>\n </div>\n \n <div class="d-flex justify-content-between">\n <small class="text-muted">\n {{loadedFormatted}} / {{totalFormatted}}\n </small>\n <small class="text-muted">\n {{percentage}}%\n </small>\n </div>\n </div>\n '}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=t.dataFormatter.pipe(this.loaded,"filesize"),this.totalFormatted=t.dataFormatter.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,i){if(!this.cancelled&&!this.completed&&(i.disabled=!0,this.markCancelled(),this.emit("cancel"),"function"==typeof this.onCancel))try{await this.onCancel()}catch(o){console.error("Error in cancel callback:",o)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=t.dataFormatter.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class FileUpload{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!(this.options.file&&this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new ToastService),this.promise=this._startUpload()}async _startUpload(){try{let t,i,o;this.options.showToast&&this._showProgressToast();try{t=await this._initiateUpload()}catch(e){throw new Error(`Failed to initiate upload: ${e.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!t||!t.upload_url)throw new Error("Invalid upload response: missing upload URL");if("string"==typeof t.upload_url)i={url:t.upload_url,method:"PUT",fields:null,headers:{}};else{if(!t.upload_url||"object"!=typeof t.upload_url||!t.upload_url.upload_url)throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(t.upload_url)}`);i={url:t.upload_url.upload_url,method:t.upload_url.method||"POST",fields:t.upload_url.fields||null,headers:t.upload_url.headers||{}}}try{o=await this._performUpload(i)}catch(e){throw new Error(`File upload failed: ${e.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(e){console.warn("Failed to mark upload as completed:",e)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw"Upload cancelled"!==e.message&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const e=t.data.error||"Upload initiation failed";throw new Error(e)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){if("Network Error"===e.message||"TypeError"===e.name)throw new Error("Network error during upload initiation. Please check your connection.");throw e}}async _performUpload(e){return new Promise((t,i)=>{if(!(this.options.file instanceof File))return void i(new Error("Only single File objects are supported"));const{url:o,method:s,fields:n,headers:a}=e,r="POST"===s&&null!==n,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=e=>{this.cancelled||this._onProgress({progress:e.loaded/e.total,loaded:e.loaded,total:e.total,percentage:Math.round(e.loaded/e.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):i(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>i(new Error("Upload failed: Network error")),l.ontimeout=()=>i(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>i(new Error("Upload cancelled"));let d=o;o.startsWith("/")&&!o.startsWith("/api/")&&(d="/api"+o);const c=this.fileModel.rest.buildUrl(d);if(l.open(s,c),l.timeout=3e4,r){for(const[t,i]of Object.entries(a||{}))"content-type"!==t.toLowerCase()&&l.setRequestHeader(t,i);const e=new FormData;for(const[t,i]of Object.entries(n))e.append(t,i);e.append("file",this.options.file),l.send(e)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[e,t]of Object.entries(a||{}))"content-type"!==e.toLowerCase()&&l.setRequestHeader(e,t);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){if("Network Error"===e.message||"TypeError"===e.name)throw new Error("Network error during upload completion. The file may have uploaded successfully.");throw e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),"function"==typeof this.options.onProgress&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&"function"==typeof this.progressToast.hide&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast:",e)}},2e3),"function"==typeof this.options.onComplete&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),"function"==typeof this.options.onError&&this.options.onError(e)}_showProgressToast(){this.progressView=new ProgressView({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return!this.cancelled&&(this.cancelled=!0,this.uploadRequest&&"function"==typeof this.uploadRequest.abort&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&"function"==typeof this.progressToast.hide&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class FileManager extends t.Model{constructor(e={}){super(e,{endpoint:"/api/fileman/manager"})}}class FileManagerList extends t.Collection{constructor(e={}){super({ModelClass:FileManager,endpoint:"/api/fileman/manager",size:10,...e})}}const o={create:{title:"Add Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,value:"s3://BUCKET_NAME/OPTION_FOLDER",placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6}]},edit:{title:"Edit Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"allowed_origins",type:"text",label:"Domains Who Can Upload",cols:12},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6},{name:"is_public",type:"switch",label:"Is Public",default:!0,cols:6}]},owners:{fields:[{type:"collection",name:"group",label:"Group (Owner)",Collection:i.GroupList,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{type:"collection",name:"user",label:"User (Owner)",Collection:i.UserList,labelField:"display_name",valueField:"id",maxItems:10,placeholder:"Search users...",emptyFetch:!1,debounceMs:300}]},credentials:{fields:[{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"}]}};let s=class extends t.Model{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return"image"===this.get("category")}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":"application/pdf"===e?"pdf":e.startsWith("text/")||"application/msword"===e||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||"application/vnd.oasis.opendocument.text"===e?"document":"application/vnd.ms-excel"===e||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||"application/vnd.oasis.opendocument.spreadsheet"===e?"spreadsheet":"application/vnd.ms-powerpoint"===e||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||"application/vnd.oasis.opendocument.presentation"===e?"presentation":"application/zip"===e||"application/x-rar-compressed"===e||"application/x-7z-compressed"===e||"application/x-tar"===e||"application/gzip"===e?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!(!e||!Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!(!e||"completed"===e||"failed"===e)}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const i=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,i)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(e=>e&&"string"==typeof e.content_type&&e.content_type.startsWith("image/"));return e.length?e.reduce((e,t)=>{const i=(parseInt(e.width)||0)*(parseInt(e.height)||0);return(parseInt(t.width)||0)*(parseInt(t.height)||0)>i?t:e}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new FileUpload(this,e)}};class FileList extends t.Collection{constructor(e={}){super({ModelClass:s,endpoint:"/api/fileman/file",size:10,...e})}}const n={create:{title:"Add File",fields:[]},edit:{title:"Edit File Backend",fields:[]}},a=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,File:s,FileForms:n,FileList:FileList,FileManager:FileManager,FileManagerForms:o,FileManagerList:FileManagerList},Symbol.toStringTag,{value:"Module"}));class ModalView extends e.View{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:ModalView._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=ModalView._openDialogs;if(0===e.length||0===t.length)return;const i=[...t].sort((e,t)=>(e._dialogZIndex||0)-(t._dialogZIndex||0)),o=document.querySelector(".table-fullscreen")||document.body;e.forEach((e,t)=>{if(t>=i.length)return;const s=i[t];e.style.zIndex=s._dialogZIndex-5,e.parentNode!==o&&o.appendChild(e)})}static updateAllBackdropStacking(){ModalView.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${!1!==e.fade?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=void 0!==e.centered&&e.centered,this.scrollable=void 0!==e.scrollable&&e.scrollable,this.autoSize=e.autoSize||"auto"===e.size,this.backdrop=void 0===e.backdrop||e.backdrop,this.keyboard=void 0===e.keyboard||e.keyboard,this.focus=void 0===e.focus||e.focus,this.header=void 0===e.header||e.header,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=void 0===e.closeButton||e.closeButton,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=void 0!==e.autoShow&&e.autoShow,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(t){if(t instanceof e.View||t&&"object"==typeof t&&"function"==typeof t.render)this.bodyView=t,this.body="",this.addChild(this.bodyView);else if("function"==typeof t)try{const i=t();i instanceof e.View?(this.bodyView=i,this.body="",this.addChild(this.bodyView)):i instanceof Promise?(this.bodyPromise=i,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=i}catch(i){console.error("ModalView: error processing body function:",i),this.body=t}else this.body=t}_processHeaderContent(t){if(t instanceof e.View)this.headerView=t,this.headerContent=null,this.addChild(this.headerView);else if("function"==typeof t)try{const i=t();i instanceof e.View?(this.headerView=i,this.headerContent=null,this.addChild(this.headerView)):i instanceof Promise?(this.headerPromise=i,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=i}catch(i){console.error("ModalView: error processing headerContent function:",i),this.headerContent=t}else this.headerContent=t}_processFooterContent(t){if(t instanceof e.View)this.footerView=t,this.footer=null,this.addChild(this.footerView);else if("function"==typeof t)try{const i=t();i instanceof e.View?(this.footerView=i,this.footer=null,this.addChild(this.footerView)):i instanceof Promise?(this.footerPromise=i,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=i}catch(i){console.error("ModalView: error processing footer function:",i),this.footer=t}else this.footer=t}async getTemplate(){const e=["modal-dialog"];return this.size&&"auto"!==this.size&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`\n <div class="${e.join(" ")}">\n <div class="modal-content">\n ${await this.buildHeader()}\n ${await this.buildBody()}\n ${await this.buildFooter()}\n </div>\n </div>\n `}async buildHeader(){if(!this.header)return"";if(this.headerView)return this.headerView.replaceById=!0,`<div class="modal-header" data-view-container="header">\n <div id="${this.headerView.id}"></div>\n </div>`;if(this.headerContent)return`<div class="modal-header">${this.headerContent}</div>`;let e="";return this.contextMenu&&this.contextMenu.items&&this.contextMenu.items.length>0?e=await this.buildContextMenu():this.closeButton&&(e='<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>'),`\n <div class="modal-header">\n ${this.title?`<h5 class="modal-title" id="${this.titleId}">${this.title}</h5>`:""}\n ${e}\n </div>\n `}async buildContextMenu(){const e=await this.filterContextMenuItems();if(0===e.length)return this.closeButton?'<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>':"";const t=this.contextMenu.icon||"bi-three-dots-vertical";return`\n <div class="dropdown">\n <button class="${this.contextMenu.buttonClass||"btn btn-link p-1 mojo-modal-context-menu-btn"}" type="button" data-bs-toggle="dropdown" aria-expanded="false">\n <i class="${t}"></i>\n </button>\n <ul class="dropdown-menu dropdown-menu-end">\n ${e.map(e=>{if("divider"===e.type)return'<li><hr class="dropdown-divider"></li>';const t=e.icon?`<i class="${e.icon} me-2"></i>`:"",i=e.label||"";if(e.href)return`<li><a class="dropdown-item" href="${e.href}"${e.target?` target="${e.target}"`:""}>${t}${i}</a></li>`;if(e.action){const o=Object.keys(e).filter(e=>e.startsWith("data-")).map(t=>`${t}="${e[t]}"`).join(" ");return`<li><a class="dropdown-item" data-action="${e.action}" ${o}>${t}${i}</a></li>`}return""}).join("")}\n </ul>\n </div>\n `}async filterContextMenuItems(){if(!this.contextMenu||!this.contextMenu.items)return[];const e=[];for(const i of this.contextMenu.items)if("divider"!==i.type){if(i.permissions)try{const e=this.getApp?.();let t=e?.activeUser||e?.getState?.("activeUser")||null;if(!t&&"undefined"!=typeof window&&window.getApp)try{t=window.getApp()?.activeUser}catch{}if(!t?.hasPermission)continue;if(!t.hasPermission(i.permissions))continue}catch(t){console.warn("ModalView: error checking permissions for context menu item:",t);continue}e.push(i)}else e.push(i);return e}async buildBody(){const e=`modal-body ${this.noBodyPadding?"modal-body-flush":""} ${this.bodyClass}`.replace(/\s+/g," ").trim();return this.bodyView?(this.bodyView.replaceById=!0,`<div class="${e}" data-view-container="body">\n <div id="${this.bodyView.id}"></div>\n </div>`):this.body||""===this.body?`<div class="${e}">${this.body}</div>`:""}async buildFooter(){if(this.footerView)return`<div class="modal-footer ${this.footerClass}" data-view-container="footer"></div>`;if(null!==this.footer&&"string"==typeof this.footer)return`<div class="modal-footer ${this.footerClass}">${this.footer}</div>`;if(this.buttons&&this.buttons.length>0){const e=this.buttons.map(e=>{const t=e.dismiss?'data-bs-dismiss="modal"':"",i=e.action?`data-action="${e.action}"`:"",o=e.id?`id="${e.id}"`:"",s=e.disabled?"disabled":"";return`\n <button type="${e.type||"button"}"\n class="btn ${e.class||"btn-secondary"}"\n ${o} ${t} ${i} ${s}>\n ${e.icon?`<i class="bi ${e.icon} me-1"></i>`:""}\n ${e.text||"Button"}\n </button>\n `}).join("");return`<div class="modal-footer ${this.footerClass}">${e}</div>`}return""}async mount(e=null){if(!this.mounted&&!this.destroyed){if(!this.element)throw new Error("Cannot mount modal without element");return await this.onBeforeMount(),ModalView.getMountTarget().appendChild(this.element),this.bindEvents(),this.mounted=!0,await this.onAfterMount(),this.emit("mounted",{view:this}),this}}async onAfterRender(){if(await super.onAfterRender(),window.Prism&&this.element&&this.element.querySelectorAll("pre code").length>0&&window.Prism.highlightAllUnder(this.element),this.autoSize)this.setupAutoSizing();else if(this.maxHeight){const e=this.element.querySelector(".modal-body");e&&(e.style.maxHeight=`${this.maxHeight}px`)}}async onAfterMount(){await super.onAfterMount(),"undefined"!=typeof window&&window.bootstrap?.Modal&&("static"===this.backdrop&&this.element.setAttribute("data-bs-backdrop","static"),this.keyboard||this.element.setAttribute("data-bs-keyboard","false"),this.modal=new window.bootstrap.Modal(this.element,{backdrop:this.backdrop,keyboard:this.keyboard,focus:this.focus}),this.bindBootstrapEvents(),this.autoShow&&this.show(this.relatedTarget))}setupAutoSizing(){this.element&&(this.element.addEventListener("shown.bs.modal",()=>{this.applyAutoSizing()},{once:!0}),setTimeout(()=>{this.isShown()&&this.applyAutoSizing()},100))}applyAutoSizing(){if(this.element)try{const e=this.element.querySelector(".modal-dialog"),t=this.element.querySelector(".modal-content"),i=this.element.querySelector(".modal-body");if(!e||!t||!i)return void console.warn("ModalView auto-sizing: required elements not found");if(this.bodyView&&!this.bodyView.element)return void setTimeout(()=>this.applyAutoSizing(),50);const o={dialogMaxWidth:e.style.maxWidth,dialogWidth:e.style.width,contentWidth:t.style.width,contentMaxHeight:t.style.maxHeight,hadScrollableClass:e.classList.contains("modal-dialog-scrollable")};e.style.maxWidth="none",e.style.width="auto",t.style.width="auto",t.style.maxHeight="none",t.offsetHeight;const s=t.getBoundingClientRect(),n=40,a=Math.min(window.innerWidth*this.maxWidthPercent,window.innerWidth-n);let r=Math.min(window.innerHeight*this.maxHeightPercent,window.innerHeight-n),l=Math.max(this.minWidth,Math.ceil(s.width+20)),d=Math.max(this.minHeight,Math.ceil(s.height));this.maxHeight&&(r=Math.min(this.maxHeight,r),e.style.maxHeight=`${r}px`),l=Math.min(l,a);const c=s.height>r;e.style.maxWidth=`${l}px`,e.style.width=`${l}px`,c&&(e.classList.contains("modal-dialog-scrollable")||e.classList.add("modal-dialog-scrollable"),t.style.maxHeight=`${r}px`,d=r),this.autoSizedWidth=l,this.autoSizedHeight=d,this._originalStyles=o}catch(e){console.error("ModalView: error in auto-sizing:",e);const t=this.element?.querySelector(".modal-dialog");t&&(t.style.maxWidth="")}}resetAutoSizing(){if(this.autoSize&&this._originalStyles&&this.element)try{const e=this.element.querySelector(".modal-dialog"),t=this.element.querySelector(".modal-content"),i=this.element.querySelector(".modal-body");e&&t&&i&&(e.style.maxWidth=this._originalStyles.dialogMaxWidth||"",e.style.width=this._originalStyles.dialogWidth||"",t.style.width=this._originalStyles.contentWidth||"",t.style.maxHeight=this._originalStyles.contentMaxHeight||"",!this._originalStyles.hadScrollableClass&&e.classList.contains("modal-dialog-scrollable")&&e.classList.remove("modal-dialog-scrollable"),delete this.autoSizedWidth,delete this.autoSizedHeight,delete this._originalStyles)}catch(e){console.error("ModalView: error resetting auto-sizing:",e)}}bindBootstrapEvents(){this.element.addEventListener("show.bs.modal",e=>{const t=ModalView._openDialogs.length,i=ModalView.getFullscreenAwareZIndex().modal+20*t;this.element.style.zIndex=i,this._dialogZIndex=i,this._backdropZIndex=i-10,ModalView._openDialogs.push(this),this.onShow&&this.onShow(e),this.emit("show",{dialog:this,relatedTarget:e.relatedTarget})}),this.element.addEventListener("shown.bs.modal",e=>{if(setTimeout(()=>ModalView.fixAllBackdropStacking(),50),this.onShown&&this.onShown(e),this.emit("shown",{dialog:this,relatedTarget:e.relatedTarget}),this.focus){const e=this.element.querySelector('input:not([type="hidden"]), textarea, select');e&&e.focus()}}),this.element.addEventListener("hide.bs.modal",e=>{const t=this.element.querySelector(":focus");t&&t.blur(),this.onHide&&!1===this.onHide(e)?e.preventDefault():this.emit("hide",{dialog:this})}),this.element.addEventListener("hidden.bs.modal",e=>{const t=ModalView._openDialogs.indexOf(this);t>-1&&ModalView._openDialogs.splice(t,1),ModalView._openDialogs.length>0&&(document.body.classList.add("modal-open"),setTimeout(()=>ModalView.fixAllBackdropStacking(),50)),this.previousFocus&&document.body.contains(this.previousFocus)&&this.previousFocus.focus(),this.onHidden&&this.onHidden(e),this.emit("hidden",{dialog:this})}),this.element.addEventListener("hidePrevented.bs.modal",e=>{this.onHidePrevented&&this.onHidePrevented(e),this.emit("hidePrevented",{dialog:this})})}show(e=null){this.previousFocus=document.activeElement,window.lastDialog=this,this.modal&&this.modal.show(e)}hide(){const e=this.element?.querySelector(":focus");e&&e.blur(),this.modal&&this.modal.hide()}toggle(e=null){this.modal&&this.modal.toggle(e)}isShown(){return this.element?.classList.contains("show")||!1}getModal(){return this.modal}handleUpdate(){this.modal&&this.modal.handleUpdate()}async setContent(t){if(t instanceof e.View){this.bodyView&&(await this.bodyView.destroy(),this.removeChild(this.bodyView)),this.bodyView=t,this.body="",this.addChild(this.bodyView);const e=this.element?.querySelector(".modal-body");e&&(e.innerHTML="",await this.bodyView.render(e))}else{this.body=t;const e=this.element?.querySelector(".modal-body");e&&(e.innerHTML=t)}this.handleUpdate()}setTitle(e){this.title=e;const t=this.element?.querySelector(".modal-title");t&&(t.textContent=e)}setLoading(e=!0,t="Loading..."){const i=this.element?.querySelector(".modal-body");i&&(e?i.innerHTML=`\n <div class="text-center py-4">\n <div class="spinner-border text-primary mb-3" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n <p>${t}</p>\n </div>\n `:this.bodyView&&i.replaceChildren(this.bodyView.element))}async destroy(){if(this.modal){const e=this.element?.querySelector(":focus");e&&e.blur(),this.modal.dispose(),this.modal=null}this.previousFocus&&document.body.contains(this.previousFocus)&&(this.previousFocus.focus(),this.previousFocus=null),this.autoSize&&this.resetAutoSizing(),await super.destroy()}async onBeforeDestroy(){this.headerView&&await this.headerView.destroy(),this.bodyView&&await this.bodyView.destroy(),this.footerView&&await this.footerView.destroy(),await super.onBeforeDestroy(),this.modal&&(this.modal.dispose(),this.modal=null)}}let r=null,l=0,d=null;const c={show(e){"string"==typeof e&&(e={message:e});const{message:t="Loading...",timeout:i=3e4}=e||{};if(l++,1===l){d&&clearTimeout(d);const e=ModalView.getFullscreenAwareZIndex().modal+1e3;r||(r=document.createElement("div"),r.className="mojo-loading-overlay",r.innerHTML=`\n <div class="mojo-loading-card">\n <div class="mojo-loading-spinner"></div>\n <div class="mojo-loading-message">${t}</div>\n </div>\n <style>\n .mojo-loading-overlay {\n position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;\n background: rgba(255, 255, 255, 0.4);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n display: flex; align-items: center; justify-content: center;\n opacity: 0; transition: opacity 0.2s ease;\n }\n .mojo-loading-overlay.show { opacity: 1; }\n .mojo-loading-card {\n display: flex; align-items: center; gap: 0.85rem;\n background: #fff;\n border: 1px solid #e9ecef;\n border-radius: 12px;\n padding: 1rem 1.5rem;\n box-shadow: 0 4px 24px rgba(0,0,0,0.08), 0 1px 4px rgba(0,0,0,0.04);\n }\n .mojo-loading-spinner {\n width: 22px; height: 22px;\n border: 2.5px solid #e9ecef;\n border-top-color: #0d6efd;\n border-radius: 50%;\n animation: mojo-spin 0.7s linear infinite;\n flex-shrink: 0;\n }\n .mojo-loading-message {\n font-size: 0.88rem;\n font-weight: 500;\n color: #495057;\n white-space: nowrap;\n }\n @keyframes mojo-spin { to { transform: rotate(360deg); } }\n</style>\n `,document.body.appendChild(r)),r.style.zIndex=String(e);const o=r.querySelector(".mojo-loading-message");o&&(o.textContent=t),requestAnimationFrame(()=>{r&&r.classList.add("show")}),i>0&&(d=setTimeout(()=>{console.error("BusyIndicator timed out."),c.hide(!0)},i))}else if(r){const e=r.querySelector(".mojo-loading-message");e&&(e.textContent=t)}},hide(e=!1){e?l=0:l--,l>0||(l=0,d&&(clearTimeout(d),d=null),r&&(r.classList.remove("show"),setTimeout(()=>{r&&0===l&&(r.remove(),r=null)},200)))},isShown:()=>null!==r&&l>0},h="\n max-height: 60vh;\n overflow-y: auto;\n background: #1e1e1e;\n color: #d4d4d4;\n padding: 1.25rem;\n border-radius: 0.5rem;\n margin: 0;\n font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', 'Monaco', monospace;\n font-size: 0.9rem;\n line-height: 1.6;\n border: 1px solid #2d2d30;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);\n".replace(/\s+/g," ").trim();class CodeViewer extends e.View{constructor(e={}){super({tagName:"div",className:"mojo-code-viewer",...e}),this.code=e.code||"",this.language=e.language||"javascript"}async getTemplate(){return CodeViewer.formatCode(this.code,this.language)}static formatCode(e,t="javascript"){let i;i=window.Prism&&window.Prism.languages[t]?window.Prism.highlight(e,window.Prism.languages[t],t):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'");const o=window.Prism?`language-${t}`:"";return`\n <style>\n .dialog-code-block .token.comment { color: #6a9955; }\n .dialog-code-block .token.string { color: #ce9178; }\n .dialog-code-block .token.keyword { color: #569cd6; }\n .dialog-code-block .token.function { color: #dcdcaa; }\n .dialog-code-block .token.number { color: #b5cea8; }\n .dialog-code-block .token.operator { color: #d4d4d4; }\n .dialog-code-block .token.class-name { color: #4ec9b0; }\n .dialog-code-block .token.punctuation { color: #d4d4d4; }\n .dialog-code-block .token.boolean { color: #569cd6; }\n .dialog-code-block .token.property { color: #9cdcfe; }\n .dialog-code-block .token.tag { color: #569cd6; }\n .dialog-code-block .token.attr-name { color: #9cdcfe; }\n .dialog-code-block .token.attr-value { color: #ce9178; }\n .dialog-code-block ::selection { background: #264f78; }\n</style>\n <pre class="${o} dialog-code-block" style="${h}">\n <code class="${o}" style="color: inherit; background: transparent; text-shadow: none;">${i}</code>\n </pre>\n `}static highlightCodeBlocks(e=document){window.Prism&&window.Prism.highlightAllUnder&&window.Prism.highlightAllUnder(e)}}class HtmlPreview extends e.View{constructor(e={}){super({tagName:"div",className:"mojo-html-preview",...e}),this.html=e.html||e.content||"",this.height=e.height||500}async getTemplate(){return`\n <div class="html-preview-container">\n <div class="d-flex justify-content-between align-items-center mb-2">\n <small class="text-muted">Preview (sandboxed)</small>\n <button type="button" class="btn btn-sm btn-outline-secondary" data-action="refresh">\n <i class="bi bi-arrow-clockwise"></i> Refresh\n </button>\n </div>\n <iframe\n class="border rounded w-100 mojo-html-preview-frame"\n style="height: ${this.height}px; background: white;"\n sandbox="allow-same-origin"\n frameborder="0"\n ></iframe>\n </div>\n `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class Modal{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:i=!1,onAction:o=null,cleanup:s=null}={}){const n=ModalView.getMountTarget();return new Promise((a,r)=>{let l=!1;const d=e=>{l||(l=!0,a(e))},c=e=>{l||(l=!0,r(e))};(async()=>{try{await e.render(!0,n)}catch(a){return void c(a)}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((i,s)=>{const n=t[s];n&&i.addEventListener("click",async t=>{if(l)return;const i=void 0!==n.value?n.value:n.action??s;if("function"!=typeof n.handler)if("function"==typeof o&&n.action)try{const a=await o(n.action,{dialog:e,button:n,index:s,event:t});if(null===a||!1===a)return;const r=!0===a||void 0===a?i:a;n.dismiss||e.hide(),d(r)}catch(a){console.error("Modal onAction error:",a)}else n.dismiss||e.hide(),d(i);else try{const o=await n.handler({dialog:e,button:n,index:s,event:t});if(null===o||!1===o)return;const a=!0===o||void 0===o?i:o;n.dismiss||e.hide(),d(a)}catch(a){console.error("Modal button handler error:",a)}})}),e.on("hidden",()=>{l||(i?c(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{"function"==typeof s&&await s(e)}catch(a){console.error("Modal cleanup error:",a)}try{await e.destroy()}catch(a){console.error("Modal destroy error:",a)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){"string"==typeof e&&(e={...arguments[2]||{},body:arguments[0],title:arguments[1]||"Alert"});const{title:t="Dialog",content:i,body:o,view:s,message:n,size:a="md",centered:r=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...c}=e,h=new ModalView({title:t,body:o??s??n??i??"",size:a,centered:r,buttons:l,...c});return Modal._renderAndAwait(h,{buttons:l,rejectOnDismiss:d})}static async drawer(t={}){const{eyebrow:i,title:o,meta:s=[],view:n,body:a,size:r="lg",...l}=t,d=s.length?`\n <div class="modal-drawer-meta">\n ${s.map(e=>"string"==typeof e?`<span>${Modal._esc(e)}</span>`:`<span>${e.icon?`<i class="${Modal._esc(e.icon)} me-1"></i>`:""}${Modal._esc(e.text||"")}</span>`).join("")}\n </div>`:"",c=`\n <div class="modal-drawer-head">\n ${i?`<span class="modal-drawer-eyebrow">${Modal._esc(i)}</span>`:""}\n <h2 class="modal-drawer-title">${Modal._esc(o||"")}</h2>\n ${d}\n </div>\n `;let h;return h=n&&"object"==typeof n&&"function"==typeof n.render?new class extends e.View{async getTemplate(){return`${c}<div class="modal-drawer-body" data-container="drawer-body"></div>`}async onInit(){n.containerId="drawer-body",this.addChild(n)}}:`${c}<div class="modal-drawer-body">${a||""}</div>`,Modal.dialog({header:!1,body:h,size:r,centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...l})}static _esc(e){const t="undefined"!=typeof document?document.createElement("div"):null;return t?(t.textContent=String(e??""),t.innerHTML):String(e??"")}static async show(e,t={}){return Modal.dialog({header:void 0!==t.title&&!!t.title,title:t.title||void 0,body:e,size:"lg",centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...t})}static async showModel(e,t={}){const i=e.constructor,o=i?.VIEW_CLASS;if(!o)throw new Error(`Modal.showModel: No VIEW_CLASS defined on ${i?.name||"model"}. Set ${i?.name||"Model"}.VIEW_CLASS = YourView to use this method.`);const s=new o({model:e});return Modal.show(s,t)}static async showModelById(e,t,i={}){const o=new e({id:t});return await o.fetch(),o.id?Modal.showModel(o,i):(Modal.alert({message:`Could not find ${e.name||"record"} with ID: ${t}`,type:"warning"}),null)}static async showModelView(e,t={}){const i=e.constructor,o=i?.VIEW_CLASS;if(!o)throw new Error(`Modal.showModelView: No VIEW_CLASS defined on ${i?.name||"model"}.`);const s=new o({model:e});return Modal.dialog({header:!1,body:s,size:"lg",centered:!1,...t})}static async alert(e={},t,i){let o;o="string"==typeof e?{message:e,...void 0!==t?{title:t}:{},...i||{}}:{...e};const{message:s="",title:n="Alert",type:a="info",icon:r,className:l,...d}=o,c="danger"===a?"error":a,h=[`modal-alert modal-alert-${c}`,l].filter(Boolean).join(" "),u=void 0!==r?r:{info:"bi-info-circle",success:"bi-check-circle",warning:"bi-exclamation-triangle",error:"bi-x-circle"}[c],p=u?`<i class="bi ${u} modal-alert-icon"></i>`:"",m=`<span class="modal-alert-headline">${n}</span>`;return Modal.dialog({title:`${p}${m}`,body:`<p class="modal-alert-message">${s}</p>`,size:"sm",centered:!0,className:h,buttons:[{text:"OK",class:"btn-primary",value:!0}],...d})}static async confirm(e,t="Confirm",i={}){let o;"object"==typeof e&&null!==e?(o=(i=e).message,t=i.title||t):o=e;const s=[{text:i.cancelText||"Cancel",class:"btn-secondary",dismiss:!0,action:"cancel"},{text:i.confirmText||"Confirm",class:i.confirmClass||"btn-primary",action:"confirm"}],n=new ModalView({title:t,body:`<p>${o}</p>`,size:i.size||"sm",centered:!0,backdrop:"static",buttons:s,...i});return"confirm"===await Modal._renderAndAwait(n,{buttons:s})}static async prompt(e,t="Input",i={}){const o=`prompt-input-${Date.now()}`,s=i.defaultValue||"",n=i.inputType||"text",a=i.placeholder||"",r=[{text:"Cancel",class:"btn-secondary",dismiss:!0},{text:"OK",class:"btn-primary",action:"ok"}],l=new ModalView({title:t,body:`\n <p>${e}</p>\n <input type="${n}"\n class="form-control"\n id="${o}"\n value="${s}"\n placeholder="${a}">\n `,size:i.size||"sm",centered:!0,backdrop:"static",buttons:r,...i});return l.on("shown",()=>{const e=l.element.querySelector(`#${o}`);e&&(e.focus(),e.select())}),Modal._renderAndAwait(l,{buttons:r,onAction:async e=>{if("ok"!==e)return null;const t=l.element.querySelector(`#${o}`);return t?t.value:null}})}static showError(e){return Modal.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:i={},size:o="md",centered:s=!0,submitText:n="Submit",cancelText:a="Cancel",...r}=e,l=new(0,(await Promise.resolve().then(()=>require("./FormView-DUXQruUZ.js")).then(e=>e.FormView$1)).default)({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:i.fields||e.fields,...i,submitButton:!1,resetButton:!1}}),d=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],c=new ModalView({title:t,body:l,size:o,centered:s,buttons:d,...r});return Modal._renderAndAwait(c,{buttons:d,onAction:async t=>{if("cancel"===t)return c.hide(),null;if("submit"!==t)return null;if(!l.validate())return l.focusFirstError(),!1;if(e.autoSave&&e.model){c.setLoading(!0);const e=await l.saveModel();return e.success?e:(c.setLoading(!1),await c.render(),c.getApp()?.toast?.error(e.message),!1)}try{return await l.getFormData()}catch(i){return console.error("Modal.form: error collecting form data:",i),l.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await l.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:i={},size:o="md",centered:s=!0,submitText:n="Save",cancelText:a="Cancel",model:r,fields:l,...d}=e;if(!r)throw new Error("Modal.modelForm requires a model");const c=new(0,(await Promise.resolve().then(()=>require("./FormView-DUXQruUZ.js")).then(e=>e.FormView$1)).default)({fileHandling:e.fileHandling||"base64",model:r,data:e.data,defaults:e.defaults,formConfig:{fields:l||i.fields||[],...i,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new ModalView({title:t,body:c,size:o,centered:s,buttons:h,...d});return Modal._renderAndAwait(u,{buttons:h,onAction:async e=>{if("cancel"===e)return u.hide(),null;if("submit"!==e)return null;u.setLoading(!0,"Saving...");try{const e=await c.handleSubmit();if(e.success)return e;u.setLoading(!1);let t=e.error;return e.data?.error&&(t=e.data.error),u.getApp()?.toast?.error(t),!1}catch(t){return console.error("Modal.modelForm: error saving:",t),await u.setContent(c),c.showError(t.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await c.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:i={},model:o=null,fields:s=[],columns:n=2,responsive:a=!0,showEmptyValues:r=!1,emptyValueText:l="—",size:d="lg",centered:c=!0,closeText:h="Close",...u}=e,p=new(0,(await Promise.resolve().then(()=>require("./DataView-VZIXSsZa.js"))).default)({data:i,model:o,fields:s,columns:n,responsive:a,showEmptyValues:r,emptyValueText:l}),m=[{text:h,class:"btn-secondary",value:"close"}],g=new ModalView({title:t,body:p,size:d,centered:c,buttons:m,...u});return p.on("field:click",e=>g.emit("dataview:field:click",e)),p.on("error",e=>g.emit("dataview:error",e)),Modal._renderAndAwait(g,{buttons:m,cleanup:async()=>{try{await p.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:i="javascript",title:o="Source Code",size:s="lg",...n}=e,a=new CodeViewer({code:t,language:i}),r=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new ModalView({title:o,body:a,size:s,scrollable:!0,buttons:r,...n});return Modal._renderAndAwait(l,{buttons:r,onAction:async e=>{if("copy"!==e)return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),Modal._showCopySuccess(l)}catch(i){console.error("Modal.code: clipboard write failed:",i)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const i=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=i,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:i="HTML Preview",size:o="lg",height:s=500,...n}=e,a=new HtmlPreview({html:t,height:s}),r=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new ModalView({title:i,body:a,size:o,scrollable:!1,buttons:r,...n});return Modal._renderAndAwait(l,{buttons:r})}static async updateModelImage(e={},t={}){const i=e.upload||!1,o=t.name||e.field||"image",n={title:"Upload Your Avatar",model:null,autoSave:!i,size:"sm",fields:[{type:"image",name:o,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},a=await Modal.form(n);if(!i||!a||!e.model)return a;const r=a[o];if(!r||!r.startsWith("data:"))return a;const l=r.split(","),d=l[0]?.match(/:(.*?);/),c=d?.[1]||"image/png",h=atob(l[1]);let u=h.length;const p=new Uint8Array(u);for(;u--;)p[u]=h.charCodeAt(u);const m=c.split("/")[1]||"png",g="undefined"!=typeof window&&window.File||globalThis.File;if(!g)throw new Error("File API is not available in this environment");const w=new g([p],`${o}.${m}`,{type:c}),f=new s;return await f.upload({file:w,name:`${o}.${m}`,description:e.uploadDescription||`${o} upload`,showToast:!0}),e.model.save({[o]:f.id})}static loading(e){c.show(e)}static hideLoading(e){c.hide(e)}static showBusy(e){return Modal.loading(e)}static hideBusy(e){return Modal.hideLoading(e)}}const u=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,default:Modal},Symbol.toStringTag,{value:"Module"}));exports.CodeViewer=CodeViewer,exports.File=s,exports.FileForms=n,exports.FileList=FileList,exports.FileManager=FileManager,exports.FileManagerForms=o,exports.FileManagerList=FileManagerList,exports.FileUpload=FileUpload,exports.Files=a,exports.Modal=Modal,exports.Modal$1=u,exports.ModalView=ModalView,exports.ProgressView=ProgressView,exports.ToastService=ToastService;
|
|
3
|
-
//# sourceMappingURL=Modal-Bm1OQ8Ou.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
import{V as e}from"./View-BxlKR1IW.js";import{d as t,M as i,C as o}from"./Collection-DNmr743A.js";import{G as s,U as n}from"./User-BM76Ughk.js";class ToastService{constructor(e={}){this.options={containerId:"toast-container",position:"top-end",autohide:!0,defaultDelay:3e3,maxToasts:5,...e},this.toasts=/* @__PURE__ */new Map,this.toastCounter=0,this.init()}init(){this.createContainer()}createContainer(){let e=document.getElementById(this.options.containerId);e||(e=document.createElement("div"),e.id=this.options.containerId,e.className=`toast-container position-fixed ${this.getPositionClasses()}`,e.style.zIndex="1070",e.setAttribute("aria-live","polite"),e.setAttribute("aria-atomic","true"),document.body.appendChild(e)),this.container=e}getPositionClasses(){const e={"top-start":"top-0 start-0 p-3","top-center":"top-0 start-50 translate-middle-x p-3","top-end":"top-0 end-0 p-3","middle-start":"top-50 start-0 translate-middle-y p-3","middle-center":"top-50 start-50 translate-middle p-3","middle-end":"top-50 end-0 translate-middle-y p-3","bottom-start":"bottom-0 start-0 p-3","bottom-center":"bottom-0 start-50 translate-middle-x p-3","bottom-end":"bottom-0 end-0 p-3"};return e[this.options.position]||e["top-end"]}success(e,t={}){return this.show(e,"success",{icon:"bi-check-circle-fill",...t})}error(e,t={}){return this.show(e,"error",{icon:"bi-exclamation-triangle-fill",autohide:!0,...t})}info(e,t={}){return this.show(e,"info",{icon:"bi-info-circle-fill",...t})}warning(e,t={}){return this.show(e,"warning",{icon:"bi-exclamation-triangle-fill",...t})}plain(e,t={}){return this.show(e,"plain",{...t})}show(e,t="info",i={}){this.enforceMaxToasts();const o="toast-"+ ++this.toastCounter,s={title:this.getDefaultTitle(t),icon:this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,...i},n=this.createToastElement(o,e,t,s);if(this.container.appendChild(n),"undefined"==typeof bootstrap)throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:s.autohide,delay:s.delay});return this.toasts.set(o,{element:n,bootstrap:a,type:t,message:e}),n.addEventListener("hidden.bs.toast",()=>{this.cleanup(o)}),a.show(),{id:o,hide:()=>{try{a.hide()}catch(e){console.warn("Error hiding toast:",e)}},dispose:()=>this.cleanup(o),updateProgress:i.updateProgress||null}}showView(e,t="info",i={}){this.enforceMaxToasts();const o="toast-"+ ++this.toastCounter,s={title:i.title||this.getDefaultTitle(t),icon:i.icon||this.getDefaultIcon(t),autohide:this.options.autohide,delay:this.options.defaultDelay,dismissible:!0,size:"md",...i},n=this.createViewToastElement(o,e,t,s);if(this.container.appendChild(n),"undefined"==typeof bootstrap)throw new Error("Bootstrap is required for ToastService. Make sure Bootstrap 5 is loaded.");const a=new bootstrap.Toast(n,{autohide:s.autohide,delay:s.delay});this.toasts.set(o,{element:n,bootstrap:a,type:t,view:e,message:"View toast"}),n.addEventListener("hidden.bs.toast",()=>{this.cleanupView(o)});const r=n.querySelector(".toast-view-body");return r&&e&&e.render(!0,r),a.show(),{id:o,view:e,hide:()=>{try{a.hide()}catch(e){console.warn("Error hiding view toast:",e)}},dispose:()=>this.cleanupView(o),updateProgress:t=>{e&&"function"==typeof e.updateProgress&&e.updateProgress(t)}}}createToastElement(e,t,i,o){const s=document.createElement("div");s.id=e,s.className=`toast toast-service-${i}${o.size?` toast-${o.size}`:""}`,s.setAttribute("role","alert"),s.setAttribute("aria-live","assertive"),s.setAttribute("aria-atomic","true");const n=o.title||o.icon?this.createToastHeader(o,i):"",a=this.createToastBody(t,o.icon&&!o.title);return s.innerHTML=`\n ${n}\n ${a}\n `,s}createViewToastElement(e,t,i,o){const s=document.createElement("div");s.id=e,s.className=`toast toast-service-${i}${o.size?` toast-${o.size}`:""}`,s.setAttribute("role","alert"),s.setAttribute("aria-live","assertive"),s.setAttribute("aria-atomic","true");const n=o.title||o.icon?this.createToastHeader(o,i):"",a=this.createViewToastBody();return s.innerHTML=`\n ${n}\n ${a}\n `,s}createViewToastBody(){return'\n <div class="toast-body p-0">\n <div class="toast-view-body p-3"></div>\n </div>\n '}createToastHeader(e,t){const i=e.icon?`<i class="${e.icon} toast-service-icon me-2"></i>`:"",o=e.title?`<strong class="me-auto">${i}${this.escapeHtml(e.title)}</strong>`:"",s=e.showTime?`<small class="text-muted">${this.getTimeString()}</small>`:"",n=e.dismissible?'<button type="button" class="btn-close toast-service-close" data-bs-dismiss="toast" aria-label="Close"></button>':"";return o||s||n?`\n <div class="toast-header">\n ${o}\n ${s}\n ${n}\n </div>\n `:""}createToastBody(e,t=!1){return`\n <div class="toast-body d-flex align-items-center">\n ${t?`<i class="${this.getDefaultIcon("info")} toast-service-icon me-2"></i>`:""}\n <span>${this.escapeHtml(e)}</span>\n </div>\n `}getDefaultTitle(e){return{success:"Success",error:"Error",warning:"Warning",info:"Information",plain:""}[e]||"Notification"}getDefaultIcon(e){return{success:"bi-check-circle-fill",error:"bi-exclamation-triangle-fill",warning:"bi-exclamation-triangle-fill",info:"bi-info-circle-fill",plain:""}[e]||"bi-info-circle-fill"}enforceMaxToasts(){if(Array.from(this.toasts.values()).length>=this.options.maxToasts){const e=this.toasts.keys().next().value,t=this.toasts.get(e);t&&t.bootstrap.hide()}}cleanup(e){const t=this.toasts.get(e);if(t){try{t.bootstrap.dispose()}catch(i){console.warn("Error disposing toast:",i)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}cleanupView(e){const t=this.toasts.get(e);if(t){if(t.view&&"function"==typeof t.view.dispose)try{t.view.dispose()}catch(i){console.warn("Error disposing view in toast:",i)}try{t.bootstrap.dispose()}catch(i){console.warn("Error disposing toast:",i)}t.element&&t.element.parentNode&&t.element.parentNode.removeChild(t.element),this.toasts.delete(e)}}hideAll(){this.toasts.forEach((e,t)=>{e.bootstrap.hide()})}clearAll(){this.toasts.forEach((e,t)=>{this.cleanup(t)})}getTimeString(){/* @__PURE__ */
|
|
2
|
-
return(new Date).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}escapeHtml(e){const t=document.createElement("div");return t.textContent=e,t.innerHTML}dispose(){this.clearAll(),this.container&&this.container.parentNode&&this.container.parentNode.removeChild(this.container)}getStats(){const e={total:this.toasts.size,byType:{}};return this.toasts.forEach(t=>{e.byType[t.type]=(e.byType[t.type]||0)+1}),e}setOptions(e){this.options={...this.options,...e},e.position&&this.container&&(this.container.className=`toast-container position-fixed ${this.getPositionClasses()}`)}}class ProgressView extends e{constructor(e={}){super({template:"progress-view-template",...e}),this.filename=e.filename||"Unknown file",this.filesize=e.filesize||0,this.filesizeFormatted=t.pipe(this.filesize,"filesize"),this.progress=0,this.percentage=0,this.loaded=0,this.total=this.filesize,this.loadedFormatted="0 B",this.totalFormatted=this.filesizeFormatted,this.status="Starting upload...",this.showCancel=!1!==e.showCancel,this.onCancel=e.onCancel||null,this.cancelled=!1,this.completed=!1}getTemplate(){return'\n <div class="progress-view">\n <div class="d-flex justify-content-between align-items-start mb-2">\n <div class="flex-grow-1 min-width-0">\n <div class="fw-medium text-truncate" title="{{filename}}">\n <i class="bi bi-file-earmark me-1"></i>\n {{filename}}\n </div>\n <small class="text-muted">{{status}}</small>\n </div>\n {{#showCancel}}\n <button type="button" \n class="btn btn-sm btn-outline-secondary ms-2" \n data-action="cancel"\n {{#cancelled}}disabled{{/cancelled}}>\n <i class="bi bi-x"></i>\n </button>\n {{/showCancel}}\n </div>\n \n <div class="progress mb-2" style="height: 8px;">\n <div class="progress-bar" \n role="progressbar" \n style="width: {{percentage}}%"\n aria-valuenow="{{percentage}}" \n aria-valuemin="0" \n aria-valuemax="100">\n </div>\n </div>\n \n <div class="d-flex justify-content-between">\n <small class="text-muted">\n {{loadedFormatted}} / {{totalFormatted}}\n </small>\n <small class="text-muted">\n {{percentage}}%\n </small>\n </div>\n </div>\n '}updateProgress(e){this.cancelled||this.completed||(this.progress=e.progress,this.percentage=e.percentage,this.loaded=e.loaded,this.total=e.total||this.filesize,this.loadedFormatted=t.pipe(this.loaded,"filesize"),this.totalFormatted=t.pipe(this.total,"filesize"),this.percentage<100?this.status=`Uploading... ${this.percentage}%`:this.status="Finalizing upload...",this.render())}markCompleted(e="Upload completed!"){this.completed=!0,this.progress=1,this.percentage=100,this.status=e,this.render()}markFailed(e="Upload failed"){this.status=e,this.render()}markCancelled(){this.cancelled=!0,this.status="Upload cancelled",this.render()}async onActionCancel(e,t,i){if(!this.cancelled&&!this.completed&&(i.disabled=!0,this.markCancelled(),this.emit("cancel"),"function"==typeof this.onCancel))try{await this.onCancel()}catch(o){console.error("Error in cancel callback:",o)}}setFilename(e){this.filename=e,this.render()}setFilesize(e){this.filesize=e,this.filesizeFormatted=t.pipe(e,"filesize"),this.total=e,this.totalFormatted=this.filesizeFormatted,this.render()}getPercentage(){return this.percentage}isCompleted(){return this.completed}isCancelled(){return this.cancelled}getStats(){return{filename:this.filename,filesize:this.filesize,progress:this.progress,percentage:this.percentage,loaded:this.loaded,total:this.total,cancelled:this.cancelled,completed:this.completed,status:this.status}}}class FileUpload{constructor(e,t={}){if(this.fileModel=e,this.options={file:null,name:null,group:null,description:null,onProgress:null,onComplete:null,onError:null,showToast:!0,...t},!(this.options.file&&this.options.file instanceof File))throw new Error("FileUpload requires a valid File object");this.cancelled=!1,this.uploadRequest=null,this.progressToast=null,this.progressView=null,this.toastService=null,this.options.showToast&&(this.toastService=new ToastService),this.promise=this._startUpload()}async _startUpload(){try{let t,i,o;this.options.showToast&&this._showProgressToast();try{t=await this._initiateUpload()}catch(e){throw new Error(`Failed to initiate upload: ${e.message}`)}if(this.cancelled)throw new Error("Upload cancelled");if(!t||!t.upload_url)throw new Error("Invalid upload response: missing upload URL");if("string"==typeof t.upload_url)i={url:t.upload_url,method:"PUT",fields:null,headers:{}};else{if(!t.upload_url||"object"!=typeof t.upload_url||!t.upload_url.upload_url)throw new Error(`Invalid upload response: unrecognised upload_url format. Server returned: ${JSON.stringify(t.upload_url)}`);i={url:t.upload_url.upload_url,method:t.upload_url.method||"POST",fields:t.upload_url.fields||null,headers:t.upload_url.headers||{}}}try{o=await this._performUpload(i)}catch(e){throw new Error(`File upload failed: ${e.message}`)}if(this.cancelled)throw new Error("Upload cancelled");try{await this._completeUpload()}catch(e){console.warn("Failed to mark upload as completed:",e)}return this._onComplete(this.fileModel),this.fileModel}catch(e){throw"Upload cancelled"!==e.message&&this._onError(e),e}}async _initiateUpload(){try{const e={filename:this.options.name||this.options.file.name,file_size:this.options.file.size,content_type:this.options.file.type};this.options.group&&(e.group=this.options.group),this.options.description&&(e.description=this.options.description);const t=await this.fileModel.rest.POST("/api/fileman/upload/initiate",e);if(!t)throw new Error("No response from upload initiation API");if(!t.data)throw new Error("Upload initiation response missing data");if(!t.data.status){const e=t.data.error||"Upload initiation failed";throw new Error(e)}if(!t.data.data)throw new Error("Upload initiation response missing data payload");return t.data.data.id&&this.fileModel.set("id",t.data.data.id),t.data.data}catch(e){if("Network Error"===e.message||"TypeError"===e.name)throw new Error("Network error during upload initiation. Please check your connection.");throw e}}async _performUpload(e){return new Promise((t,i)=>{if(!(this.options.file instanceof File))return void i(new Error("Only single File objects are supported"));const{url:o,method:s,fields:n,headers:a}=e,r="POST"===s&&null!==n,l=new XMLHttpRequest;this.uploadRequest=l,l.upload.onprogress=e=>{this.cancelled||this._onProgress({progress:e.loaded/e.total,loaded:e.loaded,total:e.total,percentage:Math.round(e.loaded/e.total*100)})},l.onload=()=>{l.status>=200&&l.status<300?t({data:l.response,status:l.status,statusText:l.statusText,xhr:l}):i(new Error(`Upload failed: ${l.status} ${l.statusText}`))},l.onerror=()=>i(new Error("Upload failed: Network error")),l.ontimeout=()=>i(new Error("Upload timed out — file may be too large or connection too slow")),l.onabort=()=>i(new Error("Upload cancelled"));let d=o;o.startsWith("/")&&!o.startsWith("/api/")&&(d="/api"+o);const c=this.fileModel.rest.buildUrl(d);if(l.open(s,c),l.timeout=3e4,r){for(const[t,i]of Object.entries(a||{}))"content-type"!==t.toLowerCase()&&l.setRequestHeader(t,i);const e=new FormData;for(const[t,i]of Object.entries(n))e.append(t,i);e.append("file",this.options.file),l.send(e)}else{l.setRequestHeader("Content-Type",this.options.file.type);for(const[e,t]of Object.entries(a||{}))"content-type"!==e.toLowerCase()&&l.setRequestHeader(e,t);l.send(this.options.file)}})}async _completeUpload(){try{const e=await this.fileModel.save({action:"mark_as_completed"});if(!e)throw new Error("No response from upload completion API");if(e.data&&!e.data.status){const t=e.data.error||"Failed to mark upload as completed";throw new Error(t)}return e}catch(e){if("Network Error"===e.message||"TypeError"===e.name)throw new Error("Network error during upload completion. The file may have uploaded successfully.");throw e}}_onProgress(e){this.progressToast&&this.progressToast.updateProgress&&this.progressToast.updateProgress(e),"function"==typeof this.options.onProgress&&this.options.onProgress(e)}_onComplete(e){this.progressView&&this.progressView.markCompleted("Upload completed successfully!"),this.progressToast&&setTimeout(()=>{try{this.progressToast&&"function"==typeof this.progressToast.hide&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast:",e)}},2e3),"function"==typeof this.options.onComplete&&this.options.onComplete(e)}_onError(e){if(this.progressToast)try{this.progressToast.hide()}catch(t){console.warn("Error hiding progress toast on error:",t)}this.toastService&&this.toastService.error(`Upload failed: ${e.message}`),"function"==typeof this.options.onError&&this.options.onError(e)}_showProgressToast(){this.progressView=new ProgressView({filename:this.options.name||this.options.file.name,filesize:this.options.file.size,showCancel:!0,onCancel:()=>this.cancel()}),this.progressToast=this.toastService.showView(this.progressView,"info",{title:"File Upload",autohide:!1,dismissible:!1})}cancel(){return!this.cancelled&&(this.cancelled=!0,this.uploadRequest&&"function"==typeof this.uploadRequest.abort&&this.uploadRequest.abort(),this.progressView&&this.progressView.markCancelled(),this.progressToast&&setTimeout(()=>{try{this.progressToast&&"function"==typeof this.progressToast.hide&&this.progressToast.hide()}catch(e){console.warn("Error hiding progress toast on cancel:",e)}},1500),!0)}isCancelled(){return this.cancelled}then(e,t){return this.promise.then(e,t)}catch(e){return this.promise.catch(e)}finally(e){return this.promise.finally(e)}getStats(){return{filename:this.options.file.name,size:this.options.file.size,type:this.options.file.type,cancelled:this.cancelled,group:this.options.group,description:this.options.description}}}class FileManager extends i{constructor(e={}){super(e,{endpoint:"/api/fileman/manager"})}}class FileManagerList extends o{constructor(e={}){super({ModelClass:FileManager,endpoint:"/api/fileman/manager",size:10,...e})}}const a={create:{title:"Add Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,value:"s3://BUCKET_NAME/OPTION_FOLDER",placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6}]},edit:{title:"Edit Storage Backend",fields:[{name:"name",type:"text",label:"Display Name",placeholder:"Enter Display Name",cols:12},{name:"use",type:"text",label:"Use",placeholder:"Enter User or Leave Blank",cols:12},{name:"backend_url",type:"text",label:"Backend URL",required:!0,placeholder:"s3://bucket_name/optional folder",help:"Format: service://path. Valid services: s3",cols:12},{name:"allowed_origins",type:"text",label:"Domains Who Can Upload",cols:12},{name:"is_default",type:"switch",label:"Is Default",cols:6},{name:"is_active",type:"switch",label:"Is Active",default:!0,cols:6},{name:"is_public",type:"switch",label:"Is Public",default:!0,cols:6}]},owners:{fields:[{type:"collection",name:"group",label:"Group (Owner)",Collection:s,labelField:"name",valueField:"id",maxItems:10,placeholder:"Search groups...",emptyFetch:!1,debounceMs:300},{type:"collection",name:"user",label:"User (Owner)",Collection:n,labelField:"display_name",valueField:"id",maxItems:10,placeholder:"Search users...",emptyFetch:!1,debounceMs:300}]},credentials:{fields:[{name:"aws_region",type:"select",label:"AWS Region (optional)",value:"us-east-1",options:[{value:"",text:"System Default"},{value:"us-east-1",text:"US East (N. Virginia)"},{value:"us-east-2",text:"US East (Ohio)"},{value:"us-west-1",text:"US West (N. California)"},{value:"us-west-2",text:"US West (Oregon)"},{value:"ca-central-1",text:"Canada (Central)"},{value:"eu-west-1",text:"Europe (Ireland)"},{value:"eu-west-2",text:"Europe (London)"},{value:"eu-west-3",text:"Europe (Paris)"},{value:"eu-central-1",text:"Europe (Frankfurt)"},{value:"eu-north-1",text:"Europe (Stockholm)"},{value:"eu-south-1",text:"Europe (Milan)"},{value:"ap-southeast-2",text:"Asia Pacific (Sydney)"}],columns:12,help:"Optional. Defaults to project AWS_REGION if omitted."},{name:"aws_key",type:"text",label:"AWS Key (optional)",placeholder:"enter your AWS Key with S3 permissions",columns:12,help:"Optional, AWS Key with S3 permissions"},{name:"aws_secret",type:"text",label:"AWS Secret (optional)",placeholder:"enter your AWS Secret with S3 permissions",columns:12,help:"Optional, AWS Secret with S3 permissions"}]}};let r=class extends i{constructor(e={}){super(e,{endpoint:"/api/fileman/file"})}isImage(){return"image"===this.get("category")}getCategory(){return this.get("category")||this._inferCategoryFromContentType()}_inferCategoryFromContentType(){const e=(this.get("content_type")||"").toLowerCase();return e?e.startsWith("image/")?"image":e.startsWith("video/")?"video":e.startsWith("audio/")?"audio":"application/pdf"===e?"pdf":e.startsWith("text/")||"application/msword"===e||e.startsWith("application/vnd.openxmlformats-officedocument.wordprocessingml")||"application/vnd.oasis.opendocument.text"===e?"document":"application/vnd.ms-excel"===e||e.startsWith("application/vnd.openxmlformats-officedocument.spreadsheetml")||"application/vnd.oasis.opendocument.spreadsheet"===e?"spreadsheet":"application/vnd.ms-powerpoint"===e||e.startsWith("application/vnd.openxmlformats-officedocument.presentationml")||"application/vnd.oasis.opendocument.presentation"===e?"presentation":"application/zip"===e||"application/x-rar-compressed"===e||"application/x-7z-compressed"===e||"application/x-tar"===e||"application/gzip"===e?"archive":"other":"other"}hasRenditions(){const e=this.get("renditions");return!(!e||!Object.keys(e).length)}isUploadPending(){const e=this.get("upload_status");return!(!e||"completed"===e||"failed"===e)}regenerateRenditions(e){const t=this.id||this.get("id");if(!t)return Promise.reject(new Error("Cannot regenerate renditions on an unsaved file"));const i=Array.isArray(e)&&e.length?{regenerate_renditions:e}:{regenerate_renditions:!0};return this.rest.POST(`${this.endpoint}/${t}`,i)}share(e=!0){const t=this.id||this.get("id");return t?this.rest.POST(`${this.endpoint}/${t}`,{share:e}):Promise.reject(new Error("Cannot share an unsaved file"))}getRenditions(){const e=this.get("renditions");return e?Object.values(e):[]}getBestImageRendition(){const e=this.getRenditions().filter(e=>e&&"string"==typeof e.content_type&&e.content_type.startsWith("image/"));return e.length?e.reduce((e,t)=>{const i=(parseInt(e.width)||0)*(parseInt(e.height)||0);return(parseInt(t.width)||0)*(parseInt(t.height)||0)>i?t:e}):null}getThumbnailUrl(){const e=this.get("renditions")||{};if(e.thumbnail&&e.thumbnail.url)return e.thumbnail.url;const t=this.getBestImageRendition();return t?t.url:null}upload(e={}){return new FileUpload(this,e)}};class FileList extends o{constructor(e={}){super({ModelClass:r,endpoint:"/api/fileman/file",size:10,...e})}}const l={create:{title:"Add File",fields:[]},edit:{title:"Edit File Backend",fields:[]}},d=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,File:r,FileForms:l,FileList:FileList,FileManager:FileManager,FileManagerForms:a,FileManagerList:FileManagerList},Symbol.toStringTag,{value:"Module"}));class ModalView extends e{static _openDialogs=[];static _baseZIndex={backdrop:1050,modal:1055};static getFullscreenAwareZIndex(){return document.querySelector(".table-fullscreen")?{backdrop:10040,modal:10050}:ModalView._baseZIndex}static fixAllBackdropStacking(){const e=document.querySelectorAll(".modal-backdrop"),t=ModalView._openDialogs;if(0===e.length||0===t.length)return;const i=[...t].sort((e,t)=>(e._dialogZIndex||0)-(t._dialogZIndex||0)),o=document.querySelector(".table-fullscreen")||document.body;e.forEach((e,t)=>{if(t>=i.length)return;const s=i[t];e.style.zIndex=s._dialogZIndex-5,e.parentNode!==o&&o.appendChild(e)})}static updateAllBackdropStacking(){ModalView.fixAllBackdropStacking()}static getMountTarget(){return document.querySelector(".table-fullscreen")||document.body}constructor(e={}){const t=e.id||`modal-${Date.now()}-${Math.random().toString(36).slice(2,7)}`;super({...e,id:t,tagName:"div",className:`modal ${!1!==e.fade?"fade":""} ${e.className||""}`.trim().replace(/\s+/g," "),attributes:{tabindex:"-1","aria-hidden":"true","aria-labelledby":e.labelledBy||`${t}-label`,"aria-describedby":e.describedBy||null,...e.attributes}}),this.modalId=t,this.title=e.title||"",this.titleId=`${this.modalId}-label`,this.size=e.size||"",this.centered=void 0!==e.centered&&e.centered,this.scrollable=void 0!==e.scrollable&&e.scrollable,this.autoSize=e.autoSize||"auto"===e.size,this.backdrop=void 0===e.backdrop||e.backdrop,this.keyboard=void 0===e.keyboard||e.keyboard,this.focus=void 0===e.focus||e.focus,this.header=void 0===e.header||e.header,this.headerContent=e.headerContent||null,this.headerView=null,this.closeButton=void 0===e.closeButton||e.closeButton,this.contextMenu=e.contextMenu||null,this._processHeaderContent(this.headerContent),this.body=e.body??e.view??e.message??e.content??"",this.bodyView=null,this.bodyClass=e.bodyClass||"",this.noBodyPadding=e.noBodyPadding||!1,this.minWidth=e.minWidth||300,this.minHeight=e.minHeight||200,e.maxHeight&&(this.maxHeight=e.maxHeight),this.maxWidthPercent=e.maxWidthPercent||.9,this.maxHeightPercent=e.maxHeightPercent||.8,this._processBodyContent(this.body),this.footer=e.footer||null,this.footerView=null,this.footerClass=e.footerClass||"",this._processFooterContent(this.footer),this.buttons=e.buttons||null,this.onShow=e.onShow||null,this.onShown=e.onShown||null,this.onHide=e.onHide||null,this.onHidden=e.onHidden||null,this.onHidePrevented=e.onHidePrevented||null,this.autoShow=void 0!==e.autoShow&&e.autoShow,this.modal=null,this.relatedTarget=e.relatedTarget||null}_processBodyContent(t){if(t instanceof e||t&&"object"==typeof t&&"function"==typeof t.render)this.bodyView=t,this.body="",this.addChild(this.bodyView);else if("function"==typeof t)try{const i=t();i instanceof e?(this.bodyView=i,this.body="",this.addChild(this.bodyView)):i instanceof Promise?(this.bodyPromise=i,this.body='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.body=i}catch(i){console.error("ModalView: error processing body function:",i),this.body=t}else this.body=t}_processHeaderContent(t){if(t instanceof e)this.headerView=t,this.headerContent=null,this.addChild(this.headerView);else if("function"==typeof t)try{const i=t();i instanceof e?(this.headerView=i,this.headerContent=null,this.addChild(this.headerView)):i instanceof Promise?(this.headerPromise=i,this.headerContent='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.headerContent=i}catch(i){console.error("ModalView: error processing headerContent function:",i),this.headerContent=t}else this.headerContent=t}_processFooterContent(t){if(t instanceof e)this.footerView=t,this.footer=null,this.addChild(this.footerView);else if("function"==typeof t)try{const i=t();i instanceof e?(this.footerView=i,this.footer=null,this.addChild(this.footerView)):i instanceof Promise?(this.footerPromise=i,this.footer='<div class="text-center"><div class="spinner-border spinner-border-sm"></div></div>'):this.footer=i}catch(i){console.error("ModalView: error processing footer function:",i),this.footer=t}else this.footer=t}async getTemplate(){const e=["modal-dialog"];return this.size&&"auto"!==this.size&&(this.size.startsWith("fullscreen")?e.push(`modal-${this.size}`):["sm","lg","xl","xxl"].includes(this.size)&&(e.push(`modal-${this.size}`),["lg","xl","xxl"].includes(this.size)&&e.push("modal-fullscreen-sm-down"))),this.centered&&e.push("modal-dialog-centered"),this.scrollable&&(this.maxHeight?e.push("overflow-hidden"):e.push("modal-dialog-scrollable")),`\n <div class="${e.join(" ")}">\n <div class="modal-content">\n ${await this.buildHeader()}\n ${await this.buildBody()}\n ${await this.buildFooter()}\n </div>\n </div>\n `}async buildHeader(){if(!this.header)return"";if(this.headerView)return this.headerView.replaceById=!0,`<div class="modal-header" data-view-container="header">\n <div id="${this.headerView.id}"></div>\n </div>`;if(this.headerContent)return`<div class="modal-header">${this.headerContent}</div>`;let e="";return this.contextMenu&&this.contextMenu.items&&this.contextMenu.items.length>0?e=await this.buildContextMenu():this.closeButton&&(e='<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>'),`\n <div class="modal-header">\n ${this.title?`<h5 class="modal-title" id="${this.titleId}">${this.title}</h5>`:""}\n ${e}\n </div>\n `}async buildContextMenu(){const e=await this.filterContextMenuItems();if(0===e.length)return this.closeButton?'<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>':"";const t=this.contextMenu.icon||"bi-three-dots-vertical";return`\n <div class="dropdown">\n <button class="${this.contextMenu.buttonClass||"btn btn-link p-1 mojo-modal-context-menu-btn"}" type="button" data-bs-toggle="dropdown" aria-expanded="false">\n <i class="${t}"></i>\n </button>\n <ul class="dropdown-menu dropdown-menu-end">\n ${e.map(e=>{if("divider"===e.type)return'<li><hr class="dropdown-divider"></li>';const t=e.icon?`<i class="${e.icon} me-2"></i>`:"",i=e.label||"";if(e.href)return`<li><a class="dropdown-item" href="${e.href}"${e.target?` target="${e.target}"`:""}>${t}${i}</a></li>`;if(e.action){const o=Object.keys(e).filter(e=>e.startsWith("data-")).map(t=>`${t}="${e[t]}"`).join(" ");return`<li><a class="dropdown-item" data-action="${e.action}" ${o}>${t}${i}</a></li>`}return""}).join("")}\n </ul>\n </div>\n `}async filterContextMenuItems(){if(!this.contextMenu||!this.contextMenu.items)return[];const e=[];for(const i of this.contextMenu.items)if("divider"!==i.type){if(i.permissions)try{const e=this.getApp?.();let t=e?.activeUser||e?.getState?.("activeUser")||null;if(!t&&"undefined"!=typeof window&&window.getApp)try{t=window.getApp()?.activeUser}catch{}if(!t?.hasPermission)continue;if(!t.hasPermission(i.permissions))continue}catch(t){console.warn("ModalView: error checking permissions for context menu item:",t);continue}e.push(i)}else e.push(i);return e}async buildBody(){const e=`modal-body ${this.noBodyPadding?"modal-body-flush":""} ${this.bodyClass}`.replace(/\s+/g," ").trim();return this.bodyView?(this.bodyView.replaceById=!0,`<div class="${e}" data-view-container="body">\n <div id="${this.bodyView.id}"></div>\n </div>`):this.body||""===this.body?`<div class="${e}">${this.body}</div>`:""}async buildFooter(){if(this.footerView)return`<div class="modal-footer ${this.footerClass}" data-view-container="footer"></div>`;if(null!==this.footer&&"string"==typeof this.footer)return`<div class="modal-footer ${this.footerClass}">${this.footer}</div>`;if(this.buttons&&this.buttons.length>0){const e=this.buttons.map(e=>{const t=e.dismiss?'data-bs-dismiss="modal"':"",i=e.action?`data-action="${e.action}"`:"",o=e.id?`id="${e.id}"`:"",s=e.disabled?"disabled":"";return`\n <button type="${e.type||"button"}"\n class="btn ${e.class||"btn-secondary"}"\n ${o} ${t} ${i} ${s}>\n ${e.icon?`<i class="bi ${e.icon} me-1"></i>`:""}\n ${e.text||"Button"}\n </button>\n `}).join("");return`<div class="modal-footer ${this.footerClass}">${e}</div>`}return""}async mount(e=null){if(!this.mounted&&!this.destroyed){if(!this.element)throw new Error("Cannot mount modal without element");return await this.onBeforeMount(),ModalView.getMountTarget().appendChild(this.element),this.bindEvents(),this.mounted=!0,await this.onAfterMount(),this.emit("mounted",{view:this}),this}}async onAfterRender(){if(await super.onAfterRender(),window.Prism&&this.element&&this.element.querySelectorAll("pre code").length>0&&window.Prism.highlightAllUnder(this.element),this.autoSize)this.setupAutoSizing();else if(this.maxHeight){const e=this.element.querySelector(".modal-body");e&&(e.style.maxHeight=`${this.maxHeight}px`)}}async onAfterMount(){await super.onAfterMount(),"undefined"!=typeof window&&window.bootstrap?.Modal&&("static"===this.backdrop&&this.element.setAttribute("data-bs-backdrop","static"),this.keyboard||this.element.setAttribute("data-bs-keyboard","false"),this.modal=new window.bootstrap.Modal(this.element,{backdrop:this.backdrop,keyboard:this.keyboard,focus:this.focus}),this.bindBootstrapEvents(),this.autoShow&&this.show(this.relatedTarget))}setupAutoSizing(){this.element&&(this.element.addEventListener("shown.bs.modal",()=>{this.applyAutoSizing()},{once:!0}),setTimeout(()=>{this.isShown()&&this.applyAutoSizing()},100))}applyAutoSizing(){if(this.element)try{const e=this.element.querySelector(".modal-dialog"),t=this.element.querySelector(".modal-content"),i=this.element.querySelector(".modal-body");if(!e||!t||!i)return void console.warn("ModalView auto-sizing: required elements not found");if(this.bodyView&&!this.bodyView.element)return void setTimeout(()=>this.applyAutoSizing(),50);const o={dialogMaxWidth:e.style.maxWidth,dialogWidth:e.style.width,contentWidth:t.style.width,contentMaxHeight:t.style.maxHeight,hadScrollableClass:e.classList.contains("modal-dialog-scrollable")};e.style.maxWidth="none",e.style.width="auto",t.style.width="auto",t.style.maxHeight="none",t.offsetHeight;const s=t.getBoundingClientRect(),n=40,a=Math.min(window.innerWidth*this.maxWidthPercent,window.innerWidth-n);let r=Math.min(window.innerHeight*this.maxHeightPercent,window.innerHeight-n),l=Math.max(this.minWidth,Math.ceil(s.width+20)),d=Math.max(this.minHeight,Math.ceil(s.height));this.maxHeight&&(r=Math.min(this.maxHeight,r),e.style.maxHeight=`${r}px`),l=Math.min(l,a);const c=s.height>r;e.style.maxWidth=`${l}px`,e.style.width=`${l}px`,c&&(e.classList.contains("modal-dialog-scrollable")||e.classList.add("modal-dialog-scrollable"),t.style.maxHeight=`${r}px`,d=r),this.autoSizedWidth=l,this.autoSizedHeight=d,this._originalStyles=o}catch(e){console.error("ModalView: error in auto-sizing:",e);const t=this.element?.querySelector(".modal-dialog");t&&(t.style.maxWidth="")}}resetAutoSizing(){if(this.autoSize&&this._originalStyles&&this.element)try{const e=this.element.querySelector(".modal-dialog"),t=this.element.querySelector(".modal-content"),i=this.element.querySelector(".modal-body");e&&t&&i&&(e.style.maxWidth=this._originalStyles.dialogMaxWidth||"",e.style.width=this._originalStyles.dialogWidth||"",t.style.width=this._originalStyles.contentWidth||"",t.style.maxHeight=this._originalStyles.contentMaxHeight||"",!this._originalStyles.hadScrollableClass&&e.classList.contains("modal-dialog-scrollable")&&e.classList.remove("modal-dialog-scrollable"),delete this.autoSizedWidth,delete this.autoSizedHeight,delete this._originalStyles)}catch(e){console.error("ModalView: error resetting auto-sizing:",e)}}bindBootstrapEvents(){this.element.addEventListener("show.bs.modal",e=>{const t=ModalView._openDialogs.length,i=ModalView.getFullscreenAwareZIndex().modal+20*t;this.element.style.zIndex=i,this._dialogZIndex=i,this._backdropZIndex=i-10,ModalView._openDialogs.push(this),this.onShow&&this.onShow(e),this.emit("show",{dialog:this,relatedTarget:e.relatedTarget})}),this.element.addEventListener("shown.bs.modal",e=>{if(setTimeout(()=>ModalView.fixAllBackdropStacking(),50),this.onShown&&this.onShown(e),this.emit("shown",{dialog:this,relatedTarget:e.relatedTarget}),this.focus){const e=this.element.querySelector('input:not([type="hidden"]), textarea, select');e&&e.focus()}}),this.element.addEventListener("hide.bs.modal",e=>{const t=this.element.querySelector(":focus");t&&t.blur(),this.onHide&&!1===this.onHide(e)?e.preventDefault():this.emit("hide",{dialog:this})}),this.element.addEventListener("hidden.bs.modal",e=>{const t=ModalView._openDialogs.indexOf(this);t>-1&&ModalView._openDialogs.splice(t,1),ModalView._openDialogs.length>0&&(document.body.classList.add("modal-open"),setTimeout(()=>ModalView.fixAllBackdropStacking(),50)),this.previousFocus&&document.body.contains(this.previousFocus)&&this.previousFocus.focus(),this.onHidden&&this.onHidden(e),this.emit("hidden",{dialog:this})}),this.element.addEventListener("hidePrevented.bs.modal",e=>{this.onHidePrevented&&this.onHidePrevented(e),this.emit("hidePrevented",{dialog:this})})}show(e=null){this.previousFocus=document.activeElement,window.lastDialog=this,this.modal&&this.modal.show(e)}hide(){const e=this.element?.querySelector(":focus");e&&e.blur(),this.modal&&this.modal.hide()}toggle(e=null){this.modal&&this.modal.toggle(e)}isShown(){return this.element?.classList.contains("show")||!1}getModal(){return this.modal}handleUpdate(){this.modal&&this.modal.handleUpdate()}async setContent(t){if(t instanceof e){this.bodyView&&(await this.bodyView.destroy(),this.removeChild(this.bodyView)),this.bodyView=t,this.body="",this.addChild(this.bodyView);const e=this.element?.querySelector(".modal-body");e&&(e.innerHTML="",await this.bodyView.render(e))}else{this.body=t;const e=this.element?.querySelector(".modal-body");e&&(e.innerHTML=t)}this.handleUpdate()}setTitle(e){this.title=e;const t=this.element?.querySelector(".modal-title");t&&(t.textContent=e)}setLoading(e=!0,t="Loading..."){const i=this.element?.querySelector(".modal-body");i&&(e?i.innerHTML=`\n <div class="text-center py-4">\n <div class="spinner-border text-primary mb-3" role="status">\n <span class="visually-hidden">Loading...</span>\n </div>\n <p>${t}</p>\n </div>\n `:this.bodyView&&i.replaceChildren(this.bodyView.element))}async destroy(){if(this.modal){const e=this.element?.querySelector(":focus");e&&e.blur(),this.modal.dispose(),this.modal=null}this.previousFocus&&document.body.contains(this.previousFocus)&&(this.previousFocus.focus(),this.previousFocus=null),this.autoSize&&this.resetAutoSizing(),await super.destroy()}async onBeforeDestroy(){this.headerView&&await this.headerView.destroy(),this.bodyView&&await this.bodyView.destroy(),this.footerView&&await this.footerView.destroy(),await super.onBeforeDestroy(),this.modal&&(this.modal.dispose(),this.modal=null)}}let c=null,h=0,u=null;const p={show(e){"string"==typeof e&&(e={message:e});const{message:t="Loading...",timeout:i=3e4}=e||{};if(h++,1===h){u&&clearTimeout(u);const e=ModalView.getFullscreenAwareZIndex().modal+1e3;c||(c=document.createElement("div"),c.className="mojo-loading-overlay",c.innerHTML=`\n <div class="mojo-loading-card">\n <div class="mojo-loading-spinner"></div>\n <div class="mojo-loading-message">${t}</div>\n </div>\n <style>\n .mojo-loading-overlay {\n position: fixed; top: 0; left: 0; width: 100vw; height: 100vh;\n background: rgba(255, 255, 255, 0.4);\n backdrop-filter: blur(2px);\n -webkit-backdrop-filter: blur(2px);\n display: flex; align-items: center; justify-content: center;\n opacity: 0; transition: opacity 0.2s ease;\n }\n .mojo-loading-overlay.show { opacity: 1; }\n .mojo-loading-card {\n display: flex; align-items: center; gap: 0.85rem;\n background: #fff;\n border: 1px solid #e9ecef;\n border-radius: 12px;\n padding: 1rem 1.5rem;\n box-shadow: 0 4px 24px rgba(0,0,0,0.08), 0 1px 4px rgba(0,0,0,0.04);\n }\n .mojo-loading-spinner {\n width: 22px; height: 22px;\n border: 2.5px solid #e9ecef;\n border-top-color: #0d6efd;\n border-radius: 50%;\n animation: mojo-spin 0.7s linear infinite;\n flex-shrink: 0;\n }\n .mojo-loading-message {\n font-size: 0.88rem;\n font-weight: 500;\n color: #495057;\n white-space: nowrap;\n }\n @keyframes mojo-spin { to { transform: rotate(360deg); } }\n</style>\n `,document.body.appendChild(c)),c.style.zIndex=String(e);const o=c.querySelector(".mojo-loading-message");o&&(o.textContent=t),requestAnimationFrame(()=>{c&&c.classList.add("show")}),i>0&&(u=setTimeout(()=>{console.error("BusyIndicator timed out."),p.hide(!0)},i))}else if(c){const e=c.querySelector(".mojo-loading-message");e&&(e.textContent=t)}},hide(e=!1){e?h=0:h--,h>0||(h=0,u&&(clearTimeout(u),u=null),c&&(c.classList.remove("show"),setTimeout(()=>{c&&0===h&&(c.remove(),c=null)},200)))},isShown:()=>null!==c&&h>0},m="\n max-height: 60vh;\n overflow-y: auto;\n background: #1e1e1e;\n color: #d4d4d4;\n padding: 1.25rem;\n border-radius: 0.5rem;\n margin: 0;\n font-family: 'Cascadia Code', 'Fira Code', 'JetBrains Mono', 'Consolas', 'Monaco', monospace;\n font-size: 0.9rem;\n line-height: 1.6;\n border: 1px solid #2d2d30;\n box-shadow: 0 4px 6px rgba(0, 0, 0, 0.3);\n".replace(/\s+/g," ").trim();class CodeViewer extends e{constructor(e={}){super({tagName:"div",className:"mojo-code-viewer",...e}),this.code=e.code||"",this.language=e.language||"javascript"}async getTemplate(){return CodeViewer.formatCode(this.code,this.language)}static formatCode(e,t="javascript"){let i;i=window.Prism&&window.Prism.languages[t]?window.Prism.highlight(e,window.Prism.languages[t],t):String(e).replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'");const o=window.Prism?`language-${t}`:"";return`\n <style>\n .dialog-code-block .token.comment { color: #6a9955; }\n .dialog-code-block .token.string { color: #ce9178; }\n .dialog-code-block .token.keyword { color: #569cd6; }\n .dialog-code-block .token.function { color: #dcdcaa; }\n .dialog-code-block .token.number { color: #b5cea8; }\n .dialog-code-block .token.operator { color: #d4d4d4; }\n .dialog-code-block .token.class-name { color: #4ec9b0; }\n .dialog-code-block .token.punctuation { color: #d4d4d4; }\n .dialog-code-block .token.boolean { color: #569cd6; }\n .dialog-code-block .token.property { color: #9cdcfe; }\n .dialog-code-block .token.tag { color: #569cd6; }\n .dialog-code-block .token.attr-name { color: #9cdcfe; }\n .dialog-code-block .token.attr-value { color: #ce9178; }\n .dialog-code-block ::selection { background: #264f78; }\n</style>\n <pre class="${o} dialog-code-block" style="${m}">\n <code class="${o}" style="color: inherit; background: transparent; text-shadow: none;">${i}</code>\n </pre>\n `}static highlightCodeBlocks(e=document){window.Prism&&window.Prism.highlightAllUnder&&window.Prism.highlightAllUnder(e)}}class HtmlPreview extends e{constructor(e={}){super({tagName:"div",className:"mojo-html-preview",...e}),this.html=e.html||e.content||"",this.height=e.height||500}async getTemplate(){return`\n <div class="html-preview-container">\n <div class="d-flex justify-content-between align-items-center mb-2">\n <small class="text-muted">Preview (sandboxed)</small>\n <button type="button" class="btn btn-sm btn-outline-secondary" data-action="refresh">\n <i class="bi bi-arrow-clockwise"></i> Refresh\n </button>\n </div>\n <iframe\n class="border rounded w-100 mojo-html-preview-frame"\n style="height: ${this.height}px; background: white;"\n sandbox="allow-same-origin"\n frameborder="0"\n ></iframe>\n </div>\n `}async onAfterMount(){await super.onAfterMount(),this._writeIframe()}onActionRefresh(){this._writeIframe()}_writeIframe(){const e=this.element?.querySelector(".mojo-html-preview-frame");if(!e)return;const t=e.contentDocument||e.contentWindow?.document;t&&(t.open(),t.write(this.html),t.close())}setHtml(e){this.html=e,this._writeIframe()}}class Modal{static _renderAndAwait(e,{buttons:t=null,rejectOnDismiss:i=!1,onAction:o=null,cleanup:s=null}={}){const n=ModalView.getMountTarget();return new Promise((a,r)=>{let l=!1;const d=e=>{l||(l=!0,a(e))},c=e=>{l||(l=!0,r(e))};(async()=>{try{await e.render(!0,n)}catch(a){return void c(a)}t&&t.length>0&&e.element&&e.element.querySelectorAll(".modal-footer button").forEach((i,s)=>{const n=t[s];n&&i.addEventListener("click",async t=>{if(l)return;const i=void 0!==n.value?n.value:n.action??s;if("function"!=typeof n.handler)if("function"==typeof o&&n.action)try{const a=await o(n.action,{dialog:e,button:n,index:s,event:t});if(null===a||!1===a)return;const r=!0===a||void 0===a?i:a;n.dismiss||e.hide(),d(r)}catch(a){console.error("Modal onAction error:",a)}else n.dismiss||e.hide(),d(i);else try{const o=await n.handler({dialog:e,button:n,index:s,event:t});if(null===o||!1===o)return;const a=!0===o||void 0===o?i:o;n.dismiss||e.hide(),d(a)}catch(a){console.error("Modal button handler error:",a)}})}),e.on("hidden",()=>{l||(i?c(new Error("Dialog dismissed")):d(null)),setTimeout(async()=>{try{"function"==typeof s&&await s(e)}catch(a){console.error("Modal cleanup error:",a)}try{await e.destroy()}catch(a){console.error("Modal destroy error:",a)}e.element?.parentNode&&e.element.parentNode.removeChild(e.element)},100)}),e.show()})()})}static async dialog(e={}){"string"==typeof e&&(e={...arguments[2]||{},body:arguments[0],title:arguments[1]||"Alert"});const{title:t="Dialog",content:i,body:o,view:s,message:n,size:a="md",centered:r=!0,buttons:l=[{text:"OK",class:"btn-primary",value:!0}],rejectOnDismiss:d=!1,...c}=e,h=new ModalView({title:t,body:o??s??n??i??"",size:a,centered:r,buttons:l,...c});return Modal._renderAndAwait(h,{buttons:l,rejectOnDismiss:d})}static async drawer(t={}){const{eyebrow:i,title:o,meta:s=[],view:n,body:a,size:r="lg",...l}=t,d=s.length?`\n <div class="modal-drawer-meta">\n ${s.map(e=>"string"==typeof e?`<span>${Modal._esc(e)}</span>`:`<span>${e.icon?`<i class="${Modal._esc(e.icon)} me-1"></i>`:""}${Modal._esc(e.text||"")}</span>`).join("")}\n </div>`:"",c=`\n <div class="modal-drawer-head">\n ${i?`<span class="modal-drawer-eyebrow">${Modal._esc(i)}</span>`:""}\n <h2 class="modal-drawer-title">${Modal._esc(o||"")}</h2>\n ${d}\n </div>\n `;let h;return h=n&&"object"==typeof n&&"function"==typeof n.render?new class extends e{async getTemplate(){return`${c}<div class="modal-drawer-body" data-container="drawer-body"></div>`}async onInit(){n.containerId="drawer-body",this.addChild(n)}}:`${c}<div class="modal-drawer-body">${a||""}</div>`,Modal.dialog({header:!1,body:h,size:r,centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...l})}static _esc(e){const t="undefined"!=typeof document?document.createElement("div"):null;return t?(t.textContent=String(e??""),t.innerHTML):String(e??"")}static async show(e,t={}){return Modal.dialog({header:void 0!==t.title&&!!t.title,title:t.title||void 0,body:e,size:"lg",centered:!1,buttons:[{text:"Close",class:"btn-secondary",dismiss:!0}],...t})}static async showModel(e,t={}){const i=e.constructor,o=i?.VIEW_CLASS;if(!o)throw new Error(`Modal.showModel: No VIEW_CLASS defined on ${i?.name||"model"}. Set ${i?.name||"Model"}.VIEW_CLASS = YourView to use this method.`);const s=new o({model:e});return Modal.show(s,t)}static async showModelById(e,t,i={}){const o=new e({id:t});return await o.fetch(),o.id?Modal.showModel(o,i):(Modal.alert({message:`Could not find ${e.name||"record"} with ID: ${t}`,type:"warning"}),null)}static async showModelView(e,t={}){const i=e.constructor,o=i?.VIEW_CLASS;if(!o)throw new Error(`Modal.showModelView: No VIEW_CLASS defined on ${i?.name||"model"}.`);const s=new o({model:e});return Modal.dialog({header:!1,body:s,size:"lg",centered:!1,...t})}static async alert(e={},t,i){let o;o="string"==typeof e?{message:e,...void 0!==t?{title:t}:{},...i||{}}:{...e};const{message:s="",title:n="Alert",type:a="info",icon:r,className:l,...d}=o,c="danger"===a?"error":a,h=[`modal-alert modal-alert-${c}`,l].filter(Boolean).join(" "),u=void 0!==r?r:{info:"bi-info-circle",success:"bi-check-circle",warning:"bi-exclamation-triangle",error:"bi-x-circle"}[c],p=u?`<i class="bi ${u} modal-alert-icon"></i>`:"",m=`<span class="modal-alert-headline">${n}</span>`;return Modal.dialog({title:`${p}${m}`,body:`<p class="modal-alert-message">${s}</p>`,size:"sm",centered:!0,className:h,buttons:[{text:"OK",class:"btn-primary",value:!0}],...d})}static async confirm(e,t="Confirm",i={}){let o;"object"==typeof e&&null!==e?(o=(i=e).message,t=i.title||t):o=e;const s=[{text:i.cancelText||"Cancel",class:"btn-secondary",dismiss:!0,action:"cancel"},{text:i.confirmText||"Confirm",class:i.confirmClass||"btn-primary",action:"confirm"}],n=new ModalView({title:t,body:`<p>${o}</p>`,size:i.size||"sm",centered:!0,backdrop:"static",buttons:s,...i});return"confirm"===await Modal._renderAndAwait(n,{buttons:s})}static async prompt(e,t="Input",i={}){const o=`prompt-input-${Date.now()}`,s=i.defaultValue||"",n=i.inputType||"text",a=i.placeholder||"",r=[{text:"Cancel",class:"btn-secondary",dismiss:!0},{text:"OK",class:"btn-primary",action:"ok"}],l=new ModalView({title:t,body:`\n <p>${e}</p>\n <input type="${n}"\n class="form-control"\n id="${o}"\n value="${s}"\n placeholder="${a}">\n `,size:i.size||"sm",centered:!0,backdrop:"static",buttons:r,...i});return l.on("shown",()=>{const e=l.element.querySelector(`#${o}`);e&&(e.focus(),e.select())}),Modal._renderAndAwait(l,{buttons:r,onAction:async e=>{if("ok"!==e)return null;const t=l.element.querySelector(`#${o}`);return t?t.value:null}})}static showError(e){return Modal.alert(e,"Error",{type:"error"})}static async form(e={}){const{title:t="Form",formConfig:i={},size:o="md",centered:s=!0,submitText:n="Submit",cancelText:a="Cancel",...r}=e,l=new(0,(await import("./FormView-COIPtbrd.js").then(e=>e.c)).default)({fileHandling:e.fileHandling||"base64",data:e.data,defaults:e.defaults,model:e.model,formConfig:{fields:i.fields||e.fields,...i,submitButton:!1,resetButton:!1}}),d=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],c=new ModalView({title:t,body:l,size:o,centered:s,buttons:d,...r});return Modal._renderAndAwait(c,{buttons:d,onAction:async t=>{if("cancel"===t)return c.hide(),null;if("submit"!==t)return null;if(!l.validate())return l.focusFirstError(),!1;if(e.autoSave&&e.model){c.setLoading(!0);const e=await l.saveModel();return e.success?e:(c.setLoading(!1),await c.render(),c.getApp()?.toast?.error(e.message),!1)}try{return await l.getFormData()}catch(i){return console.error("Modal.form: error collecting form data:",i),l.showError("Error collecting form data"),!1}},cleanup:async()=>{try{await l.destroy()}catch{}}})}static async modelForm(e={}){const{title:t="Edit",formConfig:i={},size:o="md",centered:s=!0,submitText:n="Save",cancelText:a="Cancel",model:r,fields:l,...d}=e;if(!r)throw new Error("Modal.modelForm requires a model");const c=new(0,(await import("./FormView-COIPtbrd.js").then(e=>e.c)).default)({fileHandling:e.fileHandling||"base64",model:r,data:e.data,defaults:e.defaults,formConfig:{fields:l||i.fields||[],...i,submitButton:!1,resetButton:!1}}),h=[{text:a,class:"btn-secondary",action:"cancel"},{text:n,class:"btn-primary",action:"submit"}],u=new ModalView({title:t,body:c,size:o,centered:s,buttons:h,...d});return Modal._renderAndAwait(u,{buttons:h,onAction:async e=>{if("cancel"===e)return u.hide(),null;if("submit"!==e)return null;u.setLoading(!0,"Saving...");try{const e=await c.handleSubmit();if(e.success)return e;u.setLoading(!1);let t=e.error;return e.data?.error&&(t=e.data.error),u.getApp()?.toast?.error(t),!1}catch(t){return console.error("Modal.modelForm: error saving:",t),await u.setContent(c),c.showError(t.message||"An error occurred while saving"),!1}},cleanup:async()=>{try{await c.destroy()}catch{}}})}static async data(e={}){const{title:t="Data View",data:i={},model:o=null,fields:s=[],columns:n=2,responsive:a=!0,showEmptyValues:r=!1,emptyValueText:l="—",size:d="lg",centered:c=!0,closeText:h="Close",...u}=e,p=new(0,(await import("./DataView-z2rxXk4L.js")).default)({data:i,model:o,fields:s,columns:n,responsive:a,showEmptyValues:r,emptyValueText:l}),m=[{text:h,class:"btn-secondary",value:"close"}],g=new ModalView({title:t,body:p,size:d,centered:c,buttons:m,...u});return p.on("field:click",e=>g.emit("dataview:field:click",e)),p.on("error",e=>g.emit("dataview:error",e)),Modal._renderAndAwait(g,{buttons:m,cleanup:async()=>{try{await p.destroy()}catch{}}})}static async code(e={}){const{code:t="",language:i="javascript",title:o="Source Code",size:s="lg",...n}=e,a=new CodeViewer({code:t,language:i}),r=[{text:"Copy to Clipboard",class:"btn-primary",icon:"bi-clipboard",action:"copy"},{text:"Close",class:"btn-secondary",dismiss:!0}],l=new ModalView({title:o,body:a,size:s,scrollable:!0,buttons:r,...n});return Modal._renderAndAwait(l,{buttons:r,onAction:async e=>{if("copy"!==e)return null;if(!navigator.clipboard)return!1;try{await navigator.clipboard.writeText(t),Modal._showCopySuccess(l)}catch(i){console.error("Modal.code: clipboard write failed:",i)}return!1}})}static _showCopySuccess(e){const t=e.element?.querySelector('[data-action="copy"]');if(!t)return;const i=t.innerHTML;t.innerHTML='<i class="bi bi-check me-1"></i>Copied!',t.classList.remove("btn-primary"),t.classList.add("btn-success"),t.disabled=!0,setTimeout(()=>{t.innerHTML=i,t.classList.remove("btn-success"),t.classList.add("btn-primary"),t.disabled=!1},2e3)}static async htmlPreview(e={}){const{html:t=e.content||"",title:i="HTML Preview",size:o="lg",height:s=500,...n}=e,a=new HtmlPreview({html:t,height:s}),r=[{text:"Close",class:"btn-secondary",dismiss:!0}],l=new ModalView({title:i,body:a,size:o,scrollable:!1,buttons:r,...n});return Modal._renderAndAwait(l,{buttons:r})}static async updateModelImage(e={},t={}){const i=e.upload||!1,o=t.name||e.field||"image",s={title:"Upload Your Avatar",model:null,autoSave:!i,size:"sm",fields:[{type:"image",name:o,size:"lg",imageSize:{width:200,height:200},placeholder:"Upload your image",...t}],...e},n=await Modal.form(s);if(!i||!n||!e.model)return n;const a=n[o];if(!a||!a.startsWith("data:"))return n;const l=a.split(","),d=l[0]?.match(/:(.*?);/),c=d?.[1]||"image/png",h=atob(l[1]);let u=h.length;const p=new Uint8Array(u);for(;u--;)p[u]=h.charCodeAt(u);const m=c.split("/")[1]||"png",g="undefined"!=typeof window&&window.File||globalThis.File;if(!g)throw new Error("File API is not available in this environment");const f=new g([p],`${o}.${m}`,{type:c}),w=new r;return await w.upload({file:f,name:`${o}.${m}`,description:e.uploadDescription||`${o} upload`,showToast:!0}),e.model.save({[o]:w.id})}static loading(e){p.show(e)}static hideLoading(e){p.hide(e)}static showBusy(e){return Modal.loading(e)}static hideBusy(e){return Modal.hideLoading(e)}}const g=/* @__PURE__ */Object.freeze(/* @__PURE__ */Object.defineProperty({__proto__:null,default:Modal},Symbol.toStringTag,{value:"Module"}));export{CodeViewer as C,r as F,Modal as M,ProgressView as P,ToastService as T,ModalView as a,l as b,FileList as c,FileManager as d,a as e,FileManagerList as f,FileUpload as g,d as h,g as i};
|
|
3
|
-
//# sourceMappingURL=Modal-KnJhNZ1E.js.map
|