@dacostafilipe/react-geoportail 0.1.8 → 0.2.0

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.
@@ -1 +1 @@
1
- {"version":3,"file":"react-geoportail.js","sources":["../src/utils/loader.ts","../src/hooks/useLuxApi.ts","../src/utils/coordinates.ts","../src/components/GeoportailMap.tsx","../src/hooks/useReverseGeocode.ts","../src/hooks/useGeocode.ts"],"sourcesContent":["/**\n * Dynamically injects the Geoportail v3 assets and resolves when\n * the global `lux` namespace is available.\n */\n\nconst LUX_BASE_URL = 'https://apiv3.geoportail.lu/';\nconst LUX_PROTOCOL = 'https';\nconst LUX_I18N_URL = 'https://apiv3.geoportail.lu/static-ngeo/build/fr.json';\nconst LUX_STYLESHEET_URL = 'https://apiv3.geoportail.lu/static-ngeo/build/apiv3.css';\nconst LUX_VENDOR_URL = 'https://apiv3.geoportail.lu/static-ngeo/build/vendor.js';\nconst LUX_API_URL = 'https://apiv3.geoportail.lu/static-ngeo/build/apiv3.js';\n\nconst LUX_STYLESHEET_ID = 'geoportail-apiv3-css';\nconst LUX_VENDOR_SCRIPT_ID = 'geoportail-apiv3-vendor';\nconst LUX_API_SCRIPT_ID = 'geoportail-apiv3-script';\n\nconst ELEMENT_STATUS_ATTRIBUTE = 'data-geoportail-status';\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads the Geoportail API assets exactly once.\n * Safe to call multiple times — subsequent calls return the same promise.\n */\nexport function loadLuxApi(): Promise<void> {\n if (loadPromise) return loadPromise;\n\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('loadLuxApi must be called in a browser environment'));\n }\n\n loadPromise = loadLuxApiInternal().catch((error: unknown) => {\n loadPromise = null;\n throw error instanceof Error ? error : new Error(String(error));\n });\n\n return loadPromise;\n}\n\n/**\n * The lux API may initialise asynchronously after the scripts load.\n * Poll until window.lux is defined (max ~5 s).\n */\nfunction pollForLux(resolve: () => void, reject: (err: Error) => void): void {\n const maxAttempts = 100;\n let attempts = 0;\n\n const check = () => {\n if (window.lux) {\n resolve();\n return;\n }\n if (attempts++ >= maxAttempts) {\n loadPromise = null;\n reject(new Error('Timed out waiting for window.lux to be defined'));\n return;\n }\n setTimeout(check, 50);\n };\n\n check();\n}\n\nasync function loadLuxApiInternal(): Promise<void> {\n if (window.lux) {\n configureLux(window.lux);\n return;\n }\n\n await loadStylesheetOnce(LUX_STYLESHEET_ID, LUX_STYLESHEET_URL);\n await loadScriptOnce(LUX_VENDOR_SCRIPT_ID, LUX_VENDOR_URL);\n await loadScriptOnce(LUX_API_SCRIPT_ID, LUX_API_URL);\n await waitForLux();\n configureLux(window.lux!);\n}\n\nfunction waitForLux(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n pollForLux(resolve, reject);\n });\n}\n\nfunction configureLux(lux: NonNullable<Window['lux']>): void {\n lux.setBaseUrl(LUX_BASE_URL, LUX_PROTOCOL);\n lux.setI18nUrl(LUX_I18N_URL);\n}\n\nfunction loadScriptOnce(id: string, src: string): Promise<void> {\n const existing = document.getElementById(id) as HTMLScriptElement | null;\n if (existing) {\n return waitForElementLoad(existing, src, 'script');\n }\n\n return new Promise<void>((resolve, reject) => {\n const script = document.createElement('script');\n script.id = id;\n script.src = src;\n script.async = false;\n script.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'loading');\n\n const cleanup = attachLoadHandlers(\n script,\n () => resolve(),\n () => reject(new Error(`Failed to load Geoportail script from ${src}`)),\n 'script'\n );\n\n document.head.appendChild(script);\n void cleanup;\n });\n}\n\nfunction loadStylesheetOnce(id: string, href: string): Promise<void> {\n const existing = document.getElementById(id) as HTMLLinkElement | null;\n if (existing) {\n return waitForElementLoad(existing, href, 'stylesheet');\n }\n\n return new Promise<void>((resolve, reject) => {\n const link = document.createElement('link');\n link.id = id;\n link.rel = 'stylesheet';\n link.href = href;\n link.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'loading');\n\n const cleanup = attachLoadHandlers(\n link,\n () => resolve(),\n () => reject(new Error(`Failed to load Geoportail stylesheet from ${href}`)),\n 'stylesheet'\n );\n\n document.head.appendChild(link);\n void cleanup;\n });\n}\n\nfunction waitForElementLoad(\n element: HTMLScriptElement | HTMLLinkElement,\n resourceUrl: string,\n kind: 'script' | 'stylesheet'\n): Promise<void> {\n const status = element.getAttribute(ELEMENT_STATUS_ATTRIBUTE);\n\n if (status === 'loaded') {\n return Promise.resolve();\n }\n\n if (status === 'error') {\n element.remove();\n return Promise.reject(new Error(`Failed to load Geoportail ${kind} from ${resourceUrl}`));\n }\n\n return new Promise<void>((resolve, reject) => {\n const cleanup = attachLoadHandlers(\n element,\n () => resolve(),\n () => reject(new Error(`Failed to load Geoportail ${kind} from ${resourceUrl}`)),\n kind\n );\n\n void cleanup;\n });\n}\n\nfunction attachLoadHandlers(\n element: HTMLScriptElement | HTMLLinkElement,\n onLoad: () => void,\n onError: () => void,\n kind: 'script' | 'stylesheet'\n): () => void {\n const handleLoad = () => {\n element.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'loaded');\n cleanup();\n onLoad();\n };\n\n const handleError = () => {\n element.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'error');\n cleanup();\n element.remove();\n onError();\n };\n\n const cleanup = () => {\n element.removeEventListener('load', handleLoad);\n element.removeEventListener('error', handleError);\n };\n\n element.addEventListener('load', handleLoad, { once: true });\n element.addEventListener('error', handleError, { once: true });\n\n if (kind === 'stylesheet') {\n const link = element as HTMLLinkElement;\n if (link.sheet) {\n handleLoad();\n }\n } else {\n const script = element as HTMLScriptElement;\n if (script.dataset.geoportailStatus === 'loaded') {\n handleLoad();\n }\n }\n\n return cleanup;\n}\n","import { useState, useEffect } from 'react';\nimport { loadLuxApi } from '../utils/loader';\nimport type { LuxNamespace } from '../types/lux';\n\nexport type LuxApiState =\n | { status: 'loading'; lux: null; error: null }\n | { status: 'ready'; lux: LuxNamespace; error: null }\n | { status: 'error'; lux: null; error: Error };\n\n/**\n * Loads the Geoportail runtime assets and returns the `lux` namespace once ready.\n * Deduplicates the asset load — safe to call from multiple components.\n */\nexport function useLuxApi(): LuxApiState {\n const [state, setState] = useState<LuxApiState>({\n status: 'loading',\n lux: null,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n loadLuxApi()\n .then(() => {\n if (!cancelled) {\n setState({ status: 'ready', lux: window.lux!, error: null });\n }\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n setState({\n status: 'error',\n lux: null,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, []);\n\n return state;\n}\n","/**\n * Coordinate conversion between EPSG:2169 (Luxembourg TM) and EPSG:4326 (WGS84).\n *\n * The Geoportail API operates internally in EPSG:2169 but also accepts\n * position arrays in EPSG:4326 via `lux.Map` constructor options.\n *\n * For precise server-side conversion the REST API itself is authoritative.\n * The formulas below use a 6-parameter Helmert + transverse Mercator approach\n * sufficient for Luxembourg's territory (~50 km radius).\n *\n * Reference: IGN-L / ACT official parameters for LUREF (EPSG:2169).\n */\n\n// LUREF / Luxembourg TM projection constants (EPSG:2169)\nconst FE = 80000; // False Easting (m)\nconst FN = 100000; // False Northing (m)\nconst LON0 = 6.16666666666667; // Central meridian (6°10') in degrees\nconst LAT0 = 49.8333333333333; // Latitude of origin (49°50') in degrees\nconst SCALE = 1.0; // Scale factor at central meridian\nconst A = 6378388.0; // Semi-major axis (Hayford / International 1924)\nconst F = 1 / 297.0; // Flattening\nconst B = A * (1 - F); // Semi-minor axis\n\nconst E2 = 1 - (B * B) / (A * A); // First eccentricity squared\n\n// Helmert 7-parameter shift: ETRS89 -> ED50 (approximate for Luxembourg)\n// These values transform WGS84 (≈ETRS89) to ED50 used by LUREF\nconst DX = -87.0;\nconst DY = -98.0;\nconst DZ = -121.0;\n\nfunction degToRad(d: number): number {\n return (d * Math.PI) / 180;\n}\n\nfunction radToDeg(r: number): number {\n return (r * 180) / Math.PI;\n}\n\n/**\n * Molodensky transformation: WGS84 -> ED50 (approximate, <1 m accuracy).\n */\nfunction wgs84ToEd50(\n lat: number,\n lon: number\n): { lat: number; lon: number } {\n const latR = degToRad(lat);\n const lonR = degToRad(lon);\n\n const sinLat = Math.sin(latR);\n const cosLat = Math.cos(latR);\n const sinLon = Math.sin(lonR);\n const cosLon = Math.cos(lonR);\n\n const aWgs = 6378137.0;\n const fWgs = 1 / 298.257223563;\n const bWgs = aWgs * (1 - fWgs);\n const e2Wgs = 1 - (bWgs * bWgs) / (aWgs * aWgs);\n\n const da = A - aWgs;\n const df = F - fWgs;\n\n const N = aWgs / Math.sqrt(1 - e2Wgs * sinLat * sinLat);\n const M =\n (aWgs * (1 - e2Wgs)) /\n Math.pow(1 - e2Wgs * sinLat * sinLat, 1.5);\n\n const dLat =\n (1 / M) *\n (N * (e2Wgs / (1 - e2Wgs)) * sinLat * cosLat * (da / aWgs) +\n (N / aWgs + 1) * sinLat * cosLat * df * (aWgs / bWgs) -\n (DX * sinLat * cosLon + DY * sinLat * sinLon - DZ * cosLat));\n\n const dLon =\n (1 / (N * cosLat)) * (-DX * sinLon + DY * cosLon);\n\n return {\n lat: lat + radToDeg(dLat),\n lon: lon + radToDeg(dLon),\n };\n}\n\n/**\n * ED50 -> WGS84 (inverse Molodensky, approximate).\n */\nfunction ed50ToWgs84(\n lat: number,\n lon: number\n): { lat: number; lon: number } {\n const latR = degToRad(lat);\n const lonR = degToRad(lon);\n\n const sinLat = Math.sin(latR);\n const cosLat = Math.cos(latR);\n const sinLon = Math.sin(lonR);\n const cosLon = Math.cos(lonR);\n\n const N = A / Math.sqrt(1 - E2 * sinLat * sinLat);\n const M = (A * (1 - E2)) / Math.pow(1 - E2 * sinLat * sinLat, 1.5);\n\n const da = 6378137.0 - A;\n const fWgs = 1 / 298.257223563;\n const df = fWgs - F;\n\n const dLat =\n (1 / M) *\n (N * (E2 / (1 - E2)) * sinLat * cosLat * (da / A) +\n (N / A + 1) * sinLat * cosLat * df * (A / B) +\n (DX * sinLat * cosLon + DY * sinLat * sinLon - DZ * cosLat));\n\n const dLon =\n (1 / (N * cosLat)) * (DX * sinLon - DY * cosLon);\n\n return {\n lat: lat + radToDeg(dLat),\n lon: lon + radToDeg(dLon),\n };\n}\n\n/**\n * Transverse Mercator forward projection (ED50 lat/lon -> LUREF easting/northing).\n */\nfunction tmForward(lat: number, lon: number): { easting: number; northing: number } {\n const latR = degToRad(lat);\n const lonR = degToRad(lon);\n const lon0R = degToRad(LON0);\n const lat0R = degToRad(LAT0);\n\n const sinLat = Math.sin(latR);\n const cosLat = Math.cos(latR);\n const tanLat = Math.tan(latR);\n\n const N = A / Math.sqrt(1 - E2 * sinLat * sinLat);\n const T = tanLat * tanLat;\n const C = (E2 / (1 - E2)) * cosLat * cosLat;\n const dl = lonR - lon0R;\n const XX = cosLat * dl;\n\n // Meridian arc from equator to lat\n const M = meridianArc(latR);\n const M0 = meridianArc(lat0R);\n\n const easting =\n FE +\n SCALE *\n N *\n (XX +\n (XX * XX * XX * (1 - T + C)) / 6 +\n (XX * XX * XX * XX * XX * (5 - 18 * T + T * T + 72 * C)) / 120);\n\n const northing =\n FN +\n SCALE *\n (M -\n M0 +\n N *\n tanLat *\n (XX * XX / 2 +\n (XX * XX * XX * XX * (5 - T + 9 * C + 4 * C * C)) / 24 +\n (XX * XX * XX * XX * XX * XX *\n (61 - 58 * T + T * T + 600 * C)) /\n 720));\n\n return { easting, northing };\n}\n\n/**\n * Transverse Mercator inverse projection (LUREF easting/northing -> ED50 lat/lon).\n */\nfunction tmInverse(easting: number, northing: number): { lat: number; lon: number } {\n const x = easting - FE;\n const y = northing - FN;\n const lat0R = degToRad(LAT0);\n const lon0R = degToRad(LON0);\n const M0 = meridianArc(lat0R);\n\n // Footpoint latitude\n const M1 = M0 + y / SCALE;\n const mu = M1 / (A * (1 - E2 / 4 - (3 * E2 * E2) / 64));\n\n const e1 = (1 - Math.sqrt(1 - E2)) / (1 + Math.sqrt(1 - E2));\n const phi1 =\n mu +\n ((3 * e1) / 2 - (27 * e1 * e1 * e1) / 32) * Math.sin(2 * mu) +\n ((21 * e1 * e1) / 16 - (55 * e1 * e1 * e1 * e1) / 32) *\n Math.sin(4 * mu) +\n ((151 * e1 * e1 * e1) / 96) * Math.sin(6 * mu);\n\n const sinPhi1 = Math.sin(phi1);\n const cosPhi1 = Math.cos(phi1);\n const tanPhi1 = Math.tan(phi1);\n\n const N1 = A / Math.sqrt(1 - E2 * sinPhi1 * sinPhi1);\n const T1 = tanPhi1 * tanPhi1;\n const C1 = (E2 / (1 - E2)) * cosPhi1 * cosPhi1;\n const R1 =\n (A * (1 - E2)) / Math.pow(1 - E2 * sinPhi1 * sinPhi1, 1.5);\n const D = x / (N1 * SCALE);\n\n const lat =\n phi1 -\n ((N1 * tanPhi1) / R1) *\n (D * D / 2 -\n (D * D * D * D * (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1)) / 24 +\n (D * D * D * D * D * D *\n (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1)) /\n 720);\n\n const lon =\n lon0R +\n (D -\n (D * D * D * (1 + 2 * T1 + C1)) / 6 +\n (D * D * D * D * D * (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1)) / 120) /\n cosPhi1;\n\n return { lat: radToDeg(lat), lon: radToDeg(lon) };\n}\n\nfunction meridianArc(latR: number): number {\n const e2 = E2;\n const e4 = e2 * e2;\n const e6 = e4 * e2;\n return (\n A *\n ((1 - e2 / 4 - (3 * e4) / 64 - (5 * e6) / 256) * latR -\n ((3 * e2) / 8 + (3 * e4) / 32 + (45 * e6) / 1024) *\n Math.sin(2 * latR) +\n ((15 * e4) / 256 + (45 * e6) / 1024) * Math.sin(4 * latR) -\n ((35 * e6) / 3072) * Math.sin(6 * latR))\n );\n}\n\n/**\n * Convert WGS84 (lat/lon) to EPSG:2169 (easting/northing).\n */\nexport function latLonToLuref(\n lat: number,\n lon: number\n): { easting: number; northing: number } {\n const ed50 = wgs84ToEd50(lat, lon);\n return tmForward(ed50.lat, ed50.lon);\n}\n\n/**\n * Convert EPSG:2169 (easting/northing) to WGS84 (lat/lon).\n */\nexport function lurefToLatLon(\n easting: number,\n northing: number\n): { lat: number; lon: number } {\n const ed50 = tmInverse(easting, northing);\n return ed50ToWgs84(ed50.lat, ed50.lon);\n}\n","import React, {\n useEffect,\n useRef,\n forwardRef,\n useImperativeHandle,\n useState,\n} from 'react';\nimport { useLuxApi } from '../hooks/useLuxApi';\nimport { lurefToLatLon, latLonToLuref } from '../utils/coordinates';\nimport type { LatLon, MapClickHandler, MarkerMode } from '../types';\nimport type { LuxMapInstance } from '../types/lux';\n\nconst DEFAULT_CLICK_SOURCE_PROJECTION = 'EPSG:3857';\nconst OVERLAY_PROJECTION = 'EPSG:3857';\nconst WGS84_PROJECTION = 'EPSG:4326';\nconst LUREF_PROJECTION = 'EPSG:2169';\n\nexport interface GeoportailMapProps {\n /**\n * Initial center of the map.\n * Defaults to Luxembourg City (lat: 49.6116, lon: 6.1319).\n */\n center?: LatLon;\n\n /** Initial zoom level (1–20). Default: 12 */\n zoom?: number;\n\n /**\n * Background layer identifier.\n * Default: 'basemap_2015_global'\n */\n bgLayer?: string;\n\n /**\n * Controls pin/marker behaviour:\n * - 'none' — no marker\n * - 'fixed' — show a marker at `markerPosition` (does not move on click)\n * - 'click' — user clicks map to place/move the pin; fires `onMarkerPlace`\n *\n * Default: 'none'\n */\n markerMode?: MarkerMode;\n\n /**\n * Position of the marker when `markerMode` is 'fixed' or to pre-set an\n * initial pin when `markerMode` is 'click'.\n */\n markerPosition?: LatLon;\n\n /**\n * Called whenever the user places a pin (markerMode === 'click').\n * Receives the WGS84 lat/lon of the clicked point.\n */\n onMarkerPlace?: MapClickHandler;\n\n /** CSS class applied to the map container div */\n className?: string;\n\n /** Inline styles for the map container div */\n style?: React.CSSProperties;\n\n /** Additional numeric layer IDs to add on top of the background */\n layers?: number[];\n}\n\nexport interface GeoportailMapHandle {\n /** Returns the underlying lux.Map instance (or null before ready) */\n getLuxMap(): LuxMapInstance | null;\n /** Programmatically move the map center */\n setCenter(coords: LatLon): void;\n /** Programmatically set zoom */\n setZoom(zoom: number): void;\n}\n\nconst LUXEMBOURG_CITY: LatLon = { lat: 49.6116, lon: 6.1319 };\nconst DEFAULT_BG_LAYER = 'basemap_2015_global';\n\n/**\n * Renders a Geoportail Luxembourg map inside a React component.\n *\n * Expose a ref (`GeoportailMapHandle`) to access the underlying lux.Map instance\n * or imperatively control the view.\n */\nexport const GeoportailMap = forwardRef<GeoportailMapHandle, GeoportailMapProps>(\n function GeoportailMap(\n {\n center,\n zoom = 12,\n bgLayer = DEFAULT_BG_LAYER,\n markerMode = 'none',\n markerPosition,\n onMarkerPlace,\n className,\n style,\n layers,\n },\n ref\n ) {\n const luxApi = useLuxApi();\n const mapContainerRef = useRef<HTMLDivElement | null>(null);\n const mapRef = useRef<LuxMapInstance | null>(null);\n const markerLayerRef = useRef<unknown>(null);\n const clickListenerRef = useRef<((...args: unknown[]) => void) | null>(null);\n const [isMapReady, setIsMapReady] = useState(false);\n\n // Keep stable refs to callbacks so effects don't re-run on every render\n const onMarkerPlaceRef = useRef(onMarkerPlace);\n onMarkerPlaceRef.current = onMarkerPlace;\n const initialCenter = resolveInitialCenter(center, markerMode, markerPosition);\n\n // ------------------------------------------------------------------ map init\n useEffect(() => {\n if (luxApi.status !== 'ready') return;\n if (!mapContainerRef.current) return;\n\n let cancelled = false;\n const lux = luxApi.lux;\n const { easting, northing } = latLonToLuref(initialCenter.lat, initialCenter.lon);\n\n const mapInstance = new lux.Map({\n target: mapContainerRef.current,\n bgLayer,\n zoom,\n position: [easting, northing],\n ...(layers && layers.length > 0\n ? { layers, layerOpacities: layers.map(() => 1) }\n : {}),\n });\n\n mapRef.current = mapInstance;\n setIsMapReady(false);\n\n const readyPromise = mapInstance.getMapReadyPromise?.() ?? Promise.resolve();\n void readyPromise.then(() => {\n if (!cancelled) {\n setIsMapReady(true);\n }\n });\n\n return () => {\n cancelled = true;\n // lux.Map does not expose a destroy(); we clear our references\n mapRef.current = null;\n markerLayerRef.current = null;\n clickListenerRef.current = null;\n setIsMapReady(false);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [luxApi.status]);\n\n // ------------------------------------------------------------------ marker position\n useEffect(() => {\n const map = mapRef.current;\n if (!map || luxApi.status !== 'ready' || !isMapReady) return;\n\n const displayPosition = resolveDisplayMarkerPosition(\n markerMode,\n markerPosition,\n center ?? LUXEMBOURG_CITY\n );\n\n if (!displayPosition) {\n clearMarker(markerLayerRef);\n return;\n }\n\n setMarkerPosition(map, displayPosition, markerLayerRef);\n }, [\n isMapReady,\n luxApi.status,\n markerMode,\n markerPosition?.lat,\n markerPosition?.lon,\n center?.lat,\n center?.lon,\n ]);\n\n // ------------------------------------------------------------------ click listener\n useEffect(() => {\n const map = mapRef.current;\n if (!map || luxApi.status !== 'ready' || !isMapReady) return;\n\n // Remove previous click listener\n if (clickListenerRef.current) {\n map.un('singleclick', clickListenerRef.current);\n clickListenerRef.current = null;\n }\n\n if (markerMode !== 'click') {\n return;\n }\n\n const handler = (...args: unknown[]) => {\n // Raw OpenLayers click coordinates are in the map view projection, not WGS84/LUREF.\n const evt = args[0] as { coordinate?: [number, number] };\n if (!evt.coordinate) return;\n\n const latLon = convertMapClickCoordinateToLatLon(map, evt.coordinate);\n setMarkerCoordinate(map, evt.coordinate, latLon, markerLayerRef);\n onMarkerPlaceRef.current?.(latLon);\n };\n\n clickListenerRef.current = handler;\n map.on('singleclick', handler);\n\n return () => {\n if (clickListenerRef.current) {\n map.un('singleclick', clickListenerRef.current);\n clickListenerRef.current = null;\n }\n };\n }, [\n isMapReady,\n luxApi.status,\n markerMode,\n ]);\n\n // ------------------------------------------------------------------ imperative handle\n useImperativeHandle(ref, () => ({\n getLuxMap: () => mapRef.current,\n setCenter(coords: LatLon) {\n const map = mapRef.current;\n if (!map) return;\n const { easting, northing } = latLonToLuref(coords.lat, coords.lon);\n if (map.setCenter) {\n map.setCenter([easting, northing], undefined, LUREF_PROJECTION);\n return;\n }\n map.getView().setCenter(convertLatLonToMarkerCoordinate(coords));\n },\n setZoom(z: number) {\n mapRef.current?.getView().setZoom(z);\n },\n }));\n\n // ------------------------------------------------------------------ render\n if (luxApi.status === 'error') {\n return (\n <div\n className={className}\n style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#f5f5f5', ...style }}\n >\n <span style={{ color: '#c00' }}>\n Failed to load Geoportail API: {luxApi.error.message}\n </span>\n </div>\n );\n }\n\n return (\n <div style={{ position: 'relative', ...style }} className={className}>\n {luxApi.status === 'loading' && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'rgba(255,255,255,0.7)',\n zIndex: 10,\n }}\n >\n <span>Loading map…</span>\n </div>\n )}\n <div\n ref={mapContainerRef}\n style={{ width: '100%', height: '100%' }}\n />\n </div>\n );\n }\n);\n\n// ------------------------------------------------------------------ helpers\n\n/**\n * Place/move an SVG pin marker on the map.\n * lux.Map is built on OpenLayers 3 — overlays must use the view projection.\n */\nexport function setMarkerPosition(\n map: LuxMapInstance,\n position: LatLon,\n layerRef: React.MutableRefObject<unknown>\n): void {\n const overlay = ensureMarkerOverlay(map, position, layerRef);\n if (!overlay) return;\n\n overlay.setPosition(convertLatLonToMarkerCoordinate(position));\n}\n\nexport function setMarkerCoordinate(\n map: LuxMapInstance,\n coordinate: [number, number],\n position: LatLon,\n layerRef: React.MutableRefObject<unknown>\n): void {\n const overlay = ensureMarkerOverlay(map, position, layerRef);\n if (!overlay) return;\n overlay.setPosition(coordinate);\n}\n\nexport function clearMarker(\n layerRef: React.MutableRefObject<unknown>\n): void {\n if (!layerRef.current) return;\n // Hide the existing overlay instead of discarding it so future updates can reuse it.\n (layerRef.current as OlOverlay).setPosition(undefined);\n}\n\nexport function ensureMarkerOverlay(\n map: LuxMapInstance,\n _position: LatLon,\n layerRef: React.MutableRefObject<unknown>\n): OlOverlay | null {\n if (layerRef.current) {\n return layerRef.current as OlOverlay;\n }\n\n const ol = (window as unknown as { ol?: OlLike }).ol;\n if (!ol) return null;\n\n const el = document.createElement('div');\n el.innerHTML = PIN_SVG;\n el.style.cssText =\n 'cursor:pointer;line-height:0;display:block;';\n\n const overlay = new ol.Overlay({\n element: el,\n positioning: 'bottom-center',\n stopEvent: false,\n });\n\n (map as unknown as { addOverlay(o: OlOverlay): void }).addOverlay(overlay);\n layerRef.current = overlay;\n return overlay;\n}\n\nexport function convertLatLonToMarkerCoordinate(\n position: LatLon\n): [number, number] {\n const ol = (window as unknown as { ol?: OlLike }).ol;\n const transform = ol?.proj?.transform;\n\n if (!transform) {\n const { easting, northing } = latLonToLuref(position.lat, position.lon);\n return [easting, northing];\n }\n\n return transform([position.lon, position.lat], WGS84_PROJECTION, OVERLAY_PROJECTION);\n}\n\nexport function resolveDisplayMarkerPosition(\n markerMode: MarkerMode,\n markerPosition: LatLon | undefined,\n center: LatLon\n): LatLon | undefined {\n if (markerMode === 'none') {\n return undefined;\n }\n\n if (markerPosition) {\n return markerPosition;\n }\n\n return markerMode === 'fixed' ? center : undefined;\n}\n\nexport function resolveInitialCenter(\n center: LatLon | undefined,\n markerMode: MarkerMode,\n markerPosition: LatLon | undefined\n): LatLon {\n if (markerPosition && markerMode !== 'none') {\n return markerPosition;\n }\n\n return center ?? LUXEMBOURG_CITY;\n}\n\n// Minimal pin SVG (red teardrop, 30×40)\nconst PIN_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"30\" height=\"40\" viewBox=\"0 0 30 40\">\n <path d=\"M15 0C7.268 0 1 6.268 1 14c0 10.5 14 26 14 26S29 24.5 29 14C29 6.268 22.732 0 15 0z\"\n fill=\"#e53935\" stroke=\"#b71c1c\" stroke-width=\"1.5\"/>\n <circle cx=\"15\" cy=\"14\" r=\"5\" fill=\"white\"/>\n</svg>`;\n\n// Minimal OL type stubs used only within this file\ninterface OlOverlay {\n setPosition(pos: [number, number] | undefined): void;\n}\n\ninterface OlLike {\n proj?: {\n transform(\n coordinate: [number, number],\n source: string,\n destination: string\n ): [number, number];\n };\n Overlay: new (opts: { element: HTMLElement; positioning: string; stopEvent: boolean }) => OlOverlay;\n}\n\nexport function convertMapClickCoordinateToLatLon(\n _map: LuxMapInstance,\n coordinate: [number, number]\n): LatLon {\n const ol = (window as unknown as { ol?: OlLike }).ol;\n const transform = ol?.proj?.transform;\n\n if (!transform) {\n const [easting, northing] = coordinate;\n return lurefToLatLon(easting, northing);\n }\n\n const [lon, lat] = transform(coordinate, DEFAULT_CLICK_SOURCE_PROJECTION, WGS84_PROJECTION);\n return { lat, lon };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport type { LatLon, Address } from '../types';\n\nconst REVERSE_GEOCODE_URL = 'https://apiv3.geoportail.lu/geocode/reverse';\n\nexport type ReverseGeocodeState =\n | { status: 'idle'; address: null; error: null }\n | { status: 'loading'; address: null; error: null }\n | { status: 'success'; address: Address; error: null }\n | { status: 'error'; address: null; error: Error };\n\n/**\n * Hook for reverse geocoding: convert a WGS84 lat/lon to a Luxembourg address.\n *\n * Uses the Geoportail REST reverse geocode endpoint — no API key required.\n *\n * @example\n * const { state, lookup } = useReverseGeocode();\n * // ...\n * lookup({ lat: 49.6116, lon: 6.1319 });\n * if (state.status === 'success') console.log(state.address.label);\n */\nexport function useReverseGeocode() {\n const [state, setState] = useState<ReverseGeocodeState>({\n status: 'idle',\n address: null,\n error: null,\n });\n\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => () => { abortRef.current?.abort(); }, []);\n\n const lookup = useCallback(async (position: LatLon) => {\n // Cancel any in-flight request\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n setState({ status: 'loading', address: null, error: null });\n\n try {\n const url = new URL(REVERSE_GEOCODE_URL);\n url.searchParams.set('lat', String(position.lat));\n url.searchParams.set('lon', String(position.lon));\n\n const res = await fetch(url.toString(), { signal: controller.signal });\n\n if (!res.ok) {\n throw new Error(`Reverse geocode request failed: ${res.status} ${res.statusText}`);\n }\n\n const data = (await res.json()) as {\n count?: number;\n results?: Array<{\n number?: string;\n street?: string;\n postal_code?: string;\n locality?: string;\n distance?: number;\n geom?: {\n coordinates?: [number, number];\n };\n }>;\n };\n\n const first = data.results?.[0];\n if (!first) {\n throw new Error('No results returned for this position');\n }\n\n const label = [\n [first.number, first.street].filter(Boolean).join(' ').trim(),\n [first.postal_code, first.locality].filter(Boolean).join(' ').trim(),\n ].filter(Boolean).join(', ');\n\n const [easting, northing] = first.geom?.coordinates ?? [0, 0];\n\n setState({\n status: 'success',\n address: {\n label,\n distance: first.distance ?? 0,\n easting,\n northing,\n },\n error: null,\n });\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setState({\n status: 'error',\n address: null,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState({ status: 'idle', address: null, error: null });\n }, []);\n\n return { state, lookup, reset };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { lurefToLatLon } from '../utils/coordinates';\nimport type { GeocodeQuery, LatLon } from '../types';\n\nconst GEOCODE_URL = 'https://apiv3.geoportail.lu/geocode/search';\n\nexport interface GeocodeResultItem {\n latLon: LatLon;\n easting: number;\n northing: number;\n accuracy: number;\n street?: string;\n num?: string;\n zip?: string;\n locality?: string;\n}\n\nexport type GeocodeState =\n | { status: 'idle'; results: null; error: null }\n | { status: 'loading'; results: null; error: null }\n | { status: 'success'; results: GeocodeResultItem[]; error: null }\n | { status: 'error'; results: null; error: Error };\n\n/**\n * Hook for forward geocoding: search for a Luxembourg address and get coordinates.\n *\n * @example\n * const { state, search } = useGeocode();\n * search({ queryString: '1 rue du Fort Thüngen, Luxembourg' });\n * if (state.status === 'success') {\n * const { lat, lon } = state.results[0].latLon;\n * }\n */\nexport function useGeocode() {\n const [state, setState] = useState<GeocodeState>({\n status: 'idle',\n results: null,\n error: null,\n });\n\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => () => { abortRef.current?.abort(); }, []);\n\n const search = useCallback(async (query: GeocodeQuery) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n setState({ status: 'loading', results: null, error: null });\n\n try {\n const url = new URL(GEOCODE_URL);\n\n if (query.queryString) {\n url.searchParams.set('queryString', query.queryString);\n } else {\n if (query.num) url.searchParams.set('num', query.num);\n if (query.street) url.searchParams.set('street', query.street);\n if (query.zip) url.searchParams.set('zip', query.zip);\n if (query.locality) url.searchParams.set('locality', query.locality);\n }\n\n const res = await fetch(url.toString(), { signal: controller.signal });\n\n if (!res.ok) {\n throw new Error(`Geocode request failed: ${res.status} ${res.statusText}`);\n }\n\n const data = (await res.json()) as {\n results?: Array<{\n easting: number;\n northing: number;\n accuracy?: number;\n AddressDetails?: {\n street?: string;\n number?: string;\n zip?: string;\n locality?: string;\n };\n }>;\n };\n\n const results: GeocodeResultItem[] = (data.results ?? []).map((r) => ({\n latLon: lurefToLatLon(r.easting, r.northing),\n easting: r.easting,\n northing: r.northing,\n accuracy: r.accuracy ?? 0,\n street: r.AddressDetails?.street,\n num: r.AddressDetails?.number,\n zip: r.AddressDetails?.zip,\n locality: r.AddressDetails?.locality,\n }));\n\n setState({ status: 'success', results, error: null });\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setState({\n status: 'error',\n results: null,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState({ status: 'idle', results: null, error: null });\n }, []);\n\n return { state, search, reset };\n}\n"],"names":["LUX_BASE_URL","LUX_PROTOCOL","LUX_I18N_URL","LUX_STYLESHEET_URL","LUX_VENDOR_URL","LUX_API_URL","LUX_STYLESHEET_ID","LUX_VENDOR_SCRIPT_ID","LUX_API_SCRIPT_ID","ELEMENT_STATUS_ATTRIBUTE","loadPromise","loadLuxApi","loadLuxApiInternal","error","pollForLux","resolve","reject","attempts","check","configureLux","loadStylesheetOnce","loadScriptOnce","waitForLux","lux","id","src","existing","waitForElementLoad","script","attachLoadHandlers","href","link","element","resourceUrl","kind","status","onLoad","onError","handleLoad","cleanup","handleError","useLuxApi","state","setState","useState","useEffect","cancelled","err","FE","FN","LON0","LAT0","SCALE","A","F","B","E2","DX","DY","DZ","degToRad","d","radToDeg","r","wgs84ToEd50","lat","lon","latR","lonR","sinLat","cosLat","sinLon","cosLon","aWgs","fWgs","bWgs","e2Wgs","da","df","N","dLat","dLon","ed50ToWgs84","M","tmForward","lon0R","lat0R","tanLat","T","C","dl","XX","meridianArc","M0","easting","northing","tmInverse","x","y","mu","e1","phi1","sinPhi1","cosPhi1","tanPhi1","N1","T1","C1","R1","D","e2","e4","e6","latLonToLuref","ed50","lurefToLatLon","DEFAULT_CLICK_SOURCE_PROJECTION","OVERLAY_PROJECTION","WGS84_PROJECTION","LUREF_PROJECTION","LUXEMBOURG_CITY","DEFAULT_BG_LAYER","GeoportailMap","forwardRef","center","zoom","bgLayer","markerMode","markerPosition","onMarkerPlace","className","style","layers","ref","luxApi","mapContainerRef","useRef","mapRef","markerLayerRef","clickListenerRef","isMapReady","setIsMapReady","onMarkerPlaceRef","initialCenter","resolveInitialCenter","mapInstance","_a","map","displayPosition","resolveDisplayMarkerPosition","clearMarker","setMarkerPosition","handler","args","evt","latLon","convertMapClickCoordinateToLatLon","setMarkerCoordinate","useImperativeHandle","coords","convertLatLonToMarkerCoordinate","z","jsx","jsxs","position","layerRef","overlay","ensureMarkerOverlay","coordinate","_position","ol","el","PIN_SVG","transform","_map","REVERSE_GEOCODE_URL","useReverseGeocode","abortRef","lookup","useCallback","controller","url","res","first","_b","label","_c","reset","GEOCODE_URL","useGeocode","search","query","results","_d"],"mappings":"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"}
1
+ {"version":3,"file":"react-geoportail.js","sources":["../src/utils/loader.ts","../src/hooks/useLuxApi.ts","../src/utils/coordinates.ts","../src/components/GeoportailMap.tsx","../src/hooks/useReverseGeocode.ts","../src/hooks/useGeocode.ts"],"sourcesContent":["/**\n * Dynamically injects the Geoportail v4 assets and resolves when\n * the global `lux` namespace is available.\n *\n * This mirrors what the official `https://apiv4.geoportail.lu/apiv4loader.js`\n * does, except that the official loader relies on `document.write` and can\n * therefore only be used from a synchronous `<script>` tag in the page head.\n */\n\nconst LUX_BASE_URL = 'https://apiv4.geoportail.lu/';\nconst LUX_PROTOCOL = 'https';\nconst LUX_I18N_URL = 'https://apiv4.geoportail.lu/static-ngeo/build/fr.json';\nconst LUX_STYLESHEET_URL = 'https://apiv4.geoportail.lu/static-ngeo/build/apiv4.css';\nconst LUX_OL_URL = 'https://apiv4.geoportail.lu/static-ngeo/build/ol.js';\nconst LUX_PROJ4_URL = 'https://apiv4.geoportail.lu/static-ngeo/build/proj4.js';\nconst LUX_AUTOCOMPLETE_URL =\n 'https://apiv4.geoportail.lu/static-ngeo/build/auto-complete.min.js';\nconst LUX_API_URL = 'https://apiv4.geoportail.lu/static-ngeo/build/apiv4.js';\n\nconst LUX_STYLESHEET_ID = 'geoportail-apiv4-css';\nconst LUX_OL_SCRIPT_ID = 'geoportail-apiv4-ol';\nconst LUX_PROJ4_SCRIPT_ID = 'geoportail-apiv4-proj4';\nconst LUX_AUTOCOMPLETE_SCRIPT_ID = 'geoportail-apiv4-autocomplete';\nconst LUX_API_SCRIPT_ID = 'geoportail-apiv4-script';\n\n/** LUREF (EPSG:2169) definition, as registered by the official v4 loader. */\nconst LUREF_PROJECTION_CODE = 'EPSG:2169';\nconst LUREF_PROJ4_DEF =\n '+proj=tmerc +lat_0=49.83333333333334 +lon_0=6.166666666666667 +k=1 ' +\n '+x_0=80000 +y_0=100000 +ellps=intl ' +\n '+towgs84=-189.681,18.3463,-42.7695,-0.33746,-3.09264,2.53861,0.4598 ' +\n '+units=m +no_defs';\n\nconst ELEMENT_STATUS_ATTRIBUTE = 'data-geoportail-status';\n\nlet loadPromise: Promise<void> | null = null;\n\n/**\n * Loads the Geoportail API assets exactly once.\n * Safe to call multiple times — subsequent calls return the same promise.\n */\nexport function loadLuxApi(): Promise<void> {\n if (loadPromise) return loadPromise;\n\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return Promise.reject(new Error('loadLuxApi must be called in a browser environment'));\n }\n\n loadPromise = loadLuxApiInternal().catch((error: unknown) => {\n loadPromise = null;\n throw error instanceof Error ? error : new Error(String(error));\n });\n\n return loadPromise;\n}\n\n/**\n * The lux API may initialise asynchronously after the scripts load.\n * Poll until window.lux is defined (max ~5 s).\n */\nfunction pollForLux(resolve: () => void, reject: (err: Error) => void): void {\n const maxAttempts = 100;\n let attempts = 0;\n\n const check = () => {\n if (window.lux) {\n resolve();\n return;\n }\n if (attempts++ >= maxAttempts) {\n loadPromise = null;\n reject(new Error('Timed out waiting for window.lux to be defined'));\n return;\n }\n setTimeout(check, 50);\n };\n\n check();\n}\n\nasync function loadLuxApiInternal(): Promise<void> {\n if (window.lux) {\n configureLux(window.lux);\n return;\n }\n\n await loadStylesheetOnce(LUX_STYLESHEET_ID, LUX_STYLESHEET_URL);\n await loadScriptOnce(LUX_OL_SCRIPT_ID, LUX_OL_URL);\n await loadScriptOnce(LUX_PROJ4_SCRIPT_ID, LUX_PROJ4_URL);\n registerLurefProjection();\n await loadScriptOnce(LUX_AUTOCOMPLETE_SCRIPT_ID, LUX_AUTOCOMPLETE_URL);\n await loadScriptOnce(LUX_API_SCRIPT_ID, LUX_API_URL);\n await waitForLux();\n configureLux(window.lux!);\n}\n\n/**\n * The v4 bundle expects `ol` and `proj4` as globals and does not register\n * LUREF itself — the official loader does it between loading proj4 and the\n * API bundle, so we do the same. Without it the map cannot handle the\n * EPSG:2169 positions the API works with.\n */\nfunction registerLurefProjection(): void {\n const proj4 = window.proj4;\n const ol = window.ol;\n\n if (!proj4 || !ol?.proj?.proj4?.register) return;\n\n if (!proj4.defs(LUREF_PROJECTION_CODE)) {\n proj4.defs(LUREF_PROJECTION_CODE, LUREF_PROJ4_DEF);\n }\n\n ol.proj.proj4.register(proj4);\n}\n\nfunction waitForLux(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n pollForLux(resolve, reject);\n });\n}\n\nfunction configureLux(lux: NonNullable<Window['lux']>): void {\n lux.setBaseUrl(LUX_BASE_URL, LUX_PROTOCOL);\n lux.setI18nUrl(LUX_I18N_URL);\n}\n\nfunction loadScriptOnce(id: string, src: string): Promise<void> {\n const existing = document.getElementById(id) as HTMLScriptElement | null;\n if (existing) {\n return waitForElementLoad(existing, src, 'script');\n }\n\n return new Promise<void>((resolve, reject) => {\n const script = document.createElement('script');\n script.id = id;\n script.src = src;\n script.async = false;\n script.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'loading');\n\n const cleanup = attachLoadHandlers(\n script,\n () => resolve(),\n () => reject(new Error(`Failed to load Geoportail script from ${src}`)),\n 'script'\n );\n\n document.head.appendChild(script);\n void cleanup;\n });\n}\n\nfunction loadStylesheetOnce(id: string, href: string): Promise<void> {\n const existing = document.getElementById(id) as HTMLLinkElement | null;\n if (existing) {\n return waitForElementLoad(existing, href, 'stylesheet');\n }\n\n return new Promise<void>((resolve, reject) => {\n const link = document.createElement('link');\n link.id = id;\n link.rel = 'stylesheet';\n link.href = href;\n link.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'loading');\n\n const cleanup = attachLoadHandlers(\n link,\n () => resolve(),\n () => reject(new Error(`Failed to load Geoportail stylesheet from ${href}`)),\n 'stylesheet'\n );\n\n document.head.appendChild(link);\n void cleanup;\n });\n}\n\nfunction waitForElementLoad(\n element: HTMLScriptElement | HTMLLinkElement,\n resourceUrl: string,\n kind: 'script' | 'stylesheet'\n): Promise<void> {\n const status = element.getAttribute(ELEMENT_STATUS_ATTRIBUTE);\n\n if (status === 'loaded') {\n return Promise.resolve();\n }\n\n if (status === 'error') {\n element.remove();\n return Promise.reject(new Error(`Failed to load Geoportail ${kind} from ${resourceUrl}`));\n }\n\n return new Promise<void>((resolve, reject) => {\n const cleanup = attachLoadHandlers(\n element,\n () => resolve(),\n () => reject(new Error(`Failed to load Geoportail ${kind} from ${resourceUrl}`)),\n kind\n );\n\n void cleanup;\n });\n}\n\nfunction attachLoadHandlers(\n element: HTMLScriptElement | HTMLLinkElement,\n onLoad: () => void,\n onError: () => void,\n kind: 'script' | 'stylesheet'\n): () => void {\n const handleLoad = () => {\n element.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'loaded');\n cleanup();\n onLoad();\n };\n\n const handleError = () => {\n element.setAttribute(ELEMENT_STATUS_ATTRIBUTE, 'error');\n cleanup();\n element.remove();\n onError();\n };\n\n const cleanup = () => {\n element.removeEventListener('load', handleLoad);\n element.removeEventListener('error', handleError);\n };\n\n element.addEventListener('load', handleLoad, { once: true });\n element.addEventListener('error', handleError, { once: true });\n\n if (kind === 'stylesheet') {\n const link = element as HTMLLinkElement;\n if (link.sheet) {\n handleLoad();\n }\n } else {\n const script = element as HTMLScriptElement;\n if (script.dataset.geoportailStatus === 'loaded') {\n handleLoad();\n }\n }\n\n return cleanup;\n}\n","import { useState, useEffect } from 'react';\nimport { loadLuxApi } from '../utils/loader';\nimport type { LuxNamespace } from '../types/lux';\n\nexport type LuxApiState =\n | { status: 'loading'; lux: null; error: null }\n | { status: 'ready'; lux: LuxNamespace; error: null }\n | { status: 'error'; lux: null; error: Error };\n\n/**\n * Loads the Geoportail runtime assets and returns the `lux` namespace once ready.\n * Deduplicates the asset load — safe to call from multiple components.\n */\nexport function useLuxApi(): LuxApiState {\n const [state, setState] = useState<LuxApiState>({\n status: 'loading',\n lux: null,\n error: null,\n });\n\n useEffect(() => {\n let cancelled = false;\n\n loadLuxApi()\n .then(() => {\n if (!cancelled) {\n setState({ status: 'ready', lux: window.lux!, error: null });\n }\n })\n .catch((err: unknown) => {\n if (!cancelled) {\n setState({\n status: 'error',\n lux: null,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n });\n\n return () => {\n cancelled = true;\n };\n }, []);\n\n return state;\n}\n","/**\n * Coordinate conversion between EPSG:2169 (Luxembourg TM) and EPSG:4326 (WGS84).\n *\n * The Geoportail API operates internally in EPSG:2169 but also accepts\n * position arrays in EPSG:4326 via `lux.Map` constructor options.\n *\n * For precise server-side conversion the REST API itself is authoritative.\n * The formulas below use a 6-parameter Helmert + transverse Mercator approach\n * sufficient for Luxembourg's territory (~50 km radius).\n *\n * Reference: IGN-L / ACT official parameters for LUREF (EPSG:2169).\n */\n\n// LUREF / Luxembourg TM projection constants (EPSG:2169)\nconst FE = 80000; // False Easting (m)\nconst FN = 100000; // False Northing (m)\nconst LON0 = 6.16666666666667; // Central meridian (6°10') in degrees\nconst LAT0 = 49.8333333333333; // Latitude of origin (49°50') in degrees\nconst SCALE = 1.0; // Scale factor at central meridian\nconst A = 6378388.0; // Semi-major axis (Hayford / International 1924)\nconst F = 1 / 297.0; // Flattening\nconst B = A * (1 - F); // Semi-minor axis\n\nconst E2 = 1 - (B * B) / (A * A); // First eccentricity squared\n\n// Helmert 7-parameter shift: ETRS89 -> ED50 (approximate for Luxembourg)\n// These values transform WGS84 (≈ETRS89) to ED50 used by LUREF\nconst DX = -87.0;\nconst DY = -98.0;\nconst DZ = -121.0;\n\nfunction degToRad(d: number): number {\n return (d * Math.PI) / 180;\n}\n\nfunction radToDeg(r: number): number {\n return (r * 180) / Math.PI;\n}\n\n/**\n * Molodensky transformation: WGS84 -> ED50 (approximate, <1 m accuracy).\n */\nfunction wgs84ToEd50(\n lat: number,\n lon: number\n): { lat: number; lon: number } {\n const latR = degToRad(lat);\n const lonR = degToRad(lon);\n\n const sinLat = Math.sin(latR);\n const cosLat = Math.cos(latR);\n const sinLon = Math.sin(lonR);\n const cosLon = Math.cos(lonR);\n\n const aWgs = 6378137.0;\n const fWgs = 1 / 298.257223563;\n const bWgs = aWgs * (1 - fWgs);\n const e2Wgs = 1 - (bWgs * bWgs) / (aWgs * aWgs);\n\n const da = A - aWgs;\n const df = F - fWgs;\n\n const N = aWgs / Math.sqrt(1 - e2Wgs * sinLat * sinLat);\n const M =\n (aWgs * (1 - e2Wgs)) /\n Math.pow(1 - e2Wgs * sinLat * sinLat, 1.5);\n\n const dLat =\n (1 / M) *\n (N * (e2Wgs / (1 - e2Wgs)) * sinLat * cosLat * (da / aWgs) +\n (N / aWgs + 1) * sinLat * cosLat * df * (aWgs / bWgs) -\n (DX * sinLat * cosLon + DY * sinLat * sinLon - DZ * cosLat));\n\n const dLon =\n (1 / (N * cosLat)) * (-DX * sinLon + DY * cosLon);\n\n return {\n lat: lat + radToDeg(dLat),\n lon: lon + radToDeg(dLon),\n };\n}\n\n/**\n * ED50 -> WGS84 (inverse Molodensky, approximate).\n */\nfunction ed50ToWgs84(\n lat: number,\n lon: number\n): { lat: number; lon: number } {\n const latR = degToRad(lat);\n const lonR = degToRad(lon);\n\n const sinLat = Math.sin(latR);\n const cosLat = Math.cos(latR);\n const sinLon = Math.sin(lonR);\n const cosLon = Math.cos(lonR);\n\n const N = A / Math.sqrt(1 - E2 * sinLat * sinLat);\n const M = (A * (1 - E2)) / Math.pow(1 - E2 * sinLat * sinLat, 1.5);\n\n const da = 6378137.0 - A;\n const fWgs = 1 / 298.257223563;\n const df = fWgs - F;\n\n const dLat =\n (1 / M) *\n (N * (E2 / (1 - E2)) * sinLat * cosLat * (da / A) +\n (N / A + 1) * sinLat * cosLat * df * (A / B) +\n (DX * sinLat * cosLon + DY * sinLat * sinLon - DZ * cosLat));\n\n const dLon =\n (1 / (N * cosLat)) * (DX * sinLon - DY * cosLon);\n\n return {\n lat: lat + radToDeg(dLat),\n lon: lon + radToDeg(dLon),\n };\n}\n\n/**\n * Transverse Mercator forward projection (ED50 lat/lon -> LUREF easting/northing).\n */\nfunction tmForward(lat: number, lon: number): { easting: number; northing: number } {\n const latR = degToRad(lat);\n const lonR = degToRad(lon);\n const lon0R = degToRad(LON0);\n const lat0R = degToRad(LAT0);\n\n const sinLat = Math.sin(latR);\n const cosLat = Math.cos(latR);\n const tanLat = Math.tan(latR);\n\n const N = A / Math.sqrt(1 - E2 * sinLat * sinLat);\n const T = tanLat * tanLat;\n const C = (E2 / (1 - E2)) * cosLat * cosLat;\n const dl = lonR - lon0R;\n const XX = cosLat * dl;\n\n // Meridian arc from equator to lat\n const M = meridianArc(latR);\n const M0 = meridianArc(lat0R);\n\n const easting =\n FE +\n SCALE *\n N *\n (XX +\n (XX * XX * XX * (1 - T + C)) / 6 +\n (XX * XX * XX * XX * XX * (5 - 18 * T + T * T + 72 * C)) / 120);\n\n const northing =\n FN +\n SCALE *\n (M -\n M0 +\n N *\n tanLat *\n (XX * XX / 2 +\n (XX * XX * XX * XX * (5 - T + 9 * C + 4 * C * C)) / 24 +\n (XX * XX * XX * XX * XX * XX *\n (61 - 58 * T + T * T + 600 * C)) /\n 720));\n\n return { easting, northing };\n}\n\n/**\n * Transverse Mercator inverse projection (LUREF easting/northing -> ED50 lat/lon).\n */\nfunction tmInverse(easting: number, northing: number): { lat: number; lon: number } {\n const x = easting - FE;\n const y = northing - FN;\n const lat0R = degToRad(LAT0);\n const lon0R = degToRad(LON0);\n const M0 = meridianArc(lat0R);\n\n // Footpoint latitude\n const M1 = M0 + y / SCALE;\n const mu = M1 / (A * (1 - E2 / 4 - (3 * E2 * E2) / 64));\n\n const e1 = (1 - Math.sqrt(1 - E2)) / (1 + Math.sqrt(1 - E2));\n const phi1 =\n mu +\n ((3 * e1) / 2 - (27 * e1 * e1 * e1) / 32) * Math.sin(2 * mu) +\n ((21 * e1 * e1) / 16 - (55 * e1 * e1 * e1 * e1) / 32) *\n Math.sin(4 * mu) +\n ((151 * e1 * e1 * e1) / 96) * Math.sin(6 * mu);\n\n const sinPhi1 = Math.sin(phi1);\n const cosPhi1 = Math.cos(phi1);\n const tanPhi1 = Math.tan(phi1);\n\n const N1 = A / Math.sqrt(1 - E2 * sinPhi1 * sinPhi1);\n const T1 = tanPhi1 * tanPhi1;\n const C1 = (E2 / (1 - E2)) * cosPhi1 * cosPhi1;\n const R1 =\n (A * (1 - E2)) / Math.pow(1 - E2 * sinPhi1 * sinPhi1, 1.5);\n const D = x / (N1 * SCALE);\n\n const lat =\n phi1 -\n ((N1 * tanPhi1) / R1) *\n (D * D / 2 -\n (D * D * D * D * (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1)) / 24 +\n (D * D * D * D * D * D *\n (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1)) /\n 720);\n\n const lon =\n lon0R +\n (D -\n (D * D * D * (1 + 2 * T1 + C1)) / 6 +\n (D * D * D * D * D * (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1)) / 120) /\n cosPhi1;\n\n return { lat: radToDeg(lat), lon: radToDeg(lon) };\n}\n\nfunction meridianArc(latR: number): number {\n const e2 = E2;\n const e4 = e2 * e2;\n const e6 = e4 * e2;\n return (\n A *\n ((1 - e2 / 4 - (3 * e4) / 64 - (5 * e6) / 256) * latR -\n ((3 * e2) / 8 + (3 * e4) / 32 + (45 * e6) / 1024) *\n Math.sin(2 * latR) +\n ((15 * e4) / 256 + (45 * e6) / 1024) * Math.sin(4 * latR) -\n ((35 * e6) / 3072) * Math.sin(6 * latR))\n );\n}\n\n/**\n * Convert WGS84 (lat/lon) to EPSG:2169 (easting/northing).\n */\nexport function latLonToLuref(\n lat: number,\n lon: number\n): { easting: number; northing: number } {\n const ed50 = wgs84ToEd50(lat, lon);\n return tmForward(ed50.lat, ed50.lon);\n}\n\n/**\n * Convert EPSG:2169 (easting/northing) to WGS84 (lat/lon).\n */\nexport function lurefToLatLon(\n easting: number,\n northing: number\n): { lat: number; lon: number } {\n const ed50 = tmInverse(easting, northing);\n return ed50ToWgs84(ed50.lat, ed50.lon);\n}\n","import React, {\n useEffect,\n useRef,\n forwardRef,\n useImperativeHandle,\n useState,\n} from 'react';\nimport { useLuxApi } from '../hooks/useLuxApi';\nimport { lurefToLatLon, latLonToLuref } from '../utils/coordinates';\nimport type { LatLon, MapClickHandler, MarkerMode } from '../types';\nimport type { LuxMapInstance } from '../types/lux';\n\nconst DEFAULT_CLICK_SOURCE_PROJECTION = 'EPSG:3857';\nconst OVERLAY_PROJECTION = 'EPSG:3857';\nconst WGS84_PROJECTION = 'EPSG:4326';\nconst LUREF_PROJECTION = 'EPSG:2169';\n\nexport interface GeoportailMapProps {\n /**\n * Initial center of the map.\n * Defaults to Luxembourg City (lat: 49.6116, lon: 6.1319).\n */\n center?: LatLon;\n\n /** Initial zoom level (1–20). Default: 12 */\n zoom?: number;\n\n /**\n * Background layer identifier.\n * Default: 'basemap_2015_global'\n */\n bgLayer?: string;\n\n /**\n * Controls pin/marker behaviour:\n * - 'none' — no marker\n * - 'fixed' — show a marker at `markerPosition` (does not move on click)\n * - 'click' — user clicks map to place/move the pin; fires `onMarkerPlace`\n *\n * Default: 'none'\n */\n markerMode?: MarkerMode;\n\n /**\n * Position of the marker when `markerMode` is 'fixed' or to pre-set an\n * initial pin when `markerMode` is 'click'.\n */\n markerPosition?: LatLon;\n\n /**\n * Called whenever the user places a pin (markerMode === 'click').\n * Receives the WGS84 lat/lon of the clicked point.\n */\n onMarkerPlace?: MapClickHandler;\n\n /** CSS class applied to the map container div */\n className?: string;\n\n /** Inline styles for the map container div */\n style?: React.CSSProperties;\n\n /** Additional numeric layer IDs to add on top of the background */\n layers?: number[];\n}\n\nexport interface GeoportailMapHandle {\n /** Returns the underlying lux.Map instance (or null before ready) */\n getLuxMap(): LuxMapInstance | null;\n /** Programmatically move the map center */\n setCenter(coords: LatLon): void;\n /** Programmatically set zoom */\n setZoom(zoom: number): void;\n}\n\nconst LUXEMBOURG_CITY: LatLon = { lat: 49.6116, lon: 6.1319 };\nconst DEFAULT_BG_LAYER = 'basemap_2015_global';\n\n/**\n * Renders a Geoportail Luxembourg map inside a React component.\n *\n * Expose a ref (`GeoportailMapHandle`) to access the underlying lux.Map instance\n * or imperatively control the view.\n */\nexport const GeoportailMap = forwardRef<GeoportailMapHandle, GeoportailMapProps>(\n function GeoportailMap(\n {\n center,\n zoom = 12,\n bgLayer = DEFAULT_BG_LAYER,\n markerMode = 'none',\n markerPosition,\n onMarkerPlace,\n className,\n style,\n layers,\n },\n ref\n ) {\n const luxApi = useLuxApi();\n const mapContainerRef = useRef<HTMLDivElement | null>(null);\n const mapRef = useRef<LuxMapInstance | null>(null);\n const markerLayerRef = useRef<unknown>(null);\n const clickListenerRef = useRef<((...args: unknown[]) => void) | null>(null);\n const [isMapReady, setIsMapReady] = useState(false);\n\n // Keep stable refs to callbacks so effects don't re-run on every render\n const onMarkerPlaceRef = useRef(onMarkerPlace);\n onMarkerPlaceRef.current = onMarkerPlace;\n const initialCenter = resolveInitialCenter(center, markerMode, markerPosition);\n\n // ------------------------------------------------------------------ map init\n useEffect(() => {\n if (luxApi.status !== 'ready') return;\n if (!mapContainerRef.current) return;\n\n let cancelled = false;\n const lux = luxApi.lux;\n const { easting, northing } = latLonToLuref(initialCenter.lat, initialCenter.lon);\n\n const mapInstance = new lux.Map({\n target: mapContainerRef.current,\n bgLayer,\n zoom,\n position: [easting, northing],\n ...(layers && layers.length > 0\n ? { layers, layerOpacities: layers.map(() => 1) }\n : {}),\n });\n\n mapRef.current = mapInstance;\n setIsMapReady(false);\n\n const readyPromise = mapInstance.getMapReadyPromise?.() ?? Promise.resolve();\n void readyPromise.then(() => {\n if (!cancelled) {\n setIsMapReady(true);\n }\n });\n\n return () => {\n cancelled = true;\n // lux.Map does not expose a destroy(); we clear our references\n mapRef.current = null;\n markerLayerRef.current = null;\n clickListenerRef.current = null;\n setIsMapReady(false);\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [luxApi.status]);\n\n // ------------------------------------------------------------------ marker position\n useEffect(() => {\n const map = mapRef.current;\n if (!map || luxApi.status !== 'ready' || !isMapReady) return;\n\n const displayPosition = resolveDisplayMarkerPosition(\n markerMode,\n markerPosition,\n center ?? LUXEMBOURG_CITY\n );\n\n if (!displayPosition) {\n clearMarker(markerLayerRef);\n return;\n }\n\n setMarkerPosition(map, displayPosition, markerLayerRef);\n }, [\n isMapReady,\n luxApi.status,\n markerMode,\n markerPosition?.lat,\n markerPosition?.lon,\n center?.lat,\n center?.lon,\n ]);\n\n // ------------------------------------------------------------------ click listener\n useEffect(() => {\n const map = mapRef.current;\n if (!map || luxApi.status !== 'ready' || !isMapReady) return;\n\n // Remove previous click listener\n if (clickListenerRef.current) {\n map.un('singleclick', clickListenerRef.current);\n clickListenerRef.current = null;\n }\n\n if (markerMode !== 'click') {\n return;\n }\n\n const handler = (...args: unknown[]) => {\n // Raw OpenLayers click coordinates are in the map view projection, not WGS84/LUREF.\n const evt = args[0] as { coordinate?: [number, number] };\n if (!evt.coordinate) return;\n\n const latLon = convertMapClickCoordinateToLatLon(map, evt.coordinate);\n setMarkerCoordinate(map, evt.coordinate, latLon, markerLayerRef);\n onMarkerPlaceRef.current?.(latLon);\n };\n\n clickListenerRef.current = handler;\n map.on('singleclick', handler);\n\n return () => {\n if (clickListenerRef.current) {\n map.un('singleclick', clickListenerRef.current);\n clickListenerRef.current = null;\n }\n };\n }, [\n isMapReady,\n luxApi.status,\n markerMode,\n ]);\n\n // ------------------------------------------------------------------ imperative handle\n useImperativeHandle(ref, () => ({\n getLuxMap: () => mapRef.current,\n setCenter(coords: LatLon) {\n const map = mapRef.current;\n if (!map) return;\n const { easting, northing } = latLonToLuref(coords.lat, coords.lon);\n if (map.setCenter) {\n map.setCenter([easting, northing], undefined, LUREF_PROJECTION);\n return;\n }\n map.getView().setCenter(convertLatLonToMarkerCoordinate(coords));\n },\n setZoom(z: number) {\n mapRef.current?.getView().setZoom(z);\n },\n }));\n\n // ------------------------------------------------------------------ render\n if (luxApi.status === 'error') {\n return (\n <div\n className={className}\n style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', background: '#f5f5f5', ...style }}\n >\n <span style={{ color: '#c00' }}>\n Failed to load Geoportail API: {luxApi.error.message}\n </span>\n </div>\n );\n }\n\n return (\n <div style={{ position: 'relative', ...style }} className={className}>\n {luxApi.status === 'loading' && (\n <div\n style={{\n position: 'absolute',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n background: 'rgba(255,255,255,0.7)',\n zIndex: 10,\n }}\n >\n <span>Loading map…</span>\n </div>\n )}\n <div\n ref={mapContainerRef}\n style={{ width: '100%', height: '100%' }}\n />\n </div>\n );\n }\n);\n\n// ------------------------------------------------------------------ helpers\n\n/**\n * Place/move an SVG pin marker on the map.\n * lux.Map is built on OpenLayers 3 — overlays must use the view projection.\n */\nexport function setMarkerPosition(\n map: LuxMapInstance,\n position: LatLon,\n layerRef: React.MutableRefObject<unknown>\n): void {\n const overlay = ensureMarkerOverlay(map, position, layerRef);\n if (!overlay) return;\n\n overlay.setPosition(convertLatLonToMarkerCoordinate(position));\n}\n\nexport function setMarkerCoordinate(\n map: LuxMapInstance,\n coordinate: [number, number],\n position: LatLon,\n layerRef: React.MutableRefObject<unknown>\n): void {\n const overlay = ensureMarkerOverlay(map, position, layerRef);\n if (!overlay) return;\n overlay.setPosition(coordinate);\n}\n\nexport function clearMarker(\n layerRef: React.MutableRefObject<unknown>\n): void {\n if (!layerRef.current) return;\n // Hide the existing overlay instead of discarding it so future updates can reuse it.\n (layerRef.current as OlOverlay).setPosition(undefined);\n}\n\nexport function ensureMarkerOverlay(\n map: LuxMapInstance,\n _position: LatLon,\n layerRef: React.MutableRefObject<unknown>\n): OlOverlay | null {\n if (layerRef.current) {\n return layerRef.current as OlOverlay;\n }\n\n const ol = (window as unknown as { ol?: OlLike }).ol;\n if (!ol) return null;\n\n const el = document.createElement('div');\n el.innerHTML = PIN_SVG;\n el.style.cssText =\n 'cursor:pointer;line-height:0;display:block;';\n\n const overlay = new ol.Overlay({\n element: el,\n positioning: 'bottom-center',\n stopEvent: false,\n });\n\n (map as unknown as { addOverlay(o: OlOverlay): void }).addOverlay(overlay);\n layerRef.current = overlay;\n return overlay;\n}\n\nexport function convertLatLonToMarkerCoordinate(\n position: LatLon\n): [number, number] {\n const ol = (window as unknown as { ol?: OlLike }).ol;\n const transform = ol?.proj?.transform;\n\n if (!transform) {\n const { easting, northing } = latLonToLuref(position.lat, position.lon);\n return [easting, northing];\n }\n\n return transform([position.lon, position.lat], WGS84_PROJECTION, OVERLAY_PROJECTION);\n}\n\nexport function resolveDisplayMarkerPosition(\n markerMode: MarkerMode,\n markerPosition: LatLon | undefined,\n center: LatLon\n): LatLon | undefined {\n if (markerMode === 'none') {\n return undefined;\n }\n\n if (markerPosition) {\n return markerPosition;\n }\n\n return markerMode === 'fixed' ? center : undefined;\n}\n\nexport function resolveInitialCenter(\n center: LatLon | undefined,\n markerMode: MarkerMode,\n markerPosition: LatLon | undefined\n): LatLon {\n if (markerPosition && markerMode !== 'none') {\n return markerPosition;\n }\n\n return center ?? LUXEMBOURG_CITY;\n}\n\n// Minimal pin SVG (red teardrop, 30×40)\nconst PIN_SVG = `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"30\" height=\"40\" viewBox=\"0 0 30 40\">\n <path d=\"M15 0C7.268 0 1 6.268 1 14c0 10.5 14 26 14 26S29 24.5 29 14C29 6.268 22.732 0 15 0z\"\n fill=\"#e53935\" stroke=\"#b71c1c\" stroke-width=\"1.5\"/>\n <circle cx=\"15\" cy=\"14\" r=\"5\" fill=\"white\"/>\n</svg>`;\n\n// Minimal OL type stubs used only within this file\ninterface OlOverlay {\n setPosition(pos: [number, number] | undefined): void;\n}\n\ninterface OlLike {\n proj?: {\n transform(\n coordinate: [number, number],\n source: string,\n destination: string\n ): [number, number];\n };\n Overlay: new (opts: { element: HTMLElement; positioning: string; stopEvent: boolean }) => OlOverlay;\n}\n\nexport function convertMapClickCoordinateToLatLon(\n _map: LuxMapInstance,\n coordinate: [number, number]\n): LatLon {\n const ol = (window as unknown as { ol?: OlLike }).ol;\n const transform = ol?.proj?.transform;\n\n if (!transform) {\n const [easting, northing] = coordinate;\n return lurefToLatLon(easting, northing);\n }\n\n const [lon, lat] = transform(coordinate, DEFAULT_CLICK_SOURCE_PROJECTION, WGS84_PROJECTION);\n return { lat, lon };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport type { LatLon, Address } from '../types';\n\nconst REVERSE_GEOCODE_URL = 'https://apiv4.geoportail.lu/geocode/reverse';\n\nexport type ReverseGeocodeState =\n | { status: 'idle'; address: null; error: null }\n | { status: 'loading'; address: null; error: null }\n | { status: 'success'; address: Address; error: null }\n | { status: 'error'; address: null; error: Error };\n\n/**\n * Hook for reverse geocoding: convert a WGS84 lat/lon to a Luxembourg address.\n *\n * Uses the Geoportail v4 REST reverse geocode endpoint — no API key required.\n * The endpoint accepts either `lat`/`lon` (WGS84) or `easting`/`northing`\n * (LUREF); we send WGS84 so no client-side reprojection is needed.\n *\n * @example\n * const { state, lookup } = useReverseGeocode();\n * // ...\n * lookup({ lat: 49.6116, lon: 6.1319 });\n * if (state.status === 'success') console.log(state.address.label);\n */\nexport function useReverseGeocode() {\n const [state, setState] = useState<ReverseGeocodeState>({\n status: 'idle',\n address: null,\n error: null,\n });\n\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => () => { abortRef.current?.abort(); }, []);\n\n const lookup = useCallback(async (position: LatLon) => {\n // Cancel any in-flight request\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n setState({ status: 'loading', address: null, error: null });\n\n try {\n const url = new URL(REVERSE_GEOCODE_URL);\n url.searchParams.set('lat', String(position.lat));\n url.searchParams.set('lon', String(position.lon));\n\n const res = await fetch(url.toString(), { signal: controller.signal });\n\n if (!res.ok) {\n throw new Error(`Reverse geocode request failed: ${res.status} ${res.statusText}`);\n }\n\n const data = (await res.json()) as {\n count?: number;\n results?: Array<{\n number?: string;\n street?: string;\n postal_code?: string;\n locality?: string;\n distance?: number;\n geom?: {\n coordinates?: [number, number];\n };\n }>;\n };\n\n const first = data.results?.[0];\n if (!first) {\n throw new Error('No results returned for this position');\n }\n\n const label = [\n [first.number, first.street].filter(Boolean).join(' ').trim(),\n [first.postal_code, first.locality].filter(Boolean).join(' ').trim(),\n ].filter(Boolean).join(', ');\n\n const [easting, northing] = first.geom?.coordinates ?? [0, 0];\n\n setState({\n status: 'success',\n address: {\n label,\n distance: first.distance ?? 0,\n easting,\n northing,\n },\n error: null,\n });\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setState({\n status: 'error',\n address: null,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState({ status: 'idle', address: null, error: null });\n }, []);\n\n return { state, lookup, reset };\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { lurefToLatLon } from '../utils/coordinates';\nimport type { GeocodeQuery, LatLon } from '../types';\n\nconst GEOCODE_URL = 'https://apiv4.geoportail.lu/geocode/search';\n\nexport interface GeocodeResultItem {\n latLon: LatLon;\n easting: number;\n northing: number;\n accuracy: number;\n street?: string;\n num?: string;\n zip?: string;\n locality?: string;\n}\n\n/**\n * The API returns WGS84 coordinates as a `geomlonlat` GeoJSON point (in\n * [lon, lat] order) computed server-side, which is more accurate than the\n * bundled LUREF conversion. Fall back to the local conversion if a result\n * comes back without it.\n */\nfunction toLatLon(\n coordinates: [number, number] | undefined,\n easting: number,\n northing: number\n): LatLon {\n if (coordinates) {\n const [lon, lat] = coordinates;\n return { lat, lon };\n }\n return lurefToLatLon(easting, northing);\n}\n\nexport type GeocodeState =\n | { status: 'idle'; results: null; error: null }\n | { status: 'loading'; results: null; error: null }\n | { status: 'success'; results: GeocodeResultItem[]; error: null }\n | { status: 'error'; results: null; error: Error };\n\n/**\n * Hook for forward geocoding: search for a Luxembourg address and get coordinates.\n *\n * @example\n * const { state, search } = useGeocode();\n * search({ queryString: '1 rue du Fort Thüngen, Luxembourg' });\n * if (state.status === 'success') {\n * const { lat, lon } = state.results[0].latLon;\n * }\n */\nexport function useGeocode() {\n const [state, setState] = useState<GeocodeState>({\n status: 'idle',\n results: null,\n error: null,\n });\n\n const abortRef = useRef<AbortController | null>(null);\n\n useEffect(() => () => { abortRef.current?.abort(); }, []);\n\n const search = useCallback(async (query: GeocodeQuery) => {\n abortRef.current?.abort();\n const controller = new AbortController();\n abortRef.current = controller;\n\n setState({ status: 'loading', results: null, error: null });\n\n try {\n const url = new URL(GEOCODE_URL);\n\n if (query.queryString) {\n url.searchParams.set('queryString', query.queryString);\n } else {\n if (query.num) url.searchParams.set('num', query.num);\n if (query.street) url.searchParams.set('street', query.street);\n if (query.zip) url.searchParams.set('zip', query.zip);\n if (query.locality) url.searchParams.set('locality', query.locality);\n }\n\n const res = await fetch(url.toString(), { signal: controller.signal });\n\n if (!res.ok) {\n throw new Error(`Geocode request failed: ${res.status} ${res.statusText}`);\n }\n\n const data = (await res.json()) as {\n results?: Array<{\n easting: number;\n northing: number;\n accuracy?: number;\n geomlonlat?: {\n coordinates?: [number, number];\n };\n AddressDetails?: {\n street?: string;\n postnumber?: string;\n zip?: string;\n locality?: string;\n };\n }>;\n };\n\n const results: GeocodeResultItem[] = (data.results ?? []).map((r) => ({\n latLon: toLatLon(r.geomlonlat?.coordinates, r.easting, r.northing),\n easting: r.easting,\n northing: r.northing,\n accuracy: r.accuracy ?? 0,\n street: r.AddressDetails?.street,\n num: r.AddressDetails?.postnumber,\n zip: r.AddressDetails?.zip,\n locality: r.AddressDetails?.locality,\n }));\n\n setState({ status: 'success', results, error: null });\n } catch (err: unknown) {\n if (err instanceof DOMException && err.name === 'AbortError') return;\n setState({\n status: 'error',\n results: null,\n error: err instanceof Error ? err : new Error(String(err)),\n });\n }\n }, []);\n\n const reset = useCallback(() => {\n abortRef.current?.abort();\n setState({ status: 'idle', results: null, error: null });\n }, []);\n\n return { state, search, reset };\n}\n"],"names":["LUX_BASE_URL","LUX_PROTOCOL","LUX_I18N_URL","LUX_STYLESHEET_URL","LUX_OL_URL","LUX_PROJ4_URL","LUX_AUTOCOMPLETE_URL","LUX_API_URL","LUX_STYLESHEET_ID","LUX_OL_SCRIPT_ID","LUX_PROJ4_SCRIPT_ID","LUX_AUTOCOMPLETE_SCRIPT_ID","LUX_API_SCRIPT_ID","LUREF_PROJECTION_CODE","LUREF_PROJ4_DEF","ELEMENT_STATUS_ATTRIBUTE","loadPromise","loadLuxApi","loadLuxApiInternal","error","pollForLux","resolve","reject","attempts","check","configureLux","loadStylesheetOnce","loadScriptOnce","registerLurefProjection","waitForLux","proj4","ol","_b","_a","lux","id","src","existing","waitForElementLoad","script","attachLoadHandlers","href","link","element","resourceUrl","kind","status","onLoad","onError","handleLoad","cleanup","handleError","useLuxApi","state","setState","useState","useEffect","cancelled","err","FE","FN","LON0","LAT0","SCALE","A","F","E2","DX","DY","DZ","degToRad","d","radToDeg","r","wgs84ToEd50","lat","lon","latR","lonR","sinLat","cosLat","sinLon","cosLon","aWgs","fWgs","bWgs","e2Wgs","da","df","N","dLat","dLon","ed50ToWgs84","M","tmForward","lon0R","lat0R","tanLat","T","C","dl","XX","meridianArc","M0","easting","northing","tmInverse","x","y","mu","e1","phi1","sinPhi1","cosPhi1","tanPhi1","N1","T1","C1","R1","D","e2","e4","e6","latLonToLuref","ed50","lurefToLatLon","DEFAULT_CLICK_SOURCE_PROJECTION","OVERLAY_PROJECTION","WGS84_PROJECTION","LUREF_PROJECTION","LUXEMBOURG_CITY","DEFAULT_BG_LAYER","GeoportailMap","forwardRef","center","zoom","bgLayer","markerMode","markerPosition","onMarkerPlace","className","style","layers","ref","luxApi","mapContainerRef","useRef","mapRef","markerLayerRef","clickListenerRef","isMapReady","setIsMapReady","onMarkerPlaceRef","initialCenter","resolveInitialCenter","mapInstance","map","displayPosition","resolveDisplayMarkerPosition","clearMarker","setMarkerPosition","handler","args","evt","latLon","convertMapClickCoordinateToLatLon","setMarkerCoordinate","useImperativeHandle","coords","convertLatLonToMarkerCoordinate","z","jsx","jsxs","position","layerRef","overlay","ensureMarkerOverlay","coordinate","_position","el","PIN_SVG","transform","_map","REVERSE_GEOCODE_URL","useReverseGeocode","abortRef","lookup","useCallback","controller","url","res","first","label","_c","reset","GEOCODE_URL","toLatLon","coordinates","useGeocode","search","query","results","_d","_e"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- (function(y,b){typeof exports=="object"&&typeof module<"u"?b(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],b):(y=typeof globalThis<"u"?globalThis:y||self,b(y.ReactGeoportail={},y.jsxRuntime,y.React))})(this,function(y,b,h){"use strict";const rt="https://apiv3.geoportail.lu/",it="https",at="https://apiv3.geoportail.lu/static-ngeo/build/fr.json",ct="https://apiv3.geoportail.lu/static-ngeo/build/apiv3.css",lt="https://apiv3.geoportail.lu/static-ngeo/build/vendor.js",ut="https://apiv3.geoportail.lu/static-ngeo/build/apiv3.js",dt="geoportail-apiv3-css",ft="geoportail-apiv3-vendor",pt="geoportail-apiv3-script",P="data-geoportail-status";let x=null;function W(){return x||(typeof window>"u"||typeof document>"u"?Promise.reject(new Error("loadLuxApi must be called in a browser environment")):(x=gt().catch(t=>{throw x=null,t instanceof Error?t:new Error(String(t))}),x))}function ht(t,n){let r=0;const s=()=>{if(window.lux){t();return}if(r++>=100){x=null,n(new Error("Timed out waiting for window.lux to be defined"));return}setTimeout(s,50)};s()}async function gt(){if(window.lux){z(window.lux);return}await Et(dt,ct),await V(ft,lt),await V(pt,ut),await Lt(),z(window.lux)}function Lt(){return new Promise((t,n)=>{ht(t,n)})}function z(t){t.setBaseUrl(rt,it),t.setI18nUrl(at)}function V(t,n){const o=document.getElementById(t);return o?Y(o,n,"script"):new Promise((r,s)=>{const e=document.createElement("script");e.id=t,e.src=n,e.async=!1,e.setAttribute(P,"loading"),F(e,()=>r(),()=>s(new Error(`Failed to load Geoportail script from ${n}`)),"script"),document.head.appendChild(e)})}function Et(t,n){const o=document.getElementById(t);return o?Y(o,n,"stylesheet"):new Promise((r,s)=>{const e=document.createElement("link");e.id=t,e.rel="stylesheet",e.href=n,e.setAttribute(P,"loading"),F(e,()=>r(),()=>s(new Error(`Failed to load Geoportail stylesheet from ${n}`)),"stylesheet"),document.head.appendChild(e)})}function Y(t,n,o){const r=t.getAttribute(P);return r==="loaded"?Promise.resolve():r==="error"?(t.remove(),Promise.reject(new Error(`Failed to load Geoportail ${o} from ${n}`))):new Promise((s,e)=>{F(t,()=>s(),()=>e(new Error(`Failed to load Geoportail ${o} from ${n}`)),o)})}function F(t,n,o,r){const s=()=>{t.setAttribute(P,"loaded"),f(),n()},e=()=>{t.setAttribute(P,"error"),f(),t.remove(),o()},f=()=>{t.removeEventListener("load",s),t.removeEventListener("error",e)};return t.addEventListener("load",s,{once:!0}),t.addEventListener("error",e,{once:!0}),r==="stylesheet"?t.sheet&&s():t.dataset.geoportailStatus==="loaded"&&s(),f}function H(){const[t,n]=h.useState({status:"loading",lux:null,error:null});return h.useEffect(()=>{let o=!1;return W().then(()=>{o||n({status:"ready",lux:window.lux,error:null})}).catch(r=>{o||n({status:"error",lux:null,error:r instanceof Error?r:new Error(String(r))})}),()=>{o=!0}},[]),t}const q=8e4,J=1e5,Z=6.16666666666667,K=49.8333333333333,I=1,M=6378388,N=1/297,X=M*(1-N),v=1-X*X/(M*M),U=-87,G=-98,Q=-121;function S(t){return t*Math.PI/180}function A(t){return t*180/Math.PI}function wt(t,n){const o=S(t),r=S(n),s=Math.sin(o),e=Math.cos(o),f=Math.sin(r),g=Math.cos(r),a=6378137,l=1/298.257223563,u=a*(1-l),c=1-u*u/(a*a),p=M-a,i=N-l,w=a/Math.sqrt(1-c*s*s),E=1/(a*(1-c)/Math.pow(1-c*s*s,1.5))*(w*(c/(1-c))*s*e*(p/a)+(w/a+1)*s*e*i*(a/u)-(U*s*g+G*s*f-Q*e)),T=1/(w*e)*(-U*f+G*g);return{lat:t+A(E),lon:n+A(T)}}function mt(t,n){const o=S(t),r=S(n),s=Math.sin(o),e=Math.cos(o),f=Math.sin(r),g=Math.cos(r),a=M/Math.sqrt(1-v*s*s),l=M*(1-v)/Math.pow(1-v*s*s,1.5),u=6378137-M,p=1/298.257223563-N,i=1/l*(a*(v/(1-v))*s*e*(u/M)+(a/M+1)*s*e*p*(M/X)+(U*s*g+G*s*f-Q*e)),w=1/(a*e)*(U*f-G*g);return{lat:t+A(i),lon:n+A(w)}}function vt(t,n){const o=S(t),r=S(n),s=S(Z),e=S(K),f=Math.sin(o),g=Math.cos(o),a=Math.tan(o),l=M/Math.sqrt(1-v*f*f),u=a*a,c=v/(1-v)*g*g,p=r-s,i=g*p,w=B(o),L=B(e),E=q+I*l*(i+i*i*i*(1-u+c)/6+i*i*i*i*i*(5-18*u+u*u+72*c)/120),T=J+I*(w-L+l*a*(i*i/2+i*i*i*i*(5-u+9*c+4*c*c)/24+i*i*i*i*i*i*(61-58*u+u*u+600*c)/720));return{easting:E,northing:T}}function Mt(t,n){const o=t-q,r=n-J,s=S(K),e=S(Z),a=(B(s)+r/I)/(M*(1-v/4-3*v*v/64)),l=(1-Math.sqrt(1-v))/(1+Math.sqrt(1-v)),u=a+(3*l/2-27*l*l*l/32)*Math.sin(2*a)+(21*l*l/16-55*l*l*l*l/32)*Math.sin(4*a)+151*l*l*l/96*Math.sin(6*a),c=Math.sin(u),p=Math.cos(u),i=Math.tan(u),w=M/Math.sqrt(1-v*c*c),L=i*i,E=v/(1-v)*p*p,T=M*(1-v)/Math.pow(1-v*c*c,1.5),d=o/(w*I),j=u-w*i/T*(d*d/2-d*d*d*d*(5+3*L+10*E-4*E*E)/24+d*d*d*d*d*d*(61+90*L+298*E+45*L*L)/720),m=e+(d-d*d*d*(1+2*L+E)/6+d*d*d*d*d*(5-2*E+28*L-3*E*E)/120)/p;return{lat:A(j),lon:A(m)}}function B(t){const n=v,o=n*n,r=o*n;return M*((1-n/4-3*o/64-5*r/256)*t-(3*n/8+3*o/32+45*r/1024)*Math.sin(2*t)+(15*o/256+45*r/1024)*Math.sin(4*t)-35*r/3072*Math.sin(6*t))}function D(t,n){const o=wt(t,n);return vt(o.lat,o.lon)}function $(t,n){const o=Mt(t,n);return mt(o.lat,o.lon)}const Rt="EPSG:3857",yt="EPSG:3857",tt="EPSG:4326",bt="EPSG:2169",nt={lat:49.6116,lon:6.1319},St="basemap_2015_global",Tt=h.forwardRef(function({center:n,zoom:o=12,bgLayer:r=St,markerMode:s="none",markerPosition:e,onMarkerPlace:f,className:g,style:a,layers:l},u){const c=H(),p=h.useRef(null),i=h.useRef(null),w=h.useRef(null),L=h.useRef(null),[E,T]=h.useState(!1),d=h.useRef(f);d.current=f;const j=Pt(n,s,e);return h.useEffect(()=>{var st;if(c.status!=="ready"||!p.current)return;let m=!1;const R=c.lux,{easting:O,northing:C}=D(j.lat,j.lon),_=new R.Map({target:p.current,bgLayer:r,zoom:o,position:[O,C],...l&&l.length>0?{layers:l,layerOpacities:l.map(()=>1)}:{}});return i.current=_,T(!1),(((st=_.getMapReadyPromise)==null?void 0:st.call(_))??Promise.resolve()).then(()=>{m||T(!0)}),()=>{m=!0,i.current=null,w.current=null,L.current=null,T(!1)}},[c.status]),h.useEffect(()=>{const m=i.current;if(!m||c.status!=="ready"||!E)return;const R=At(s,e,n??nt);if(!R){xt(w);return}Ct(m,R,w)},[E,c.status,s,e==null?void 0:e.lat,e==null?void 0:e.lon,n==null?void 0:n.lat,n==null?void 0:n.lon]),h.useEffect(()=>{const m=i.current;if(!m||c.status!=="ready"||!E||(L.current&&(m.un("singleclick",L.current),L.current=null),s!=="click"))return;const R=(...O)=>{var k;const C=O[0];if(!C.coordinate)return;const _=It(m,C.coordinate);_t(m,C.coordinate,_,w),(k=d.current)==null||k.call(d,_)};return L.current=R,m.on("singleclick",R),()=>{L.current&&(m.un("singleclick",L.current),L.current=null)}},[E,c.status,s]),h.useImperativeHandle(u,()=>({getLuxMap:()=>i.current,setCenter(m){const R=i.current;if(!R)return;const{easting:O,northing:C}=D(m.lat,m.lon);if(R.setCenter){R.setCenter([O,C],void 0,bt);return}R.getView().setCenter(ot(m))},setZoom(m){var R;(R=i.current)==null||R.getView().setZoom(m)}})),c.status==="error"?b.jsx("div",{className:g,style:{display:"flex",alignItems:"center",justifyContent:"center",background:"#f5f5f5",...a},children:b.jsxs("span",{style:{color:"#c00"},children:["Failed to load Geoportail API: ",c.error.message]})}):b.jsxs("div",{style:{position:"relative",...a},className:g,children:[c.status==="loading"&&b.jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(255,255,255,0.7)",zIndex:10},children:b.jsx("span",{children:"Loading map…"})}),b.jsx("div",{ref:p,style:{width:"100%",height:"100%"}})]})});function Ct(t,n,o){const r=et(t,n,o);r&&r.setPosition(ot(n))}function _t(t,n,o,r){const s=et(t,o,r);s&&s.setPosition(n)}function xt(t){t.current&&t.current.setPosition(void 0)}function et(t,n,o){if(o.current)return o.current;const r=window.ol;if(!r)return null;const s=document.createElement("div");s.innerHTML=Ot,s.style.cssText="cursor:pointer;line-height:0;display:block;";const e=new r.Overlay({element:s,positioning:"bottom-center",stopEvent:!1});return t.addOverlay(e),o.current=e,e}function ot(t){var r;const n=window.ol,o=(r=n==null?void 0:n.proj)==null?void 0:r.transform;if(!o){const{easting:s,northing:e}=D(t.lat,t.lon);return[s,e]}return o([t.lon,t.lat],tt,yt)}function At(t,n,o){if(t!=="none")return n||(t==="fixed"?o:void 0)}function Pt(t,n,o){return o&&n!=="none"?o:t??nt}const Ot=`<svg xmlns="http://www.w3.org/2000/svg" width="30" height="40" viewBox="0 0 30 40">
1
+ (function(R,y){typeof exports=="object"&&typeof module<"u"?y(exports,require("react/jsx-runtime"),require("react")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react"],y):(R=typeof globalThis<"u"?globalThis:R||self,y(R.ReactGeoportail={},R.jsxRuntime,R.React))})(this,function(R,y,g){"use strict";const it="https://apiv4.geoportail.lu/",at="https",ct="https://apiv4.geoportail.lu/static-ngeo/build/fr.json",lt="https://apiv4.geoportail.lu/static-ngeo/build/apiv4.css",ut="https://apiv4.geoportail.lu/static-ngeo/build/ol.js",dt="https://apiv4.geoportail.lu/static-ngeo/build/proj4.js",ft="https://apiv4.geoportail.lu/static-ngeo/build/auto-complete.min.js",pt="https://apiv4.geoportail.lu/static-ngeo/build/apiv4.js",gt="geoportail-apiv4-css",ht="geoportail-apiv4-ol",Lt="geoportail-apiv4-proj4",Et="geoportail-apiv4-autocomplete",wt="geoportail-apiv4-script",W="EPSG:2169",mt="+proj=tmerc +lat_0=49.83333333333334 +lon_0=6.166666666666667 +k=1 +x_0=80000 +y_0=100000 +ellps=intl +towgs84=-189.681,18.3463,-42.7695,-0.33746,-3.09264,2.53861,0.4598 +units=m +no_defs",x="data-geoportail-status";let P=null;function z(){return P||(typeof window>"u"||typeof document>"u"?Promise.reject(new Error("loadLuxApi must be called in a browser environment")):(P=_t().catch(t=>{throw P=null,t instanceof Error?t:new Error(String(t))}),P))}function vt(t,n){let r=0;const s=()=>{if(window.lux){t();return}if(r++>=100){P=null,n(new Error("Timed out waiting for window.lux to be defined"));return}setTimeout(s,50)};s()}async function _t(){if(window.lux){Y(window.lux);return}await Tt(gt,lt),await U(ht,ut),await U(Lt,dt),Mt(),await U(Et,ft),await U(wt,pt),await Rt(),Y(window.lux)}function Mt(){var e,r;const t=window.proj4,n=window.ol;!t||!((r=(e=n==null?void 0:n.proj)==null?void 0:e.proj4)!=null&&r.register)||(t.defs(W)||t.defs(W,mt),n.proj.proj4.register(t))}function Rt(){return new Promise((t,n)=>{vt(t,n)})}function Y(t){t.setBaseUrl(it,at),t.setI18nUrl(ct)}function U(t,n){const e=document.getElementById(t);return e?H(e,n,"script"):new Promise((r,s)=>{const o=document.createElement("script");o.id=t,o.src=n,o.async=!1,o.setAttribute(x,"loading"),X(o,()=>r(),()=>s(new Error(`Failed to load Geoportail script from ${n}`)),"script"),document.head.appendChild(o)})}function Tt(t,n){const e=document.getElementById(t);return e?H(e,n,"stylesheet"):new Promise((r,s)=>{const o=document.createElement("link");o.id=t,o.rel="stylesheet",o.href=n,o.setAttribute(x,"loading"),X(o,()=>r(),()=>s(new Error(`Failed to load Geoportail stylesheet from ${n}`)),"stylesheet"),document.head.appendChild(o)})}function H(t,n,e){const r=t.getAttribute(x);return r==="loaded"?Promise.resolve():r==="error"?(t.remove(),Promise.reject(new Error(`Failed to load Geoportail ${e} from ${n}`))):new Promise((s,o)=>{X(t,()=>s(),()=>o(new Error(`Failed to load Geoportail ${e} from ${n}`)),e)})}function X(t,n,e,r){const s=()=>{t.setAttribute(x,"loaded"),f(),n()},o=()=>{t.setAttribute(x,"error"),f(),t.remove(),e()},f=()=>{t.removeEventListener("load",s),t.removeEventListener("error",o)};return t.addEventListener("load",s,{once:!0}),t.addEventListener("error",o,{once:!0}),r==="stylesheet"?t.sheet&&s():t.dataset.geoportailStatus==="loaded"&&s(),f}function V(){const[t,n]=g.useState({status:"loading",lux:null,error:null});return g.useEffect(()=>{let e=!1;return z().then(()=>{e||n({status:"ready",lux:window.lux,error:null})}).catch(r=>{e||n({status:"error",lux:null,error:r instanceof Error?r:new Error(String(r))})}),()=>{e=!0}},[]),t}const q=8e4,Z=1e5,K=6.16666666666667,Q=49.8333333333333,I=1,_=6378388,N=1/297,B=_*(1-N),v=1-B*B/(_*_),j=-87,G=-98,tt=-121;function C(t){return t*Math.PI/180}function O(t){return t*180/Math.PI}function yt(t,n){const e=C(t),r=C(n),s=Math.sin(e),o=Math.cos(e),f=Math.sin(r),h=Math.cos(r),a=6378137,l=1/298.257223563,u=a*(1-l),c=1-u*u/(a*a),p=_-a,i=N-l,w=a/Math.sqrt(1-c*s*s),E=1/(a*(1-c)/Math.pow(1-c*s*s,1.5))*(w*(c/(1-c))*s*o*(p/a)+(w/a+1)*s*o*i*(a/u)-(j*s*h+G*s*f-tt*o)),T=1/(w*o)*(-j*f+G*h);return{lat:t+O(E),lon:n+O(T)}}function Ct(t,n){const e=C(t),r=C(n),s=Math.sin(e),o=Math.cos(e),f=Math.sin(r),h=Math.cos(r),a=_/Math.sqrt(1-v*s*s),l=_*(1-v)/Math.pow(1-v*s*s,1.5),u=6378137-_,p=1/298.257223563-N,i=1/l*(a*(v/(1-v))*s*o*(u/_)+(a/_+1)*s*o*p*(_/B)+(j*s*h+G*s*f-tt*o)),w=1/(a*o)*(j*f-G*h);return{lat:t+O(i),lon:n+O(w)}}function St(t,n){const e=C(t),r=C(n),s=C(K),o=C(Q),f=Math.sin(e),h=Math.cos(e),a=Math.tan(e),l=_/Math.sqrt(1-v*f*f),u=a*a,c=v/(1-v)*h*h,p=r-s,i=h*p,w=$(e),L=$(o),E=q+I*l*(i+i*i*i*(1-u+c)/6+i*i*i*i*i*(5-18*u+u*u+72*c)/120),T=Z+I*(w-L+l*a*(i*i/2+i*i*i*i*(5-u+9*c+4*c*c)/24+i*i*i*i*i*i*(61-58*u+u*u+600*c)/720));return{easting:E,northing:T}}function bt(t,n){const e=t-q,r=n-Z,s=C(Q),o=C(K),a=($(s)+r/I)/(_*(1-v/4-3*v*v/64)),l=(1-Math.sqrt(1-v))/(1+Math.sqrt(1-v)),u=a+(3*l/2-27*l*l*l/32)*Math.sin(2*a)+(21*l*l/16-55*l*l*l*l/32)*Math.sin(4*a)+151*l*l*l/96*Math.sin(6*a),c=Math.sin(u),p=Math.cos(u),i=Math.tan(u),w=_/Math.sqrt(1-v*c*c),L=i*i,E=v/(1-v)*p*p,T=_*(1-v)/Math.pow(1-v*c*c,1.5),d=e/(w*I),F=u-w*i/T*(d*d/2-d*d*d*d*(5+3*L+10*E-4*E*E)/24+d*d*d*d*d*d*(61+90*L+298*E+45*L*L)/720),m=o+(d-d*d*d*(1+2*L+E)/6+d*d*d*d*d*(5-2*E+28*L-3*E*E)/120)/p;return{lat:O(F),lon:O(m)}}function $(t){const n=v,e=n*n,r=e*n;return _*((1-n/4-3*e/64-5*r/256)*t-(3*n/8+3*e/32+45*r/1024)*Math.sin(2*t)+(15*e/256+45*r/1024)*Math.sin(4*t)-35*r/3072*Math.sin(6*t))}function D(t,n){const e=yt(t,n);return St(e.lat,e.lon)}function k(t,n){const e=bt(t,n);return Ct(e.lat,e.lon)}const Pt="EPSG:3857",Ot="EPSG:3857",nt="EPSG:4326",xt="EPSG:2169",et={lat:49.6116,lon:6.1319},At="basemap_2015_global",Ut=g.forwardRef(function({center:n,zoom:e=12,bgLayer:r=At,markerMode:s="none",markerPosition:o,onMarkerPlace:f,className:h,style:a,layers:l},u){const c=V(),p=g.useRef(null),i=g.useRef(null),w=g.useRef(null),L=g.useRef(null),[E,T]=g.useState(!1),d=g.useRef(f);d.current=f;const F=Ft(n,s,o);return g.useEffect(()=>{var rt;if(c.status!=="ready"||!p.current)return;let m=!1;const M=c.lux,{easting:A,northing:S}=D(F.lat,F.lon),b=new M.Map({target:p.current,bgLayer:r,zoom:e,position:[A,S],...l&&l.length>0?{layers:l,layerOpacities:l.map(()=>1)}:{}});return i.current=b,T(!1),(((rt=b.getMapReadyPromise)==null?void 0:rt.call(b))??Promise.resolve()).then(()=>{m||T(!0)}),()=>{m=!0,i.current=null,w.current=null,L.current=null,T(!1)}},[c.status]),g.useEffect(()=>{const m=i.current;if(!m||c.status!=="ready"||!E)return;const M=Dt(s,o,n??et);if(!M){Gt(w);return}It(m,M,w)},[E,c.status,s,o==null?void 0:o.lat,o==null?void 0:o.lon,n==null?void 0:n.lat,n==null?void 0:n.lon]),g.useEffect(()=>{const m=i.current;if(!m||c.status!=="ready"||!E||(L.current&&(m.un("singleclick",L.current),L.current=null),s!=="click"))return;const M=(...A)=>{var J;const S=A[0];if(!S.coordinate)return;const b=Nt(m,S.coordinate);jt(m,S.coordinate,b,w),(J=d.current)==null||J.call(d,b)};return L.current=M,m.on("singleclick",M),()=>{L.current&&(m.un("singleclick",L.current),L.current=null)}},[E,c.status,s]),g.useImperativeHandle(u,()=>({getLuxMap:()=>i.current,setCenter(m){const M=i.current;if(!M)return;const{easting:A,northing:S}=D(m.lat,m.lon);if(M.setCenter){M.setCenter([A,S],void 0,xt);return}M.getView().setCenter(st(m))},setZoom(m){var M;(M=i.current)==null||M.getView().setZoom(m)}})),c.status==="error"?y.jsx("div",{className:h,style:{display:"flex",alignItems:"center",justifyContent:"center",background:"#f5f5f5",...a},children:y.jsxs("span",{style:{color:"#c00"},children:["Failed to load Geoportail API: ",c.error.message]})}):y.jsxs("div",{style:{position:"relative",...a},className:h,children:[c.status==="loading"&&y.jsx("div",{style:{position:"absolute",inset:0,display:"flex",alignItems:"center",justifyContent:"center",background:"rgba(255,255,255,0.7)",zIndex:10},children:y.jsx("span",{children:"Loading map…"})}),y.jsx("div",{ref:p,style:{width:"100%",height:"100%"}})]})});function It(t,n,e){const r=ot(t,n,e);r&&r.setPosition(st(n))}function jt(t,n,e,r){const s=ot(t,e,r);s&&s.setPosition(n)}function Gt(t){t.current&&t.current.setPosition(void 0)}function ot(t,n,e){if(e.current)return e.current;const r=window.ol;if(!r)return null;const s=document.createElement("div");s.innerHTML=Xt,s.style.cssText="cursor:pointer;line-height:0;display:block;";const o=new r.Overlay({element:s,positioning:"bottom-center",stopEvent:!1});return t.addOverlay(o),e.current=o,o}function st(t){var r;const n=window.ol,e=(r=n==null?void 0:n.proj)==null?void 0:r.transform;if(!e){const{easting:s,northing:o}=D(t.lat,t.lon);return[s,o]}return e([t.lon,t.lat],nt,Ot)}function Dt(t,n,e){if(t!=="none")return n||(t==="fixed"?e:void 0)}function Ft(t,n,e){return e&&n!=="none"?e:t??et}const Xt=`<svg xmlns="http://www.w3.org/2000/svg" width="30" height="40" viewBox="0 0 30 40">
2
2
  <path d="M15 0C7.268 0 1 6.268 1 14c0 10.5 14 26 14 26S29 24.5 29 14C29 6.268 22.732 0 15 0z"
3
3
  fill="#e53935" stroke="#b71c1c" stroke-width="1.5"/>
4
4
  <circle cx="15" cy="14" r="5" fill="white"/>
5
- </svg>`;function It(t,n){var f;const o=window.ol,r=(f=o==null?void 0:o.proj)==null?void 0:f.transform;if(!r){const[g,a]=n;return $(g,a)}const[s,e]=r(n,Rt,tt);return{lat:e,lon:s}}const Ut="https://apiv3.geoportail.lu/geocode/reverse";function Gt(){const[t,n]=h.useState({status:"idle",address:null,error:null}),o=h.useRef(null);h.useEffect(()=>()=>{var e;(e=o.current)==null||e.abort()},[]);const r=h.useCallback(async e=>{var g,a,l;(g=o.current)==null||g.abort();const f=new AbortController;o.current=f,n({status:"loading",address:null,error:null});try{const u=new URL(Ut);u.searchParams.set("lat",String(e.lat)),u.searchParams.set("lon",String(e.lon));const c=await fetch(u.toString(),{signal:f.signal});if(!c.ok)throw new Error(`Reverse geocode request failed: ${c.status} ${c.statusText}`);const i=(a=(await c.json()).results)==null?void 0:a[0];if(!i)throw new Error("No results returned for this position");const w=[[i.number,i.street].filter(Boolean).join(" ").trim(),[i.postal_code,i.locality].filter(Boolean).join(" ").trim()].filter(Boolean).join(", "),[L,E]=((l=i.geom)==null?void 0:l.coordinates)??[0,0];n({status:"success",address:{label:w,distance:i.distance??0,easting:L,northing:E},error:null})}catch(u){if(u instanceof DOMException&&u.name==="AbortError")return;n({status:"error",address:null,error:u instanceof Error?u:new Error(String(u))})}},[]),s=h.useCallback(()=>{var e;(e=o.current)==null||e.abort(),n({status:"idle",address:null,error:null})},[]);return{state:t,lookup:r,reset:s}}const Dt="https://apiv3.geoportail.lu/geocode/search";function jt(){const[t,n]=h.useState({status:"idle",results:null,error:null}),o=h.useRef(null);h.useEffect(()=>()=>{var e;(e=o.current)==null||e.abort()},[]);const r=h.useCallback(async e=>{var g;(g=o.current)==null||g.abort();const f=new AbortController;o.current=f,n({status:"loading",results:null,error:null});try{const a=new URL(Dt);e.queryString?a.searchParams.set("queryString",e.queryString):(e.num&&a.searchParams.set("num",e.num),e.street&&a.searchParams.set("street",e.street),e.zip&&a.searchParams.set("zip",e.zip),e.locality&&a.searchParams.set("locality",e.locality));const l=await fetch(a.toString(),{signal:f.signal});if(!l.ok)throw new Error(`Geocode request failed: ${l.status} ${l.statusText}`);const c=((await l.json()).results??[]).map(p=>{var i,w,L,E;return{latLon:$(p.easting,p.northing),easting:p.easting,northing:p.northing,accuracy:p.accuracy??0,street:(i=p.AddressDetails)==null?void 0:i.street,num:(w=p.AddressDetails)==null?void 0:w.number,zip:(L=p.AddressDetails)==null?void 0:L.zip,locality:(E=p.AddressDetails)==null?void 0:E.locality}});n({status:"success",results:c,error:null})}catch(a){if(a instanceof DOMException&&a.name==="AbortError")return;n({status:"error",results:null,error:a instanceof Error?a:new Error(String(a))})}},[]),s=h.useCallback(()=>{var e;(e=o.current)==null||e.abort(),n({status:"idle",results:null,error:null})},[]);return{state:t,search:r,reset:s}}y.GeoportailMap=Tt,y.latLonToLuref=D,y.loadLuxApi=W,y.lurefToLatLon=$,y.useGeocode=jt,y.useLuxApi=H,y.useReverseGeocode=Gt,Object.defineProperty(y,Symbol.toStringTag,{value:"Module"})});
5
+ </svg>`;function Nt(t,n){var f;const e=window.ol,r=(f=e==null?void 0:e.proj)==null?void 0:f.transform;if(!r){const[h,a]=n;return k(h,a)}const[s,o]=r(n,Pt,nt);return{lat:o,lon:s}}const Bt="https://apiv4.geoportail.lu/geocode/reverse";function $t(){const[t,n]=g.useState({status:"idle",address:null,error:null}),e=g.useRef(null);g.useEffect(()=>()=>{var o;(o=e.current)==null||o.abort()},[]);const r=g.useCallback(async o=>{var h,a,l;(h=e.current)==null||h.abort();const f=new AbortController;e.current=f,n({status:"loading",address:null,error:null});try{const u=new URL(Bt);u.searchParams.set("lat",String(o.lat)),u.searchParams.set("lon",String(o.lon));const c=await fetch(u.toString(),{signal:f.signal});if(!c.ok)throw new Error(`Reverse geocode request failed: ${c.status} ${c.statusText}`);const i=(a=(await c.json()).results)==null?void 0:a[0];if(!i)throw new Error("No results returned for this position");const w=[[i.number,i.street].filter(Boolean).join(" ").trim(),[i.postal_code,i.locality].filter(Boolean).join(" ").trim()].filter(Boolean).join(", "),[L,E]=((l=i.geom)==null?void 0:l.coordinates)??[0,0];n({status:"success",address:{label:w,distance:i.distance??0,easting:L,northing:E},error:null})}catch(u){if(u instanceof DOMException&&u.name==="AbortError")return;n({status:"error",address:null,error:u instanceof Error?u:new Error(String(u))})}},[]),s=g.useCallback(()=>{var o;(o=e.current)==null||o.abort(),n({status:"idle",address:null,error:null})},[]);return{state:t,lookup:r,reset:s}}const kt="https://apiv4.geoportail.lu/geocode/search";function Jt(t,n,e){if(t){const[r,s]=t;return{lat:s,lon:r}}return k(n,e)}function Wt(){const[t,n]=g.useState({status:"idle",results:null,error:null}),e=g.useRef(null);g.useEffect(()=>()=>{var o;(o=e.current)==null||o.abort()},[]);const r=g.useCallback(async o=>{var h;(h=e.current)==null||h.abort();const f=new AbortController;e.current=f,n({status:"loading",results:null,error:null});try{const a=new URL(kt);o.queryString?a.searchParams.set("queryString",o.queryString):(o.num&&a.searchParams.set("num",o.num),o.street&&a.searchParams.set("street",o.street),o.zip&&a.searchParams.set("zip",o.zip),o.locality&&a.searchParams.set("locality",o.locality));const l=await fetch(a.toString(),{signal:f.signal});if(!l.ok)throw new Error(`Geocode request failed: ${l.status} ${l.statusText}`);const c=((await l.json()).results??[]).map(p=>{var i,w,L,E,T;return{latLon:Jt((i=p.geomlonlat)==null?void 0:i.coordinates,p.easting,p.northing),easting:p.easting,northing:p.northing,accuracy:p.accuracy??0,street:(w=p.AddressDetails)==null?void 0:w.street,num:(L=p.AddressDetails)==null?void 0:L.postnumber,zip:(E=p.AddressDetails)==null?void 0:E.zip,locality:(T=p.AddressDetails)==null?void 0:T.locality}});n({status:"success",results:c,error:null})}catch(a){if(a instanceof DOMException&&a.name==="AbortError")return;n({status:"error",results:null,error:a instanceof Error?a:new Error(String(a))})}},[]),s=g.useCallback(()=>{var o;(o=e.current)==null||o.abort(),n({status:"idle",results:null,error:null})},[]);return{state:t,search:r,reset:s}}R.GeoportailMap=Ut,R.latLonToLuref=D,R.loadLuxApi=z,R.lurefToLatLon=k,R.useGeocode=Wt,R.useLuxApi=V,R.useReverseGeocode=$t,Object.defineProperty(R,Symbol.toStringTag,{value:"Module"})});
6
6
  //# sourceMappingURL=react-geoportail.umd.cjs.map