@emuanalytics/flow-rdf-core 4.0.3 → 4.0.5

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 (89) hide show
  1. package/README.md +1 -64
  2. package/dist/index.d.mts +36 -31
  3. package/dist/index.d.ts +36 -31
  4. package/dist/index.mjs +20 -3249
  5. package/dist/lib/context/context-registry.mjs +63 -0
  6. package/dist/lib/context/debugger.mjs +240 -0
  7. package/dist/lib/context/flow-context.mjs +61 -0
  8. package/dist/lib/context/global-state.mjs +70 -0
  9. package/dist/lib/context/map-registry.mjs +59 -0
  10. package/dist/lib/context/query-registry.mjs +53 -0
  11. package/dist/lib/errors/flow-error.mjs +10 -0
  12. package/dist/lib/errors/flow-expression-error.mjs +14 -0
  13. package/dist/lib/errors/flow-map-error.mjs +9 -0
  14. package/dist/lib/expressions/expression-parser.mjs +198 -0
  15. package/dist/lib/expressions/functions/from-palette.mjs +75 -0
  16. package/dist/lib/expressions/functions/regex.mjs +25 -0
  17. package/dist/lib/expressions/functions/state.mjs +25 -0
  18. package/dist/lib/expressions/parser-helpers.mjs +37 -0
  19. package/dist/lib/expressions/reactive-expression.mjs +253 -0
  20. package/dist/lib/map/flow-core-map.mjs +749 -0
  21. package/dist/lib/map/plugins/annotations/annotation-layers.mjs +163 -0
  22. package/dist/lib/map/plugins/annotations/annotation.events.mjs +27 -0
  23. package/dist/lib/map/plugins/annotations/annotation.plugin.mjs +498 -0
  24. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DirectModeOverride.mjs +67 -0
  25. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/modes/DragCircleMode.mjs +65 -0
  26. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/utils/create_supplementary_points_circle.mjs +15 -0
  27. package/dist/lib/map/plugins/annotations/maplibre-gl-draw-circle/lib/utils/drag_pan.mjs +20 -0
  28. package/dist/lib/map/plugins/data-join.plugin.mjs +173 -0
  29. package/dist/lib/map/plugins/export/export.plugin.mjs +21 -0
  30. package/dist/lib/map/plugins/export/map-exporter.mjs +177 -0
  31. package/dist/lib/map/plugins/hover-effect.plugin.mjs +58 -0
  32. package/dist/lib/map/plugins/index.d.mts +37 -72
  33. package/dist/lib/map/plugins/index.d.ts +37 -72
  34. package/dist/lib/map/plugins/index.mjs +11 -1811
  35. package/dist/lib/map/plugins/keyboard-shortcut-manager.mjs +120 -0
  36. package/dist/lib/map/plugins/map-plugin-base.mjs +25 -0
  37. package/dist/lib/map/plugins/plugin-manager.mjs +135 -0
  38. package/dist/lib/map/plugins/popup.plugin.mjs +55 -0
  39. package/dist/lib/map/plugins/selection/selection.events.mjs +21 -0
  40. package/dist/lib/map/plugins/selection/selection.plugin.mjs +136 -0
  41. package/dist/lib/map/plugins/selection/source-selection.mjs +156 -0
  42. package/dist/lib/map/plugins/url-sync.plugin.mjs +55 -0
  43. package/dist/lib/map/support/image-registry.mjs +82 -0
  44. package/dist/lib/map/support/map-events.mjs +71 -0
  45. package/dist/lib/map/support/map-feature-stream.mjs +158 -0
  46. package/dist/lib/map/support/map-popup.mjs +159 -0
  47. package/dist/lib/map/types.mjs +7 -0
  48. package/dist/lib/map-style/map-data-source.mjs +192 -0
  49. package/dist/lib/map-style/map-layer-style-builder-generated.mjs +1307 -0
  50. package/dist/lib/map-style/map-layer-style-builder.mjs +86 -0
  51. package/dist/lib/map-style/map-layer.mjs +223 -0
  52. package/dist/lib/map-style/map-style.mjs +178 -0
  53. package/dist/lib/queries/async-committer.mjs +30 -0
  54. package/dist/lib/queries/query.mjs +172 -0
  55. package/dist/lib/state-store/decorators.mjs +83 -0
  56. package/dist/lib/state-store/state-store.mjs +534 -0
  57. package/dist/lib/state-store/utils.mjs +7 -0
  58. package/dist/lib/utils/announce.mjs +12 -0
  59. package/dist/lib/utils/assert.mjs +12 -0
  60. package/dist/{shared/flow-rdf-core.187cb345.mjs → lib/utils/debounce.mjs} +3 -39
  61. package/dist/lib/utils/decorators.mjs +59 -0
  62. package/dist/lib/utils/deferred.mjs +11 -0
  63. package/dist/lib/utils/ensure-array.mjs +16 -0
  64. package/dist/{shared/flow-rdf-core.1f0901c5.mjs → lib/utils/feature-type-checks.mjs} +2 -2
  65. package/dist/lib/utils/functional.mjs +22 -0
  66. package/dist/lib/utils/global.mjs +18 -0
  67. package/dist/lib/utils/index.mjs +8 -5
  68. package/dist/lib/utils/random-id.mjs +9 -0
  69. package/dist/lib/utils/string-utils.mjs +3 -0
  70. package/dist/lib/utils/throttle.mjs +20 -0
  71. package/dist/{shared/flow-rdf-core.25e5f6d7.mjs → lib/utils/type-checks.mjs} +1 -26
  72. package/dist/lib/utils/watchable-promise.mjs +55 -0
  73. package/dist/package.json.mjs +3 -0
  74. package/dist/shared/{flow-rdf-core.4dde996e.d.cts → flow-rdf-core.8b5acf14.d.mts} +1315 -172
  75. package/dist/shared/{flow-rdf-core.4dde996e.d.ts → flow-rdf-core.8b5acf14.d.ts} +1315 -172
  76. package/package.json +4 -8
  77. package/dist/index.cjs +0 -3316
  78. package/dist/index.d.cts +0 -90
  79. package/dist/lib/map/plugins/index.cjs +0 -1851
  80. package/dist/lib/map/plugins/index.d.cts +0 -345
  81. package/dist/lib/utils/index.cjs +0 -48
  82. package/dist/lib/utils/index.d.cts +0 -160
  83. package/dist/shared/flow-rdf-core.06e85a6c.cjs +0 -1394
  84. package/dist/shared/flow-rdf-core.4dde996e.d.mts +0 -1916
  85. package/dist/shared/flow-rdf-core.55c169ca.cjs +0 -150
  86. package/dist/shared/flow-rdf-core.63162669.d.cts +0 -10
  87. package/dist/shared/flow-rdf-core.65045caf.mjs +0 -1360
  88. package/dist/shared/flow-rdf-core.a82b9be4.cjs +0 -34
  89. package/dist/shared/flow-rdf-core.f50908f0.cjs +0 -102
@@ -0,0 +1,163 @@
1
+ import { MapDataSource } from '../../../map-style/map-data-source.mjs';
2
+ import { MapLayer } from '../../../map-style/map-layer.mjs';
3
+
4
+ function addAnnotationLayers(map) {
5
+ map.transaction(() => {
6
+ const annotationSource = new MapDataSource({
7
+ id: "map-annotations",
8
+ type: "geojson",
9
+ src: { type: "FeatureCollection", features: [] },
10
+ featureId: "id"
11
+ });
12
+ map.addSource(annotationSource);
13
+ const polygonFillLayer = new MapLayer({
14
+ id: "map-annotations-polygon-fill",
15
+ type: "fill",
16
+ source: annotationSource.id,
17
+ filter: `geometry-type() == 'Polygon' && coalesce(@visible, true)`,
18
+ style: `
19
+ fill-color: @fillColor;
20
+ `
21
+ });
22
+ map.addLayer(polygonFillLayer);
23
+ const polygonStrokeLayer = new MapLayer({
24
+ id: "map-annotations-polygon-stroke",
25
+ type: "line",
26
+ source: annotationSource.id,
27
+ filter: `geometry-type() == 'Polygon' && coalesce(@visible, true)`,
28
+ style: `
29
+ line-color: @strokeColor;
30
+ line-width: @strokeWidth;
31
+ `
32
+ });
33
+ map.addLayer(polygonStrokeLayer);
34
+ const lineStrokeLayer = new MapLayer({
35
+ id: "map-annotations-line-stroke",
36
+ type: "line",
37
+ source: annotationSource.id,
38
+ filter: `geometry-type() == 'LineString' && coalesce(@visible, true)`,
39
+ style: `
40
+ line-color: @strokeColor;
41
+ line-width: @strokeWidth;
42
+ `
43
+ });
44
+ map.addLayer(lineStrokeLayer);
45
+ const pointLayer = new MapLayer({
46
+ id: "map-annotations-point",
47
+ type: "circle",
48
+ source: annotationSource.id,
49
+ filter: `geometry-type() == 'Point' && coalesce(@visible, true)`,
50
+ style: `
51
+ circle-radius: @radius;
52
+ circle-color: @fillColor;
53
+ circle-stroke-color: @strokeColor;
54
+ circle-stroke-width: @strokeWidth;
55
+ `
56
+ });
57
+ map.addLayer(pointLayer);
58
+ const polygonLabelsLayer = new MapLayer({
59
+ id: "map-annotations-polygon-labels",
60
+ type: "symbol",
61
+ source: annotationSource.id,
62
+ filter: `geometry-type() == 'Polygon' && to-boolean(@labelText) && coalesce(@visible, true)`,
63
+ interactive: false,
64
+ style: `
65
+ symbol-placement: 'point';
66
+ text-field: @labelText;
67
+ text-color: @labelColor;
68
+ text-size: @labelSize;
69
+ text-anchor: @polygonLabelAnchor;
70
+ /* text-offset: @labelOffset; */
71
+ text-justify: @labelJustify;
72
+ text-max-width: @labelMaxWidth;
73
+ text-allow-overlap: true;
74
+ `
75
+ });
76
+ map.addLayer(polygonLabelsLayer);
77
+ const pointLabelsLayer = new MapLayer({
78
+ id: "map-annotations-point-labels",
79
+ type: "symbol",
80
+ source: annotationSource.id,
81
+ filter: `geometry-type() == 'Point' && to-boolean(@labelText) && coalesce(@visible, true)`,
82
+ interactive: false,
83
+ style: `
84
+ symbol-placement: 'point';
85
+ text-field: @labelText;
86
+ text-color: @labelColor;
87
+ text-size: @labelSize;
88
+ text-anchor: @labelAnchor;
89
+ text-offset: @labelOffset;
90
+ /* text-radial-offset: (@radius + 8) / coalesce(@labelSize, {{annotationsStyleDefaults.labelSize}}); */
91
+ text-justify: @labelJustify;
92
+ text-max-width: @labelMaxWidth;
93
+ text-allow-overlap: true;
94
+ `
95
+ });
96
+ map.addLayer(pointLabelsLayer);
97
+ const lineLabelsLayer = new MapLayer({
98
+ id: "map-annotations-line-labels",
99
+ type: "symbol",
100
+ source: annotationSource.id,
101
+ filter: `geometry-type() == 'LineString' && to-boolean(@labelText) && coalesce(@visible, true)`,
102
+ interactive: false,
103
+ style: `
104
+ symbol-placement: 'line-center';
105
+ text-field: @labelText;
106
+ text-color: @labelColor;
107
+ text-anchor: @labelAnchor;
108
+ text-size: @labelSize;
109
+ /* text-offset: @labelOffset; */
110
+ text-justify: @labelJustify;
111
+ text-max-width: @labelMaxWidth;
112
+ text-allow-overlap: true;
113
+ text-ignore-placement: true;
114
+ `
115
+ });
116
+ map.addLayer(lineLabelsLayer);
117
+ const polygonSelectionLayer = new MapLayer({
118
+ id: "map-annotations-polygon-selection",
119
+ type: "line",
120
+ source: annotationSource.id,
121
+ filter: `geometry-type() == 'Polygon' && coalesce(@visible, true)`,
122
+ interactive: false,
123
+ style: `
124
+ line-color: @@selected ? @selectionStrokeColor : @@hover ? @hoverStrokeColor : transparent;
125
+ line-width: @selectionWidth;
126
+ line-opacity: @selectionStrokeOpacity;
127
+ `
128
+ });
129
+ map.addLayer(polygonSelectionLayer);
130
+ const pointSelectionLayer = new MapLayer({
131
+ id: "map-annotations-point-selection",
132
+ type: "circle",
133
+ source: annotationSource.id,
134
+ filter: `geometry-type() == 'Point' && coalesce(@visible, true)`,
135
+ interactive: false,
136
+ style: `
137
+ circle-radius: @radius + 1;
138
+ circle-color: transparent;
139
+ circle-stroke-color: @@selected ? @selectionStrokeColor : @@hover ? @hoverStrokeColor : transparent;
140
+ circle-stroke-width: @selectionWidth;
141
+ circle-stroke-opacity: @selectionStrokeOpacity;
142
+ `
143
+ });
144
+ map.addLayer(pointSelectionLayer);
145
+ const lineSelectionLayer = new MapLayer({
146
+ id: "map-annotations-line-selection",
147
+ type: "line",
148
+ source: annotationSource.id,
149
+ filter: `geometry-type() == 'LineString' && coalesce(@visible, true)`,
150
+ interactive: false,
151
+ style: `
152
+ line-color: @@selected ? @selectionStrokeColor : @@hover ? @hoverStrokeColor : transparent;
153
+ line-opacity: @selectionStrokeOpacity;
154
+ line-width: @selectionWidth/2;
155
+ line-gap-width: @strokeWidth;
156
+ `
157
+ });
158
+ map.addLayer(lineSelectionLayer);
159
+ });
160
+ return map.getSource("map-annotations");
161
+ }
162
+
163
+ export { addAnnotationLayers };
@@ -0,0 +1,27 @@
1
+ import { MapEvent } from '../../support/map-events.mjs';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
5
+ var __publicField = (obj, key, value) => {
6
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
7
+ return value;
8
+ };
9
+ class AnnotationEvent extends MapEvent {
10
+ constructor(type, map, data) {
11
+ super(type, map);
12
+ __publicField(this, "mode");
13
+ __publicField(this, "canUndo");
14
+ __publicField(this, "canRedo");
15
+ __publicField(this, "activeFeatureId");
16
+ __publicField(this, "activeFeatureType");
17
+ __publicField(this, "features");
18
+ this.mode = data.mode;
19
+ this.canUndo = data.canUndo;
20
+ this.canRedo = data.canRedo;
21
+ this.activeFeatureId = data.activeFeatureId;
22
+ this.activeFeatureType = data.activeFeatureType;
23
+ this.features = data.features;
24
+ }
25
+ }
26
+
27
+ export { AnnotationEvent };
@@ -0,0 +1,498 @@
1
+ import MapboxDraw from '@emuanalytics/mapbox-gl-draw';
2
+ import turfArea from '@turf/area';
3
+ import turfBBox from '@turf/bbox';
4
+ import turfBooleanEqual from '@turf/boolean-equal';
5
+ import turfBuffer from '@turf/buffer';
6
+ import turfLength from '@turf/length';
7
+ import Debug from 'debug';
8
+ import { isPolygon, isLineString, isPoint } from '../../../utils/feature-type-checks.mjs';
9
+ import { isNumber, isStringFull } from '../../../utils/type-checks.mjs';
10
+ import { randomId } from '../../../utils/random-id.mjs';
11
+ import { MapPluginBase } from '../map-plugin-base.mjs';
12
+ import { SelectionPlugin } from '../selection/selection.plugin.mjs';
13
+ import { addAnnotationLayers } from './annotation-layers.mjs';
14
+ import { AnnotationEvent } from './annotation.events.mjs';
15
+ import DirectMode from './maplibre-gl-draw-circle/lib/modes/DirectModeOverride.mjs';
16
+ import DragCircleMode from './maplibre-gl-draw-circle/lib/modes/DragCircleMode.mjs';
17
+ import { FlowCoreError } from '../../../errors/flow-error.mjs';
18
+
19
+ var __defProp = Object.defineProperty;
20
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
21
+ var __publicField = (obj, key, value) => {
22
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
23
+ return value;
24
+ };
25
+ Debug("flow:annotation-plugin");
26
+ const _AnnotationPlugin = class _AnnotationPlugin extends MapPluginBase {
27
+ constructor(pluginManager, options) {
28
+ super(pluginManager, options);
29
+ __publicField(this, "name", "AnnotationPlugin");
30
+ // Feature data model
31
+ __publicField(this, "_features", /* @__PURE__ */ new Map());
32
+ __publicField(this, "_featureIds", []);
33
+ // Undo/redo stacks
34
+ __publicField(this, "_undoStack", []);
35
+ __publicField(this, "_redoStack", []);
36
+ // Editing state
37
+ __publicField(this, "_mode", "idle");
38
+ __publicField(this, "_activeFeatureId", null);
39
+ __publicField(this, "_activeFeatureType", null);
40
+ __publicField(this, "_onCommitCleanup", []);
41
+ __publicField(this, "_annotationDataSource");
42
+ __publicField(this, "_drawControl", null);
43
+ __publicField(this, "_removeKeyboardShortcuts", null);
44
+ this.options = { ..._AnnotationPlugin._defaultOptions, ...options };
45
+ this.options.defaultStyle = { ..._AnnotationPlugin._defaultOptions.defaultStyle, ...options?.defaultStyle };
46
+ }
47
+ initialize() {
48
+ this._annotationDataSource = addAnnotationLayers(this.map);
49
+ if (this.options.selectionOptions) {
50
+ this.map.getPlugin(SelectionPlugin).enableSelection(this._annotationDataSource.id, this.options.selectionOptions);
51
+ }
52
+ if (this.options.interactive) {
53
+ this._removeKeyboardShortcuts = this.pluginManager.addKeyboardShortcuts({
54
+ "Enter,Escape": () => {
55
+ this.commit();
56
+ },
57
+ "Delete,Backspace": () => this.deleteSelectedFeature(),
58
+ "Ctrl+KeyZ": () => {
59
+ this.undo();
60
+ },
61
+ "Ctrl+Shift+KeyZ": () => {
62
+ this.redo();
63
+ },
64
+ KeyP: () => this.createFeature("Polygon"),
65
+ KeyL: () => this.createFeature("LineString"),
66
+ KeyM: () => this.createFeature("Point"),
67
+ KeyC: () => this.createFeature("Circle")
68
+ });
69
+ }
70
+ }
71
+ destroy() {
72
+ if (this._removeKeyboardShortcuts)
73
+ this._removeKeyboardShortcuts();
74
+ }
75
+ clear() {
76
+ this.commit();
77
+ this._featureIds = [];
78
+ this._features = /* @__PURE__ */ new Map();
79
+ this._undoStack = [];
80
+ this._redoStack = [];
81
+ this._mode = "idle";
82
+ this._activeFeatureId = null;
83
+ this._activeFeatureType = null;
84
+ this.render();
85
+ return this;
86
+ }
87
+ undo() {
88
+ const operation = this._undoStack.pop();
89
+ if (operation) {
90
+ operation.undo();
91
+ this._redoStack.push(operation);
92
+ this.render();
93
+ }
94
+ return this;
95
+ }
96
+ /**
97
+ * Redo the last undone operation.
98
+ */
99
+ redo() {
100
+ const operation = this._redoStack.pop();
101
+ if (operation) {
102
+ operation.do();
103
+ this._undoStack.push(operation);
104
+ this.render();
105
+ }
106
+ return this;
107
+ }
108
+ getFeature(featureId) {
109
+ const feature = this._features.get(featureId);
110
+ if (!feature) {
111
+ throw new FlowCoreError(`<AnnotationPlugin>: No feature with id '${featureId}'`);
112
+ }
113
+ return feature;
114
+ }
115
+ getFeatures() {
116
+ return this._featureIds.map((id) => this._features.get(id));
117
+ }
118
+ setFeatures(features) {
119
+ this.commit();
120
+ const normalizedFeatures = features.map((f) => this.applyDefaults(f));
121
+ const oldFeatures = this._features;
122
+ const oldFeatureIds = this._featureIds;
123
+ const operation = {
124
+ do: () => {
125
+ this._featureIds = normalizedFeatures.map((f) => f.id);
126
+ this._features = new Map(normalizedFeatures.map((f) => [f.id, f]));
127
+ },
128
+ undo: () => {
129
+ this._featureIds = oldFeatureIds;
130
+ this._features = oldFeatures;
131
+ }
132
+ };
133
+ this.performOperation(operation);
134
+ return this;
135
+ }
136
+ addFeature(feature) {
137
+ this.commit();
138
+ const fullFeature = this.applyDefaults(feature);
139
+ const operation = {
140
+ do: () => {
141
+ this._features.set(fullFeature.id, fullFeature);
142
+ this._featureIds.push(fullFeature.id);
143
+ },
144
+ undo: () => {
145
+ this._features.delete(fullFeature.id);
146
+ const index = this._featureIds.indexOf(fullFeature.id);
147
+ if (index !== -1) {
148
+ this._featureIds.splice(index, 1);
149
+ }
150
+ }
151
+ };
152
+ this.performOperation(operation);
153
+ return fullFeature;
154
+ }
155
+ deleteFeature(featureId) {
156
+ this.commit();
157
+ if (!featureId) {
158
+ return this;
159
+ }
160
+ this.deselectFeature(featureId);
161
+ const feature = this.getFeature(featureId);
162
+ const operation = {
163
+ do: () => {
164
+ this._features.delete(featureId);
165
+ const index = this._featureIds.indexOf(featureId);
166
+ if (index !== -1) {
167
+ this._featureIds.splice(index, 1);
168
+ }
169
+ },
170
+ undo: () => {
171
+ this._features.set(featureId, feature);
172
+ this._featureIds.push(featureId);
173
+ }
174
+ };
175
+ this.performOperation(operation);
176
+ return this;
177
+ }
178
+ createFeature(featureType) {
179
+ this.commit();
180
+ this.startDrawing();
181
+ this._drawControl.changeMode(this.drawModeForFeatureType(featureType));
182
+ this._mode = "creating";
183
+ this._activeFeatureId = null;
184
+ this._activeFeatureType = featureType;
185
+ this.emitStateChange();
186
+ const commitChanges = () => {
187
+ setTimeout(() => this.commit(), 0);
188
+ };
189
+ this.map.maplibreMap.once("draw.create", commitChanges);
190
+ this.map.maplibreMap.once("draw.modechange", commitChanges);
191
+ this._onCommitCleanup.push(() => {
192
+ this.map.maplibreMap.off("draw.create", commitChanges);
193
+ this.map.maplibreMap.off("draw.modechange", commitChanges);
194
+ });
195
+ }
196
+ editFeature(featureId) {
197
+ const feature = this.getFeature(featureId);
198
+ this._mode = "editing";
199
+ this._activeFeatureId = featureId;
200
+ this._activeFeatureType = feature.properties.type;
201
+ const commitChanges = () => {
202
+ setTimeout(() => this.commit(), 0);
203
+ };
204
+ this.startDrawing();
205
+ this._drawControl.add(feature);
206
+ this.setFeatureProperty(featureId, "visible", false);
207
+ this.render();
208
+ switch (this.editModeForFeature(feature)) {
209
+ case "direct_select":
210
+ this._drawControl.changeMode("direct_select", {
211
+ featureId
212
+ });
213
+ this.map.maplibreMap.once("draw.modechange", commitChanges);
214
+ this._onCommitCleanup.push(() => this.map.maplibreMap.off("draw.modechange", commitChanges));
215
+ break;
216
+ case "simple_select":
217
+ this._drawControl.changeMode("simple_select", {
218
+ featureIds: [featureId]
219
+ });
220
+ this.map.maplibreMap.once("draw.selectionchange", commitChanges);
221
+ this._onCommitCleanup.push(() => this.map.maplibreMap.off("draw.selectionchange", commitChanges));
222
+ break;
223
+ }
224
+ }
225
+ zoomToFeature(featureId, animationOptions) {
226
+ const feature = this.getFeature(featureId);
227
+ if (!feature)
228
+ return this;
229
+ const bbox = feature.properties.type === "Point" ? turfBBox(turfBuffer(feature, 50)) : turfBBox(feature);
230
+ this.map.setBounds(bbox, animationOptions);
231
+ return this;
232
+ }
233
+ setFeatureProperty(featureId, property, value) {
234
+ const feature = this.getFeature(featureId);
235
+ const featureCopy = {
236
+ ...feature,
237
+ properties: { ...feature.properties, [property]: value }
238
+ };
239
+ this._features.set(featureId, featureCopy);
240
+ return this;
241
+ }
242
+ setFeatureProperties(featureId, properties) {
243
+ const feature = this.getFeature(featureId);
244
+ const featureCopy = {
245
+ ...feature,
246
+ properties: { ...feature.properties, ...properties }
247
+ };
248
+ this._features.set(featureId, featureCopy);
249
+ return this;
250
+ }
251
+ commit() {
252
+ this._onCommitCleanup.forEach((f) => f());
253
+ this._onCommitCleanup = [];
254
+ if (this._mode === "idle")
255
+ return this;
256
+ const drawControlFeature = this._drawControl.getAll().features[0];
257
+ let operation = null;
258
+ if (this._mode === "editing") {
259
+ const mapFeature = this.getFeature(this._activeFeatureId);
260
+ this.setFeatureProperty(mapFeature.id, "visible", true);
261
+ if (!turfBooleanEqual(mapFeature.geometry, drawControlFeature.geometry)) {
262
+ operation = {
263
+ do: () => {
264
+ this.setFeatureGeometry(mapFeature.id, drawControlFeature.geometry);
265
+ if (drawControlFeature.properties.type === "Circle") {
266
+ this.setFeatureProperty(mapFeature.id, "center", drawControlFeature.properties.circleCenter);
267
+ this.setFeatureProperty(mapFeature.id, "radiusInKm", drawControlFeature.properties.circleRadius);
268
+ }
269
+ },
270
+ undo: () => {
271
+ this.setFeatureGeometry(mapFeature.id, mapFeature.geometry);
272
+ if (mapFeature.properties.type === "Circle") {
273
+ this.setFeatureProperty(mapFeature.id, "center", mapFeature.properties.circleCenter);
274
+ this.setFeatureProperty(mapFeature.id, "radiusInKm", mapFeature.properties.circleRadius);
275
+ }
276
+ }
277
+ };
278
+ }
279
+ } else if (this._mode === "creating") {
280
+ if (this.isValidGeometry(drawControlFeature)) {
281
+ let createdFeature = drawControlFeature;
282
+ createdFeature.id = "";
283
+ this.applyDefaults(createdFeature);
284
+ operation = {
285
+ do: () => {
286
+ this._features.set(drawControlFeature.id, drawControlFeature);
287
+ this._featureIds.push(drawControlFeature.id);
288
+ if (this.options.selectionOptions?.mode === "single" || this.options.selectionOptions?.mode === "multi") {
289
+ this.map.getPlugin(SelectionPlugin).selectFeatures(this._annotationDataSource.id, drawControlFeature.id);
290
+ }
291
+ },
292
+ undo: () => {
293
+ createdFeature = this._features.get(createdFeature.id);
294
+ this._features.delete(createdFeature.id);
295
+ const index = this._featureIds.indexOf(createdFeature.id);
296
+ if (index !== -1) {
297
+ this._featureIds.splice(index, 1);
298
+ }
299
+ }
300
+ };
301
+ }
302
+ }
303
+ if (operation) {
304
+ this.performOperation(operation);
305
+ }
306
+ this._mode = "idle";
307
+ this._activeFeatureId = null;
308
+ this._activeFeatureType = null;
309
+ this.endDrawing();
310
+ this.render();
311
+ return this;
312
+ }
313
+ cancel() {
314
+ this._onCommitCleanup.forEach((f) => f());
315
+ this._onCommitCleanup = [];
316
+ if (this._mode === "idle")
317
+ return this;
318
+ if (this._mode === "editing") {
319
+ this.setFeatureProperty(this._activeFeatureId, "visible", true);
320
+ }
321
+ this._activeFeatureId = null;
322
+ this._activeFeatureType = null;
323
+ this._mode = "idle";
324
+ this.endDrawing();
325
+ this.render();
326
+ return this;
327
+ }
328
+ render() {
329
+ const renderedFeatures = {
330
+ type: "FeatureCollection",
331
+ features: this._featureIds.map((id) => this._features.get(id))
332
+ };
333
+ this._annotationDataSource.setSrc(renderedFeatures);
334
+ this.emitStateChange();
335
+ return this;
336
+ }
337
+ handleDblClick(event) {
338
+ if (!this.options.interactive) {
339
+ return;
340
+ }
341
+ const clickedFeature = event.features[0];
342
+ if (clickedFeature && clickedFeature.source === this._annotationDataSource.id) {
343
+ this.editFeature(clickedFeature.id.toString());
344
+ }
345
+ }
346
+ handleBeforeStyleChanged(event) {
347
+ const { oldStyle, newStyle } = event;
348
+ if (this._drawControl) {
349
+ if (oldStyle.sources["mapbox-gl-draw"]) {
350
+ newStyle.sources["mapbox-gl-draw"] = oldStyle.sources["mapbox-gl-draw"];
351
+ }
352
+ oldStyle.layers.filter((l) => l.id.startsWith("gl-draw")).forEach((l) => newStyle.layers.push(l));
353
+ }
354
+ return newStyle;
355
+ }
356
+ startDrawing() {
357
+ if (this._drawControl) {
358
+ return this._drawControl;
359
+ }
360
+ this.pluginManager.setExclusivePlugin(this);
361
+ this._drawControl = new MapboxDraw({
362
+ displayControlsDefault: false,
363
+ keybindings: false,
364
+ modes: {
365
+ ...MapboxDraw.modes,
366
+ drag_circle: DragCircleMode,
367
+ direct_select: DirectMode
368
+ //...options.modes
369
+ },
370
+ userProperties: true
371
+ });
372
+ this.map.maplibreMap.addControl(this._drawControl);
373
+ return this._drawControl;
374
+ }
375
+ endDrawing() {
376
+ this.pluginManager.removeExclusivePlugin(this);
377
+ if (this._drawControl) {
378
+ this.map.maplibreMap.removeControl(this._drawControl);
379
+ this._drawControl = null;
380
+ }
381
+ }
382
+ applyDefaults(feature) {
383
+ feature.id = feature.properties.id = this.generateFeatureId(feature);
384
+ feature.properties = {
385
+ id: this.generateFeatureId(feature),
386
+ name: this.generateFeatureName(feature),
387
+ type: feature.properties.type ?? feature.geometry.type,
388
+ selected: false,
389
+ ...this.options.defaultStyle,
390
+ ...feature.properties
391
+ };
392
+ feature.id = feature.properties.id;
393
+ return feature;
394
+ }
395
+ generateFeatureId(feature) {
396
+ if (isNumber(feature.id) || isStringFull(feature.id)) {
397
+ return feature.id.toString();
398
+ } else {
399
+ return randomId("feature");
400
+ }
401
+ }
402
+ generateFeatureName(feature) {
403
+ const type = feature.properties.type ?? feature.geometry.type;
404
+ return `${type} ${this._featureIds.length}`;
405
+ }
406
+ performOperation(operation) {
407
+ this._undoStack.push(operation);
408
+ this._redoStack.length = 0;
409
+ operation.do();
410
+ }
411
+ deselectFeature(featureId) {
412
+ if (this.options.selectionOptions?.mode === "single" || this.options.selectionOptions?.mode === "multi") {
413
+ this.map.getPlugin(SelectionPlugin).deselectFeatures(this._annotationDataSource.id, featureId);
414
+ }
415
+ }
416
+ deleteSelectedFeature() {
417
+ if (this.options.selectionOptions?.mode === "single" || this.options.selectionOptions?.mode === "multi") {
418
+ const selected = this.map.getPlugin(SelectionPlugin).selectedFeatureIds(this._annotationDataSource.id);
419
+ selected.forEach((id) => this.deleteFeature(id));
420
+ this.render();
421
+ }
422
+ }
423
+ editModeForFeature(feature) {
424
+ switch (feature.geometry.type) {
425
+ case "Point":
426
+ return "simple_select";
427
+ default:
428
+ return "direct_select";
429
+ }
430
+ }
431
+ drawModeForFeatureType(featureType) {
432
+ switch (featureType) {
433
+ case "Polygon":
434
+ return "draw_polygon";
435
+ case "LineString":
436
+ return "draw_line_string";
437
+ case "Point":
438
+ return "draw_point";
439
+ case "Circle":
440
+ return "drag_circle";
441
+ default:
442
+ throw new Error(`Unrecognized feature type: ${featureType}`);
443
+ }
444
+ }
445
+ setFeatureGeometry(featureId, geometry) {
446
+ const feature = this.getFeature(featureId);
447
+ const featureCopy = {
448
+ ...feature,
449
+ geometry
450
+ };
451
+ this._features.set(featureId, featureCopy);
452
+ return featureCopy;
453
+ }
454
+ isValidGeometry(feature) {
455
+ if (isPolygon(feature)) {
456
+ return feature.geometry.coordinates[0][0] !== null && feature.geometry.coordinates[0].length > 3 && turfArea(feature) > 0;
457
+ } else if (isLineString(feature)) {
458
+ return feature.geometry.coordinates.length > 1 && turfLength(feature) > 0;
459
+ } else if (isPoint(feature)) {
460
+ return feature.geometry.coordinates.length > 0;
461
+ }
462
+ return false;
463
+ }
464
+ emitStateChange() {
465
+ const eventData = {
466
+ mode: this._mode,
467
+ canUndo: this._undoStack.length > 0,
468
+ canRedo: this._redoStack.length > 0,
469
+ activeFeatureId: this._activeFeatureId,
470
+ activeFeatureType: this._activeFeatureType,
471
+ features: this._featureIds.map((id) => this._features.get(id))
472
+ };
473
+ this.emit("annotationStateChanged", new AnnotationEvent("annotationStateChanged", this.map, eventData));
474
+ }
475
+ };
476
+ __publicField(_AnnotationPlugin, "_defaultOptions", {
477
+ interactive: true,
478
+ defaultStyle: {
479
+ labelSize: 10,
480
+ labelColor: "#ffffff",
481
+ labelMaxWidth: 10,
482
+ labelOffset: [0, 0.5],
483
+ labelJustify: "auto",
484
+ labelAnchor: "top",
485
+ polygonLabelAnchor: "center",
486
+ radius: 5,
487
+ fillColor: "rgba(204,204,204,0.65)",
488
+ strokeWidth: 1,
489
+ strokeColor: "#ffffff",
490
+ selectionStrokeColor: "orange",
491
+ selectionStrokeOpacity: 0.5,
492
+ selectionWidth: 3,
493
+ hoverStrokeColor: "transparent"
494
+ }
495
+ });
496
+ let AnnotationPlugin = _AnnotationPlugin;
497
+
498
+ export { AnnotationPlugin };