{"version":3,"file":"main.umd.cjs","names":[],"sources":["../src/main.ts"],"sourcesContent":["import type { VistaData, VistaExtension, VistaImageParams, VistaView } from 'vistaview';\nimport { VistaBox } from 'vistaview';\n\nexport interface MapboxConfig {\n  accessToken: string;\n  zoom?: number; // Default zoom level (0-22)\n  width?: number; // Map width in pixels\n  height?: number; // Map height in pixels\n  style?: string; // Map style (e.g., 'streets-v12', 'satellite-v9', 'outdoors-v12')\n  pitch?: number; // Camera pitch (0-60)\n  bearing?: number; // Camera bearing (0-359)\n}\n\nexport interface MapboxLocation {\n  lng: number;\n  lat: number;\n  zoom?: number;\n  bearing?: number;\n  pitch?: number;\n}\n\n/**\n * Parse Mapbox URL and extract location data\n * Supports various Mapbox URL formats:\n * - https://api.mapbox.com/styles/v1/{username}/{style_id}/static/-74.0060,40.7128,15,0/800x600\n * - Custom format: mapbox://-74.0060,40.7128,15\n * @param url - Mapbox URL or coordinate string\n * @returns Location data or null if not found\n */\nexport function parseMapboxLocation(url: string): MapboxLocation | null {\n  if (!url) return null;\n\n  try {\n    // Match pattern: lng,lat,zoom or lng,lat,zoom,bearing,pitch\n    const coordMatch = url.match(\n      /(-?\\d+\\.?\\d*),\\s*(-?\\d+\\.?\\d*),?\\s*(\\d+\\.?\\d*)?,?\\s*(\\d+\\.?\\d*)?,?\\s*(\\d+\\.?\\d*)?/\n    );\n    if (coordMatch) {\n      return {\n        lng: parseFloat(coordMatch[1]),\n        lat: parseFloat(coordMatch[2]),\n        zoom: coordMatch[3] ? parseFloat(coordMatch[3]) : undefined,\n        bearing: coordMatch[4] ? parseFloat(coordMatch[4]) : undefined,\n        pitch: coordMatch[5] ? parseFloat(coordMatch[5]) : undefined,\n      };\n    }\n\n    // Try URL parsing for mapbox.com links\n    const urlObj = new URL(url);\n    if (urlObj.hostname.includes('mapbox.com')) {\n      // Extract from pathname like /@lng,lat,zoom\n      const atMatch = urlObj.pathname.match(/@(-?\\d+\\.?\\d*),(-?\\d+\\.?\\d*),(\\d+\\.?\\d*)?/);\n      if (atMatch) {\n        return {\n          lng: parseFloat(atMatch[1]),\n          lat: parseFloat(atMatch[2]),\n          zoom: atMatch[3] ? parseFloat(atMatch[3]) : undefined,\n        };\n      }\n    }\n  } catch (error) {\n    // Not a valid URL, might be coordinate string - already handled above\n  }\n\n  return null;\n}\n\n/**\n * Get Mapbox static image URL\n * @param location - Location data\n * @param config - Mapbox configuration\n * @returns Static map image URL\n */\nexport function getMapboxStaticImage(location: MapboxLocation, config: MapboxConfig): string {\n  const zoom = location.zoom || config.zoom || 15;\n  const width = config.width || 800;\n  const height = config.height || 600;\n  const style = config.style || 'streets-v12';\n  const bearing = location.bearing || config.bearing || 0;\n  const pitch = location.pitch || config.pitch || 0;\n\n  // Add marker overlay\n  const marker = `pin-s+ff0000(${location.lng},${location.lat})`;\n\n  return `https://api.mapbox.com/styles/v1/mapbox/${style}/static/${marker}/${location.lng},${location.lat},${zoom},${bearing},${pitch}/${width}x${height}@2x?access_token=${config.accessToken}`;\n}\n\nexport class VistaMapbox extends VistaBox {\n  element: HTMLDivElement;\n  private mapboxConfig: MapboxConfig;\n  private location: MapboxLocation;\n  private thumbnailImage: HTMLImageElement;\n\n  constructor(par: VistaImageParams, config: MapboxConfig, location: MapboxLocation) {\n    super(par);\n\n    this.mapboxConfig = config;\n    this.location = location;\n\n    const div = document.createElement('div');\n    div.style.position = 'relative';\n    this.thumbnailImage = document.createElement('img');\n    div.appendChild(this.thumbnailImage);\n    this.thumbnailImage.src = this.origin?.image.src || getMapboxStaticImage(location, config);\n    this.thumbnailImage.style.width = '100%';\n    this.thumbnailImage.style.height = '100%';\n    this.thumbnailImage.style.objectFit = 'cover';\n    this.thumbnailImage.classList.add('vvw--pulsing');\n\n    this.element = div;\n\n    this.element.classList.add('vvw-img-hi');\n\n    // Set sizes\n    const { width: fullWidth, height: fullHeight } = this.getFullSizeDim();\n    this.fullH = fullHeight;\n    this.fullW = fullWidth;\n    this.minW = this.fullW * 0.5;\n    this.maxW = this.fullW; // no scaling\n    this.element.style.width = `${fullWidth}px`;\n    this.element.style.height = `${fullHeight}px`;\n\n    // Trigger setSizes to setup thumb and map initial style\n    this.setSizes({ stableSize: false, initDimension: true });\n\n    if (this.pos === 0) {\n      // Load Mapbox GL JS dynamically if not already loaded\n      this.loadMapboxGL().then(() => {\n        this.initializeMap(div);\n      });\n    } else {\n      this.isLoadedResolved!(true);\n    }\n  }\n\n  private async loadMapboxGL(): Promise<void> {\n    // Check if Mapbox GL is already loaded\n    if ((window as any).mapboxgl) {\n      return;\n    }\n\n    // Load CSS\n    if (!document.querySelector('.vistaview-mapbox-gl-css')) {\n      const link = document.createElement('link');\n      link.rel = 'stylesheet';\n      link.href = 'https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.css';\n      link.className = 'vistaview-mapbox-gl-css';\n      document.head.appendChild(link);\n    }\n\n    // Load JS\n    if (document.querySelector('.vistaview-mapbox-gl-js')) {\n      return;\n    }\n\n    return new Promise((resolve, reject) => {\n      const script = document.createElement('script');\n      script.src = 'https://api.mapbox.com/mapbox-gl-js/v3.0.1/mapbox-gl.js';\n      script.className = 'vistaview-mapbox-gl-js';\n      script.onload = () => resolve();\n      script.onerror = () => reject(new Error('Failed to load Mapbox GL JS'));\n      document.head.appendChild(script);\n    });\n  }\n\n  private initializeMap(container: HTMLDivElement): void {\n    const mapboxgl = (window as any).mapboxgl;\n    if (!mapboxgl) {\n      this.isLoadedRejected!(new Error('Mapbox GL JS not loaded'));\n      return;\n    }\n\n    // Create map container div\n    const mapDiv = document.createElement('div');\n    mapDiv.style.position = 'absolute';\n    mapDiv.style.top = '0';\n    mapDiv.style.left = '0';\n    mapDiv.style.width = '100%';\n    mapDiv.style.height = '100%';\n    mapDiv.style.opacity = '0';\n    mapDiv.style.transition = 'opacity 1s ease';\n    container.appendChild(mapDiv);\n\n    // Stop pointer events from propagating to VistaView's drag handlers\n    mapDiv.addEventListener('pointerdown', (e) => {\n      e.stopPropagation();\n    });\n\n    mapboxgl.accessToken = this.mapboxConfig.accessToken;\n\n    const map = new mapboxgl.Map({\n      container: mapDiv,\n      style: `mapbox://styles/mapbox/${this.mapboxConfig.style || 'streets-v12'}`,\n      center: [this.location.lng, this.location.lat],\n      zoom: this.location.zoom || this.mapboxConfig.zoom || 15,\n      bearing: this.location.bearing || this.mapboxConfig.bearing || 0,\n      pitch: this.location.pitch || this.mapboxConfig.pitch || 0,\n    });\n\n    // Add marker\n    new mapboxgl.Marker({ color: '#ff0000' })\n      .setLngLat([this.location.lng, this.location.lat])\n      .addTo(map);\n\n    // Add navigation controls\n    map.addControl(new mapboxgl.NavigationControl());\n\n    map.on('load', () => {\n      this.onImageReady = () => {\n        map.resize();\n        mapDiv.style.opacity = '1';\n        this.thumbnailImage.classList.remove('vvw--pulsing');\n      };\n\n      this.isLoadedResolved!(true);\n    });\n\n    map.on('error', (e: any) => {\n      this.isLoadedRejected!(e);\n    });\n  }\n\n  // Use 16:9 aspect ratio with max 800px width\n  protected getFullSizeDim(): { width: number; height: number } {\n    const maxWidth = Math.min(window.innerWidth, this.mapboxConfig.width || 800);\n    return {\n      width: maxWidth,\n      height: (maxWidth * 9) / 16,\n    };\n  }\n\n  // Override to avoid propagating content change event\n  setFinalTransform() {\n    return super.setFinalTransform({ propagateEvent: false });\n  }\n}\n\nexport function mapbox(config: MapboxConfig): VistaExtension {\n  if (!config.accessToken) {\n    console.error('Mapbox access token is required');\n  }\n\n  return {\n    name: 'mapbox',\n    onInitializeImage: (params: VistaImageParams) => {\n      const url = params.elm.config.src;\n      const location = parseMapboxLocation(url);\n      if (!location) return;\n\n      return new VistaMapbox(params, config, location);\n    },\n    onImageView: async (data: VistaData, v: VistaView) => {\n      const mainData = data.images.to![Math.floor(data.images.to!.length / 2)];\n      if (mainData instanceof VistaMapbox) {\n        v.deactivateUi(['download', 'zoomIn', 'zoomOut'], mainData);\n      }\n    },\n  };\n}\n"],"mappings":"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"}