@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Sindicum
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,149 @@
1
+ # LibreDraw
2
+
3
+ [![npm version](https://img.shields.io/npm/v/%40sindicum%2Flibre-draw.svg)](https://www.npmjs.com/package/@sindicum/libre-draw)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ A polygon drawing and editing library for [MapLibre GL JS](https://maplibre.org/).
7
+
8
+ ## Features
9
+
10
+ - **Zero-config** — `new LibreDraw(map)` gives you a full toolbar and drawing capabilities out of the box
11
+ - **Draw polygons** — Click/tap to place vertices, double-click/double-tap to finish
12
+ - **Select & edit** — Click a polygon to select it, drag vertices to reshape, drag midpoints to add vertices
13
+ - **Polygon drag** — Drag an entire selected polygon to reposition it
14
+ - **Undo / Redo** — Full history support for all operations
15
+ - **GeoJSON in/out** — Import and export standard GeoJSON FeatureCollections
16
+ - **Touch-first** — Designed for mobile with proper touch targets (44px+), long-press support, and gesture handling
17
+ - **Self-intersection prevention** — Invalid geometries are rejected during editing
18
+ - **Framework-agnostic** — Works with vanilla JS, React, Vue, or any framework
19
+ - **TypeScript** — Full type definitions included
20
+ - **Headless mode** — Disable the toolbar and drive everything via API
21
+
22
+ ## Quick Start
23
+
24
+ ```bash
25
+ npm install @sindicum/libre-draw maplibre-gl
26
+ ```
27
+
28
+ ```typescript
29
+ import maplibregl from 'maplibre-gl';
30
+ import 'maplibre-gl/dist/maplibre-gl.css';
31
+ import { LibreDraw } from '@sindicum/libre-draw';
32
+
33
+ const map = new maplibregl.Map({
34
+ container: 'map',
35
+ style: 'https://demotiles.maplibre.org/style.json',
36
+ center: [0, 0],
37
+ zoom: 2,
38
+ });
39
+
40
+ const draw = new LibreDraw(map);
41
+
42
+ draw.on('create', (e) => {
43
+ console.log('Polygon created:', e.feature);
44
+ });
45
+
46
+ draw.on('update', (e) => {
47
+ console.log('Polygon updated:', e.feature);
48
+ });
49
+ ```
50
+
51
+ ## API
52
+
53
+ ### Constructor
54
+
55
+ ```typescript
56
+ new LibreDraw(map: maplibregl.Map, options?: LibreDrawOptions)
57
+ ```
58
+
59
+ ### Methods
60
+
61
+ | Method | Description |
62
+ | ------------------------- | ----------------------------------------------------- |
63
+ | `setMode(mode)` | Set active mode: `'idle'`, `'draw'`, or `'select'` |
64
+ | `getMode()` | Get the current mode |
65
+ | `getFeatures()` | Get all features as an array |
66
+ | `getFeatureById(id)` | Get a single feature by ID |
67
+ | `setFeatures(geojson)` | Replace all features with a GeoJSON FeatureCollection |
68
+ | `addFeatures(features)` | Add an array of GeoJSON Feature objects |
69
+ | `deleteFeature(id)` | Delete a feature by ID (undoable) |
70
+ | `selectFeature(id)` | Programmatically select a feature |
71
+ | `clearSelection()` | Clear the current selection |
72
+ | `getSelectedFeatureIds()` | Get IDs of selected features |
73
+ | `undo()` | Undo the last action |
74
+ | `redo()` | Redo the last undone action |
75
+ | `on(event, callback)` | Register an event listener |
76
+ | `off(event, callback)` | Remove an event listener |
77
+ | `destroy()` | Clean up all resources |
78
+
79
+ ### Events
80
+
81
+ | Event | Payload | Description |
82
+ | ----------------- | ------------------------ | --------------------- |
83
+ | `create` | `{ feature }` | A polygon was created |
84
+ | `update` | `{ feature }` | A polygon was updated |
85
+ | `delete` | `{ feature }` | A polygon was deleted |
86
+ | `selectionchange` | `{ selectedIds }` | Selection changed |
87
+ | `modechange` | `{ mode, previousMode }` | Active mode changed |
88
+
89
+ ### Options
90
+
91
+ ```typescript
92
+ interface LibreDrawOptions {
93
+ toolbar?:
94
+ | boolean
95
+ | {
96
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
97
+ controls?: {
98
+ draw?: boolean;
99
+ select?: boolean;
100
+ delete?: boolean;
101
+ undo?: boolean;
102
+ redo?: boolean;
103
+ };
104
+ };
105
+ historyLimit?: number; // Default: 100
106
+ }
107
+ ```
108
+
109
+ Set `toolbar: false` for headless mode (API-only, no UI).
110
+
111
+ ## Documentation
112
+
113
+ Full documentation with interactive demos is available at:
114
+
115
+ **https://sindicum.github.io/libre-draw/**
116
+
117
+ ## Development
118
+
119
+ ```bash
120
+ # Install dependencies
121
+ npm install
122
+
123
+ # Run dev server with example
124
+ npm run dev
125
+
126
+ # Run tests
127
+ npm test
128
+
129
+ # Lint
130
+ npm run lint
131
+
132
+ # Type check
133
+ npm run typecheck
134
+
135
+ # Build
136
+ npm run build
137
+
138
+ # Documentation site
139
+ npm run docs:dev
140
+ ```
141
+
142
+ ## Requirements
143
+
144
+ - MapLibre GL JS >= 3.0.0, v3.x and v4.x supported (peer dependency)
145
+ - Modern browser with WebGL support
146
+
147
+ ## License
148
+
149
+ [MIT](./LICENSE)
@@ -0,0 +1,359 @@
1
+ import type { Map as MaplibreMap } from 'maplibre-gl';
2
+ import type { LibreDrawFeature, LibreDrawEventMap, LibreDrawOptions } from './types';
3
+ import type { ModeName } from './core/ModeManager';
4
+ /**
5
+ * LibreDraw - A MapLibre GL JS polygon drawing and editing library.
6
+ *
7
+ * This is the main facade class that wires together all internal modules
8
+ * (event bus, feature store, history, modes, input, rendering, toolbar)
9
+ * and exposes a clean public API.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const draw = new LibreDraw(map, { toolbar: true });
14
+ * draw.setMode('draw');
15
+ * draw.on('create', (e) => console.log('Created:', e.feature));
16
+ * ```
17
+ */
18
+ export declare class LibreDraw {
19
+ private map;
20
+ private eventBus;
21
+ private featureStore;
22
+ private historyManager;
23
+ private modeManager;
24
+ private inputHandler;
25
+ private sourceManager;
26
+ private renderManager;
27
+ private toolbar;
28
+ private selectMode;
29
+ private destroyed;
30
+ /**
31
+ * Create a new LibreDraw instance attached to a MapLibre GL JS map.
32
+ *
33
+ * Initializes all internal modules and sets up map integration.
34
+ * The instance is ready to use once the map's style is loaded.
35
+ *
36
+ * @param map - The MapLibre GL JS map instance to draw on.
37
+ * @param options - Configuration options. Defaults to toolbar enabled
38
+ * and 100-action history limit.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * const draw = new LibreDraw(map);
43
+ * // Or with options:
44
+ * const draw = new LibreDraw(map, {
45
+ * toolbar: { position: 'top-right' },
46
+ * historyLimit: 50,
47
+ * });
48
+ * ```
49
+ */
50
+ constructor(map: MaplibreMap, options?: LibreDrawOptions);
51
+ /**
52
+ * Set the active drawing mode.
53
+ *
54
+ * Switching modes deactivates the current mode (clearing any
55
+ * in-progress state) and activates the new mode. A `'modechange'`
56
+ * event is emitted on every transition.
57
+ *
58
+ * @param mode - `'idle'` (no interaction), `'draw'` (create polygons),
59
+ * or `'select'` (select/edit existing polygons).
60
+ *
61
+ * @throws {LibreDrawError} If this instance has been destroyed.
62
+ *
63
+ * @example
64
+ * ```ts
65
+ * draw.setMode('draw');
66
+ * draw.on('modechange', (e) => {
67
+ * console.log(`${e.previousMode} -> ${e.mode}`);
68
+ * });
69
+ * ```
70
+ */
71
+ setMode(mode: ModeName): void;
72
+ /**
73
+ * Get the current drawing mode.
74
+ *
75
+ * @returns The active mode name: `'idle'`, `'draw'`, or `'select'`.
76
+ *
77
+ * @throws {LibreDrawError} If this instance has been destroyed.
78
+ *
79
+ * @example
80
+ * ```ts
81
+ * if (draw.getMode() === 'draw') {
82
+ * console.log('Currently drawing');
83
+ * }
84
+ * ```
85
+ */
86
+ getMode(): ModeName;
87
+ /**
88
+ * Get all features as an array.
89
+ *
90
+ * Returns a snapshot of all polygon features currently in the store.
91
+ *
92
+ * @returns An array of all {@link LibreDrawFeature} objects.
93
+ *
94
+ * @throws {LibreDrawError} If this instance has been destroyed.
95
+ *
96
+ * @example
97
+ * ```ts
98
+ * const features = draw.getFeatures();
99
+ * console.log(`${features.length} polygons on the map`);
100
+ * ```
101
+ */
102
+ getFeatures(): LibreDrawFeature[];
103
+ /**
104
+ * Replace all features in the store with the given GeoJSON FeatureCollection.
105
+ *
106
+ * Validates the input, clears the current store and history, and
107
+ * re-renders the map. Undo/redo history is reset after this call.
108
+ *
109
+ * @param geojson - A GeoJSON FeatureCollection containing Polygon features.
110
+ *
111
+ * @throws {LibreDrawError} If this instance has been destroyed.
112
+ * @throws {LibreDrawError} If the input is not a valid FeatureCollection
113
+ * or contains invalid polygon geometries.
114
+ *
115
+ * @example
116
+ * ```ts
117
+ * draw.setFeatures({
118
+ * type: 'FeatureCollection',
119
+ * features: [{
120
+ * type: 'Feature',
121
+ * geometry: {
122
+ * type: 'Polygon',
123
+ * coordinates: [[[0,0],[10,0],[10,10],[0,10],[0,0]]]
124
+ * },
125
+ * properties: {}
126
+ * }]
127
+ * });
128
+ * ```
129
+ */
130
+ setFeatures(geojson: unknown): void;
131
+ /**
132
+ * Add features to the store from an array of GeoJSON Feature objects.
133
+ *
134
+ * Each feature is validated and added. Unlike {@link setFeatures},
135
+ * this does not clear existing features or history.
136
+ *
137
+ * @param features - An array of GeoJSON Feature objects with Polygon geometry.
138
+ *
139
+ * @throws {LibreDrawError} If this instance has been destroyed.
140
+ * @throws {LibreDrawError} If any feature has invalid geometry.
141
+ *
142
+ * @example
143
+ * ```ts
144
+ * draw.addFeatures([{
145
+ * type: 'Feature',
146
+ * geometry: {
147
+ * type: 'Polygon',
148
+ * coordinates: [[[0,0],[5,0],[5,5],[0,5],[0,0]]]
149
+ * },
150
+ * properties: { name: 'Zone A' }
151
+ * }]);
152
+ * ```
153
+ */
154
+ addFeatures(features: unknown[]): void;
155
+ /**
156
+ * Get the IDs of currently selected features.
157
+ *
158
+ * Returns selected IDs in select mode. In other modes, returns
159
+ * an empty array since selection is cleared on mode transition.
160
+ *
161
+ * @returns An array of selected feature IDs.
162
+ *
163
+ * @throws {LibreDrawError} If this instance has been destroyed.
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * draw.on('selectionchange', (e) => {
168
+ * const ids = draw.getSelectedFeatureIds();
169
+ * console.log('Selected:', ids);
170
+ * });
171
+ * ```
172
+ */
173
+ getSelectedFeatureIds(): string[];
174
+ /**
175
+ * Get a feature by its ID.
176
+ *
177
+ * @param id - The unique identifier of the feature.
178
+ * @returns The feature, or `undefined` if not found.
179
+ *
180
+ * @throws {LibreDrawError} If this instance has been destroyed.
181
+ *
182
+ * @example
183
+ * ```ts
184
+ * const feature = draw.getFeatureById('abc-123');
185
+ * if (feature) {
186
+ * console.log(feature.geometry.coordinates);
187
+ * }
188
+ * ```
189
+ */
190
+ getFeatureById(id: string): LibreDrawFeature | undefined;
191
+ /**
192
+ * Delete a feature by its ID.
193
+ *
194
+ * Removes the feature from the store, records a {@link DeleteAction}
195
+ * in the history (making it undoable), and emits a `'delete'` event.
196
+ * If the feature is currently selected, the selection is also cleared.
197
+ *
198
+ * @param id - The unique identifier of the feature to delete.
199
+ * @returns The deleted feature, or `undefined` if not found.
200
+ *
201
+ * @throws {LibreDrawError} If this instance has been destroyed.
202
+ *
203
+ * @example
204
+ * ```ts
205
+ * const deleted = draw.deleteFeature('abc-123');
206
+ * if (deleted) {
207
+ * draw.undo(); // restores the deleted feature
208
+ * }
209
+ * ```
210
+ */
211
+ deleteFeature(id: string): LibreDrawFeature | undefined;
212
+ /**
213
+ * Programmatically select a feature by its ID.
214
+ *
215
+ * Switches to select mode if not already active. The feature
216
+ * must exist in the store.
217
+ *
218
+ * @param id - The unique identifier of the feature to select.
219
+ *
220
+ * @throws {LibreDrawError} If this instance has been destroyed.
221
+ * @throws {LibreDrawError} If no feature with the given ID exists.
222
+ *
223
+ * @example
224
+ * ```ts
225
+ * draw.selectFeature('abc-123');
226
+ * console.log(draw.getSelectedFeatureIds()); // ['abc-123']
227
+ * console.log(draw.getMode()); // 'select'
228
+ * ```
229
+ */
230
+ selectFeature(id: string): void;
231
+ /**
232
+ * Clear the current feature selection.
233
+ *
234
+ * Deselects all features, removes vertex handles, and emits
235
+ * a `'selectionchange'` event. No-op if nothing is selected.
236
+ *
237
+ * @throws {LibreDrawError} If this instance has been destroyed.
238
+ *
239
+ * @example
240
+ * ```ts
241
+ * draw.selectFeature('abc-123');
242
+ * draw.clearSelection();
243
+ * console.log(draw.getSelectedFeatureIds()); // []
244
+ * ```
245
+ */
246
+ clearSelection(): void;
247
+ /**
248
+ * Undo the last action.
249
+ *
250
+ * Reverts the most recent action (create, update, or delete) and
251
+ * updates the map rendering. If a feature is selected and its
252
+ * geometry changes, vertex handles are refreshed.
253
+ *
254
+ * @returns `true` if an action was undone, `false` if nothing to undo.
255
+ *
256
+ * @throws {LibreDrawError} If this instance has been destroyed.
257
+ *
258
+ * @example
259
+ * ```ts
260
+ * if (draw.undo()) {
261
+ * console.log('Action undone');
262
+ * }
263
+ * ```
264
+ */
265
+ undo(): boolean;
266
+ /**
267
+ * Redo the last undone action.
268
+ *
269
+ * Re-applies the most recently undone action. The redo stack is
270
+ * cleared whenever a new action is performed.
271
+ *
272
+ * @returns `true` if an action was redone, `false` if nothing to redo.
273
+ *
274
+ * @throws {LibreDrawError} If this instance has been destroyed.
275
+ *
276
+ * @example
277
+ * ```ts
278
+ * draw.undo();
279
+ * draw.redo(); // re-applies the undone action
280
+ * ```
281
+ */
282
+ redo(): boolean;
283
+ /**
284
+ * Register an event listener.
285
+ *
286
+ * Supported events: `'create'`, `'update'`, `'delete'`,
287
+ * `'selectionchange'`, `'modechange'`.
288
+ *
289
+ * @param type - The event type to listen for.
290
+ * @param listener - The callback to invoke when the event fires.
291
+ *
292
+ * @throws {LibreDrawError} If this instance has been destroyed.
293
+ *
294
+ * @example
295
+ * ```ts
296
+ * draw.on('create', (e) => console.log('Created:', e.feature.id));
297
+ * draw.on('update', (e) => console.log('Updated:', e.feature.id));
298
+ * draw.on('delete', (e) => console.log('Deleted:', e.feature.id));
299
+ * draw.on('selectionchange', (e) => console.log('Selected:', e.selectedIds));
300
+ * draw.on('modechange', (e) => console.log(`${e.previousMode} -> ${e.mode}`));
301
+ * ```
302
+ */
303
+ on<K extends keyof LibreDrawEventMap>(type: K, listener: (payload: LibreDrawEventMap[K]) => void): void;
304
+ /**
305
+ * Remove an event listener.
306
+ *
307
+ * The listener must be the same function reference passed to {@link on}.
308
+ *
309
+ * @param type - The event type to stop listening for.
310
+ * @param listener - The callback to remove.
311
+ *
312
+ * @throws {LibreDrawError} If this instance has been destroyed.
313
+ *
314
+ * @example
315
+ * ```ts
316
+ * const handler = (e: CreateEvent) => console.log(e.feature);
317
+ * draw.on('create', handler);
318
+ * draw.off('create', handler);
319
+ * ```
320
+ */
321
+ off<K extends keyof LibreDrawEventMap>(type: K, listener: (payload: LibreDrawEventMap[K]) => void): void;
322
+ /**
323
+ * Destroy the LibreDraw instance, cleaning up all resources.
324
+ *
325
+ * Switches to idle mode, removes all map layers/sources, clears
326
+ * the event bus, history, and feature store, and removes the toolbar.
327
+ * After calling destroy, all other methods will throw
328
+ * {@link LibreDrawError}. Calling destroy on an already-destroyed
329
+ * instance is a no-op.
330
+ *
331
+ * @example
332
+ * ```ts
333
+ * draw.destroy();
334
+ * // draw.getFeatures(); // throws LibreDrawError
335
+ * ```
336
+ */
337
+ destroy(): void;
338
+ /**
339
+ * Initialize rendering and input handling after the map is ready.
340
+ */
341
+ private initialize;
342
+ /**
343
+ * Render all features from the store to the map.
344
+ */
345
+ private renderAllFeatures;
346
+ /**
347
+ * Create the toolbar UI.
348
+ */
349
+ private createToolbar;
350
+ /**
351
+ * Update toolbar undo/redo button states.
352
+ */
353
+ private updateToolbarHistoryState;
354
+ /**
355
+ * Assert that this instance has not been destroyed.
356
+ * @throws LibreDrawError if destroyed.
357
+ */
358
+ private assertNotDestroyed;
359
+ }
@@ -0,0 +1,37 @@
1
+ import type { LibreDrawEventMap } from '../types/events';
2
+ /**
3
+ * A listener callback for a given event type.
4
+ */
5
+ type Listener<T> = (payload: T) => void;
6
+ /**
7
+ * Type-safe event bus for LibreDraw events.
8
+ *
9
+ * Supports registering, removing, and emitting events
10
+ * defined in LibreDrawEventMap.
11
+ */
12
+ export declare class EventBus {
13
+ private listeners;
14
+ /**
15
+ * Register a listener for a specific event type.
16
+ * @param type - The event type to listen for.
17
+ * @param listener - The callback to invoke when the event fires.
18
+ */
19
+ on<K extends keyof LibreDrawEventMap>(type: K, listener: Listener<LibreDrawEventMap[K]>): void;
20
+ /**
21
+ * Remove a listener for a specific event type.
22
+ * @param type - The event type to stop listening for.
23
+ * @param listener - The callback to remove.
24
+ */
25
+ off<K extends keyof LibreDrawEventMap>(type: K, listener: Listener<LibreDrawEventMap[K]>): void;
26
+ /**
27
+ * Emit an event, invoking all registered listeners.
28
+ * @param type - The event type to emit.
29
+ * @param payload - The event payload.
30
+ */
31
+ emit<K extends keyof LibreDrawEventMap>(type: K, payload: LibreDrawEventMap[K]): void;
32
+ /**
33
+ * Remove all listeners for all event types.
34
+ */
35
+ removeAllListeners(): void;
36
+ }
37
+ export {};
@@ -0,0 +1,68 @@
1
+ import type { LibreDrawFeature, FeatureStoreInterface } from '../types/features';
2
+ /**
3
+ * A GeoJSON FeatureCollection containing LibreDraw polygons.
4
+ */
5
+ export interface FeatureCollection {
6
+ type: 'FeatureCollection';
7
+ features: LibreDrawFeature[];
8
+ }
9
+ /**
10
+ * Internal store for managing LibreDraw features.
11
+ *
12
+ * Features are stored in a Map keyed by their unique ID.
13
+ * Implements FeatureStoreInterface so that Action objects
14
+ * can manipulate the store.
15
+ */
16
+ export declare class FeatureStore implements FeatureStoreInterface {
17
+ private features;
18
+ /**
19
+ * Add a feature to the store. If the feature has no ID,
20
+ * a new UUID will be generated.
21
+ * @param feature - The feature to add.
22
+ * @returns The added feature (with ID assigned).
23
+ */
24
+ add(feature: LibreDrawFeature): LibreDrawFeature;
25
+ /**
26
+ * Update a feature in the store by ID.
27
+ * @param id - The ID of the feature to update.
28
+ * @param feature - The new feature data.
29
+ */
30
+ update(id: string, feature: LibreDrawFeature): void;
31
+ /**
32
+ * Remove a feature from the store by ID.
33
+ * @param id - The ID of the feature to remove.
34
+ * @returns The removed feature, or undefined if not found.
35
+ */
36
+ remove(id: string): LibreDrawFeature | undefined;
37
+ /**
38
+ * Get all features in the store.
39
+ * @returns An array of all features.
40
+ */
41
+ getAll(): LibreDrawFeature[];
42
+ /**
43
+ * Get a feature by its ID.
44
+ * @param id - The feature ID.
45
+ * @returns The feature, or undefined if not found.
46
+ */
47
+ getById(id: string): LibreDrawFeature | undefined;
48
+ /**
49
+ * Remove all features from the store.
50
+ */
51
+ clear(): void;
52
+ /**
53
+ * Replace all features in the store with the given array.
54
+ * @param features - The features to set.
55
+ */
56
+ setAll(features: LibreDrawFeature[]): void;
57
+ /**
58
+ * Export all features as a GeoJSON FeatureCollection.
59
+ * @returns A GeoJSON FeatureCollection.
60
+ */
61
+ toGeoJSON(): FeatureCollection;
62
+ /**
63
+ * Create a deep clone of a feature suitable for history snapshots.
64
+ * @param feature - The feature to clone.
65
+ * @returns A deep-cloned feature.
66
+ */
67
+ static cloneFeature(feature: LibreDrawFeature): LibreDrawFeature;
68
+ }
@@ -0,0 +1,47 @@
1
+ import type { Action, FeatureStoreInterface } from '../types/features';
2
+ /**
3
+ * Manages undo/redo history using an action-based stack.
4
+ *
5
+ * Each action knows how to apply and revert itself on the feature store.
6
+ * A configurable limit prevents unbounded memory growth.
7
+ */
8
+ export declare class HistoryManager {
9
+ private undoStack;
10
+ private redoStack;
11
+ private readonly limit;
12
+ /**
13
+ * Create a new HistoryManager.
14
+ * @param limit - Maximum number of actions to retain. Defaults to 100.
15
+ */
16
+ constructor(limit?: number);
17
+ /**
18
+ * Push a new action onto the history stack.
19
+ * Clears the redo stack since a new action invalidates any redo history.
20
+ * @param action - The action to record.
21
+ */
22
+ push(action: Action): void;
23
+ /**
24
+ * Undo the most recent action.
25
+ * @param store - The feature store to revert the action on.
26
+ * @returns True if an action was undone, false if the stack was empty.
27
+ */
28
+ undo(store: FeatureStoreInterface): boolean;
29
+ /**
30
+ * Redo the most recently undone action.
31
+ * @param store - The feature store to re-apply the action on.
32
+ * @returns True if an action was redone, false if the stack was empty.
33
+ */
34
+ redo(store: FeatureStoreInterface): boolean;
35
+ /**
36
+ * Whether there are actions that can be undone.
37
+ */
38
+ canUndo(): boolean;
39
+ /**
40
+ * Whether there are actions that can be redone.
41
+ */
42
+ canRedo(): boolean;
43
+ /**
44
+ * Clear all history.
45
+ */
46
+ clear(): void;
47
+ }