@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.
- package/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/LibreDraw.d.ts +359 -0
- package/dist/core/EventBus.d.ts +37 -0
- package/dist/core/FeatureStore.d.ts +68 -0
- package/dist/core/HistoryManager.d.ts +47 -0
- package/dist/core/ModeManager.d.ts +44 -0
- package/dist/core/errors.d.ts +6 -0
- package/dist/index.d.ts +7 -0
- package/dist/input/InputHandler.d.ts +29 -0
- package/dist/input/KeyboardInput.d.ts +31 -0
- package/dist/input/MouseInput.d.ts +41 -0
- package/dist/input/TouchInput.d.ts +58 -0
- package/dist/libre-draw.cjs +2 -0
- package/dist/libre-draw.cjs.map +1 -0
- package/dist/libre-draw.js +2116 -0
- package/dist/libre-draw.js.map +1 -0
- package/dist/modes/DrawMode.d.ts +70 -0
- package/dist/modes/IdleMode.d.ts +16 -0
- package/dist/modes/Mode.d.ts +26 -0
- package/dist/modes/SelectMode.d.ts +158 -0
- package/dist/rendering/RenderManager.d.ts +80 -0
- package/dist/rendering/SourceManager.d.ts +52 -0
- package/dist/types/events.d.ts +43 -0
- package/dist/types/features.d.ts +80 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/input.d.ts +23 -0
- package/dist/types/options.d.ts +30 -0
- package/dist/ui/Toolbar.d.ts +59 -0
- package/dist/ui/ToolbarButton.d.ts +53 -0
- package/dist/ui/icons/delete.d.ts +4 -0
- package/dist/ui/icons/draw.d.ts +4 -0
- package/dist/ui/icons/redo.d.ts +4 -0
- package/dist/ui/icons/select.d.ts +4 -0
- package/dist/ui/icons/undo.d.ts +4 -0
- package/dist/validation/geojson.d.ts +20 -0
- package/dist/validation/intersection.d.ts +28 -0
- 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
|
+
[](https://www.npmjs.com/package/@sindicum/libre-draw)
|
|
4
|
+
[](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
|
+
}
|