@sindicum/libre-draw 0.1.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.
Files changed (38) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +149 -0
  3. package/dist/LibreDraw.d.ts +359 -0
  4. package/dist/core/EventBus.d.ts +37 -0
  5. package/dist/core/FeatureStore.d.ts +68 -0
  6. package/dist/core/HistoryManager.d.ts +47 -0
  7. package/dist/core/ModeManager.d.ts +44 -0
  8. package/dist/core/errors.d.ts +6 -0
  9. package/dist/index.d.ts +7 -0
  10. package/dist/input/InputHandler.d.ts +29 -0
  11. package/dist/input/KeyboardInput.d.ts +31 -0
  12. package/dist/input/MouseInput.d.ts +41 -0
  13. package/dist/input/TouchInput.d.ts +58 -0
  14. package/dist/libre-draw.cjs +2 -0
  15. package/dist/libre-draw.cjs.map +1 -0
  16. package/dist/libre-draw.js +2116 -0
  17. package/dist/libre-draw.js.map +1 -0
  18. package/dist/modes/DrawMode.d.ts +70 -0
  19. package/dist/modes/IdleMode.d.ts +16 -0
  20. package/dist/modes/Mode.d.ts +26 -0
  21. package/dist/modes/SelectMode.d.ts +158 -0
  22. package/dist/rendering/RenderManager.d.ts +80 -0
  23. package/dist/rendering/SourceManager.d.ts +52 -0
  24. package/dist/types/events.d.ts +43 -0
  25. package/dist/types/features.d.ts +80 -0
  26. package/dist/types/index.d.ts +5 -0
  27. package/dist/types/input.d.ts +23 -0
  28. package/dist/types/options.d.ts +30 -0
  29. package/dist/ui/Toolbar.d.ts +59 -0
  30. package/dist/ui/ToolbarButton.d.ts +53 -0
  31. package/dist/ui/icons/delete.d.ts +4 -0
  32. package/dist/ui/icons/draw.d.ts +4 -0
  33. package/dist/ui/icons/redo.d.ts +4 -0
  34. package/dist/ui/icons/select.d.ts +4 -0
  35. package/dist/ui/icons/undo.d.ts +4 -0
  36. package/dist/validation/geojson.d.ts +20 -0
  37. package/dist/validation/intersection.d.ts +28 -0
  38. package/package.json +76 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"libre-draw.js","sources":["../src/types/features.ts","../src/core/EventBus.ts","../src/core/FeatureStore.ts","../src/core/HistoryManager.ts","../src/core/ModeManager.ts","../src/core/errors.ts","../src/validation/intersection.ts","../src/validation/geojson.ts","../src/modes/IdleMode.ts","../src/modes/DrawMode.ts","../node_modules/robust-predicates/esm/util.js","../node_modules/robust-predicates/esm/orient2d.js","../node_modules/point-in-polygon-hao/dist/esm/index.js","../node_modules/@turf/helpers/dist/esm/index.js","../node_modules/@turf/invariant/dist/esm/index.js","../node_modules/@turf/boolean-point-in-polygon/dist/esm/index.js","../src/modes/SelectMode.ts","../src/input/MouseInput.ts","../src/input/TouchInput.ts","../src/input/KeyboardInput.ts","../src/input/InputHandler.ts","../src/rendering/SourceManager.ts","../src/rendering/RenderManager.ts","../src/ui/ToolbarButton.ts","../src/ui/icons/draw.ts","../src/ui/icons/select.ts","../src/ui/icons/delete.ts","../src/ui/icons/undo.ts","../src/ui/icons/redo.ts","../src/ui/Toolbar.ts","../src/LibreDraw.ts"],"sourcesContent":["/**\n * A geographic coordinate pair [longitude, latitude].\n */\nexport type Position = [number, number];\n\n/**\n * GeoJSON Polygon geometry.\n */\nexport interface PolygonGeometry {\n type: 'Polygon';\n coordinates: Position[][];\n}\n\n/**\n * Arbitrary key-value properties attached to a feature.\n */\nexport interface FeatureProperties {\n [key: string]: unknown;\n}\n\n/**\n * A GeoJSON Feature with Polygon geometry used internally by LibreDraw.\n */\nexport interface LibreDrawFeature {\n id: string;\n type: 'Feature';\n geometry: PolygonGeometry;\n properties: FeatureProperties;\n}\n\n/**\n * The type of history action.\n */\nexport type ActionType = 'create' | 'update' | 'delete';\n\n/**\n * A reversible action that can be applied and reverted on a FeatureStore.\n */\nexport interface Action {\n type: ActionType;\n apply(store: FeatureStoreInterface): void;\n revert(store: FeatureStoreInterface): void;\n}\n\n/**\n * Minimal interface for the FeatureStore used by actions.\n * This avoids circular imports between types and core modules.\n */\nexport interface FeatureStoreInterface {\n add(feature: LibreDrawFeature): void;\n update(id: string, feature: LibreDrawFeature): void;\n remove(id: string): void;\n getById(id: string): LibreDrawFeature | undefined;\n}\n\n/**\n * Action that represents the creation of a new feature.\n */\nexport class CreateAction implements Action {\n public readonly type: ActionType = 'create';\n\n constructor(public readonly feature: LibreDrawFeature) {}\n\n apply(store: FeatureStoreInterface): void {\n store.add(this.feature);\n }\n\n revert(store: FeatureStoreInterface): void {\n store.remove(this.feature.id);\n }\n}\n\n/**\n * Action that represents the update of an existing feature.\n */\nexport class UpdateAction implements Action {\n public readonly type: ActionType = 'update';\n\n constructor(\n public readonly id: string,\n public readonly oldFeature: LibreDrawFeature,\n public readonly newFeature: LibreDrawFeature,\n ) {}\n\n apply(store: FeatureStoreInterface): void {\n store.update(this.id, this.newFeature);\n }\n\n revert(store: FeatureStoreInterface): void {\n store.update(this.id, this.oldFeature);\n }\n}\n\n/**\n * Action that represents the deletion of a feature.\n */\nexport class DeleteAction implements Action {\n public readonly type: ActionType = 'delete';\n\n constructor(public readonly feature: LibreDrawFeature) {}\n\n apply(store: FeatureStoreInterface): void {\n store.remove(this.feature.id);\n }\n\n revert(store: FeatureStoreInterface): void {\n store.add(this.feature);\n }\n}\n","import type { LibreDrawEventMap } from '../types/events';\n\n/**\n * A listener callback for a given event type.\n */\ntype Listener<T> = (payload: T) => void;\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AnyListener = Listener<any>;\n\n/**\n * Type-safe event bus for LibreDraw events.\n *\n * Supports registering, removing, and emitting events\n * defined in LibreDrawEventMap.\n */\nexport class EventBus {\n private listeners: Map<string, Set<AnyListener>> = new Map();\n\n /**\n * Register a listener for a specific event type.\n * @param type - The event type to listen for.\n * @param listener - The callback to invoke when the event fires.\n */\n on<K extends keyof LibreDrawEventMap>(\n type: K,\n listener: Listener<LibreDrawEventMap[K]>,\n ): void {\n let set = this.listeners.get(type as string);\n if (!set) {\n set = new Set();\n this.listeners.set(type as string, set);\n }\n set.add(listener as AnyListener);\n }\n\n /**\n * Remove a listener for a specific event type.\n * @param type - The event type to stop listening for.\n * @param listener - The callback to remove.\n */\n off<K extends keyof LibreDrawEventMap>(\n type: K,\n listener: Listener<LibreDrawEventMap[K]>,\n ): void {\n const set = this.listeners.get(type as string);\n if (set) {\n set.delete(listener as AnyListener);\n }\n }\n\n /**\n * Emit an event, invoking all registered listeners.\n * @param type - The event type to emit.\n * @param payload - The event payload.\n */\n emit<K extends keyof LibreDrawEventMap>(\n type: K,\n payload: LibreDrawEventMap[K],\n ): void {\n const set = this.listeners.get(type as string);\n if (set) {\n for (const listener of set) {\n listener(payload);\n }\n }\n }\n\n /**\n * Remove all listeners for all event types.\n */\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import type {\n LibreDrawFeature,\n Position,\n FeatureStoreInterface,\n} from '../types/features';\n\n/**\n * A GeoJSON FeatureCollection containing LibreDraw polygons.\n */\nexport interface FeatureCollection {\n type: 'FeatureCollection';\n features: LibreDrawFeature[];\n}\n\n/**\n * Internal store for managing LibreDraw features.\n *\n * Features are stored in a Map keyed by their unique ID.\n * Implements FeatureStoreInterface so that Action objects\n * can manipulate the store.\n */\nexport class FeatureStore implements FeatureStoreInterface {\n private features: Map<string, LibreDrawFeature> = new Map();\n\n /**\n * Add a feature to the store. If the feature has no ID,\n * a new UUID will be generated.\n * @param feature - The feature to add.\n * @returns The added feature (with ID assigned).\n */\n add(feature: LibreDrawFeature): LibreDrawFeature {\n const id = feature.id || crypto.randomUUID();\n const stored: LibreDrawFeature = { ...feature, id };\n this.features.set(id, stored);\n return stored;\n }\n\n /**\n * Update a feature in the store by ID.\n * @param id - The ID of the feature to update.\n * @param feature - The new feature data.\n */\n update(id: string, feature: LibreDrawFeature): void {\n if (!this.features.has(id)) {\n return;\n }\n this.features.set(id, { ...feature, id });\n }\n\n /**\n * Remove a feature from the store by ID.\n * @param id - The ID of the feature to remove.\n * @returns The removed feature, or undefined if not found.\n */\n remove(id: string): LibreDrawFeature | undefined {\n const feature = this.features.get(id);\n if (feature) {\n this.features.delete(id);\n }\n return feature;\n }\n\n /**\n * Get all features in the store.\n * @returns An array of all features.\n */\n getAll(): LibreDrawFeature[] {\n return Array.from(this.features.values());\n }\n\n /**\n * Get a feature by its ID.\n * @param id - The feature ID.\n * @returns The feature, or undefined if not found.\n */\n getById(id: string): LibreDrawFeature | undefined {\n return this.features.get(id);\n }\n\n /**\n * Remove all features from the store.\n */\n clear(): void {\n this.features.clear();\n }\n\n /**\n * Replace all features in the store with the given array.\n * @param features - The features to set.\n */\n setAll(features: LibreDrawFeature[]): void {\n this.features.clear();\n for (const feature of features) {\n const id = feature.id || crypto.randomUUID();\n this.features.set(id, { ...feature, id });\n }\n }\n\n /**\n * Export all features as a GeoJSON FeatureCollection.\n * @returns A GeoJSON FeatureCollection.\n */\n toGeoJSON(): FeatureCollection {\n return {\n type: 'FeatureCollection',\n features: this.getAll(),\n };\n }\n\n /**\n * Create a deep clone of a feature suitable for history snapshots.\n * @param feature - The feature to clone.\n * @returns A deep-cloned feature.\n */\n static cloneFeature(feature: LibreDrawFeature): LibreDrawFeature {\n return {\n id: feature.id,\n type: 'Feature',\n geometry: {\n type: 'Polygon',\n coordinates: feature.geometry.coordinates.map(\n (ring) => ring.map((pos) => [...pos] as Position),\n ),\n },\n properties: { ...feature.properties },\n };\n }\n}\n","import type { Action, FeatureStoreInterface } from '../types/features';\n\n/**\n * Manages undo/redo history using an action-based stack.\n *\n * Each action knows how to apply and revert itself on the feature store.\n * A configurable limit prevents unbounded memory growth.\n */\nexport class HistoryManager {\n private undoStack: Action[] = [];\n private redoStack: Action[] = [];\n private readonly limit: number;\n\n /**\n * Create a new HistoryManager.\n * @param limit - Maximum number of actions to retain. Defaults to 100.\n */\n constructor(limit: number = 100) {\n this.limit = limit;\n }\n\n /**\n * Push a new action onto the history stack.\n * Clears the redo stack since a new action invalidates any redo history.\n * @param action - The action to record.\n */\n push(action: Action): void {\n this.undoStack.push(action);\n this.redoStack = [];\n if (this.undoStack.length > this.limit) {\n this.undoStack.shift();\n }\n }\n\n /**\n * Undo the most recent action.\n * @param store - The feature store to revert the action on.\n * @returns True if an action was undone, false if the stack was empty.\n */\n undo(store: FeatureStoreInterface): boolean {\n const action = this.undoStack.pop();\n if (!action) {\n return false;\n }\n action.revert(store);\n this.redoStack.push(action);\n return true;\n }\n\n /**\n * Redo the most recently undone action.\n * @param store - The feature store to re-apply the action on.\n * @returns True if an action was redone, false if the stack was empty.\n */\n redo(store: FeatureStoreInterface): boolean {\n const action = this.redoStack.pop();\n if (!action) {\n return false;\n }\n action.apply(store);\n this.undoStack.push(action);\n return true;\n }\n\n /**\n * Whether there are actions that can be undone.\n */\n canUndo(): boolean {\n return this.undoStack.length > 0;\n }\n\n /**\n * Whether there are actions that can be redone.\n */\n canRedo(): boolean {\n return this.redoStack.length > 0;\n }\n\n /**\n * Clear all history.\n */\n clear(): void {\n this.undoStack = [];\n this.redoStack = [];\n }\n}\n","import type { Mode } from '../modes/Mode';\n\n/**\n * The available drawing modes.\n */\nexport type ModeName = 'idle' | 'draw' | 'select';\n\n/**\n * Manages the active drawing mode and handles transitions between modes.\n *\n * When switching modes, the current mode is deactivated and the new mode\n * is activated. A callback is invoked on mode changes so the LibreDraw\n * facade can emit the appropriate event.\n */\nexport class ModeManager {\n private modes: Map<ModeName, Mode> = new Map();\n private currentModeName: ModeName = 'idle';\n private onModeChange?: (mode: ModeName, previousMode: ModeName) => void;\n\n /**\n * Register a mode implementation.\n * @param name - The mode name.\n * @param mode - The mode implementation.\n */\n registerMode(name: ModeName, mode: Mode): void {\n this.modes.set(name, mode);\n }\n\n /**\n * Set a callback to be invoked on mode changes.\n * @param callback - The callback receiving (newMode, previousMode).\n */\n setOnModeChange(\n callback: (mode: ModeName, previousMode: ModeName) => void,\n ): void {\n this.onModeChange = callback;\n }\n\n /**\n * Switch to a new mode.\n * Deactivates the current mode and activates the new one.\n * @param name - The mode to switch to.\n */\n setMode(name: ModeName): void {\n if (name === this.currentModeName) {\n return;\n }\n\n const previousMode = this.currentModeName;\n const current = this.modes.get(this.currentModeName);\n if (current) {\n current.deactivate();\n }\n\n this.currentModeName = name;\n const next = this.modes.get(name);\n if (next) {\n next.activate();\n }\n\n if (this.onModeChange) {\n this.onModeChange(name, previousMode);\n }\n }\n\n /**\n * Get the current mode name.\n * @returns The active mode name.\n */\n getMode(): ModeName {\n return this.currentModeName;\n }\n\n /**\n * Get the current mode implementation.\n * @returns The active Mode object, or undefined.\n */\n getCurrentMode(): Mode | undefined {\n return this.modes.get(this.currentModeName);\n }\n}\n","/**\n * Base error class for all LibreDraw errors.\n */\nexport class LibreDrawError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'LibreDrawError';\n }\n}\n","import type { Position } from '../types/features';\n\n/**\n * Compute the orientation of triplet (p, q, r).\n * @returns 0 if collinear, 1 if clockwise, 2 if counter-clockwise.\n */\nfunction orientation(p: Position, q: Position, r: Position): number {\n const val = (q[1] - p[1]) * (r[0] - q[0]) - (q[0] - p[0]) * (r[1] - q[1]);\n if (Math.abs(val) < 1e-10) return 0; // collinear\n return val > 0 ? 1 : 2;\n}\n\n/**\n * Check if point q lies on segment pr, given that p, q, r are collinear.\n */\nfunction onSegment(p: Position, q: Position, r: Position): boolean {\n return (\n q[0] <= Math.max(p[0], r[0]) &&\n q[0] >= Math.min(p[0], r[0]) &&\n q[1] <= Math.max(p[1], r[1]) &&\n q[1] >= Math.min(p[1], r[1])\n );\n}\n\n/**\n * Check if two positions are approximately equal.\n */\nfunction posEqual(a: Position, b: Position): boolean {\n return Math.abs(a[0] - b[0]) < 1e-10 && Math.abs(a[1] - b[1]) < 1e-10;\n}\n\n/**\n * Check if two line segments (p1-p2) and (p3-p4) truly intersect.\n * Segments that share an endpoint are NOT considered intersecting.\n */\nexport function segmentsIntersect(\n p1: Position,\n p2: Position,\n p3: Position,\n p4: Position,\n): boolean {\n // Skip if segments share an endpoint\n if (posEqual(p1, p3) || posEqual(p1, p4) || posEqual(p2, p3) || posEqual(p2, p4)) {\n return false;\n }\n\n const o1 = orientation(p1, p2, p3);\n const o2 = orientation(p1, p2, p4);\n const o3 = orientation(p3, p4, p1);\n const o4 = orientation(p3, p4, p2);\n\n // General case: segments straddle each other\n if (o1 !== o2 && o3 !== o4) {\n return true;\n }\n\n // Collinear special cases: check if points lie on segment\n if (o1 === 0 && onSegment(p1, p3, p2)) return true;\n if (o2 === 0 && onSegment(p1, p4, p2)) return true;\n if (o3 === 0 && onSegment(p3, p1, p4)) return true;\n if (o4 === 0 && onSegment(p3, p2, p4)) return true;\n\n return false;\n}\n\n/**\n * Check if a closed polygon ring has any self-intersections.\n * The ring should include the closing point (first === last).\n * @param ring - The polygon ring coordinates.\n * @returns True if the ring has self-intersections.\n */\nexport function hasRingSelfIntersection(ring: Position[]): boolean {\n const n = ring.length - 1; // number of edges (exclude closing point)\n if (n < 3) return false;\n\n for (let i = 0; i < n; i++) {\n for (let j = i + 2; j < n; j++) {\n // Skip adjacent edges that share a vertex (first and last edge are adjacent)\n if (i === 0 && j === n - 1) continue;\n\n if (segmentsIntersect(ring[i], ring[i + 1], ring[j], ring[j + 1])) {\n return true;\n }\n }\n }\n\n return false;\n}\n\n/**\n * Check if adding a new vertex to the current drawing vertices would cause\n * the new edge to intersect any existing edge.\n * @param vertices - Current vertices (NOT closed, no closing point).\n * @param newVertex - The vertex to add.\n * @returns True if adding the vertex would cause an intersection.\n */\nexport function wouldNewVertexCauseIntersection(\n vertices: Position[],\n newVertex: Position,\n): boolean {\n // Need at least 2 existing vertices to have an edge to check against\n if (vertices.length < 2) return false;\n\n const lastVertex = vertices[vertices.length - 1];\n\n // Check new edge (lastVertex → newVertex) against all existing edges\n // except the last edge (which shares lastVertex)\n for (let i = 0; i < vertices.length - 2; i++) {\n if (segmentsIntersect(lastVertex, newVertex, vertices[i], vertices[i + 1])) {\n return true;\n }\n }\n\n return false;\n}\n\n/**\n * Check if closing the polygon (connecting last vertex to first) would cause\n * the closing edge to intersect any existing edge.\n * @param vertices - Current vertices (NOT closed, no closing point).\n * @returns True if closing would cause an intersection.\n */\nexport function wouldClosingCauseIntersection(vertices: Position[]): boolean {\n // Need at least 3 vertices to form a polygon\n if (vertices.length < 3) return false;\n\n const first = vertices[0];\n const last = vertices[vertices.length - 1];\n\n // Check closing edge (last → first) against all edges except\n // the first edge (shares first vertex) and the last edge (shares last vertex)\n for (let i = 1; i < vertices.length - 2; i++) {\n if (segmentsIntersect(last, first, vertices[i], vertices[i + 1])) {\n return true;\n }\n }\n\n return false;\n}\n","import type { LibreDrawFeature, Position } from '../types/features';\nimport { LibreDrawError } from '../core/errors';\nimport { hasRingSelfIntersection } from './intersection';\n\n/**\n * A GeoJSON FeatureCollection type for validation purposes.\n */\ninterface FeatureCollectionLike {\n type: 'FeatureCollection';\n features: unknown[];\n}\n\n/**\n * Check if two positions are equal.\n */\nfunction positionsEqual(a: Position, b: Position): boolean {\n return a[0] === b[0] && a[1] === b[1];\n}\n\n/**\n * Validate that a coordinate is within valid geographic bounds.\n * @param position - The coordinate to validate.\n */\nfunction validateCoordinate(position: Position): void {\n const [lng, lat] = position;\n if (typeof lng !== 'number' || typeof lat !== 'number') {\n throw new LibreDrawError(\n `Invalid coordinate: expected [number, number], got [${typeof lng}, ${typeof lat}]`,\n );\n }\n if (lng < -180 || lng > 180) {\n throw new LibreDrawError(\n `Invalid longitude: ${lng}. Must be between -180 and 180.`,\n );\n }\n if (lat < -90 || lat > 90) {\n throw new LibreDrawError(\n `Invalid latitude: ${lat}. Must be between -90 and 90.`,\n );\n }\n}\n\n/**\n * Validate that a ring (array of positions) is a valid linear ring.\n * A valid ring must have at least 4 positions and be closed\n * (first position equals last position).\n * @param ring - The ring to validate.\n */\nfunction validateRing(ring: Position[]): void {\n if (!Array.isArray(ring)) {\n throw new LibreDrawError('Ring must be an array of positions.');\n }\n if (ring.length < 4) {\n throw new LibreDrawError(\n `Ring must have at least 4 positions (got ${ring.length}). A valid polygon ring requires 3 unique vertices plus a closing vertex.`,\n );\n }\n\n const first = ring[0];\n const last = ring[ring.length - 1];\n if (!positionsEqual(first, last)) {\n throw new LibreDrawError(\n 'Ring is not closed. The first and last positions must be identical.',\n );\n }\n\n for (const pos of ring) {\n if (!Array.isArray(pos) || pos.length < 2) {\n throw new LibreDrawError(\n 'Each position in a ring must be an array of at least 2 numbers.',\n );\n }\n validateCoordinate(pos as Position);\n }\n\n if (hasRingSelfIntersection(ring as Position[])) {\n throw new LibreDrawError(\n 'Ring has self-intersections. Polygon edges must not cross each other.',\n );\n }\n}\n\n/**\n * Validate a single GeoJSON-like object as a valid LibreDraw Feature\n * with Polygon geometry.\n * @param feature - The object to validate.\n * @returns The validated feature.\n * @throws LibreDrawError if the feature is invalid.\n */\nexport function validateFeature(feature: unknown): LibreDrawFeature {\n if (\n feature === null ||\n feature === undefined ||\n typeof feature !== 'object'\n ) {\n throw new LibreDrawError('Feature must be a non-null object.');\n }\n\n const f = feature as Record<string, unknown>;\n\n if (f.type !== 'Feature') {\n throw new LibreDrawError(\n `Feature.type must be \"Feature\", got \"${String(f.type)}\".`,\n );\n }\n\n if (\n f.geometry === null ||\n f.geometry === undefined ||\n typeof f.geometry !== 'object'\n ) {\n throw new LibreDrawError('Feature.geometry must be a non-null object.');\n }\n\n const geom = f.geometry as Record<string, unknown>;\n\n if (geom.type !== 'Polygon') {\n throw new LibreDrawError(\n `Feature.geometry.type must be \"Polygon\", got \"${String(geom.type)}\".`,\n );\n }\n\n if (!Array.isArray(geom.coordinates)) {\n throw new LibreDrawError(\n 'Feature.geometry.coordinates must be an array.',\n );\n }\n\n const coordinates = geom.coordinates as Position[][];\n if (coordinates.length === 0) {\n throw new LibreDrawError(\n 'Polygon must have at least one ring (outer ring).',\n );\n }\n\n for (const ring of coordinates) {\n validateRing(ring);\n }\n\n return feature as LibreDrawFeature;\n}\n\n/**\n * Validate that an unknown value is a valid GeoJSON FeatureCollection\n * containing only valid Polygon features.\n * @param geojson - The value to validate.\n * @returns The validated FeatureCollection.\n * @throws LibreDrawError if the value is invalid.\n */\nexport function validateGeoJSON(geojson: unknown): {\n type: 'FeatureCollection';\n features: LibreDrawFeature[];\n} {\n if (\n geojson === null ||\n geojson === undefined ||\n typeof geojson !== 'object'\n ) {\n throw new LibreDrawError('GeoJSON must be a non-null object.');\n }\n\n const obj = geojson as Record<string, unknown>;\n\n if (obj.type !== 'FeatureCollection') {\n throw new LibreDrawError(\n `GeoJSON.type must be \"FeatureCollection\", got \"${String(obj.type)}\".`,\n );\n }\n\n if (!Array.isArray(obj.features)) {\n throw new LibreDrawError('GeoJSON.features must be an array.');\n }\n\n const fc = geojson as FeatureCollectionLike;\n const validatedFeatures: LibreDrawFeature[] = [];\n\n for (let i = 0; i < fc.features.length; i++) {\n try {\n validatedFeatures.push(validateFeature(fc.features[i]));\n } catch (err) {\n if (err instanceof LibreDrawError) {\n throw new LibreDrawError(\n `Invalid feature at index ${i}: ${err.message}`,\n );\n }\n throw err;\n }\n }\n\n return {\n type: 'FeatureCollection',\n features: validatedFeatures,\n };\n}\n","import type { Mode } from './Mode';\nimport type { NormalizedInputEvent } from '../types/input';\n\n/**\n * The idle mode where no drawing or editing is active.\n * All input handlers are no-ops.\n */\nexport class IdleMode implements Mode {\n activate(): void {\n // No-op\n }\n\n deactivate(): void {\n // No-op\n }\n\n onPointerDown(_event: NormalizedInputEvent): void {\n // No-op\n }\n\n onPointerMove(_event: NormalizedInputEvent): void {\n // No-op\n }\n\n onPointerUp(_event: NormalizedInputEvent): void {\n // No-op\n }\n\n onDoubleClick(_event: NormalizedInputEvent): void {\n // No-op\n }\n\n onLongPress(_event: NormalizedInputEvent): void {\n // No-op\n }\n\n onKeyDown(_key: string, _event: KeyboardEvent): void {\n // No-op\n }\n}\n","import type { Mode } from './Mode';\nimport type { NormalizedInputEvent } from '../types/input';\nimport type {\n LibreDrawFeature,\n Position,\n Action,\n} from '../types/features';\nimport type { LibreDrawEventMap } from '../types/events';\nimport { CreateAction } from '../types/features';\nimport {\n wouldNewVertexCauseIntersection,\n wouldClosingCauseIntersection,\n} from '../validation/intersection';\n\n/**\n * Threshold in pixels: if a click is within this distance of the first\n * vertex, the polygon is automatically closed.\n */\nconst CLOSE_THRESHOLD_PX = 10;\n\n/**\n * Minimum number of unique vertices required to form a valid polygon.\n */\nconst MIN_VERTICES = 3;\n\n/**\n * Callbacks that DrawMode needs from the host application.\n */\nexport interface DrawModeCallbacks {\n /** Add a feature to the store and return it with its assigned ID. */\n addFeatureToStore(feature: LibreDrawFeature): LibreDrawFeature;\n /** Push an action to the history manager. */\n pushToHistory(action: Action): void;\n /** Emit an event through the event bus. */\n emitEvent<K extends keyof LibreDrawEventMap>(\n type: K,\n payload: LibreDrawEventMap[K],\n ): void;\n /** Render a preview of the polygon being drawn. */\n renderPreview(coordinates: Position[]): void;\n /** Clear the drawing preview. */\n clearPreview(): void;\n /** Re-render all features. */\n renderFeatures(): void;\n /** Convert a geographic coordinate to a screen point. */\n getScreenPoint(lngLat: { lng: number; lat: number }): { x: number; y: number };\n}\n\n/**\n * Drawing mode for creating new polygons.\n *\n * Users click to add vertices. The polygon is finalized when:\n * - The user double-clicks (with at least 3 vertices), or\n * - The user clicks within 10px of the first vertex (closing the ring).\n *\n * Long press removes the last vertex (undo last point).\n * Escape cancels the entire drawing.\n */\nexport class DrawMode implements Mode {\n private vertices: Position[] = [];\n private isActive = false;\n private callbacks: DrawModeCallbacks;\n\n constructor(callbacks: DrawModeCallbacks) {\n this.callbacks = callbacks;\n }\n\n activate(): void {\n this.isActive = true;\n this.vertices = [];\n }\n\n deactivate(): void {\n this.isActive = false;\n this.vertices = [];\n this.callbacks.clearPreview();\n }\n\n onPointerDown(event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n const newVertex: Position = [event.lngLat.lng, event.lngLat.lat];\n\n // Check if this click is close to the first vertex (closing the polygon)\n if (this.vertices.length >= MIN_VERTICES) {\n const firstVertex = this.vertices[0];\n const firstScreenPt = this.callbacks.getScreenPoint({\n lng: firstVertex[0],\n lat: firstVertex[1],\n });\n const dx = event.point.x - firstScreenPt.x;\n const dy = event.point.y - firstScreenPt.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n if (dist <= CLOSE_THRESHOLD_PX) {\n // Reject closing if it would cause self-intersection\n if (wouldClosingCauseIntersection(this.vertices)) return;\n this.finalizePolygon();\n return;\n }\n }\n\n // Reject vertex if it would cause self-intersection\n if (wouldNewVertexCauseIntersection(this.vertices, newVertex)) return;\n\n this.vertices.push(newVertex);\n this.updatePreview(event);\n }\n\n onPointerMove(event: NormalizedInputEvent): void {\n if (!this.isActive || this.vertices.length === 0) return;\n this.updatePreview(event);\n }\n\n onPointerUp(_event: NormalizedInputEvent): void {\n // No-op for draw mode; action happens on pointer down\n }\n\n onDoubleClick(event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n // Remove the last vertex added by the double-click's second pointerdown\n // (it would have been added in onPointerDown before onDoubleClick fires)\n if (this.vertices.length > MIN_VERTICES) {\n this.vertices.pop();\n }\n\n if (this.vertices.length >= MIN_VERTICES) {\n // Reject closing if it would cause self-intersection\n if (!wouldClosingCauseIntersection(this.vertices)) {\n this.finalizePolygon();\n }\n }\n\n // Prevent the double click from being handled by the map\n event.originalEvent.preventDefault();\n event.originalEvent.stopPropagation();\n }\n\n onLongPress(_event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n // Remove the last vertex (undo last point)\n if (this.vertices.length > 0) {\n this.vertices.pop();\n if (this.vertices.length === 0) {\n this.callbacks.clearPreview();\n } else {\n this.callbacks.renderPreview(this.buildPreviewCoordinates());\n }\n }\n }\n\n onKeyDown(key: string, _event: KeyboardEvent): void {\n if (!this.isActive) return;\n\n if (key === 'Escape') {\n this.cancelDrawing();\n }\n }\n\n /**\n * Build the preview coordinate ring for rendering,\n * including cursor position if available.\n */\n private buildPreviewCoordinates(\n cursorPos?: Position,\n ): Position[] {\n const coords = [...this.vertices];\n if (cursorPos) {\n coords.push(cursorPos);\n }\n // Close the ring for preview\n if (coords.length > 0) {\n coords.push([...coords[0]] as Position);\n }\n return coords;\n }\n\n /**\n * Update the preview rendering with the current cursor position.\n */\n private updatePreview(event: NormalizedInputEvent): void {\n const cursorPos: Position = [event.lngLat.lng, event.lngLat.lat];\n const previewCoords = this.buildPreviewCoordinates(cursorPos);\n this.callbacks.renderPreview(previewCoords);\n }\n\n /**\n * Finalize the polygon: create the feature, push to history, emit event.\n */\n private finalizePolygon(): void {\n if (this.vertices.length < MIN_VERTICES) return;\n\n // Close the ring\n const ring: Position[] = [\n ...this.vertices,\n [...this.vertices[0]] as Position,\n ];\n\n const feature: LibreDrawFeature = {\n id: crypto.randomUUID(),\n type: 'Feature',\n geometry: {\n type: 'Polygon',\n coordinates: [ring],\n },\n properties: {},\n };\n\n const stored = this.callbacks.addFeatureToStore(feature);\n const action = new CreateAction(stored);\n this.callbacks.pushToHistory(action);\n this.callbacks.emitEvent('create', { feature: stored });\n this.callbacks.renderFeatures();\n\n // Reset state for next drawing\n this.vertices = [];\n this.callbacks.clearPreview();\n }\n\n /**\n * Cancel the current drawing operation.\n */\n private cancelDrawing(): void {\n this.vertices = [];\n this.callbacks.clearPreview();\n }\n}\n","export const epsilon = 1.1102230246251565e-16;\nexport const splitter = 134217729;\nexport const resulterrbound = (3 + 8 * epsilon) * epsilon;\n\n// fast_expansion_sum_zeroelim routine from oritinal code\nexport function sum(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if ((fnow > enow) === (fnow > -enow)) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if ((fnow > enow) === (fnow > -enow)) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function sum_three(alen, a, blen, b, clen, c, tmp, out) {\n return sum(sum(alen, a, blen, b, tmp), tmp, clen, c, out);\n}\n\n// scale_expansion_zeroelim routine from oritinal code\nexport function scale(elen, e, b, h) {\n let Q, sum, hh, product1, product0;\n let bvirt, c, ahi, alo, bhi, blo;\n\n c = splitter * b;\n bhi = c - (c - b);\n blo = b - bhi;\n let enow = e[0];\n Q = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n hh = alo * blo - (Q - ahi * bhi - alo * bhi - ahi * blo);\n let hindex = 0;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n for (let i = 1; i < elen; i++) {\n enow = e[i];\n product1 = enow * b;\n c = splitter * enow;\n ahi = c - (c - enow);\n alo = enow - ahi;\n product0 = alo * blo - (product1 - ahi * bhi - alo * bhi - ahi * blo);\n sum = Q + product0;\n bvirt = sum - Q;\n hh = Q - (sum - bvirt) + (product0 - bvirt);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n Q = product1 + sum;\n hh = sum - (Q - product1);\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\n\nexport function negate(elen, e) {\n for (let i = 0; i < elen; i++) e[i] = -e[i];\n return elen;\n}\n\nexport function estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\n\nexport function vec(n) {\n return new Float64Array(n);\n}\n","import {epsilon, splitter, resulterrbound, estimate, vec, sum} from './util.js';\n\nconst ccwerrboundA = (3 + 16 * epsilon) * epsilon;\nconst ccwerrboundB = (2 + 12 * epsilon) * epsilon;\nconst ccwerrboundC = (9 + 64 * epsilon) * epsilon * epsilon;\n\nconst B = vec(4);\nconst C1 = vec(8);\nconst C2 = vec(12);\nconst D = vec(16);\nconst u = vec(4);\n\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t1, t0, u3;\n\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n\n s1 = acx * bcy;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcx;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n B[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n B[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n B[2] = _j - (u3 - bvirt) + (_i - bvirt);\n B[3] = u3;\n\n let det = estimate(4, B);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += (acx * bcytail + bcy * acxtail) - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n\n s1 = acxtail * bcy;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcy;\n bhi = c - (c - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcx;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcx;\n bhi = c - (c - bcx);\n blo = bcx - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C1len = sum(4, B, 4, u, C1);\n\n s1 = acx * bcytail;\n c = splitter * acx;\n ahi = c - (c - acx);\n alo = acx - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acy * bcxtail;\n c = splitter * acy;\n ahi = c - (c - acy);\n alo = acy - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const C2len = sum(C1len, C1, 4, u, C2);\n\n s1 = acxtail * bcytail;\n c = splitter * acxtail;\n ahi = c - (c - acxtail);\n alo = acxtail - ahi;\n c = splitter * bcytail;\n bhi = c - (c - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t1 = acytail * bcxtail;\n c = splitter * acytail;\n ahi = c - (c - acytail);\n alo = acytail - ahi;\n c = splitter * bcxtail;\n bhi = c - (c - bcxtail);\n blo = bcxtail - bhi;\n t0 = alo * blo - (t1 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t0;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t0);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t1;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t1);\n u3 = _j + _i;\n bvirt = u3 - _j;\n u[2] = _j - (u3 - bvirt) + (_i - bvirt);\n u[3] = u3;\n const Dlen = sum(C2len, C2, 4, u, D);\n\n return D[Dlen - 1];\n}\n\nexport function orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\nexport function orient2dfast(ax, ay, bx, by, cx, cy) {\n return (ay - cy) * (bx - cx) - (ax - cx) * (by - cy);\n}\n","import { orient2d } from 'robust-predicates';\n\nfunction pointInPolygon(p, polygon) {\n var i;\n var ii;\n var k = 0;\n var f;\n var u1;\n var v1;\n var u2;\n var v2;\n var currentP;\n var nextP;\n\n var x = p[0];\n var y = p[1];\n\n var numContours = polygon.length;\n for (i = 0; i < numContours; i++) {\n ii = 0;\n var contour = polygon[i];\n var contourLen = contour.length - 1;\n\n currentP = contour[0];\n if (currentP[0] !== contour[contourLen][0] &&\n currentP[1] !== contour[contourLen][1]) {\n throw new Error('First and last coordinates in a ring must be the same')\n }\n\n u1 = currentP[0] - x;\n v1 = currentP[1] - y;\n\n for (ii; ii < contourLen; ii++) {\n nextP = contour[ii + 1];\n\n u2 = nextP[0] - x;\n v2 = nextP[1] - y;\n\n if (v1 === 0 && v2 === 0) {\n if ((u2 <= 0 && u1 >= 0) || (u1 <= 0 && u2 >= 0)) { return 0 }\n } else if ((v2 >= 0 && v1 <= 0) || (v2 <= 0 && v1 >= 0)) {\n f = orient2d(u1, u2, v1, v2, 0, 0);\n if (f === 0) { return 0 }\n if ((f > 0 && v2 > 0 && v1 <= 0) || (f < 0 && v2 <= 0 && v1 > 0)) { k++; }\n }\n currentP = nextP;\n v1 = v2;\n u1 = u2;\n }\n }\n\n if (k % 2 === 0) { return false }\n return true\n}\n\nexport { pointInPolygon as default };\n","// index.ts\nvar earthRadius = 63710088e-1;\nvar factors = {\n centimeters: earthRadius * 100,\n centimetres: earthRadius * 100,\n degrees: 360 / (2 * Math.PI),\n feet: earthRadius * 3.28084,\n inches: earthRadius * 39.37,\n kilometers: earthRadius / 1e3,\n kilometres: earthRadius / 1e3,\n meters: earthRadius,\n metres: earthRadius,\n miles: earthRadius / 1609.344,\n millimeters: earthRadius * 1e3,\n millimetres: earthRadius * 1e3,\n nauticalmiles: earthRadius / 1852,\n radians: 1,\n yards: earthRadius * 1.0936\n};\nvar areaFactors = {\n acres: 247105e-9,\n centimeters: 1e4,\n centimetres: 1e4,\n feet: 10.763910417,\n hectares: 1e-4,\n inches: 1550.003100006,\n kilometers: 1e-6,\n kilometres: 1e-6,\n meters: 1,\n metres: 1,\n miles: 386e-9,\n nauticalmiles: 29155334959812285e-23,\n millimeters: 1e6,\n millimetres: 1e6,\n yards: 1.195990046\n};\nfunction feature(geom, properties, options = {}) {\n const feat = { type: \"Feature\" };\n if (options.id === 0 || options.id) {\n feat.id = options.id;\n }\n if (options.bbox) {\n feat.bbox = options.bbox;\n }\n feat.properties = properties || {};\n feat.geometry = geom;\n return feat;\n}\nfunction geometry(type, coordinates, _options = {}) {\n switch (type) {\n case \"Point\":\n return point(coordinates).geometry;\n case \"LineString\":\n return lineString(coordinates).geometry;\n case \"Polygon\":\n return polygon(coordinates).geometry;\n case \"MultiPoint\":\n return multiPoint(coordinates).geometry;\n case \"MultiLineString\":\n return multiLineString(coordinates).geometry;\n case \"MultiPolygon\":\n return multiPolygon(coordinates).geometry;\n default:\n throw new Error(type + \" is invalid\");\n }\n}\nfunction point(coordinates, properties, options = {}) {\n if (!coordinates) {\n throw new Error(\"coordinates is required\");\n }\n if (!Array.isArray(coordinates)) {\n throw new Error(\"coordinates must be an Array\");\n }\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be at least 2 numbers long\");\n }\n if (!isNumber(coordinates[0]) || !isNumber(coordinates[1])) {\n throw new Error(\"coordinates must contain numbers\");\n }\n const geom = {\n type: \"Point\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction points(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return point(coords, properties);\n }),\n options\n );\n}\nfunction polygon(coordinates, properties, options = {}) {\n for (const ring of coordinates) {\n if (ring.length < 4) {\n throw new Error(\n \"Each LinearRing of a Polygon must have 4 or more Positions.\"\n );\n }\n if (ring[ring.length - 1].length !== ring[0].length) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n for (let j = 0; j < ring[ring.length - 1].length; j++) {\n if (ring[ring.length - 1][j] !== ring[0][j]) {\n throw new Error(\"First and last Position are not equivalent.\");\n }\n }\n }\n const geom = {\n type: \"Polygon\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction polygons(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return polygon(coords, properties);\n }),\n options\n );\n}\nfunction lineString(coordinates, properties, options = {}) {\n if (coordinates.length < 2) {\n throw new Error(\"coordinates must be an array of two or more positions\");\n }\n const geom = {\n type: \"LineString\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction lineStrings(coordinates, properties, options = {}) {\n return featureCollection(\n coordinates.map((coords) => {\n return lineString(coords, properties);\n }),\n options\n );\n}\nfunction featureCollection(features, options = {}) {\n const fc = { type: \"FeatureCollection\" };\n if (options.id) {\n fc.id = options.id;\n }\n if (options.bbox) {\n fc.bbox = options.bbox;\n }\n fc.features = features;\n return fc;\n}\nfunction multiLineString(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiLineString\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction multiPoint(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiPoint\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction multiPolygon(coordinates, properties, options = {}) {\n const geom = {\n type: \"MultiPolygon\",\n coordinates\n };\n return feature(geom, properties, options);\n}\nfunction geometryCollection(geometries, properties, options = {}) {\n const geom = {\n type: \"GeometryCollection\",\n geometries\n };\n return feature(geom, properties, options);\n}\nfunction round(num, precision = 0) {\n if (precision && !(precision >= 0)) {\n throw new Error(\"precision must be a positive number\");\n }\n const multiplier = Math.pow(10, precision || 0);\n return Math.round(num * multiplier) / multiplier;\n}\nfunction radiansToLength(radians, units = \"kilometers\") {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return radians * factor;\n}\nfunction lengthToRadians(distance, units = \"kilometers\") {\n const factor = factors[units];\n if (!factor) {\n throw new Error(units + \" units is invalid\");\n }\n return distance / factor;\n}\nfunction lengthToDegrees(distance, units) {\n return radiansToDegrees(lengthToRadians(distance, units));\n}\nfunction bearingToAzimuth(bearing) {\n let angle = bearing % 360;\n if (angle < 0) {\n angle += 360;\n }\n return angle;\n}\nfunction azimuthToBearing(angle) {\n angle = angle % 360;\n if (angle > 180) {\n return angle - 360;\n } else if (angle < -180) {\n return angle + 360;\n }\n return angle;\n}\nfunction radiansToDegrees(radians) {\n const normalisedRadians = radians % (2 * Math.PI);\n return normalisedRadians * 180 / Math.PI;\n}\nfunction degreesToRadians(degrees) {\n const normalisedDegrees = degrees % 360;\n return normalisedDegrees * Math.PI / 180;\n}\nfunction convertLength(length, originalUnit = \"kilometers\", finalUnit = \"kilometers\") {\n if (!(length >= 0)) {\n throw new Error(\"length must be a positive number\");\n }\n return radiansToLength(lengthToRadians(length, originalUnit), finalUnit);\n}\nfunction convertArea(area, originalUnit = \"meters\", finalUnit = \"kilometers\") {\n if (!(area >= 0)) {\n throw new Error(\"area must be a positive number\");\n }\n const startFactor = areaFactors[originalUnit];\n if (!startFactor) {\n throw new Error(\"invalid original units\");\n }\n const finalFactor = areaFactors[finalUnit];\n if (!finalFactor) {\n throw new Error(\"invalid final units\");\n }\n return area / startFactor * finalFactor;\n}\nfunction isNumber(num) {\n return !isNaN(num) && num !== null && !Array.isArray(num);\n}\nfunction isObject(input) {\n return input !== null && typeof input === \"object\" && !Array.isArray(input);\n}\nfunction validateBBox(bbox) {\n if (!bbox) {\n throw new Error(\"bbox is required\");\n }\n if (!Array.isArray(bbox)) {\n throw new Error(\"bbox must be an Array\");\n }\n if (bbox.length !== 4 && bbox.length !== 6) {\n throw new Error(\"bbox must be an Array of 4 or 6 numbers\");\n }\n bbox.forEach((num) => {\n if (!isNumber(num)) {\n throw new Error(\"bbox must only contain numbers\");\n }\n });\n}\nfunction validateId(id) {\n if (!id) {\n throw new Error(\"id is required\");\n }\n if ([\"string\", \"number\"].indexOf(typeof id) === -1) {\n throw new Error(\"id must be a number or a string\");\n }\n}\nexport {\n areaFactors,\n azimuthToBearing,\n bearingToAzimuth,\n convertArea,\n convertLength,\n degreesToRadians,\n earthRadius,\n factors,\n feature,\n featureCollection,\n geometry,\n geometryCollection,\n isNumber,\n isObject,\n lengthToDegrees,\n lengthToRadians,\n lineString,\n lineStrings,\n multiLineString,\n multiPoint,\n multiPolygon,\n point,\n points,\n polygon,\n polygons,\n radiansToDegrees,\n radiansToLength,\n round,\n validateBBox,\n validateId\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport { isNumber } from \"@turf/helpers\";\nfunction getCoord(coord) {\n if (!coord) {\n throw new Error(\"coord is required\");\n }\n if (!Array.isArray(coord)) {\n if (coord.type === \"Feature\" && coord.geometry !== null && coord.geometry.type === \"Point\") {\n return [...coord.geometry.coordinates];\n }\n if (coord.type === \"Point\") {\n return [...coord.coordinates];\n }\n }\n if (Array.isArray(coord) && coord.length >= 2 && !Array.isArray(coord[0]) && !Array.isArray(coord[1])) {\n return [...coord];\n }\n throw new Error(\"coord must be GeoJSON Point or an Array of numbers\");\n}\nfunction getCoords(coords) {\n if (Array.isArray(coords)) {\n return coords;\n }\n if (coords.type === \"Feature\") {\n if (coords.geometry !== null) {\n return coords.geometry.coordinates;\n }\n } else {\n if (coords.coordinates) {\n return coords.coordinates;\n }\n }\n throw new Error(\n \"coords must be GeoJSON Feature, Geometry Object or an Array\"\n );\n}\nfunction containsNumber(coordinates) {\n if (coordinates.length > 1 && isNumber(coordinates[0]) && isNumber(coordinates[1])) {\n return true;\n }\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error(\"coordinates must only contain numbers\");\n}\nfunction geojsonType(value, type, name) {\n if (!type || !name) {\n throw new Error(\"type and name required\");\n }\n if (!value || value.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + value.type\n );\n }\n}\nfunction featureOf(feature, type, name) {\n if (!feature) {\n throw new Error(\"No feature passed\");\n }\n if (!name) {\n throw new Error(\".featureOf() requires a name\");\n }\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\n \"Invalid input to \" + name + \", Feature with geometry required\"\n );\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + feature.geometry.type\n );\n }\n}\nfunction collectionOf(featureCollection, type, name) {\n if (!featureCollection) {\n throw new Error(\"No featureCollection passed\");\n }\n if (!name) {\n throw new Error(\".collectionOf() requires a name\");\n }\n if (!featureCollection || featureCollection.type !== \"FeatureCollection\") {\n throw new Error(\n \"Invalid input to \" + name + \", FeatureCollection required\"\n );\n }\n for (const feature of featureCollection.features) {\n if (!feature || feature.type !== \"Feature\" || !feature.geometry) {\n throw new Error(\n \"Invalid input to \" + name + \", Feature with geometry required\"\n );\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error(\n \"Invalid input to \" + name + \": must be a \" + type + \", given \" + feature.geometry.type\n );\n }\n }\n}\nfunction getGeom(geojson) {\n if (geojson.type === \"Feature\") {\n return geojson.geometry;\n }\n return geojson;\n}\nfunction getType(geojson, _name) {\n if (geojson.type === \"FeatureCollection\") {\n return \"FeatureCollection\";\n }\n if (geojson.type === \"GeometryCollection\") {\n return \"GeometryCollection\";\n }\n if (geojson.type === \"Feature\" && geojson.geometry !== null) {\n return geojson.geometry.type;\n }\n return geojson.type;\n}\nexport {\n collectionOf,\n containsNumber,\n featureOf,\n geojsonType,\n getCoord,\n getCoords,\n getGeom,\n getType\n};\n//# sourceMappingURL=index.js.map","// index.ts\nimport pip from \"point-in-polygon-hao\";\nimport { getCoord, getGeom } from \"@turf/invariant\";\nfunction booleanPointInPolygon(point, polygon, options = {}) {\n if (!point) {\n throw new Error(\"point is required\");\n }\n if (!polygon) {\n throw new Error(\"polygon is required\");\n }\n const pt = getCoord(point);\n const geom = getGeom(polygon);\n const type = geom.type;\n const bbox = polygon.bbox;\n let polys = geom.coordinates;\n if (bbox && inBBox(pt, bbox) === false) {\n return false;\n }\n if (type === \"Polygon\") {\n polys = [polys];\n }\n let result = false;\n for (var i = 0; i < polys.length; ++i) {\n const polyResult = pip(pt, polys[i]);\n if (polyResult === 0) return options.ignoreBoundary ? false : true;\n else if (polyResult) result = true;\n }\n return result;\n}\nfunction inBBox(pt, bbox) {\n return bbox[0] <= pt[0] && bbox[1] <= pt[1] && bbox[2] >= pt[0] && bbox[3] >= pt[1];\n}\nvar index_default = booleanPointInPolygon;\nexport {\n booleanPointInPolygon,\n index_default as default\n};\n//# sourceMappingURL=index.js.map","import type { Mode } from './Mode';\nimport type { NormalizedInputEvent } from '../types/input';\nimport type {\n LibreDrawFeature,\n Position,\n Action,\n} from '../types/features';\nimport type { LibreDrawEventMap } from '../types/events';\nimport { DeleteAction, UpdateAction } from '../types/features';\nimport { FeatureStore } from '../core/FeatureStore';\nimport booleanPointInPolygon from '@turf/boolean-point-in-polygon';\nimport { point as turfPoint } from '@turf/helpers';\nimport { hasRingSelfIntersection } from '../validation/intersection';\n\n/**\n * Threshold in pixels for vertex/midpoint hit testing (mouse).\n */\nconst HIT_THRESHOLD_MOUSE_PX = 10;\n\n/**\n * Threshold in pixels for vertex/midpoint hit testing (touch).\n */\nconst HIT_THRESHOLD_TOUCH_PX = 24;\n\n/**\n * Minimum number of unique vertices a polygon must maintain.\n */\nconst MIN_VERTICES = 3;\n\n/**\n * Callbacks that SelectMode needs from the host application.\n */\nexport interface SelectModeCallbacks {\n /** Remove a feature from the store. */\n removeFeatureFromStore(id: string): LibreDrawFeature | undefined;\n /** Push an action to the history manager. */\n pushToHistory(action: Action): void;\n /** Emit an event through the event bus. */\n emitEvent<K extends keyof LibreDrawEventMap>(\n type: K,\n payload: LibreDrawEventMap[K],\n ): void;\n /** Re-render all features. */\n renderFeatures(): void;\n /** Get a feature by ID. */\n getFeatureById(id: string): LibreDrawFeature | undefined;\n /** Get all features in the store. */\n getAllFeatures(): LibreDrawFeature[];\n /** Convert a geographic coordinate to a screen point. */\n getScreenPoint(lngLat: { lng: number; lat: number }): { x: number; y: number };\n /** Update a feature in the store. */\n updateFeatureInStore(id: string, feature: LibreDrawFeature): void;\n /** Render vertex and midpoint markers for editing. */\n renderVertices(featureId: string, vertices: Position[], midpoints: Position[], highlightIndex?: number): void;\n /** Clear vertex/midpoint markers. */\n clearVertices(): void;\n /** Enable or disable map drag panning. */\n setDragPan(enabled: boolean): void;\n}\n\n/**\n * Selection and editing mode for existing polygons.\n *\n * Users click on a polygon to select it. Selected polygons display\n * vertex handles that can be dragged to reshape the polygon. Midpoint\n * handles appear between vertices and can be dragged to add new vertices.\n * Double-clicking a vertex removes it (minimum 3 vertices maintained).\n */\nexport class SelectMode implements Mode {\n private selectedIds: Set<string> = new Set();\n private isActive = false;\n private callbacks: SelectModeCallbacks;\n private onSelectionChange?: (selectedIds: string[]) => void;\n\n // Vertex drag state\n private dragging = false;\n private dragVertexIndex = -1;\n private dragStartFeature: LibreDrawFeature | null = null;\n\n // Polygon drag state\n private draggingPolygon = false;\n private dragPolygonStartLngLat: { lng: number; lat: number } | null = null;\n\n // Highlight state\n private highlightedVertexIndex = -1;\n\n constructor(\n callbacks: SelectModeCallbacks,\n onSelectionChange?: (selectedIds: string[]) => void,\n ) {\n this.callbacks = callbacks;\n this.onSelectionChange = onSelectionChange;\n }\n\n activate(): void {\n this.isActive = true;\n }\n\n deactivate(): void {\n this.isActive = false;\n this.highlightedVertexIndex = -1;\n this.endDrag();\n if (this.selectedIds.size > 0) {\n this.selectedIds.clear();\n this.callbacks.clearVertices();\n this.notifySelectionChange();\n }\n }\n\n /**\n * Get the currently selected feature IDs.\n */\n getSelectedIds(): string[] {\n return Array.from(this.selectedIds);\n }\n\n /**\n * Programmatically select a feature by ID.\n *\n * Replaces any existing selection. Renders vertex handles and\n * emits a selectionchange event. Cancels any in-progress drag.\n *\n * @param id - The feature ID to select.\n * @returns `true` if the feature was found and selected, `false` otherwise.\n */\n selectFeature(id: string): boolean {\n if (!this.isActive) return false;\n\n const feature = this.callbacks.getFeatureById(id);\n if (!feature) return false;\n\n this.highlightedVertexIndex = -1;\n this.endDrag();\n this.selectedIds.clear();\n this.selectedIds.add(id);\n this.showVertexHandles(feature);\n this.notifySelectionChange();\n this.callbacks.renderFeatures();\n return true;\n }\n\n /**\n * Programmatically clear the current selection.\n *\n * Removes vertex handles and emits a selectionchange event.\n * No-op if nothing is selected or mode is not active.\n */\n clearSelection(): void {\n if (!this.isActive) return;\n if (this.selectedIds.size === 0) return;\n\n this.highlightedVertexIndex = -1;\n this.endDrag();\n this.selectedIds.clear();\n this.callbacks.clearVertices();\n this.notifySelectionChange();\n this.callbacks.renderFeatures();\n }\n\n onPointerDown(event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n // If a feature is selected, check vertex/midpoint hits first\n const selectedId = this.getFirstSelectedId();\n if (selectedId) {\n const feature = this.callbacks.getFeatureById(selectedId);\n if (feature) {\n const vertices = this.getVertices(feature);\n const threshold = this.getThreshold(event);\n\n // Check vertex hit\n const vertexIdx = this.findNearestVertex(\n vertices,\n event.point,\n threshold,\n );\n if (vertexIdx >= 0) {\n this.startDrag(feature, vertexIdx);\n return;\n }\n\n // Check midpoint hit\n const midpoints = this.computeMidpoints(vertices);\n const midIdx = this.findNearestPoint(midpoints, event.point, threshold);\n if (midIdx >= 0) {\n // Capture state BEFORE insertion for correct undo\n const beforeInsert = FeatureStore.cloneFeature(feature);\n // Insert new vertex at the midpoint position\n const newFeature = this.insertVertex(feature, midIdx + 1, midpoints[midIdx]);\n this.callbacks.updateFeatureInStore(selectedId, newFeature);\n this.showVertexHandles(newFeature);\n this.startDrag(newFeature, midIdx + 1);\n // Override dragStartFeature with pre-insertion state so undo reverts the insertion too\n this.dragStartFeature = beforeInsert;\n return;\n }\n\n // Check if click is inside the selected polygon body → start polygon drag\n const bodyClick = turfPoint([event.lngLat.lng, event.lngLat.lat]);\n if (booleanPointInPolygon(bodyClick, feature.geometry)) {\n this.startPolygonDrag(feature, event.lngLat);\n return;\n }\n }\n }\n\n // Reset highlight on selection change\n this.highlightedVertexIndex = -1;\n\n // Standard polygon selection logic\n const clickPoint = turfPoint([event.lngLat.lng, event.lngLat.lat]);\n const features = this.callbacks.getAllFeatures();\n\n let hitFeature: LibreDrawFeature | undefined;\n for (let i = features.length - 1; i >= 0; i--) {\n const feature = features[i];\n const polygon = feature.geometry;\n if (booleanPointInPolygon(clickPoint, polygon)) {\n hitFeature = feature;\n break;\n }\n }\n\n if (hitFeature) {\n if (this.selectedIds.has(hitFeature.id)) {\n this.selectedIds.delete(hitFeature.id);\n this.callbacks.clearVertices();\n } else {\n this.selectedIds.clear();\n this.selectedIds.add(hitFeature.id);\n this.showVertexHandles(hitFeature);\n }\n } else {\n this.selectedIds.clear();\n this.callbacks.clearVertices();\n }\n\n this.notifySelectionChange();\n this.callbacks.renderFeatures();\n }\n\n onPointerMove(event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n // Vertex drag: move single vertex\n if (this.dragging) {\n const selectedId = this.getFirstSelectedId();\n if (!selectedId) return;\n\n const feature = this.callbacks.getFeatureById(selectedId);\n if (!feature) return;\n\n const newPos: Position = [event.lngLat.lng, event.lngLat.lat];\n const updatedFeature = this.moveVertex(feature, this.dragVertexIndex, newPos);\n\n // Reject move if it would cause self-intersection\n if (hasRingSelfIntersection(updatedFeature.geometry.coordinates[0])) {\n return;\n }\n\n this.callbacks.updateFeatureInStore(selectedId, updatedFeature);\n this.callbacks.renderFeatures();\n this.showVertexHandles(updatedFeature);\n return;\n }\n\n // Polygon drag: move entire polygon\n if (this.draggingPolygon) {\n const selectedId = this.getFirstSelectedId();\n if (!selectedId || !this.dragStartFeature || !this.dragPolygonStartLngLat) return;\n\n const dLng = event.lngLat.lng - this.dragPolygonStartLngLat.lng;\n const dLat = event.lngLat.lat - this.dragPolygonStartLngLat.lat;\n const updatedFeature = this.movePolygon(this.dragStartFeature, dLng, dLat);\n\n this.callbacks.updateFeatureInStore(selectedId, updatedFeature);\n this.callbacks.renderFeatures();\n this.showVertexHandles(updatedFeature);\n return;\n }\n\n // Non-drag: highlight nearest vertex\n const selectedId = this.getFirstSelectedId();\n if (!selectedId) return;\n\n const feature = this.callbacks.getFeatureById(selectedId);\n if (!feature) return;\n\n const vertices = this.getVertices(feature);\n const threshold = this.getThreshold(event);\n const nearIdx = this.findNearestVertex(vertices, event.point, threshold);\n\n if (nearIdx !== this.highlightedVertexIndex) {\n this.highlightedVertexIndex = nearIdx;\n this.showVertexHandles(feature);\n }\n }\n\n onPointerUp(_event: NormalizedInputEvent): void {\n if (!this.isActive || (!this.dragging && !this.draggingPolygon)) return;\n\n const selectedId = this.getFirstSelectedId();\n if (!selectedId || !this.dragStartFeature) {\n this.endDrag();\n return;\n }\n\n const currentFeature = this.callbacks.getFeatureById(selectedId);\n if (currentFeature) {\n const action = new UpdateAction(\n selectedId,\n this.dragStartFeature,\n FeatureStore.cloneFeature(currentFeature),\n );\n this.callbacks.pushToHistory(action);\n this.callbacks.emitEvent('update', {\n feature: currentFeature,\n oldFeature: this.dragStartFeature,\n });\n }\n\n this.endDrag();\n }\n\n onDoubleClick(event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n const selectedId = this.getFirstSelectedId();\n if (!selectedId) return;\n\n const feature = this.callbacks.getFeatureById(selectedId);\n if (!feature) return;\n\n const vertices = this.getVertices(feature);\n const threshold = this.getThreshold(event);\n const vertexIdx = this.findNearestVertex(vertices, event.point, threshold);\n\n // Delete vertex if hit and polygon has more than MIN_VERTICES\n if (vertexIdx >= 0 && vertices.length > MIN_VERTICES) {\n const oldFeature = FeatureStore.cloneFeature(feature);\n const updatedFeature = this.removeVertex(feature, vertexIdx);\n this.callbacks.updateFeatureInStore(selectedId, updatedFeature);\n\n const action = new UpdateAction(selectedId, oldFeature, FeatureStore.cloneFeature(updatedFeature));\n this.callbacks.pushToHistory(action);\n this.callbacks.emitEvent('update', {\n feature: updatedFeature,\n oldFeature,\n });\n\n this.callbacks.renderFeatures();\n this.showVertexHandles(updatedFeature);\n\n event.originalEvent.preventDefault();\n event.originalEvent.stopPropagation();\n }\n }\n\n onLongPress(event: NormalizedInputEvent): void {\n if (!this.isActive) return;\n\n const selectedId = this.getFirstSelectedId();\n if (!selectedId) {\n return;\n }\n\n const feature = this.callbacks.getFeatureById(selectedId);\n if (!feature) return;\n\n // Check if long press is on a vertex — delete it\n const vertices = this.getVertices(feature);\n const threshold = this.getThreshold(event);\n const vertexIdx = this.findNearestVertex(vertices, event.point, threshold);\n if (vertexIdx >= 0 && vertices.length > MIN_VERTICES) {\n const oldFeature = FeatureStore.cloneFeature(feature);\n const updatedFeature = this.removeVertex(feature, vertexIdx);\n this.callbacks.updateFeatureInStore(selectedId, updatedFeature);\n\n const action = new UpdateAction(selectedId, oldFeature, FeatureStore.cloneFeature(updatedFeature));\n this.callbacks.pushToHistory(action);\n this.callbacks.emitEvent('update', {\n feature: updatedFeature,\n oldFeature,\n });\n\n this.callbacks.renderFeatures();\n this.showVertexHandles(updatedFeature);\n }\n }\n\n onKeyDown(key: string, _event: KeyboardEvent): void {\n if (!this.isActive) return;\n\n if (key === 'Delete' || key === 'Backspace') {\n this.deleteSelected();\n }\n }\n\n /**\n * Get the hit-test threshold based on input type.\n */\n private getThreshold(event: NormalizedInputEvent): number {\n return event.inputType === 'touch'\n ? HIT_THRESHOLD_TOUCH_PX\n : HIT_THRESHOLD_MOUSE_PX;\n }\n\n /**\n * Get the unique vertices (excluding closing point) of a polygon.\n */\n private getVertices(feature: LibreDrawFeature): Position[] {\n const ring = feature.geometry.coordinates[0];\n // Exclude the closing point (last == first)\n return ring.slice(0, ring.length - 1);\n }\n\n /**\n * Find the nearest vertex within the hit threshold.\n * @returns The vertex index, or -1 if none is close enough.\n */\n private findNearestVertex(\n vertices: Position[],\n clickPoint: { x: number; y: number },\n threshold?: number,\n ): number {\n return this.findNearestPoint(vertices, clickPoint, threshold);\n }\n\n /**\n * Find the nearest point (vertex or midpoint) within the hit threshold.\n * @returns The index, or -1 if none is close enough.\n */\n private findNearestPoint(\n points: Position[],\n clickPoint: { x: number; y: number },\n threshold: number = HIT_THRESHOLD_MOUSE_PX,\n ): number {\n let minDist = Infinity;\n let minIdx = -1;\n\n for (let i = 0; i < points.length; i++) {\n const screenPt = this.callbacks.getScreenPoint({\n lng: points[i][0],\n lat: points[i][1],\n });\n const dx = clickPoint.x - screenPt.x;\n const dy = clickPoint.y - screenPt.y;\n const dist = Math.sqrt(dx * dx + dy * dy);\n if (dist <= threshold && dist < minDist) {\n minDist = dist;\n minIdx = i;\n }\n }\n\n return minIdx;\n }\n\n /**\n * Compute midpoints for each edge of the polygon.\n */\n private computeMidpoints(vertices: Position[]): Position[] {\n const midpoints: Position[] = [];\n for (let i = 0; i < vertices.length; i++) {\n const next = (i + 1) % vertices.length;\n midpoints.push([\n (vertices[i][0] + vertices[next][0]) / 2,\n (vertices[i][1] + vertices[next][1]) / 2,\n ]);\n }\n return midpoints;\n }\n\n /**\n * Start a vertex drag operation.\n */\n private startDrag(feature: LibreDrawFeature, vertexIndex: number): void {\n this.dragging = true;\n this.dragVertexIndex = vertexIndex;\n this.dragStartFeature = FeatureStore.cloneFeature(feature);\n this.callbacks.setDragPan(false);\n }\n\n /**\n * Start a polygon drag (whole-polygon move) operation.\n */\n private startPolygonDrag(\n feature: LibreDrawFeature,\n startLngLat: { lng: number; lat: number },\n ): void {\n this.draggingPolygon = true;\n this.dragPolygonStartLngLat = startLngLat;\n this.dragStartFeature = FeatureStore.cloneFeature(feature);\n this.callbacks.setDragPan(false);\n }\n\n /**\n * End a drag operation and restore map interactions.\n */\n private endDrag(): void {\n if (this.dragging || this.draggingPolygon) {\n this.callbacks.setDragPan(true);\n }\n this.dragging = false;\n this.dragVertexIndex = -1;\n this.dragStartFeature = null;\n this.draggingPolygon = false;\n this.dragPolygonStartLngLat = null;\n this.highlightedVertexIndex = -1;\n }\n\n /**\n * Create a new feature with a vertex moved to a new position.\n */\n private moveVertex(\n feature: LibreDrawFeature,\n vertexIndex: number,\n newPos: Position,\n ): LibreDrawFeature {\n const ring = [...feature.geometry.coordinates[0]];\n ring[vertexIndex] = newPos;\n // If moving first vertex, also update closing point\n if (vertexIndex === 0) {\n ring[ring.length - 1] = newPos;\n }\n // If moving last vertex (same as first), also update first\n if (vertexIndex === ring.length - 1) {\n ring[0] = newPos;\n }\n return {\n ...feature,\n geometry: {\n type: 'Polygon',\n coordinates: [ring],\n },\n };\n }\n\n /**\n * Create a new feature with all vertices translated by the given delta.\n */\n private movePolygon(\n feature: LibreDrawFeature,\n dLng: number,\n dLat: number,\n ): LibreDrawFeature {\n const ring = feature.geometry.coordinates[0].map(\n (pos): Position => [pos[0] + dLng, pos[1] + dLat],\n );\n return {\n ...feature,\n geometry: {\n type: 'Polygon',\n coordinates: [ring],\n },\n };\n }\n\n /**\n * Create a new feature with a vertex inserted at the given index.\n */\n private insertVertex(\n feature: LibreDrawFeature,\n insertIndex: number,\n pos: Position,\n ): LibreDrawFeature {\n const ring = [...feature.geometry.coordinates[0]];\n ring.splice(insertIndex, 0, pos);\n return {\n ...feature,\n geometry: {\n type: 'Polygon',\n coordinates: [ring],\n },\n };\n }\n\n /**\n * Create a new feature with a vertex removed at the given index.\n */\n private removeVertex(\n feature: LibreDrawFeature,\n vertexIndex: number,\n ): LibreDrawFeature {\n const vertices = this.getVertices(feature);\n const newVertices = vertices.filter((_, i) => i !== vertexIndex);\n // Close the ring\n const ring: Position[] = [...newVertices, [...newVertices[0]] as Position];\n return {\n ...feature,\n geometry: {\n type: 'Polygon',\n coordinates: [ring],\n },\n };\n }\n\n /**\n * Refresh vertex/midpoint handles for the currently selected feature.\n * Call this after external geometry changes (e.g. undo/redo).\n */\n refreshVertexHandles(): void {\n if (!this.isActive) return;\n\n const selectedId = this.getFirstSelectedId();\n if (!selectedId) return;\n\n const feature = this.callbacks.getFeatureById(selectedId);\n if (feature) {\n this.showVertexHandles(feature);\n } else {\n // Feature was removed (e.g. undo of a create) — clear selection\n this.selectedIds.delete(selectedId);\n this.callbacks.clearVertices();\n this.notifySelectionChange();\n }\n }\n\n /**\n * Show vertex and midpoint handles for a selected feature.\n */\n private showVertexHandles(feature: LibreDrawFeature): void {\n const vertices = this.getVertices(feature);\n const midpoints = this.computeMidpoints(vertices);\n this.callbacks.renderVertices(\n feature.id,\n vertices,\n midpoints,\n this.highlightedVertexIndex >= 0 ? this.highlightedVertexIndex : undefined,\n );\n }\n\n /**\n * Get the first selected feature ID.\n */\n private getFirstSelectedId(): string | undefined {\n return this.selectedIds.values().next().value;\n }\n\n /**\n * Delete all currently selected features.\n */\n private deleteSelected(): void {\n if (this.selectedIds.size === 0) return;\n\n const idsToDelete = Array.from(this.selectedIds);\n for (const id of idsToDelete) {\n const feature = this.callbacks.getFeatureById(id);\n if (feature) {\n this.callbacks.removeFeatureFromStore(id);\n const action = new DeleteAction(feature);\n this.callbacks.pushToHistory(action);\n this.callbacks.emitEvent('delete', { feature });\n }\n }\n\n this.selectedIds.clear();\n this.callbacks.clearVertices();\n this.notifySelectionChange();\n this.callbacks.renderFeatures();\n }\n\n /**\n * Notify the host about selection changes.\n */\n private notifySelectionChange(): void {\n const ids = this.getSelectedIds();\n this.callbacks.emitEvent('selectionchange', { selectedIds: ids });\n if (this.onSelectionChange) {\n this.onSelectionChange(ids);\n }\n }\n}\n","import type { Map as MaplibreMap } from 'maplibre-gl';\nimport type { NormalizedInputEvent } from '../types/input';\n\n/**\n * Callbacks that MouseInput dispatches to.\n */\nexport interface MouseInputCallbacks {\n onPointerDown(event: NormalizedInputEvent): void;\n onPointerMove(event: NormalizedInputEvent): void;\n onPointerUp(event: NormalizedInputEvent): void;\n onDoubleClick(event: NormalizedInputEvent): void;\n}\n\n/**\n * Handles mouse input events on the map canvas and converts them\n * to normalized input events.\n */\nexport class MouseInput {\n private map: MaplibreMap;\n private callbacks: MouseInputCallbacks;\n private canvas: HTMLElement;\n\n private handleMouseDown = (e: MouseEvent): void => {\n this.callbacks.onPointerDown(this.normalize(e));\n };\n\n private handleMouseMove = (e: MouseEvent): void => {\n this.callbacks.onPointerMove(this.normalize(e));\n };\n\n private handleMouseUp = (e: MouseEvent): void => {\n this.callbacks.onPointerUp(this.normalize(e));\n };\n\n private handleDblClick = (e: MouseEvent): void => {\n this.callbacks.onDoubleClick(this.normalize(e));\n };\n\n constructor(map: MaplibreMap, callbacks: MouseInputCallbacks) {\n this.map = map;\n this.callbacks = callbacks;\n this.canvas = map.getCanvasContainer();\n }\n\n /**\n * Start listening for mouse events on the map canvas.\n */\n enable(): void {\n this.canvas.addEventListener('mousedown', this.handleMouseDown);\n this.canvas.addEventListener('mousemove', this.handleMouseMove);\n this.canvas.addEventListener('mouseup', this.handleMouseUp);\n this.canvas.addEventListener('dblclick', this.handleDblClick);\n }\n\n /**\n * Stop listening for mouse events.\n */\n disable(): void {\n this.canvas.removeEventListener('mousedown', this.handleMouseDown);\n this.canvas.removeEventListener('mousemove', this.handleMouseMove);\n this.canvas.removeEventListener('mouseup', this.handleMouseUp);\n this.canvas.removeEventListener('dblclick', this.handleDblClick);\n }\n\n /**\n * Destroy the mouse input handler and remove all listeners.\n */\n destroy(): void {\n this.disable();\n }\n\n /**\n * Convert a raw MouseEvent into a NormalizedInputEvent.\n */\n private normalize(e: MouseEvent): NormalizedInputEvent {\n const rect = this.canvas.getBoundingClientRect();\n const x = e.clientX - rect.left;\n const y = e.clientY - rect.top;\n const lngLat = this.map.unproject([x, y]);\n\n return {\n lngLat: { lng: lngLat.lng, lat: lngLat.lat },\n point: { x, y },\n originalEvent: e,\n inputType: 'mouse',\n };\n }\n}\n","import type { Map as MaplibreMap } from 'maplibre-gl';\nimport type { NormalizedInputEvent } from '../types/input';\n\n/**\n * Double-tap detection window in milliseconds.\n */\nconst DOUBLE_TAP_MS = 300;\n\n/**\n * Long press detection threshold in milliseconds.\n */\nconst LONG_PRESS_MS = 500;\n\n/**\n * Maximum movement (in pixels) allowed during a long press.\n */\nconst LONG_PRESS_TOLERANCE = 15;\n\n/**\n * Callbacks that TouchInput dispatches to.\n */\nexport interface TouchInputCallbacks {\n onPointerDown(event: NormalizedInputEvent): void;\n onPointerMove(event: NormalizedInputEvent): void;\n onPointerUp(event: NormalizedInputEvent): void;\n onDoubleClick(event: NormalizedInputEvent): void;\n onLongPress(event: NormalizedInputEvent): void;\n}\n\n/**\n * Handles touch input events on the map canvas.\n *\n * Provides gesture detection for:\n * - Double tap (within 300ms)\n * - Long press (hold for 500ms)\n * - Pinch detection (2+ fingers, passes through to map)\n */\nexport class TouchInput {\n private map: MaplibreMap;\n private callbacks: TouchInputCallbacks;\n private canvas: HTMLElement;\n\n private lastTapTime = 0;\n private longPressTimer: ReturnType<typeof setTimeout> | null = null;\n private touchStartPos: { x: number; y: number } | null = null;\n private isPinching = false;\n\n private handleTouchStart = (e: TouchEvent): void => {\n // Ignore multi-finger gestures (pinch/rotate)\n if (e.touches.length >= 2) {\n this.isPinching = true;\n this.cancelLongPress();\n return;\n }\n\n this.isPinching = false;\n const normalized = this.normalize(e);\n this.touchStartPos = { x: normalized.point.x, y: normalized.point.y };\n\n // Start long press timer\n this.cancelLongPress();\n this.longPressTimer = setTimeout(() => {\n if (this.touchStartPos) {\n this.callbacks.onLongPress(normalized);\n this.touchStartPos = null; // prevent pointerUp from firing\n }\n }, LONG_PRESS_MS);\n\n this.callbacks.onPointerDown(normalized);\n };\n\n private handleTouchMove = (e: TouchEvent): void => {\n if (this.isPinching || e.touches.length >= 2) {\n this.cancelLongPress();\n return;\n }\n\n const normalized = this.normalize(e);\n\n // Cancel long press if the finger has moved too far\n if (this.touchStartPos) {\n const dx = normalized.point.x - this.touchStartPos.x;\n const dy = normalized.point.y - this.touchStartPos.y;\n if (Math.sqrt(dx * dx + dy * dy) > LONG_PRESS_TOLERANCE) {\n this.cancelLongPress();\n }\n }\n\n this.callbacks.onPointerMove(normalized);\n };\n\n private handleTouchEnd = (e: TouchEvent): void => {\n this.cancelLongPress();\n\n if (this.isPinching) {\n if (e.touches.length === 0) {\n this.isPinching = false;\n }\n return;\n }\n\n // We need to use changedTouches for touch end\n if (e.changedTouches.length === 0) return;\n\n const normalized = this.normalizeChangedTouch(e);\n\n // Double-tap detection\n const now = Date.now();\n if (now - this.lastTapTime < DOUBLE_TAP_MS) {\n this.callbacks.onDoubleClick(normalized);\n this.lastTapTime = 0; // Reset to prevent triple-tap detection\n } else {\n this.lastTapTime = now;\n }\n\n if (this.touchStartPos) {\n this.callbacks.onPointerUp(normalized);\n this.touchStartPos = null;\n }\n };\n\n constructor(map: MaplibreMap, callbacks: TouchInputCallbacks) {\n this.map = map;\n this.callbacks = callbacks;\n this.canvas = map.getCanvasContainer();\n }\n\n /**\n * Start listening for touch events on the map canvas.\n */\n enable(): void {\n this.canvas.addEventListener('touchstart', this.handleTouchStart, {\n passive: false,\n });\n this.canvas.addEventListener('touchmove', this.handleTouchMove, {\n passive: false,\n });\n this.canvas.addEventListener('touchend', this.handleTouchEnd);\n }\n\n /**\n * Stop listening for touch events.\n */\n disable(): void {\n this.canvas.removeEventListener('touchstart', this.handleTouchStart);\n this.canvas.removeEventListener('touchmove', this.handleTouchMove);\n this.canvas.removeEventListener('touchend', this.handleTouchEnd);\n this.cancelLongPress();\n }\n\n /**\n * Destroy the touch input handler and remove all listeners.\n */\n destroy(): void {\n this.disable();\n }\n\n /**\n * Cancel the long press detection timer.\n */\n private cancelLongPress(): void {\n if (this.longPressTimer !== null) {\n clearTimeout(this.longPressTimer);\n this.longPressTimer = null;\n }\n }\n\n /**\n * Convert a TouchEvent into a NormalizedInputEvent using the first touch.\n */\n private normalize(e: TouchEvent): NormalizedInputEvent {\n const touch = e.touches[0];\n const rect = this.canvas.getBoundingClientRect();\n const x = touch.clientX - rect.left;\n const y = touch.clientY - rect.top;\n const lngLat = this.map.unproject([x, y]);\n\n return {\n lngLat: { lng: lngLat.lng, lat: lngLat.lat },\n point: { x, y },\n originalEvent: e,\n inputType: 'touch',\n };\n }\n\n /**\n * Convert a TouchEvent into a NormalizedInputEvent using changedTouches\n * (for touchend events where touches array is empty).\n */\n private normalizeChangedTouch(e: TouchEvent): NormalizedInputEvent {\n const touch = e.changedTouches[0];\n const rect = this.canvas.getBoundingClientRect();\n const x = touch.clientX - rect.left;\n const y = touch.clientY - rect.top;\n const lngLat = this.map.unproject([x, y]);\n\n return {\n lngLat: { lng: lngLat.lng, lat: lngLat.lat },\n point: { x, y },\n originalEvent: e,\n inputType: 'touch',\n };\n }\n}\n","/**\n * Callback for keyboard key events.\n */\nexport interface KeyboardInputCallbacks {\n onKeyDown(key: string, event: KeyboardEvent): void;\n}\n\n/**\n * Handles keyboard input events for the drawing interface.\n *\n * Listens for key events on the document and dispatches\n * relevant keys (Escape, Delete, Backspace) to the active mode.\n */\nexport class KeyboardInput {\n private callbacks: KeyboardInputCallbacks;\n\n /** The set of keys that this handler cares about. */\n private static readonly RELEVANT_KEYS = new Set([\n 'Escape',\n 'Delete',\n 'Backspace',\n ]);\n\n private handleKeyDown = (e: KeyboardEvent): void => {\n if (KeyboardInput.RELEVANT_KEYS.has(e.key)) {\n this.callbacks.onKeyDown(e.key, e);\n }\n };\n\n constructor(callbacks: KeyboardInputCallbacks) {\n this.callbacks = callbacks;\n }\n\n /**\n * Start listening for keyboard events.\n */\n enable(): void {\n document.addEventListener('keydown', this.handleKeyDown);\n }\n\n /**\n * Stop listening for keyboard events.\n */\n disable(): void {\n document.removeEventListener('keydown', this.handleKeyDown);\n }\n\n /**\n * Destroy the keyboard input handler and remove all listeners.\n */\n destroy(): void {\n this.disable();\n }\n}\n","import type { Map as MaplibreMap } from 'maplibre-gl';\nimport type { NormalizedInputEvent } from '../types/input';\nimport type { Mode } from '../modes/Mode';\nimport { MouseInput } from './MouseInput';\nimport { TouchInput } from './TouchInput';\nimport { KeyboardInput } from './KeyboardInput';\n\n/**\n * Callback to retrieve the currently active mode.\n */\nexport type GetActiveModeCallback = () => Mode | undefined;\n\n/**\n * Orchestrates all input handlers (mouse, touch, keyboard) and\n * dispatches events to the currently active drawing mode.\n */\nexport class InputHandler {\n private mouseInput: MouseInput;\n private touchInput: TouchInput;\n private keyboardInput: KeyboardInput;\n private getActiveMode: GetActiveModeCallback;\n\n constructor(map: MaplibreMap, getActiveMode: GetActiveModeCallback) {\n this.getActiveMode = getActiveMode;\n\n const pointerCallbacks = {\n onPointerDown: (event: NormalizedInputEvent) => {\n this.getActiveMode()?.onPointerDown(event);\n },\n onPointerMove: (event: NormalizedInputEvent) => {\n this.getActiveMode()?.onPointerMove(event);\n },\n onPointerUp: (event: NormalizedInputEvent) => {\n this.getActiveMode()?.onPointerUp(event);\n },\n onDoubleClick: (event: NormalizedInputEvent) => {\n this.getActiveMode()?.onDoubleClick(event);\n },\n onLongPress: (event: NormalizedInputEvent) => {\n this.getActiveMode()?.onLongPress(event);\n },\n };\n\n this.mouseInput = new MouseInput(map, pointerCallbacks);\n this.touchInput = new TouchInput(map, pointerCallbacks);\n this.keyboardInput = new KeyboardInput({\n onKeyDown: (key: string, event: KeyboardEvent) => {\n this.getActiveMode()?.onKeyDown(key, event);\n },\n });\n }\n\n /**\n * Enable all input handlers.\n */\n enable(): void {\n this.mouseInput.enable();\n this.touchInput.enable();\n this.keyboardInput.enable();\n }\n\n /**\n * Disable all input handlers.\n */\n disable(): void {\n this.mouseInput.disable();\n this.touchInput.disable();\n this.keyboardInput.disable();\n }\n\n /**\n * Destroy all input handlers and remove event listeners.\n */\n destroy(): void {\n this.mouseInput.destroy();\n this.touchInput.destroy();\n this.keyboardInput.destroy();\n }\n}\n","import type { Map as MaplibreMap, GeoJSONSource } from 'maplibre-gl';\n\n/**\n * The GeoJSON source IDs used by LibreDraw.\n */\nexport const SOURCE_IDS = {\n FEATURES: 'libre-draw-features',\n PREVIEW: 'libre-draw-preview',\n EDIT_VERTICES: 'libre-draw-edit-vertices',\n} as const;\n\n/**\n * An empty GeoJSON FeatureCollection.\n */\nconst EMPTY_FC: GeoJSON.FeatureCollection = {\n type: 'FeatureCollection',\n features: [],\n};\n\n/**\n * Manages MapLibre GeoJSON sources for the drawing layers.\n *\n * Provides methods to add, update, and remove the sources that\n * the RenderManager's layers read from.\n */\nexport class SourceManager {\n private map: MaplibreMap;\n private initialized = false;\n\n constructor(map: MaplibreMap) {\n this.map = map;\n }\n\n /**\n * Initialize the GeoJSON sources on the map.\n * Should be called after the map style has loaded.\n */\n initialize(): void {\n if (this.initialized) return;\n\n if (!this.map.getSource(SOURCE_IDS.FEATURES)) {\n this.map.addSource(SOURCE_IDS.FEATURES, {\n type: 'geojson',\n data: EMPTY_FC,\n });\n }\n\n if (!this.map.getSource(SOURCE_IDS.PREVIEW)) {\n this.map.addSource(SOURCE_IDS.PREVIEW, {\n type: 'geojson',\n data: EMPTY_FC,\n });\n }\n\n if (!this.map.getSource(SOURCE_IDS.EDIT_VERTICES)) {\n this.map.addSource(SOURCE_IDS.EDIT_VERTICES, {\n type: 'geojson',\n data: EMPTY_FC,\n });\n }\n\n this.initialized = true;\n }\n\n /**\n * Update the features source with new GeoJSON data.\n * @param data - A GeoJSON FeatureCollection.\n */\n updateFeatures(data: GeoJSON.FeatureCollection): void {\n const source = this.map.getSource<GeoJSONSource>(SOURCE_IDS.FEATURES);\n if (source) {\n source.setData(data);\n }\n }\n\n /**\n * Update the preview source with new GeoJSON data.\n * @param data - A GeoJSON FeatureCollection.\n */\n updatePreview(data: GeoJSON.FeatureCollection): void {\n const source = this.map.getSource<GeoJSONSource>(SOURCE_IDS.PREVIEW);\n if (source) {\n source.setData(data);\n }\n }\n\n /**\n * Clear the preview source.\n */\n clearPreview(): void {\n this.updatePreview(EMPTY_FC);\n }\n\n /**\n * Update the edit vertices source with new GeoJSON data.\n * @param data - A GeoJSON FeatureCollection of Point features.\n */\n updateEditVertices(data: GeoJSON.FeatureCollection): void {\n const source = this.map.getSource<GeoJSONSource>(SOURCE_IDS.EDIT_VERTICES);\n if (source) {\n source.setData(data);\n }\n }\n\n /**\n * Clear the edit vertices source.\n */\n clearEditVertices(): void {\n this.updateEditVertices(EMPTY_FC);\n }\n\n /**\n * Remove all sources from the map.\n */\n destroy(): void {\n if (this.map.getSource(SOURCE_IDS.FEATURES)) {\n this.map.removeSource(SOURCE_IDS.FEATURES);\n }\n if (this.map.getSource(SOURCE_IDS.PREVIEW)) {\n this.map.removeSource(SOURCE_IDS.PREVIEW);\n }\n if (this.map.getSource(SOURCE_IDS.EDIT_VERTICES)) {\n this.map.removeSource(SOURCE_IDS.EDIT_VERTICES);\n }\n this.initialized = false;\n }\n}\n","import type { Map as MaplibreMap } from 'maplibre-gl';\nimport type { LibreDrawFeature, Position } from '../types/features';\nimport { SourceManager, SOURCE_IDS } from './SourceManager';\n\n/**\n * Layer IDs used by LibreDraw for rendering.\n */\nexport const LAYER_IDS = {\n FILL: 'libre-draw-fill',\n OUTLINE: 'libre-draw-outline',\n VERTICES: 'libre-draw-vertices',\n PREVIEW: 'libre-draw-preview',\n EDIT_VERTICES: 'libre-draw-edit-vertices',\n EDIT_MIDPOINTS: 'libre-draw-edit-midpoints',\n} as const;\n\n/**\n * Default colors used by the rendering layers.\n */\nconst COLORS = {\n FILL: '#3bb2d0',\n FILL_OPACITY: 0.2,\n FILL_SELECTED: '#fbb03b',\n FILL_SELECTED_OPACITY: 0.4,\n OUTLINE: '#3bb2d0',\n OUTLINE_WIDTH: 2,\n OUTLINE_SELECTED: '#fbb03b',\n VERTEX_COLOR: '#ffffff',\n VERTEX_STROKE: '#3bb2d0',\n VERTEX_RADIUS: 4,\n PREVIEW_FILL: '#3bb2d0',\n PREVIEW_FILL_OPACITY: 0.1,\n PREVIEW_OUTLINE: '#3bb2d0',\n PREVIEW_OUTLINE_DASH: [2, 2] as number[],\n EDIT_VERTEX_COLOR: '#ffffff',\n EDIT_VERTEX_STROKE: '#3bb2d0',\n EDIT_VERTEX_RADIUS: 5,\n EDIT_VERTEX_STROKE_WIDTH: 2,\n MIDPOINT_COLOR: '#3bb2d0',\n MIDPOINT_OPACITY: 0.5,\n MIDPOINT_RADIUS: 3,\n} as const;\n\n/**\n * Manages the rendering layers for LibreDraw.\n *\n * Creates and manages MapLibre layers for:\n * - Fill: polygon fill rendering\n * - Outline: polygon border rendering\n * - Vertices: vertex point rendering\n * - Preview: in-progress drawing preview\n *\n * Uses requestAnimationFrame for batch updates to avoid\n * redundant re-renders within a single frame.\n */\nexport class RenderManager {\n private map: MaplibreMap;\n private sourceManager: SourceManager;\n private selectedIds: Set<string> = new Set();\n private pendingRender = false;\n private pendingFeatures: LibreDrawFeature[] | null = null;\n private initialized = false;\n\n constructor(map: MaplibreMap, sourceManager: SourceManager) {\n this.map = map;\n this.sourceManager = sourceManager;\n }\n\n /**\n * Initialize rendering layers on the map.\n * Should be called after the map style and sources are ready.\n */\n initialize(): void {\n if (this.initialized) return;\n\n this.sourceManager.initialize();\n\n // Feature fill layer\n if (!this.map.getLayer(LAYER_IDS.FILL)) {\n this.map.addLayer({\n id: LAYER_IDS.FILL,\n type: 'fill',\n source: SOURCE_IDS.FEATURES,\n paint: {\n 'fill-color': [\n 'case',\n ['boolean', ['get', '_selected'], false],\n COLORS.FILL_SELECTED,\n COLORS.FILL,\n ],\n 'fill-opacity': [\n 'case',\n ['boolean', ['get', '_selected'], false],\n COLORS.FILL_SELECTED_OPACITY,\n COLORS.FILL_OPACITY,\n ],\n },\n });\n }\n\n // Feature outline layer\n if (!this.map.getLayer(LAYER_IDS.OUTLINE)) {\n this.map.addLayer({\n id: LAYER_IDS.OUTLINE,\n type: 'line',\n source: SOURCE_IDS.FEATURES,\n paint: {\n 'line-color': [\n 'case',\n ['boolean', ['get', '_selected'], false],\n COLORS.OUTLINE_SELECTED,\n COLORS.OUTLINE,\n ],\n 'line-width': COLORS.OUTLINE_WIDTH,\n },\n });\n }\n\n // Feature vertices layer (circle markers at each vertex)\n if (!this.map.getLayer(LAYER_IDS.VERTICES)) {\n this.map.addLayer({\n id: LAYER_IDS.VERTICES,\n type: 'circle',\n source: SOURCE_IDS.FEATURES,\n filter: ['==', '$type', 'Point'],\n paint: {\n 'circle-radius': COLORS.VERTEX_RADIUS,\n 'circle-color': COLORS.VERTEX_COLOR,\n 'circle-stroke-color': COLORS.VERTEX_STROKE,\n 'circle-stroke-width': 2,\n },\n });\n }\n\n // Preview layer (dashed outline for in-progress drawing)\n if (!this.map.getLayer(LAYER_IDS.PREVIEW)) {\n this.map.addLayer({\n id: LAYER_IDS.PREVIEW,\n type: 'line',\n source: SOURCE_IDS.PREVIEW,\n paint: {\n 'line-color': COLORS.PREVIEW_OUTLINE,\n 'line-width': 2,\n 'line-dasharray': COLORS.PREVIEW_OUTLINE_DASH,\n },\n });\n }\n\n // Edit midpoints layer (semi-transparent small circles at edge midpoints)\n if (!this.map.getLayer(LAYER_IDS.EDIT_MIDPOINTS)) {\n this.map.addLayer({\n id: LAYER_IDS.EDIT_MIDPOINTS,\n type: 'circle',\n source: SOURCE_IDS.EDIT_VERTICES,\n filter: ['==', ['get', '_type'], 'midpoint'],\n paint: {\n 'circle-radius': COLORS.MIDPOINT_RADIUS,\n 'circle-color': COLORS.MIDPOINT_COLOR,\n 'circle-opacity': COLORS.MIDPOINT_OPACITY,\n },\n });\n }\n\n // Edit vertices layer (white circles with blue stroke at polygon vertices)\n // Uses data-driven styling to highlight the nearest vertex\n if (!this.map.getLayer(LAYER_IDS.EDIT_VERTICES)) {\n this.map.addLayer({\n id: LAYER_IDS.EDIT_VERTICES,\n type: 'circle',\n source: SOURCE_IDS.EDIT_VERTICES,\n filter: ['==', ['get', '_type'], 'vertex'],\n paint: {\n 'circle-radius': [\n 'case',\n ['boolean', ['get', '_highlighted'], false],\n 7,\n COLORS.EDIT_VERTEX_RADIUS,\n ],\n 'circle-color': [\n 'case',\n ['boolean', ['get', '_highlighted'], false],\n '#ff4444',\n COLORS.EDIT_VERTEX_COLOR,\n ],\n 'circle-stroke-color': [\n 'case',\n ['boolean', ['get', '_highlighted'], false],\n '#cc0000',\n COLORS.EDIT_VERTEX_STROKE,\n ],\n 'circle-stroke-width': COLORS.EDIT_VERTEX_STROKE_WIDTH,\n },\n });\n }\n\n this.initialized = true;\n }\n\n /**\n * Render features to the map. Uses requestAnimationFrame\n * to batch multiple render calls within a single frame.\n * @param features - The features to render.\n */\n render(features: LibreDrawFeature[]): void {\n this.pendingFeatures = features;\n if (!this.pendingRender) {\n this.pendingRender = true;\n requestAnimationFrame(() => {\n this.performRender();\n this.pendingRender = false;\n });\n }\n }\n\n /**\n * Render a polygon preview for in-progress drawing.\n * @param coordinates - The preview polygon coordinates (ring).\n */\n renderPreview(coordinates: Position[]): void {\n if (coordinates.length < 2) {\n this.clearPreview();\n return;\n }\n\n const geojsonCoords = coordinates.map(\n (pos) => [pos[0], pos[1]] as [number, number],\n );\n\n const previewGeoJSON: GeoJSON.FeatureCollection = {\n type: 'FeatureCollection',\n features: [\n {\n type: 'Feature',\n properties: {},\n geometry: {\n type: 'LineString',\n coordinates: geojsonCoords,\n },\n },\n ],\n };\n\n this.sourceManager.updatePreview(previewGeoJSON);\n }\n\n /**\n * Clear the drawing preview.\n */\n clearPreview(): void {\n this.sourceManager.clearPreview();\n }\n\n /**\n * Render vertex and midpoint markers for editing a selected polygon.\n * @param vertices - The polygon vertex positions.\n * @param midpoints - The edge midpoint positions.\n * @param highlightIndex - Optional index of the vertex to highlight.\n */\n renderVertices(vertices: Position[], midpoints: Position[], highlightIndex?: number): void {\n const features: GeoJSON.Feature[] = [];\n\n for (let i = 0; i < vertices.length; i++) {\n const v = vertices[i];\n features.push({\n type: 'Feature',\n properties: {\n _type: 'vertex',\n _highlighted: i === highlightIndex,\n },\n geometry: { type: 'Point', coordinates: [v[0], v[1]] },\n });\n }\n\n for (const m of midpoints) {\n features.push({\n type: 'Feature',\n properties: { _type: 'midpoint' },\n geometry: { type: 'Point', coordinates: [m[0], m[1]] },\n });\n }\n\n this.sourceManager.updateEditVertices({\n type: 'FeatureCollection',\n features,\n });\n }\n\n /**\n * Clear the vertex/midpoint markers.\n */\n clearVertices(): void {\n this.sourceManager.clearEditVertices();\n }\n\n /**\n * Set the IDs of selected features for visual highlighting.\n * @param ids - The selected feature IDs.\n */\n setSelectedIds(ids: string[]): void {\n this.selectedIds = new Set(ids);\n }\n\n /**\n * Remove all layers and sources from the map.\n */\n destroy(): void {\n const layerIds = [\n LAYER_IDS.EDIT_VERTICES,\n LAYER_IDS.EDIT_MIDPOINTS,\n LAYER_IDS.PREVIEW,\n LAYER_IDS.VERTICES,\n LAYER_IDS.OUTLINE,\n LAYER_IDS.FILL,\n ];\n\n for (const id of layerIds) {\n if (this.map.getLayer(id)) {\n this.map.removeLayer(id);\n }\n }\n\n this.sourceManager.destroy();\n this.initialized = false;\n }\n\n /**\n * Perform the actual render, converting features to GeoJSON\n * with selection state embedded in properties.\n */\n private performRender(): void {\n if (!this.pendingFeatures) return;\n\n const geojsonFeatures: GeoJSON.Feature[] = this.pendingFeatures.map(\n (feature) => ({\n type: 'Feature' as const,\n id: feature.id as unknown as number,\n properties: {\n ...feature.properties,\n _id: feature.id,\n _selected: this.selectedIds.has(feature.id),\n },\n geometry: feature.geometry,\n }),\n );\n\n const featureCollection: GeoJSON.FeatureCollection = {\n type: 'FeatureCollection',\n features: geojsonFeatures,\n };\n\n this.sourceManager.updateFeatures(featureCollection);\n this.pendingFeatures = null;\n }\n}\n","/**\n * Options for creating a toolbar button.\n */\nexport interface ToolbarButtonOptions {\n /** The unique identifier for this button. */\n id: string;\n /** The SVG icon string to display. */\n icon: string;\n /** Tooltip text for the button. */\n title: string;\n /** Click handler callback. */\n onClick: () => void;\n /** Whether this is a toggle button (draw/select) vs. action button (delete/undo/redo). */\n isToggle?: boolean;\n}\n\n/**\n * Creates and manages a single toolbar button DOM element.\n *\n * Supports active and disabled states for visual feedback.\n * All DOM creation uses createElement for security (no innerHTML).\n */\nexport class ToolbarButton {\n private element: HTMLButtonElement;\n private iconContainer: HTMLSpanElement;\n private options: ToolbarButtonOptions;\n\n constructor(options: ToolbarButtonOptions) {\n this.options = options;\n this.element = document.createElement('button');\n this.element.type = 'button';\n this.element.title = options.title;\n this.element.setAttribute('aria-label', options.title);\n this.element.dataset.libreDrawButton = options.id;\n\n // Apply base styles\n this.applyStyles();\n\n // Create icon container\n this.iconContainer = document.createElement('span');\n this.iconContainer.style.display = 'flex';\n this.iconContainer.style.alignItems = 'center';\n this.iconContainer.style.justifyContent = 'center';\n this.setIcon(options.icon);\n this.element.appendChild(this.iconContainer);\n\n // Attach click handler\n this.element.addEventListener('click', (e) => {\n e.preventDefault();\n e.stopPropagation();\n if (!this.element.disabled) {\n options.onClick();\n }\n });\n }\n\n /**\n * Get the DOM element for this button.\n */\n getElement(): HTMLButtonElement {\n return this.element;\n }\n\n /**\n * Set the active state of the button.\n * @param active - Whether the button should appear active.\n */\n setActive(active: boolean): void {\n if (active) {\n this.element.style.backgroundColor = '#3bb2d0';\n this.element.style.color = '#ffffff';\n } else {\n this.element.style.backgroundColor = '#ffffff';\n this.element.style.color = '#333333';\n }\n this.element.setAttribute('aria-pressed', String(active));\n }\n\n /**\n * Set the disabled state of the button.\n * @param disabled - Whether the button should be disabled.\n */\n setDisabled(disabled: boolean): void {\n this.element.disabled = disabled;\n this.element.style.opacity = disabled ? '0.4' : '1';\n this.element.style.cursor = disabled ? 'not-allowed' : 'pointer';\n }\n\n /**\n * Clean up the button element.\n */\n destroy(): void {\n this.element.remove();\n }\n\n /**\n * Set the icon SVG content using DOM parsing (no innerHTML).\n */\n private setIcon(svgString: string): void {\n const parser = new DOMParser();\n const doc = parser.parseFromString(svgString, 'image/svg+xml');\n const svg = doc.documentElement;\n // Clear existing children\n while (this.iconContainer.firstChild) {\n this.iconContainer.removeChild(this.iconContainer.firstChild);\n }\n this.iconContainer.appendChild(\n document.importNode(svg, true),\n );\n }\n\n /**\n * Apply the base CSS styles to the button.\n */\n private applyStyles(): void {\n const s = this.element.style;\n s.display = 'flex';\n s.alignItems = 'center';\n s.justifyContent = 'center';\n // 44px minimum for mobile touch targets\n s.width = '44px';\n s.height = '44px';\n s.padding = '0';\n s.margin = '0';\n s.border = '1px solid #ddd';\n s.borderRadius = '4px';\n s.backgroundColor = '#ffffff';\n s.color = '#333333';\n s.cursor = 'pointer';\n s.outline = 'none';\n s.transition = 'background-color 0.15s, color 0.15s';\n s.boxSizing = 'border-box';\n }\n}\n","/**\n * Pentagon SVG icon for the draw tool.\n */\nexport const drawIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M12 2l8.5 6.2-3.2 9.8H6.7L3.5 8.2z\"/></svg>`;\n","/**\n * Cursor SVG icon for the select tool.\n */\nexport const selectIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/></svg>`;\n","/**\n * Trash can SVG icon for the delete tool.\n */\nexport const deleteIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"3 6 5 6 21 6\"/><path d=\"M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/></svg>`;\n","/**\n * Left arrow SVG icon for the undo action.\n */\nexport const undoIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"9 14 4 9 9 4\"/><path d=\"M20 20v-7a4 4 0 00-4-4H4\"/></svg>`;\n","/**\n * Right arrow SVG icon for the redo action.\n */\nexport const redoIcon = `<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" width=\"18\" height=\"18\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"15 14 20 9 15 4\"/><path d=\"M4 20v-7a4 4 0 014-4h12\"/></svg>`;\n","import type { Map as MaplibreMap } from 'maplibre-gl';\nimport type { ToolbarOptions, ToolbarControls } from '../types/options';\nimport { ToolbarButton } from './ToolbarButton';\nimport { drawIcon } from './icons/draw';\nimport { selectIcon } from './icons/select';\nimport { deleteIcon } from './icons/delete';\nimport { undoIcon } from './icons/undo';\nimport { redoIcon } from './icons/redo';\n\n/**\n * Default toolbar control visibility.\n */\nconst DEFAULT_CONTROLS: Required<ToolbarControls> = {\n draw: true,\n select: true,\n delete: true,\n undo: true,\n redo: true,\n};\n\n/**\n * Callbacks that the Toolbar needs from the host application.\n */\nexport interface ToolbarCallbacks {\n onDrawClick(): void;\n onSelectClick(): void;\n onDeleteClick(): void;\n onUndoClick(): void;\n onRedoClick(): void;\n}\n\n/**\n * Creates and manages the drawing toolbar UI.\n *\n * The toolbar is positioned on the map using MapLibre's control\n * container system. It creates buttons for draw, select, delete,\n * undo, and redo actions. Button states are updated externally\n * to reflect the current mode and history state.\n */\nexport class Toolbar {\n private map: MaplibreMap;\n private container: HTMLDivElement;\n private buttons: Map<string, ToolbarButton> = new Map();\n private callbacks: ToolbarCallbacks;\n private options: ToolbarOptions;\n\n constructor(\n map: MaplibreMap,\n callbacks: ToolbarCallbacks,\n options: ToolbarOptions = {},\n ) {\n this.map = map;\n this.callbacks = callbacks;\n this.options = options;\n\n this.container = document.createElement('div');\n this.container.className = 'libre-draw-toolbar';\n this.applyContainerStyles();\n\n this.createButtons();\n this.mount();\n }\n\n /**\n * Update the active mode displayed in the toolbar.\n * @param mode - The active mode name ('idle', 'draw', 'select').\n */\n setActiveMode(mode: string): void {\n const drawBtn = this.buttons.get('draw');\n const selectBtn = this.buttons.get('select');\n\n if (drawBtn) {\n drawBtn.setActive(mode === 'draw');\n }\n if (selectBtn) {\n selectBtn.setActive(mode === 'select');\n }\n }\n\n /**\n * Update the undo/redo button states.\n * @param canUndo - Whether undo is available.\n * @param canRedo - Whether redo is available.\n */\n setHistoryState(canUndo: boolean, canRedo: boolean): void {\n const undoBtn = this.buttons.get('undo');\n const redoBtn = this.buttons.get('redo');\n\n if (undoBtn) {\n undoBtn.setDisabled(!canUndo);\n }\n if (redoBtn) {\n redoBtn.setDisabled(!canRedo);\n }\n }\n\n /**\n * Remove the toolbar from the map and clean up.\n */\n destroy(): void {\n for (const button of this.buttons.values()) {\n button.destroy();\n }\n this.buttons.clear();\n this.container.remove();\n }\n\n /**\n * Create all toolbar buttons based on the configured controls.\n */\n private createButtons(): void {\n const controls: Required<ToolbarControls> = {\n ...DEFAULT_CONTROLS,\n ...this.options.controls,\n };\n\n if (controls.draw) {\n this.addButton('draw', drawIcon, 'Draw polygon', () => {\n this.callbacks.onDrawClick();\n }, true);\n }\n\n if (controls.select) {\n this.addButton('select', selectIcon, 'Select feature', () => {\n this.callbacks.onSelectClick();\n }, true);\n }\n\n if (controls.delete) {\n this.addButton('delete', deleteIcon, 'Delete selected', () => {\n this.callbacks.onDeleteClick();\n });\n }\n\n if (controls.undo) {\n this.addButton('undo', undoIcon, 'Undo', () => {\n this.callbacks.onUndoClick();\n });\n }\n\n if (controls.redo) {\n this.addButton('redo', redoIcon, 'Redo', () => {\n this.callbacks.onRedoClick();\n });\n }\n }\n\n /**\n * Create a button and add it to the toolbar.\n */\n private addButton(\n id: string,\n icon: string,\n title: string,\n onClick: () => void,\n isToggle?: boolean,\n ): void {\n const button = new ToolbarButton({ id, icon, title, onClick, isToggle });\n this.buttons.set(id, button);\n this.container.appendChild(button.getElement());\n }\n\n /**\n * Mount the toolbar container to the map's control container.\n */\n private mount(): void {\n const position = this.options.position || 'top-right';\n\n // MapLibre organizes controls into positioned containers\n const mapContainer = this.map.getContainer();\n const controlContainer = mapContainer.querySelector(\n `.maplibregl-ctrl-${position}`,\n );\n\n if (controlContainer) {\n controlContainer.appendChild(this.container);\n } else {\n // Fallback: append to the map container directly\n mapContainer.appendChild(this.container);\n }\n }\n\n /**\n * Apply CSS styles to the toolbar container.\n */\n private applyContainerStyles(): void {\n const s = this.container.style;\n s.display = 'flex';\n s.flexDirection = 'column';\n s.gap = '4px';\n s.padding = '4px';\n s.backgroundColor = 'rgba(255, 255, 255, 0.9)';\n s.borderRadius = '4px';\n s.boxShadow = '0 1px 4px rgba(0, 0, 0, 0.3)';\n s.zIndex = '1';\n // MapLibre's control containers have pointer-events: none;\n // controls need pointer-events: auto to receive clicks\n s.pointerEvents = 'auto';\n }\n}\n","import type { Map as MaplibreMap } from 'maplibre-gl';\nimport type {\n LibreDrawFeature,\n LibreDrawEventMap,\n LibreDrawOptions,\n ToolbarOptions,\n} from './types';\nimport { DeleteAction } from './types/features';\nimport { EventBus } from './core/EventBus';\nimport { FeatureStore } from './core/FeatureStore';\nimport { HistoryManager } from './core/HistoryManager';\nimport { ModeManager } from './core/ModeManager';\nimport type { ModeName } from './core/ModeManager';\nimport { LibreDrawError } from './core/errors';\nimport { validateGeoJSON, validateFeature } from './validation/geojson';\nimport { IdleMode } from './modes/IdleMode';\nimport { DrawMode } from './modes/DrawMode';\nimport { SelectMode } from './modes/SelectMode';\nimport { InputHandler } from './input/InputHandler';\nimport { SourceManager } from './rendering/SourceManager';\nimport { RenderManager } from './rendering/RenderManager';\nimport { Toolbar } from './ui/Toolbar';\n\n/**\n * LibreDraw - A MapLibre GL JS polygon drawing and editing library.\n *\n * This is the main facade class that wires together all internal modules\n * (event bus, feature store, history, modes, input, rendering, toolbar)\n * and exposes a clean public API.\n *\n * @example\n * ```ts\n * const draw = new LibreDraw(map, { toolbar: true });\n * draw.setMode('draw');\n * draw.on('create', (e) => console.log('Created:', e.feature));\n * ```\n */\nexport class LibreDraw {\n private map: MaplibreMap;\n private eventBus: EventBus;\n private featureStore: FeatureStore;\n private historyManager: HistoryManager;\n private modeManager: ModeManager;\n private inputHandler: InputHandler;\n private sourceManager: SourceManager;\n private renderManager: RenderManager;\n private toolbar: Toolbar | null = null;\n private selectMode: SelectMode;\n private destroyed = false;\n\n /**\n * Create a new LibreDraw instance attached to a MapLibre GL JS map.\n *\n * Initializes all internal modules and sets up map integration.\n * The instance is ready to use once the map's style is loaded.\n *\n * @param map - The MapLibre GL JS map instance to draw on.\n * @param options - Configuration options. Defaults to toolbar enabled\n * and 100-action history limit.\n *\n * @example\n * ```ts\n * const draw = new LibreDraw(map);\n * // Or with options:\n * const draw = new LibreDraw(map, {\n * toolbar: { position: 'top-right' },\n * historyLimit: 50,\n * });\n * ```\n */\n constructor(map: MaplibreMap, options: LibreDrawOptions = {}) {\n this.map = map;\n\n // Core modules\n this.eventBus = new EventBus();\n this.featureStore = new FeatureStore();\n this.historyManager = new HistoryManager(options.historyLimit ?? 100);\n this.modeManager = new ModeManager();\n\n // Rendering\n this.sourceManager = new SourceManager(map);\n this.renderManager = new RenderManager(map, this.sourceManager);\n\n // Mode setup\n const drawMode = new DrawMode({\n addFeatureToStore: (feature) => this.featureStore.add(feature),\n pushToHistory: (action) => {\n this.historyManager.push(action);\n this.updateToolbarHistoryState();\n },\n emitEvent: (type, payload) => this.eventBus.emit(type, payload),\n renderPreview: (coords) => this.renderManager.renderPreview(coords),\n clearPreview: () => this.renderManager.clearPreview(),\n renderFeatures: () => this.renderAllFeatures(),\n getScreenPoint: (lngLat) => {\n const pt = map.project([lngLat.lng, lngLat.lat]);\n return { x: pt.x, y: pt.y };\n },\n });\n\n this.selectMode = new SelectMode(\n {\n removeFeatureFromStore: (id) => this.featureStore.remove(id),\n pushToHistory: (action) => {\n this.historyManager.push(action);\n this.updateToolbarHistoryState();\n },\n emitEvent: (type, payload) => this.eventBus.emit(type, payload),\n renderFeatures: () => this.renderAllFeatures(),\n getFeatureById: (id) => this.featureStore.getById(id),\n getAllFeatures: () => this.featureStore.getAll(),\n getScreenPoint: (lngLat) => {\n const pt = map.project([lngLat.lng, lngLat.lat]);\n return { x: pt.x, y: pt.y };\n },\n updateFeatureInStore: (id, feature) =>\n this.featureStore.update(id, feature),\n renderVertices: (_featureId, vertices, midpoints, highlightIndex) =>\n this.renderManager.renderVertices(vertices, midpoints, highlightIndex),\n clearVertices: () => this.renderManager.clearVertices(),\n setDragPan: (enabled) => {\n if (enabled) {\n map.dragPan.enable();\n } else {\n map.dragPan.disable();\n }\n },\n },\n (selectedIds) => {\n this.renderManager.setSelectedIds(selectedIds);\n },\n );\n\n // Register modes\n this.modeManager.registerMode('idle', new IdleMode());\n this.modeManager.registerMode('draw', drawMode);\n this.modeManager.registerMode('select', this.selectMode);\n\n // Mode change event\n this.modeManager.setOnModeChange((mode, previousMode) => {\n this.eventBus.emit('modechange', { mode, previousMode });\n if (this.toolbar) {\n this.toolbar.setActiveMode(mode);\n }\n\n // Disable map interactions that conflict with drawing/editing\n if (mode === 'draw') {\n map.dragPan.disable();\n map.doubleClickZoom.disable();\n } else if (mode === 'select') {\n map.doubleClickZoom.disable();\n // dragPan stays enabled; SelectMode disables it during vertex drag\n } else {\n map.dragPan.enable();\n map.doubleClickZoom.enable();\n }\n });\n\n // Input handling\n this.inputHandler = new InputHandler(\n map,\n () => this.modeManager.getCurrentMode(),\n );\n\n // Toolbar\n if (options.toolbar !== false && options.toolbar !== undefined) {\n const toolbarOpts: ToolbarOptions =\n typeof options.toolbar === 'object' ? options.toolbar : {};\n this.createToolbar(toolbarOpts);\n }\n\n // Initialize when map is ready\n if (map.isStyleLoaded()) {\n this.initialize();\n } else {\n map.once('load', () => {\n this.initialize();\n });\n }\n }\n\n /**\n * Set the active drawing mode.\n *\n * Switching modes deactivates the current mode (clearing any\n * in-progress state) and activates the new mode. A `'modechange'`\n * event is emitted on every transition.\n *\n * @param mode - `'idle'` (no interaction), `'draw'` (create polygons),\n * or `'select'` (select/edit existing polygons).\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * draw.setMode('draw');\n * draw.on('modechange', (e) => {\n * console.log(`${e.previousMode} -> ${e.mode}`);\n * });\n * ```\n */\n setMode(mode: ModeName): void {\n this.assertNotDestroyed();\n this.modeManager.setMode(mode);\n }\n\n /**\n * Get the current drawing mode.\n *\n * @returns The active mode name: `'idle'`, `'draw'`, or `'select'`.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * if (draw.getMode() === 'draw') {\n * console.log('Currently drawing');\n * }\n * ```\n */\n getMode(): ModeName {\n this.assertNotDestroyed();\n return this.modeManager.getMode();\n }\n\n /**\n * Get all features as an array.\n *\n * Returns a snapshot of all polygon features currently in the store.\n *\n * @returns An array of all {@link LibreDrawFeature} objects.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * const features = draw.getFeatures();\n * console.log(`${features.length} polygons on the map`);\n * ```\n */\n getFeatures(): LibreDrawFeature[] {\n this.assertNotDestroyed();\n return this.featureStore.getAll();\n }\n\n /**\n * Replace all features in the store with the given GeoJSON FeatureCollection.\n *\n * Validates the input, clears the current store and history, and\n * re-renders the map. Undo/redo history is reset after this call.\n *\n * @param geojson - A GeoJSON FeatureCollection containing Polygon features.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n * @throws {LibreDrawError} If the input is not a valid FeatureCollection\n * or contains invalid polygon geometries.\n *\n * @example\n * ```ts\n * draw.setFeatures({\n * type: 'FeatureCollection',\n * features: [{\n * type: 'Feature',\n * geometry: {\n * type: 'Polygon',\n * coordinates: [[[0,0],[10,0],[10,10],[0,10],[0,0]]]\n * },\n * properties: {}\n * }]\n * });\n * ```\n */\n setFeatures(geojson: unknown): void {\n this.assertNotDestroyed();\n const validated = validateGeoJSON(geojson);\n this.featureStore.setAll(validated.features);\n this.historyManager.clear();\n this.renderAllFeatures();\n this.updateToolbarHistoryState();\n }\n\n /**\n * Add features to the store from an array of GeoJSON Feature objects.\n *\n * Each feature is validated and added. Unlike {@link setFeatures},\n * this does not clear existing features or history.\n *\n * @param features - An array of GeoJSON Feature objects with Polygon geometry.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n * @throws {LibreDrawError} If any feature has invalid geometry.\n *\n * @example\n * ```ts\n * draw.addFeatures([{\n * type: 'Feature',\n * geometry: {\n * type: 'Polygon',\n * coordinates: [[[0,0],[5,0],[5,5],[0,5],[0,0]]]\n * },\n * properties: { name: 'Zone A' }\n * }]);\n * ```\n */\n addFeatures(features: unknown[]): void {\n this.assertNotDestroyed();\n for (const feature of features) {\n const validated = validateFeature(feature);\n this.featureStore.add(validated);\n }\n this.renderAllFeatures();\n }\n\n /**\n * Get the IDs of currently selected features.\n *\n * Returns selected IDs in select mode. In other modes, returns\n * an empty array since selection is cleared on mode transition.\n *\n * @returns An array of selected feature IDs.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * draw.on('selectionchange', (e) => {\n * const ids = draw.getSelectedFeatureIds();\n * console.log('Selected:', ids);\n * });\n * ```\n */\n getSelectedFeatureIds(): string[] {\n this.assertNotDestroyed();\n return this.selectMode.getSelectedIds();\n }\n\n /**\n * Get a feature by its ID.\n *\n * @param id - The unique identifier of the feature.\n * @returns The feature, or `undefined` if not found.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * const feature = draw.getFeatureById('abc-123');\n * if (feature) {\n * console.log(feature.geometry.coordinates);\n * }\n * ```\n */\n getFeatureById(id: string): LibreDrawFeature | undefined {\n this.assertNotDestroyed();\n return this.featureStore.getById(id);\n }\n\n /**\n * Delete a feature by its ID.\n *\n * Removes the feature from the store, records a {@link DeleteAction}\n * in the history (making it undoable), and emits a `'delete'` event.\n * If the feature is currently selected, the selection is also cleared.\n *\n * @param id - The unique identifier of the feature to delete.\n * @returns The deleted feature, or `undefined` if not found.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * const deleted = draw.deleteFeature('abc-123');\n * if (deleted) {\n * draw.undo(); // restores the deleted feature\n * }\n * ```\n */\n deleteFeature(id: string): LibreDrawFeature | undefined {\n this.assertNotDestroyed();\n\n const feature = this.featureStore.getById(id);\n if (!feature) return undefined;\n\n // Clear selection if the feature is selected\n const selectedIds = this.selectMode.getSelectedIds();\n if (selectedIds.includes(id)) {\n this.selectMode.clearSelection();\n }\n\n this.featureStore.remove(id);\n const action = new DeleteAction(feature);\n this.historyManager.push(action);\n this.eventBus.emit('delete', { feature });\n this.renderAllFeatures();\n this.updateToolbarHistoryState();\n\n return feature;\n }\n\n /**\n * Programmatically select a feature by its ID.\n *\n * Switches to select mode if not already active. The feature\n * must exist in the store.\n *\n * @param id - The unique identifier of the feature to select.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n * @throws {LibreDrawError} If no feature with the given ID exists.\n *\n * @example\n * ```ts\n * draw.selectFeature('abc-123');\n * console.log(draw.getSelectedFeatureIds()); // ['abc-123']\n * console.log(draw.getMode()); // 'select'\n * ```\n */\n selectFeature(id: string): void {\n this.assertNotDestroyed();\n\n const feature = this.featureStore.getById(id);\n if (!feature) {\n throw new LibreDrawError(`Feature not found: ${id}`);\n }\n\n if (this.modeManager.getMode() !== 'select') {\n this.modeManager.setMode('select');\n }\n\n this.selectMode.selectFeature(id);\n }\n\n /**\n * Clear the current feature selection.\n *\n * Deselects all features, removes vertex handles, and emits\n * a `'selectionchange'` event. No-op if nothing is selected.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * draw.selectFeature('abc-123');\n * draw.clearSelection();\n * console.log(draw.getSelectedFeatureIds()); // []\n * ```\n */\n clearSelection(): void {\n this.assertNotDestroyed();\n this.selectMode.clearSelection();\n }\n\n /**\n * Undo the last action.\n *\n * Reverts the most recent action (create, update, or delete) and\n * updates the map rendering. If a feature is selected and its\n * geometry changes, vertex handles are refreshed.\n *\n * @returns `true` if an action was undone, `false` if nothing to undo.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * if (draw.undo()) {\n * console.log('Action undone');\n * }\n * ```\n */\n undo(): boolean {\n this.assertNotDestroyed();\n const result = this.historyManager.undo(this.featureStore);\n if (result) {\n this.renderAllFeatures();\n this.selectMode.refreshVertexHandles();\n this.updateToolbarHistoryState();\n }\n return result;\n }\n\n /**\n * Redo the last undone action.\n *\n * Re-applies the most recently undone action. The redo stack is\n * cleared whenever a new action is performed.\n *\n * @returns `true` if an action was redone, `false` if nothing to redo.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * draw.undo();\n * draw.redo(); // re-applies the undone action\n * ```\n */\n redo(): boolean {\n this.assertNotDestroyed();\n const result = this.historyManager.redo(this.featureStore);\n if (result) {\n this.renderAllFeatures();\n this.selectMode.refreshVertexHandles();\n this.updateToolbarHistoryState();\n }\n return result;\n }\n\n /**\n * Register an event listener.\n *\n * Supported events: `'create'`, `'update'`, `'delete'`,\n * `'selectionchange'`, `'modechange'`.\n *\n * @param type - The event type to listen for.\n * @param listener - The callback to invoke when the event fires.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * draw.on('create', (e) => console.log('Created:', e.feature.id));\n * draw.on('update', (e) => console.log('Updated:', e.feature.id));\n * draw.on('delete', (e) => console.log('Deleted:', e.feature.id));\n * draw.on('selectionchange', (e) => console.log('Selected:', e.selectedIds));\n * draw.on('modechange', (e) => console.log(`${e.previousMode} -> ${e.mode}`));\n * ```\n */\n on<K extends keyof LibreDrawEventMap>(\n type: K,\n listener: (payload: LibreDrawEventMap[K]) => void,\n ): void {\n this.assertNotDestroyed();\n this.eventBus.on(type, listener);\n }\n\n /**\n * Remove an event listener.\n *\n * The listener must be the same function reference passed to {@link on}.\n *\n * @param type - The event type to stop listening for.\n * @param listener - The callback to remove.\n *\n * @throws {LibreDrawError} If this instance has been destroyed.\n *\n * @example\n * ```ts\n * const handler = (e: CreateEvent) => console.log(e.feature);\n * draw.on('create', handler);\n * draw.off('create', handler);\n * ```\n */\n off<K extends keyof LibreDrawEventMap>(\n type: K,\n listener: (payload: LibreDrawEventMap[K]) => void,\n ): void {\n this.assertNotDestroyed();\n this.eventBus.off(type, listener);\n }\n\n /**\n * Destroy the LibreDraw instance, cleaning up all resources.\n *\n * Switches to idle mode, removes all map layers/sources, clears\n * the event bus, history, and feature store, and removes the toolbar.\n * After calling destroy, all other methods will throw\n * {@link LibreDrawError}. Calling destroy on an already-destroyed\n * instance is a no-op.\n *\n * @example\n * ```ts\n * draw.destroy();\n * // draw.getFeatures(); // throws LibreDrawError\n * ```\n */\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n this.modeManager.setMode('idle');\n this.inputHandler.destroy();\n this.renderManager.destroy();\n this.eventBus.removeAllListeners();\n this.historyManager.clear();\n this.featureStore.clear();\n\n if (this.toolbar) {\n this.toolbar.destroy();\n this.toolbar = null;\n }\n }\n\n /**\n * Initialize rendering and input handling after the map is ready.\n */\n private initialize(): void {\n if (this.destroyed) return;\n this.renderManager.initialize();\n this.inputHandler.enable();\n }\n\n /**\n * Render all features from the store to the map.\n */\n private renderAllFeatures(): void {\n const features = this.featureStore.getAll();\n this.renderManager.render(features);\n }\n\n /**\n * Create the toolbar UI.\n */\n private createToolbar(options: ToolbarOptions): void {\n this.toolbar = new Toolbar(\n this.map,\n {\n onDrawClick: () => {\n const current = this.modeManager.getMode();\n this.modeManager.setMode(current === 'draw' ? 'idle' : 'draw');\n },\n onSelectClick: () => {\n const current = this.modeManager.getMode();\n this.modeManager.setMode(\n current === 'select' ? 'idle' : 'select',\n );\n },\n onDeleteClick: () => {\n if (this.modeManager.getMode() === 'select') {\n const selectedIds = this.selectMode.getSelectedIds();\n for (const id of selectedIds) {\n this.deleteFeature(id);\n }\n }\n },\n onUndoClick: () => {\n this.undo();\n },\n onRedoClick: () => {\n this.redo();\n },\n },\n options,\n );\n\n // Set initial states\n this.toolbar.setActiveMode(this.modeManager.getMode());\n this.toolbar.setHistoryState(\n this.historyManager.canUndo(),\n this.historyManager.canRedo(),\n );\n }\n\n /**\n * Update toolbar undo/redo button states.\n */\n private updateToolbarHistoryState(): void {\n if (this.toolbar) {\n this.toolbar.setHistoryState(\n this.historyManager.canUndo(),\n this.historyManager.canRedo(),\n );\n }\n }\n\n /**\n * Assert that this instance has not been destroyed.\n * @throws LibreDrawError if destroyed.\n */\n private assertNotDestroyed(): void {\n if (this.destroyed) {\n throw new LibreDrawError(\n 'This LibreDraw instance has been destroyed.',\n );\n }\n }\n}\n"],"names":["CreateAction","feature","store","UpdateAction","id","oldFeature","newFeature","DeleteAction","EventBus","type","listener","set","payload","FeatureStore","stored","features","ring","pos","HistoryManager","limit","action","ModeManager","name","mode","callback","previousMode","current","next","LibreDrawError","message","orientation","p","q","r","val","onSegment","posEqual","a","b","segmentsIntersect","p1","p2","p3","p4","o1","o2","o3","o4","hasRingSelfIntersection","n","i","j","wouldNewVertexCauseIntersection","vertices","newVertex","lastVertex","wouldClosingCauseIntersection","first","last","positionsEqual","validateCoordinate","position","lng","lat","validateRing","validateFeature","f","geom","coordinates","validateGeoJSON","geojson","obj","fc","validatedFeatures","err","IdleMode","_event","_key","CLOSE_THRESHOLD_PX","MIN_VERTICES","DrawMode","callbacks","event","firstVertex","firstScreenPt","dx","dy","key","cursorPos","coords","previewCoords","epsilon","splitter","resulterrbound","sum","elen","flen","h","Q","Qnew","hh","bvirt","enow","fnow","eindex","findex","hindex","estimate","vec","ccwerrboundA","ccwerrboundB","ccwerrboundC","B","C1","C2","D","u","orient2dadapt","ax","ay","bx","by","cx","cy","detsum","acxtail","acytail","bcxtail","bcytail","ahi","alo","bhi","blo","_i","_j","_0","s1","s0","t1","t0","u3","acx","bcx","acy","bcy","det","errbound","C1len","C2len","Dlen","orient2d","detleft","detright","pointInPolygon","polygon","ii","k","u1","v1","u2","v2","currentP","nextP","x","y","numContours","contour","contourLen","properties","options","feat","point","isNumber","num","getCoord","coord","getGeom","booleanPointInPolygon","pt","bbox","polys","inBBox","result","polyResult","pip","index_default","HIT_THRESHOLD_MOUSE_PX","HIT_THRESHOLD_TOUCH_PX","SelectMode","onSelectionChange","selectedId","threshold","vertexIdx","midpoints","midIdx","beforeInsert","bodyClick","turfPoint","clickPoint","hitFeature","newPos","updatedFeature","dLng","dLat","nearIdx","currentFeature","points","minDist","minIdx","screenPt","dist","vertexIndex","startLngLat","insertIndex","newVertices","_","idsToDelete","ids","MouseInput","map","e","rect","lngLat","DOUBLE_TAP_MS","LONG_PRESS_MS","LONG_PRESS_TOLERANCE","TouchInput","normalized","now","touch","_KeyboardInput","KeyboardInput","InputHandler","getActiveMode","pointerCallbacks","_a","SOURCE_IDS","EMPTY_FC","SourceManager","data","source","LAYER_IDS","COLORS","RenderManager","sourceManager","geojsonCoords","previewGeoJSON","highlightIndex","v","m","layerIds","featureCollection","ToolbarButton","active","disabled","svgString","svg","s","drawIcon","selectIcon","deleteIcon","undoIcon","redoIcon","DEFAULT_CONTROLS","Toolbar","drawBtn","selectBtn","canUndo","canRedo","undoBtn","redoBtn","button","controls","icon","title","onClick","isToggle","mapContainer","controlContainer","LibreDraw","drawMode","_featureId","enabled","selectedIds","toolbarOpts","validated"],"mappings":"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","x_google_ignoreList":[10,11,12,13,14,15]}
@@ -0,0 +1,70 @@
1
+ import type { Mode } from './Mode';
2
+ import type { NormalizedInputEvent } from '../types/input';
3
+ import type { LibreDrawFeature, Position, Action } from '../types/features';
4
+ import type { LibreDrawEventMap } from '../types/events';
5
+ /**
6
+ * Callbacks that DrawMode needs from the host application.
7
+ */
8
+ export interface DrawModeCallbacks {
9
+ /** Add a feature to the store and return it with its assigned ID. */
10
+ addFeatureToStore(feature: LibreDrawFeature): LibreDrawFeature;
11
+ /** Push an action to the history manager. */
12
+ pushToHistory(action: Action): void;
13
+ /** Emit an event through the event bus. */
14
+ emitEvent<K extends keyof LibreDrawEventMap>(type: K, payload: LibreDrawEventMap[K]): void;
15
+ /** Render a preview of the polygon being drawn. */
16
+ renderPreview(coordinates: Position[]): void;
17
+ /** Clear the drawing preview. */
18
+ clearPreview(): void;
19
+ /** Re-render all features. */
20
+ renderFeatures(): void;
21
+ /** Convert a geographic coordinate to a screen point. */
22
+ getScreenPoint(lngLat: {
23
+ lng: number;
24
+ lat: number;
25
+ }): {
26
+ x: number;
27
+ y: number;
28
+ };
29
+ }
30
+ /**
31
+ * Drawing mode for creating new polygons.
32
+ *
33
+ * Users click to add vertices. The polygon is finalized when:
34
+ * - The user double-clicks (with at least 3 vertices), or
35
+ * - The user clicks within 10px of the first vertex (closing the ring).
36
+ *
37
+ * Long press removes the last vertex (undo last point).
38
+ * Escape cancels the entire drawing.
39
+ */
40
+ export declare class DrawMode implements Mode {
41
+ private vertices;
42
+ private isActive;
43
+ private callbacks;
44
+ constructor(callbacks: DrawModeCallbacks);
45
+ activate(): void;
46
+ deactivate(): void;
47
+ onPointerDown(event: NormalizedInputEvent): void;
48
+ onPointerMove(event: NormalizedInputEvent): void;
49
+ onPointerUp(_event: NormalizedInputEvent): void;
50
+ onDoubleClick(event: NormalizedInputEvent): void;
51
+ onLongPress(_event: NormalizedInputEvent): void;
52
+ onKeyDown(key: string, _event: KeyboardEvent): void;
53
+ /**
54
+ * Build the preview coordinate ring for rendering,
55
+ * including cursor position if available.
56
+ */
57
+ private buildPreviewCoordinates;
58
+ /**
59
+ * Update the preview rendering with the current cursor position.
60
+ */
61
+ private updatePreview;
62
+ /**
63
+ * Finalize the polygon: create the feature, push to history, emit event.
64
+ */
65
+ private finalizePolygon;
66
+ /**
67
+ * Cancel the current drawing operation.
68
+ */
69
+ private cancelDrawing;
70
+ }
@@ -0,0 +1,16 @@
1
+ import type { Mode } from './Mode';
2
+ import type { NormalizedInputEvent } from '../types/input';
3
+ /**
4
+ * The idle mode where no drawing or editing is active.
5
+ * All input handlers are no-ops.
6
+ */
7
+ export declare class IdleMode implements Mode {
8
+ activate(): void;
9
+ deactivate(): void;
10
+ onPointerDown(_event: NormalizedInputEvent): void;
11
+ onPointerMove(_event: NormalizedInputEvent): void;
12
+ onPointerUp(_event: NormalizedInputEvent): void;
13
+ onDoubleClick(_event: NormalizedInputEvent): void;
14
+ onLongPress(_event: NormalizedInputEvent): void;
15
+ onKeyDown(_key: string, _event: KeyboardEvent): void;
16
+ }
@@ -0,0 +1,26 @@
1
+ import type { NormalizedInputEvent } from '../types/input';
2
+ /**
3
+ * Interface that all drawing modes must implement.
4
+ *
5
+ * Each mode handles user input differently and can maintain
6
+ * its own internal state. Modes are activated and deactivated
7
+ * by the ModeManager during transitions.
8
+ */
9
+ export interface Mode {
10
+ /** Called when the mode becomes active. */
11
+ activate(): void;
12
+ /** Called when the mode is deactivated. */
13
+ deactivate(): void;
14
+ /** Handle a pointer down (mouse click or touch start). */
15
+ onPointerDown(event: NormalizedInputEvent): void;
16
+ /** Handle pointer movement. */
17
+ onPointerMove(event: NormalizedInputEvent): void;
18
+ /** Handle pointer up (mouse release or touch end). */
19
+ onPointerUp(event: NormalizedInputEvent): void;
20
+ /** Handle a double-click or double-tap. */
21
+ onDoubleClick(event: NormalizedInputEvent): void;
22
+ /** Handle a long press (touch hold). */
23
+ onLongPress(event: NormalizedInputEvent): void;
24
+ /** Handle a key down event. */
25
+ onKeyDown(key: string, event: KeyboardEvent): void;
26
+ }