import maplibregl from "maplibre-gl"; import { Geometry } from "@/lib/useEditorState"; type ModeGetter = () => "idle" | "draw" | "select" | "add-point" | "add-line" | "add-path" | "add-circle"; export function initDrawing( map: maplibregl.Map, getMode: ModeGetter, onComplete: (geometry: Geometry) => void ) { let coords: [number, number][] = []; /** * Close polygon ring if not closed. */ function closePolygon(c: [number, number][]) { if (c.length < 3) return c; const first = c[0]; const last = c[c.length - 1]; if (first[0] !== last[0] || first[1] !== last[1]) { return [...c, first]; } return c; } /** * Update preview layer while drawing. */ function update(c: [number, number][]) { const closed = closePolygon(c); (map.getSource("draw-preview") as maplibregl.GeoJSONSource)?.setData({ type: "FeatureCollection", features: [ { type: "Feature", properties: {}, geometry: { type: "Polygon", coordinates: [closed], }, }, ], }); } function onClick(e: maplibregl.MapLayerMouseEvent) { if (getMode() !== "draw") return; coords.push([e.lngLat.lng, e.lngLat.lat] as [number, number]); update(coords); } function onMove(e: maplibregl.MapLayerMouseEvent) { if (getMode() !== "draw" || coords.length === 0) return; const preview: [number, number][] = [ ...coords, [e.lngLat.lng, e.lngLat.lat] as [number, number], ]; update(preview); } /** * Finalize polygon, emit geometry to caller, reset preview. */ function finishDrawing() { if (getMode() !== "draw" || coords.length < 3) return; const geometry: Geometry = { type: "Polygon", coordinates: [closePolygon(coords)], }; onComplete(geometry); coords = []; (map.getSource("draw-preview") as maplibregl.GeoJSONSource | undefined)?.setData({ type: "FeatureCollection", features: [], }); } function onKeyDown(e: KeyboardEvent) { if (e.key === "Enter") { finishDrawing(); } } map.on("click", onClick); map.on("mousemove", onMove); document.addEventListener("keydown", onKeyDown); return () => { map.off("click", onClick); map.off("mousemove", onMove); document.removeEventListener("keydown", onKeyDown); }; }