/** * Author: Simon-Pierre Boucher * Contact: contact@spboucher.ai * Project: Groupe Ka / Ka Maps * * URL state serialization: /map?lat=46.8139&lng=-71.2080&zoom=13 * Each app decides which extra parameters it exposes; Ka Maps only owns * the camera portion so URLs stay short and stable. */ export interface CameraUrlState { lat: number; lng: number; zoom: number; } /** Serialize camera state into URLSearchParams (mutates a copy, returns it). */ export function cameraToParams( state: CameraUrlState, base?: URLSearchParams, ): URLSearchParams { const params = new URLSearchParams(base); params.set("lat", state.lat.toFixed(5)); params.set("lng", state.lng.toFixed(5)); params.set("zoom", trimZoom(state.zoom)); return params; } /** Parse camera state from URLSearchParams; null when absent or malformed. */ export function cameraFromParams(params: URLSearchParams): CameraUrlState | null { const rawLat = params.get("lat"); const rawLng = params.get("lng"); const rawZoom = params.get("zoom"); if (rawLat === null || rawLng === null || rawZoom === null) return null; const lat = Number(rawLat); const lng = Number(rawLng); const zoom = Number(rawZoom); if (!Number.isFinite(lat) || !Number.isFinite(lng) || !Number.isFinite(zoom)) return null; if (lat < -90 || lat > 90 || lng < -180 || lng > 180) return null; return { lat, lng, zoom: Math.min(22, Math.max(0, zoom)) }; } function trimZoom(zoom: number): string { return (Math.round(zoom * 100) / 100).toString(); }