{"version":3,"file":"leaflet-map.cjs","names":[],"sources":["../../src/geo/leaflet-map.tsx"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { boundingBox } from \"./bounds\";\nimport type { Coordinate } from \"./types\";\n\n/**\n * Minimal structural typing for the slice of the Leaflet API this layer uses.\n * Declared locally so the SDK type-checks and builds even when `leaflet` (an\n * optional peer) is not installed — the real module is loaded at runtime.\n */\ninterface LeafletMapInstance {\n    setView: (center: [number, number], zoom: number) => LeafletMapInstance;\n    fitBounds: (bounds: [[number, number], [number, number]], options?: unknown) => void;\n    remove: () => void;\n}\ninterface LeafletLayer {\n    addTo: (map: LeafletMapInstance) => LeafletLayer;\n}\ninterface LeafletModule {\n    map: (el: HTMLElement, options?: unknown) => LeafletMapInstance;\n    tileLayer: (url: string, options?: unknown) => LeafletLayer;\n    polyline: (latlngs: [number, number][], options?: unknown) => LeafletLayer;\n    circleMarker: (latlng: [number, number], options?: unknown) => LeafletLayer;\n}\n\nexport interface LeafletTrajectoryProps {\n    points: readonly Coordinate[];\n    current?: Coordinate | null;\n    tileUrl: string;\n    tileAttribution?: string;\n    strokeColor?: string;\n}\n\n/**\n * Leaflet-backed tile layer for {@link TrajectoryMap}. Loaded lazily and only\n * when a `tileUrl` is provided. Requires `leaflet` to be installed by the app\n * (optional peer dependency) plus its stylesheet imported once:\n * `import \"leaflet/dist/leaflet.css\"`.\n */\nexport function LeafletTrajectory({\n    points,\n    current,\n    tileUrl,\n    tileAttribution,\n    strokeColor,\n}: LeafletTrajectoryProps) {\n    const nodeRef = useRef<HTMLDivElement>(null);\n    const [error, setError] = useState<string | null>(null);\n\n    useEffect(() => {\n        let map: LeafletMapInstance | null = null;\n        let cancelled = false;\n\n        const specifier = \"leaflet\";\n        import(/* @vite-ignore */ specifier)\n            .then((mod: { default?: LeafletModule } & LeafletModule) => {\n                if (cancelled || !nodeRef.current) return;\n                const L: LeafletModule = mod.default ?? mod;\n\n                map = L.map(nodeRef.current, { attributionControl: true });\n                L.tileLayer(tileUrl, {\n                    attribution: tileAttribution ?? \"\",\n                    maxZoom: 19,\n                }).addTo(map);\n\n                const latlngs = points.map((p): [number, number] => [p.latitude, p.longitude]);\n                if (latlngs.length > 0) {\n                    L.polyline(latlngs, {\n                        color: strokeColor ?? \"#2563eb\",\n                        weight: 4,\n                    }).addTo(map);\n                    L.circleMarker(latlngs[0], { radius: 6, color: \"#16a34a\" }).addTo(map);\n                }\n\n                const marker = current ?? points[points.length - 1];\n                if (marker) {\n                    L.circleMarker([marker.latitude, marker.longitude], {\n                        radius: 6,\n                        color: strokeColor ?? \"#2563eb\",\n                    }).addTo(map);\n                }\n\n                const box = boundingBox(current ? [...points, current] : [...points]);\n                if (box) {\n                    map.fitBounds(\n                        [\n                            [box.minLatitude, box.minLongitude],\n                            [box.maxLatitude, box.maxLongitude],\n                        ],\n                        { padding: [24, 24] },\n                    );\n                } else {\n                    map.setView([0, 0], 2);\n                }\n            })\n            .catch(() => {\n                if (!cancelled) {\n                    setError(\n                        \"Leaflet não encontrado. Instale `leaflet` para usar tiles, ou remova `tileUrl` para o plot SVG.\",\n                    );\n                }\n            });\n\n        return () => {\n            cancelled = true;\n            map?.remove();\n        };\n    }, [points, current, tileUrl, tileAttribution, strokeColor]);\n\n    if (error) {\n        return (\n            <div style={{ padding: 16, fontSize: 13, color: \"var(--tempest-danger-fg)\" }}>\n                {error}\n            </div>\n        );\n    }\n\n    return <div ref={nodeRef} style={{ width: \"100%\", height: \"100%\" }} />;\n}\n"],"mappings":"sFAsCA,SAAgB,EAAkB,CAC9B,SACA,UACA,UACA,kBACA,eACuB,CACvB,IAAM,GAAA,EAAU,EAAA,OAAA,CAAuB,IAAI,EACrC,CAAC,EAAO,IAAA,EAAY,EAAA,SAAA,CAAwB,IAAI,EAsEtD,OApEA,EAAA,EAAA,UAAA,KAAgB,CACZ,IAAI,EAAiC,KACjC,EAAY,GAoDhB,OAjDA,OAA0B,UAAU,CAC/B,KAAM,GAAqD,CACxD,GAAI,GAAa,CAAC,EAAQ,QAAS,OACnC,IAAM,EAAmB,EAAI,SAAW,EAExC,EAAM,EAAE,IAAI,EAAQ,QAAS,CAAE,mBAAoB,EAAK,CAAC,EACzD,EAAE,UAAU,EAAS,CACjB,YAAa,GAAmB,GAChC,QAAS,EACb,CAAC,CAAC,CAAC,MAAM,CAAG,EAEZ,IAAM,EAAU,EAAO,IAAK,GAAwB,CAAC,EAAE,SAAU,EAAE,SAAS,CAAC,EACzE,EAAQ,OAAS,IACjB,EAAE,SAAS,EAAS,CAChB,MAAO,GAAe,UACtB,OAAQ,CACZ,CAAC,CAAC,CAAC,MAAM,CAAG,EACZ,EAAE,aAAa,EAAQ,GAAI,CAAE,OAAQ,EAAG,MAAO,SAAU,CAAC,CAAC,CAAC,MAAM,CAAG,GAGzE,IAAM,EAAS,GAAW,EAAO,EAAO,OAAS,GAC7C,GACA,EAAE,aAAa,CAAC,EAAO,SAAU,EAAO,SAAS,EAAG,CAChD,OAAQ,EACR,MAAO,GAAe,SAC1B,CAAC,CAAC,CAAC,MAAM,CAAG,EAGhB,IAAM,EAAM,EAAA,YAAY,EAAU,CAAC,GAAG,EAAQ,CAAO,EAAI,CAAC,GAAG,CAAM,CAAC,EAChE,EACA,EAAI,UACA,CACI,CAAC,EAAI,YAAa,EAAI,YAAY,EAClC,CAAC,EAAI,YAAa,EAAI,YAAY,CACtC,EACA,CAAE,QAAS,CAAC,GAAI,EAAE,CAAE,CACxB,EAEA,EAAI,QAAQ,CAAC,EAAG,CAAC,EAAG,CAAC,CAE7B,CAAC,CAAC,CACD,UAAY,CACJ,GACD,EACI,iGACJ,CAER,CAAC,MAEQ,CACT,EAAY,GACZ,GAAK,OAAO,CAChB,CACJ,EAAG,CAAC,EAAQ,EAAS,EAAS,EAAiB,CAAW,CAAC,EAEvD,GAEI,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,MAAO,CAAE,QAAS,GAAI,SAAU,GAAI,MAAO,0BAA2B,EACtE,SAAA,CACA,CAAA,GAIN,EAAA,EAAA,IAAA,CAAC,MAAD,CAAK,IAAK,EAAS,MAAO,CAAE,MAAO,OAAQ,OAAQ,MAAO,CAAI,CAAA,CACzE"}