import L from 'leaflet' import { useEffect } from 'react' import { useMap } from 'react-leaflet' import type { Map as MapboxMap } from 'mapbox-gl' import 'mapbox-gl-leaflet' import 'mapbox-gl/dist/mapbox-gl.css' type MapboxGLLayer = L.Layer & { getMapboxMap: () => MapboxMap | undefined } interface MapboxGLLayerOptions { accessToken: string style: string attribution?: string } type LeafletWithMapbox = typeof L & { mapboxGL: (options: MapboxGLLayerOptions) => MapboxGLLayer } type MapboxMapWithProjection = MapboxMap & { setProjection?: (projectionName: string) => void } interface MapboxVectorTileLayerProps { mapboxStyle: string mapboxToken: string attribution: string } /** * Component to render Mapbox Vector Tiles using mapbox-gl-leaflet * @category Map */ export const MapboxVectorTileLayer = ({ mapboxStyle, mapboxToken, attribution, }: MapboxVectorTileLayerProps) => { const map = useMap() useEffect(() => { if (!mapboxStyle || !mapboxToken) return // Create Mapbox GL layer const leafletWithMapbox = L as LeafletWithMapbox const gl = leafletWithMapbox.mapboxGL({ accessToken: mapboxToken, style: mapboxStyle, attribution, }) gl.addTo(map) // Access the Mapbox GL map instance and disable globe projection const mapboxMap = gl.getMapboxMap() as MapboxMapWithProjection | undefined mapboxMap?.setProjection('mercator') // Cleanup on unmount return () => { if (map.hasLayer(gl)) { map.removeLayer(gl) } } }, [attribution, map, mapboxStyle, mapboxToken]) return null }