@emuanalytics/flow-rdf-core 0.0.15

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 (34) hide show
  1. package/README.md +64 -0
  2. package/dist/flow-rdf-core.css +1 -0
  3. package/dist/index.cjs +3102 -0
  4. package/dist/index.d.cts +61 -0
  5. package/dist/index.d.mts +61 -0
  6. package/dist/index.d.ts +61 -0
  7. package/dist/index.mjs +3062 -0
  8. package/dist/lib/map/plugins/index.cjs +1652 -0
  9. package/dist/lib/map/plugins/index.d.cts +309 -0
  10. package/dist/lib/map/plugins/index.d.mts +309 -0
  11. package/dist/lib/map/plugins/index.d.ts +309 -0
  12. package/dist/lib/map/plugins/index.mjs +1614 -0
  13. package/dist/lib/utils/index.cjs +45 -0
  14. package/dist/lib/utils/index.d.cts +39 -0
  15. package/dist/lib/utils/index.d.mts +39 -0
  16. package/dist/lib/utils/index.d.ts +39 -0
  17. package/dist/lib/utils/index.mjs +5 -0
  18. package/dist/shared/flow-rdf-core.08975378.d.cts +68 -0
  19. package/dist/shared/flow-rdf-core.08975378.d.mts +68 -0
  20. package/dist/shared/flow-rdf-core.08975378.d.ts +68 -0
  21. package/dist/shared/flow-rdf-core.278a260a.cjs +1364 -0
  22. package/dist/shared/flow-rdf-core.2e456f93.mjs +83 -0
  23. package/dist/shared/flow-rdf-core.3042be4a.cjs +93 -0
  24. package/dist/shared/flow-rdf-core.84eded74.cjs +34 -0
  25. package/dist/shared/flow-rdf-core.b4b16e78.mjs +1329 -0
  26. package/dist/shared/flow-rdf-core.b80085b4.mjs +66 -0
  27. package/dist/shared/flow-rdf-core.bd95d618.mjs +29 -0
  28. package/dist/shared/flow-rdf-core.c44cf082.cjs +88 -0
  29. package/dist/shared/flow-rdf-core.c9d2f730.d.cts +1815 -0
  30. package/dist/shared/flow-rdf-core.c9d2f730.d.mts +1815 -0
  31. package/dist/shared/flow-rdf-core.c9d2f730.d.ts +1815 -0
  32. package/package.json +106 -0
  33. package/plugins/package.json +7 -0
  34. package/utils/package.json +7 -0
@@ -0,0 +1,1652 @@
1
+ 'use strict';
2
+
3
+ const mapFeatureStream = require('../../../shared/flow-rdf-core.278a260a.cjs');
4
+ const MapboxDraw = require('@emuanalytics/mapbox-gl-draw');
5
+ const turfArea = require('@turf/area');
6
+ const turfBBox = require('@turf/bbox');
7
+ const turfBooleanEqual = require('@turf/boolean-equal');
8
+ const turfBuffer = require('@turf/buffer');
9
+ const turfLength = require('@turf/length');
10
+ const Debug = require('debug');
11
+ const featureTypeChecks = require('../../../shared/flow-rdf-core.84eded74.cjs');
12
+ const EventEmitter = require('eventemitter3');
13
+ const stringUtils = require('../../../shared/flow-rdf-core.3042be4a.cjs');
14
+ const lit = require('lit-html');
15
+ const maplibre = require('@emuanalytics/maplibre-gl');
16
+ const turfCircle = require('@turf/circle');
17
+ const turfDistance = require('@turf/distance');
18
+ const helpers = require('@turf/helpers');
19
+ const mobx = require('mobx');
20
+ require('@emuanalytics/maplibre-gl-style-spec');
21
+ require('mobx-utils');
22
+ require('parsimmon');
23
+ require('colorbrewer');
24
+ require('nanoid');
25
+ require('@turf/invariant');
26
+
27
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
28
+
29
+ function _interopNamespaceCompat(e) {
30
+ if (e && typeof e === 'object' && 'default' in e) return e;
31
+ const n = Object.create(null);
32
+ if (e) {
33
+ for (const k in e) {
34
+ n[k] = e[k];
35
+ }
36
+ }
37
+ n.default = e;
38
+ return n;
39
+ }
40
+
41
+ const MapboxDraw__default = /*#__PURE__*/_interopDefaultCompat(MapboxDraw);
42
+ const turfArea__default = /*#__PURE__*/_interopDefaultCompat(turfArea);
43
+ const turfBBox__default = /*#__PURE__*/_interopDefaultCompat(turfBBox);
44
+ const turfBooleanEqual__default = /*#__PURE__*/_interopDefaultCompat(turfBooleanEqual);
45
+ const turfBuffer__default = /*#__PURE__*/_interopDefaultCompat(turfBuffer);
46
+ const turfLength__default = /*#__PURE__*/_interopDefaultCompat(turfLength);
47
+ const Debug__default = /*#__PURE__*/_interopDefaultCompat(Debug);
48
+ const EventEmitter__default = /*#__PURE__*/_interopDefaultCompat(EventEmitter);
49
+ const lit__namespace = /*#__PURE__*/_interopNamespaceCompat(lit);
50
+ const maplibre__default = /*#__PURE__*/_interopDefaultCompat(maplibre);
51
+ const turfCircle__default = /*#__PURE__*/_interopDefaultCompat(turfCircle);
52
+ const turfDistance__default = /*#__PURE__*/_interopDefaultCompat(turfDistance);
53
+
54
+ var __defProp$a = Object.defineProperty;
55
+ var __defNormalProp$a = (obj, key, value) => key in obj ? __defProp$a(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
56
+ var __publicField$a = (obj, key, value) => {
57
+ __defNormalProp$a(obj, typeof key !== "symbol" ? key + "" : key, value);
58
+ return value;
59
+ };
60
+ class AnnotationEvent extends mapFeatureStream.MapEvent {
61
+ constructor(type, map, data) {
62
+ super(type, map);
63
+ __publicField$a(this, "mode");
64
+ __publicField$a(this, "canUndo");
65
+ __publicField$a(this, "canRedo");
66
+ __publicField$a(this, "activeFeatureId");
67
+ __publicField$a(this, "activeFeatureType");
68
+ __publicField$a(this, "features");
69
+ this.mode = data.mode;
70
+ this.canUndo = data.canUndo;
71
+ this.canRedo = data.canRedo;
72
+ this.activeFeatureId = data.activeFeatureId;
73
+ this.activeFeatureType = data.activeFeatureType;
74
+ this.features = data.features;
75
+ }
76
+ }
77
+
78
+ var __defProp$9 = Object.defineProperty;
79
+ var __defNormalProp$9 = (obj, key, value) => key in obj ? __defProp$9(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
80
+ var __publicField$9 = (obj, key, value) => {
81
+ __defNormalProp$9(obj, typeof key !== "symbol" ? key + "" : key, value);
82
+ return value;
83
+ };
84
+ class MapPluginBase extends EventEmitter.EventEmitter {
85
+ constructor(pluginManager, options) {
86
+ super();
87
+ __publicField$9(this, "_pluginManager");
88
+ __publicField$9(this, "options");
89
+ this._pluginManager = pluginManager;
90
+ this.options = options ?? {};
91
+ }
92
+ get map() {
93
+ return this._pluginManager.map;
94
+ }
95
+ get pluginManager() {
96
+ return this._pluginManager;
97
+ }
98
+ }
99
+
100
+ function isFeatureWithId(f) {
101
+ return stringUtils.isDefined(f) && stringUtils.isDefined(f.source) && stringUtils.isDefined(f.id);
102
+ }
103
+
104
+ var __defProp$8 = Object.defineProperty;
105
+ var __defNormalProp$8 = (obj, key, value) => key in obj ? __defProp$8(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
106
+ var __publicField$8 = (obj, key, value) => {
107
+ __defNormalProp$8(obj, typeof key !== "symbol" ? key + "" : key, value);
108
+ return value;
109
+ };
110
+ Debug__default("flow:map-popup");
111
+ class MapPopup extends EventEmitter__default {
112
+ /**
113
+ * Constructs a new `MapPopup` instance.
114
+ *
115
+ * This is called by the `FlowMap::openPopup` method.
116
+ *
117
+ * @param map Parent Flo.w map.
118
+ * @param options Popup options.
119
+ */
120
+ constructor(map, options) {
121
+ super();
122
+ this.map = map;
123
+ this.options = options;
124
+ __publicField$8(this, "_feature");
125
+ __publicField$8(this, "_contentContainer");
126
+ __publicField$8(this, "_featureStream", null);
127
+ //private _featureStreamSubscription: ISubscription | null = null;
128
+ __publicField$8(this, "_maplibrePopup", null);
129
+ __publicField$8(this, "_featureStreamDisposer");
130
+ this.options = {
131
+ // Defaults
132
+ closeButton: true,
133
+ closeOnClick: false,
134
+ closeOnMove: false,
135
+ maxWidth: "300px",
136
+ trackFeature: true,
137
+ //
138
+ ...this.options
139
+ };
140
+ }
141
+ get feature() {
142
+ return this._feature;
143
+ }
144
+ /**
145
+ * Close the popup.
146
+ */
147
+ close() {
148
+ if (this._maplibrePopup) {
149
+ this._maplibrePopup.remove();
150
+ this._maplibrePopup = null;
151
+ }
152
+ }
153
+ /**
154
+ * Move the popup to a new location.
155
+ *
156
+ * @param lngLat New location.
157
+ */
158
+ moveTo(lngLat) {
159
+ this._maplibrePopup.setLngLat(lngLat);
160
+ }
161
+ open(eventOrLngLat, feature) {
162
+ if (this._maplibrePopup) {
163
+ return;
164
+ }
165
+ if (eventOrLngLat instanceof mapFeatureStream.MapMouseEvent) {
166
+ if (isFeatureWithId(eventOrLngLat.features[0])) {
167
+ feature = eventOrLngLat.features[0];
168
+ }
169
+ eventOrLngLat = eventOrLngLat.lngLat;
170
+ }
171
+ if (feature) {
172
+ mapFeatureStream.assert(isFeatureWithId(feature), "MapPopup.open(): feature must have unique ID");
173
+ }
174
+ this._maplibrePopup = new maplibre__default.Popup({
175
+ className: this.cssClasses().join(" "),
176
+ closeButton: this.options.closeButton,
177
+ closeOnClick: this.options.closeOnClick,
178
+ closeOnMove: this.options.closeOnMove,
179
+ maxWidth: this.options.maxWidth
180
+ });
181
+ this._maplibrePopup.once("close", this.popupCloseHandler.bind(this));
182
+ this._contentContainer = document.createElement("div");
183
+ this._contentContainer.classList.add("flow-map-popup-content");
184
+ this._maplibrePopup.setDOMContent(this._contentContainer);
185
+ this._maplibrePopup.addTo(this.map.maplibreMap);
186
+ if (feature) {
187
+ this._feature = feature;
188
+ this._featureStream = new mapFeatureStream.MapFeatureStream({
189
+ map: this.map,
190
+ source: feature.source,
191
+ sourceLayer: feature.sourceLayer,
192
+ featureIds: [feature.id]
193
+ });
194
+ this._featureStreamDisposer = this.map.context.state.autorun(() => {
195
+ const data = this._featureStream?.featureData;
196
+ if (data) {
197
+ this.handleFeatureUpdate(data[feature.id]);
198
+ }
199
+ });
200
+ } else {
201
+ this.moveTo(eventOrLngLat);
202
+ this.renderContent(null);
203
+ }
204
+ }
205
+ cssClasses() {
206
+ const classes = ["flow-map-popup"];
207
+ if (stringUtils.isStringFull(this.options.class)) {
208
+ classes.push(this.options.class);
209
+ }
210
+ if (this.options.closeButton) {
211
+ classes.push("flow-map-popup--with-close");
212
+ }
213
+ return classes;
214
+ }
215
+ handleFeatureUpdate(feature) {
216
+ if (!feature) {
217
+ this.close();
218
+ return;
219
+ }
220
+ if (this.options.trackFeature) {
221
+ switch (feature.geometry.type) {
222
+ case "Point":
223
+ this.moveTo(feature.geometry.coordinates);
224
+ break;
225
+ case "MultiPoint":
226
+ this.moveTo(feature.geometry.coordinates[0]);
227
+ break;
228
+ }
229
+ }
230
+ this.renderContent(feature);
231
+ }
232
+ popupCloseHandler() {
233
+ if (this._featureStreamDisposer) {
234
+ this._featureStreamDisposer();
235
+ this._featureStreamDisposer = void 0;
236
+ }
237
+ this.emit("closed", this);
238
+ this.removeAllListeners();
239
+ }
240
+ renderContent(feature) {
241
+ const state = this.map.context.state;
242
+ const content = stringUtils.isFunction(this.options.content) ? this.options.content(feature, state) : this.options.content;
243
+ if (stringUtils.isString(content)) {
244
+ this._contentContainer.innerHTML = content;
245
+ } else if (content instanceof Node) {
246
+ this._contentContainer.innerHTML = "";
247
+ this._contentContainer.appendChild(content);
248
+ } else {
249
+ lit__namespace.render(content, this._contentContainer);
250
+ }
251
+ }
252
+ }
253
+
254
+ var __defProp$7 = Object.defineProperty;
255
+ var __defNormalProp$7 = (obj, key, value) => key in obj ? __defProp$7(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
256
+ var __publicField$7 = (obj, key, value) => {
257
+ __defNormalProp$7(obj, typeof key !== "symbol" ? key + "" : key, value);
258
+ return value;
259
+ };
260
+ class PopupPlugin extends MapPluginBase {
261
+ constructor(pluginManager) {
262
+ super(pluginManager);
263
+ __publicField$7(this, "_popupTemplates", /* @__PURE__ */ new Map());
264
+ __publicField$7(this, "_popups", /* @__PURE__ */ new Set());
265
+ __publicField$7(this, "name", "PopupPlugin");
266
+ }
267
+ registerPopup(id, options) {
268
+ this._popupTemplates.set(id, options);
269
+ }
270
+ openPopup(id, eventOrLngLat, feature) {
271
+ const popupOptions = this._popupTemplates.get(id);
272
+ if (!popupOptions) {
273
+ throw new mapFeatureStream.FlowError(`MapPopup: no popup with id '${id}'`);
274
+ }
275
+ const popup = new MapPopup(this.map, popupOptions);
276
+ this._popups.add(popup);
277
+ popup.once("closed", () => {
278
+ this._popups.delete(popup);
279
+ });
280
+ if (eventOrLngLat instanceof mapFeatureStream.MapMouseEvent) {
281
+ popup.open(eventOrLngLat);
282
+ } else {
283
+ popup.open(eventOrLngLat, feature);
284
+ }
285
+ return popup;
286
+ }
287
+ closeAllPopups() {
288
+ this._popups.forEach((popup) => popup.close());
289
+ this._popups.clear();
290
+ }
291
+ closePopupsForSources(sources) {
292
+ sources = stringUtils.ensureArray(sources);
293
+ this._popups.forEach((popup) => {
294
+ if (popup.feature?.source && sources.indexOf(popup.feature?.source) >= 0) {
295
+ popup.close();
296
+ this._popups.delete(popup);
297
+ }
298
+ });
299
+ }
300
+ }
301
+
302
+ var __defProp$6 = Object.defineProperty;
303
+ var __defNormalProp$6 = (obj, key, value) => key in obj ? __defProp$6(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
304
+ var __publicField$6 = (obj, key, value) => {
305
+ __defNormalProp$6(obj, typeof key !== "symbol" ? key + "" : key, value);
306
+ return value;
307
+ };
308
+ class SelectionEvent extends mapFeatureStream.MapEvent {
309
+ constructor(type, map, sourceIdentifier, features) {
310
+ super(type, map);
311
+ __publicField$6(this, "source");
312
+ __publicField$6(this, "sourceLayer");
313
+ __publicField$6(this, "features");
314
+ this.source = sourceIdentifier.source;
315
+ this.sourceLayer = sourceIdentifier.sourceLayer;
316
+ this.features = features;
317
+ }
318
+ }
319
+
320
+ var __defProp$5 = Object.defineProperty;
321
+ var __defNormalProp$5 = (obj, key, value) => key in obj ? __defProp$5(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
322
+ var __publicField$5 = (obj, key, value) => {
323
+ __defNormalProp$5(obj, typeof key !== "symbol" ? key + "" : key, value);
324
+ return value;
325
+ };
326
+ class SourceSelection {
327
+ constructor(plugin, source, options) {
328
+ __publicField$5(this, "_featureStream");
329
+ __publicField$5(this, "_map");
330
+ __publicField$5(this, "_options");
331
+ __publicField$5(this, "_plugin");
332
+ __publicField$5(this, "_popups", /* @__PURE__ */ new Map());
333
+ __publicField$5(this, "_selectedFeatureIds", /* @__PURE__ */ new Set());
334
+ __publicField$5(this, "_sourceId");
335
+ __publicField$5(this, "_stateSubscription", null);
336
+ this._plugin = plugin;
337
+ this._map = plugin.map;
338
+ this._options = options;
339
+ const sourceType = plugin.map.getSource(source).type;
340
+ this._sourceId = {
341
+ source,
342
+ sourceLayer: sourceType === "vector" ? options.sourceLayer ?? "geometry" : void 0
343
+ };
344
+ this._featureStream = this._map.featureStream({
345
+ source,
346
+ sourceLayer: options.sourceLayer,
347
+ featureIds: []
348
+ });
349
+ if (options.selectionState) {
350
+ this._stateSubscription = this._map.context.state.toStream(options.selectionState, true).subscribe((val) => {
351
+ val = new Set(stringUtils.ensureArray(val));
352
+ this.updateSelection(val);
353
+ });
354
+ }
355
+ }
356
+ get options() {
357
+ return this._options;
358
+ }
359
+ get selectedFeatureIds() {
360
+ return this._selectedFeatureIds;
361
+ }
362
+ get selectedFeatureStream() {
363
+ return this._featureStream;
364
+ }
365
+ destroy() {
366
+ this._popups.forEach((popup) => popup.close());
367
+ this._stateSubscription?.unsubscribe();
368
+ this._selectedFeatureIds = /* @__PURE__ */ new Set();
369
+ this.updateMapSelectionState();
370
+ }
371
+ handleClick(lngLat, feature, selectionOptions, multiSelect, enablePopups) {
372
+ if (this._options.mode === "none") {
373
+ return;
374
+ }
375
+ const selectedFeatureIDs = new Set(this._selectedFeatureIds);
376
+ let clearSelection = false;
377
+ let toggleFeature = false;
378
+ let showPopup = false;
379
+ if (feature && feature.source === this._sourceId.source) {
380
+ if (this._options.mode === "single") {
381
+ if (selectedFeatureIDs.has(feature.id)) {
382
+ toggleFeature = true;
383
+ } else {
384
+ clearSelection = true;
385
+ toggleFeature = true;
386
+ }
387
+ } else {
388
+ if (!multiSelect) {
389
+ clearSelection = true;
390
+ }
391
+ toggleFeature = true;
392
+ }
393
+ } else if (feature && feature.source !== this._sourceId.source) {
394
+ clearSelection = this._options.clear === "group" ? selectionOptions?.group === this._options.group : !!this._options.clear;
395
+ } else {
396
+ clearSelection = !multiSelect;
397
+ }
398
+ if (clearSelection) {
399
+ selectedFeatureIDs.clear();
400
+ }
401
+ if (toggleFeature) {
402
+ mapFeatureStream.assert(isFeatureWithId(feature));
403
+ if (selectedFeatureIDs.has(feature.id) && multiSelect) {
404
+ selectedFeatureIDs.delete(feature.id);
405
+ if (this._popups.has(feature.id))
406
+ this._popups.get(feature.id).close();
407
+ } else {
408
+ selectedFeatureIDs.add(feature.id);
409
+ showPopup = true;
410
+ }
411
+ }
412
+ this.updateSelection(selectedFeatureIDs);
413
+ if (enablePopups && showPopup && this._options.popup) {
414
+ mapFeatureStream.assert(isFeatureWithId(feature));
415
+ if (!this._popups.has(feature.id)) {
416
+ const popup = this._map.getPlugin(PopupPlugin).openPopup(this._options.popup, lngLat, feature);
417
+ if (popup) {
418
+ popup.on("closed", () => {
419
+ this._popups.delete(feature.id);
420
+ });
421
+ this._popups.set(feature.id, popup);
422
+ }
423
+ }
424
+ }
425
+ }
426
+ updateSelection(featureIds) {
427
+ if (!this.areSetsEqual(featureIds, this._selectedFeatureIds)) {
428
+ this._selectedFeatureIds = featureIds;
429
+ this.updateMapSelectionState();
430
+ this.updateStateStore();
431
+ this._featureStream.featureIds = Array.from(featureIds);
432
+ this._popups.forEach((popup) => {
433
+ mapFeatureStream.assert(isFeatureWithId(popup.feature));
434
+ if (popup.feature.id && !featureIds.has(popup.feature.id)) {
435
+ popup.close();
436
+ }
437
+ });
438
+ const event = new SelectionEvent(
439
+ "selectionChanged",
440
+ this._map,
441
+ this._sourceId,
442
+ Array.from(this._selectedFeatureIds)
443
+ );
444
+ this._plugin.emit(event.type, event);
445
+ }
446
+ }
447
+ areSetsEqual(a, b) {
448
+ return a.size === b.size && [...a].every((value) => b.has(value));
449
+ }
450
+ updateMapSelectionState() {
451
+ this._map.removeFeatureState(this._sourceId, "selected", false);
452
+ this._selectedFeatureIds.forEach(
453
+ (id) => this._map.setFeatureState({ ...this._sourceId, id }, { selected: true }, false)
454
+ );
455
+ }
456
+ updateStateStore() {
457
+ if (stringUtils.isStringFull(this._options.selectionState)) {
458
+ const selectedIds = Array.from(this._selectedFeatureIds);
459
+ if (this._options.mode === "single") {
460
+ this._map.context.state.set(this._options.selectionState, selectedIds[0]);
461
+ } else if (this._options.mode === "multi") {
462
+ this._map.context.state.set(this._options.selectionState, selectedIds);
463
+ }
464
+ }
465
+ }
466
+ }
467
+
468
+ var __defProp$4 = Object.defineProperty;
469
+ var __defNormalProp$4 = (obj, key, value) => key in obj ? __defProp$4(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
470
+ var __publicField$4 = (obj, key, value) => {
471
+ __defNormalProp$4(obj, typeof key !== "symbol" ? key + "" : key, value);
472
+ return value;
473
+ };
474
+ class SelectionPlugin extends MapPluginBase {
475
+ constructor(pluginManager) {
476
+ super(pluginManager);
477
+ __publicField$4(this, "_sourceSelections", /* @__PURE__ */ new Map());
478
+ __publicField$4(this, "_enablePopups", true);
479
+ __publicField$4(this, "name", "SelectionPlugin");
480
+ }
481
+ clearSelection(source) {
482
+ const sourceSelection = this._sourceSelections.get(source);
483
+ if (!sourceSelection) {
484
+ return;
485
+ }
486
+ switch (sourceSelection.options.mode) {
487
+ case "single":
488
+ case "multi":
489
+ sourceSelection.updateSelection(/* @__PURE__ */ new Set());
490
+ }
491
+ }
492
+ deselectFeatures(source, features) {
493
+ const sourceSelection = this._sourceSelections.get(source);
494
+ if (!sourceSelection) {
495
+ return;
496
+ }
497
+ features = stringUtils.ensureArray(features);
498
+ const currentSelection = new Set(sourceSelection.selectedFeatureIds);
499
+ switch (sourceSelection.options.mode) {
500
+ case "single":
501
+ case "multi":
502
+ features.forEach((f) => currentSelection.delete(f));
503
+ sourceSelection.updateSelection(currentSelection);
504
+ }
505
+ }
506
+ destroy() {
507
+ this._sourceSelections.forEach((sel) => sel.destroy());
508
+ this._sourceSelections.clear();
509
+ }
510
+ disableSelection(source) {
511
+ if (this._sourceSelections.has(source)) {
512
+ this._sourceSelections.get(source).destroy();
513
+ this._sourceSelections.delete(source);
514
+ }
515
+ }
516
+ enableSelection(source, options) {
517
+ if (options.popup) {
518
+ try {
519
+ this.map.getPlugin(PopupPlugin);
520
+ } catch (e) {
521
+ throw new mapFeatureStream.FlowMapError(`enableSelection(): Popup plugin is required for automatic selection popups`);
522
+ }
523
+ }
524
+ this.disableSelection(source);
525
+ this._sourceSelections.set(source, new SourceSelection(this, source, options));
526
+ }
527
+ handleBeforeSourceRemoved(event) {
528
+ if (this._sourceSelections.has(event.source)) {
529
+ this._sourceSelections.get(event.source)?.destroy();
530
+ this._sourceSelections.delete(event.source);
531
+ }
532
+ }
533
+ handleClick(event) {
534
+ const multiSelect = event.originalEvent.shiftKey || event.originalEvent.altKey || event.originalEvent.metaKey;
535
+ const clickedFeature = event.features[0];
536
+ const clickedSource = clickedFeature?.source;
537
+ const selectionOptions = this._sourceSelections.get(clickedSource)?.options;
538
+ this._sourceSelections.forEach((sel) => sel.handleClick(event.lngLat, clickedFeature, selectionOptions, multiSelect, this._enablePopups));
539
+ }
540
+ selectFeatures(source, features) {
541
+ const sourceSelection = this._sourceSelections.get(source);
542
+ if (!sourceSelection) {
543
+ return;
544
+ }
545
+ features = stringUtils.ensureArray(features);
546
+ let currentSelection = new Set(sourceSelection.selectedFeatureIds);
547
+ switch (sourceSelection.options.mode) {
548
+ case "single":
549
+ currentSelection = /* @__PURE__ */ new Set([features[0]]);
550
+ sourceSelection.updateSelection(currentSelection);
551
+ break;
552
+ case "multi":
553
+ features.forEach((f) => currentSelection.add(f));
554
+ sourceSelection.updateSelection(currentSelection);
555
+ break;
556
+ }
557
+ if (sourceSelection.selectedFeatureIds.size && stringUtils.isStringFull(sourceSelection.options.group)) {
558
+ this._sourceSelections.forEach((s) => {
559
+ if (s != sourceSelection && s.options.clear === "group" && s.options.group == sourceSelection.options.group) {
560
+ s.updateSelection(/* @__PURE__ */ new Set());
561
+ }
562
+ });
563
+ }
564
+ }
565
+ selectedFeatureIds(source) {
566
+ const sourceSelection = this._sourceSelections.get(source);
567
+ if (!sourceSelection) {
568
+ return [];
569
+ }
570
+ return Array.from(sourceSelection.selectedFeatureIds);
571
+ }
572
+ selectedFeatureStream(source) {
573
+ const sourceSelection = this._sourceSelections.get(source);
574
+ if (!sourceSelection) {
575
+ throw new mapFeatureStream.FlowMapError("no source selection");
576
+ }
577
+ return sourceSelection.selectedFeatureStream;
578
+ }
579
+ enablePopups(enabled = true) {
580
+ this._enablePopups = true;
581
+ }
582
+ disablePopups() {
583
+ if (this._enablePopups) {
584
+ this.map.getPlugin(PopupPlugin).closeAllPopups();
585
+ this._enablePopups = false;
586
+ }
587
+ }
588
+ }
589
+
590
+ function addAnnotationLayers(map) {
591
+ map.transaction(() => {
592
+ const annotationSource = new mapFeatureStream.MapDataSource({
593
+ id: "map-annotations",
594
+ type: "geojson",
595
+ src: { type: "FeatureCollection", features: [] },
596
+ featureId: "id"
597
+ });
598
+ map.addSource(annotationSource);
599
+ const polygonFillLayer = new mapFeatureStream.MapLayer({
600
+ id: "map-annotations-polygon-fill",
601
+ type: "fill",
602
+ source: annotationSource.id,
603
+ filter: `geometry-type() == 'Polygon' && coalesce(@visible, true)`,
604
+ style: `
605
+ fill-color: @fillColor;
606
+ `
607
+ });
608
+ map.addLayer(polygonFillLayer);
609
+ const polygonStrokeLayer = new mapFeatureStream.MapLayer({
610
+ id: "map-annotations-polygon-stroke",
611
+ type: "line",
612
+ source: annotationSource.id,
613
+ filter: `geometry-type() == 'Polygon' && coalesce(@visible, true)`,
614
+ style: `
615
+ line-color: @strokeColor;
616
+ line-width: @strokeWidth;
617
+ `
618
+ });
619
+ map.addLayer(polygonStrokeLayer);
620
+ const lineStrokeLayer = new mapFeatureStream.MapLayer({
621
+ id: "map-annotations-line-stroke",
622
+ type: "line",
623
+ source: annotationSource.id,
624
+ filter: `geometry-type() == 'LineString' && coalesce(@visible, true)`,
625
+ style: `
626
+ line-color: @strokeColor;
627
+ line-width: @strokeWidth;
628
+ `
629
+ });
630
+ map.addLayer(lineStrokeLayer);
631
+ const pointLayer = new mapFeatureStream.MapLayer({
632
+ id: "map-annotations-point",
633
+ type: "circle",
634
+ source: annotationSource.id,
635
+ filter: `geometry-type() == 'Point' && coalesce(@visible, true)`,
636
+ style: `
637
+ circle-radius: @radius;
638
+ circle-color: @fillColor;
639
+ circle-stroke-color: @strokeColor;
640
+ circle-stroke-width: @strokeWidth;
641
+ `
642
+ });
643
+ map.addLayer(pointLayer);
644
+ const polygonLabelsLayer = new mapFeatureStream.MapLayer({
645
+ id: "map-annotations-polygon-labels",
646
+ type: "symbol",
647
+ source: annotationSource.id,
648
+ filter: `geometry-type() == 'Polygon' && to-boolean(@labelText) && coalesce(@visible, true)`,
649
+ interactive: false,
650
+ style: `
651
+ symbol-placement: 'point';
652
+ text-field: @labelText;
653
+ text-color: @labelColor;
654
+ text-size: @labelSize;
655
+ text-anchor: @polygonLabelAnchor;
656
+ /* text-offset: @labelOffset; */
657
+ text-justify: @labelJustify;
658
+ text-max-width: @labelMaxWidth;
659
+ text-allow-overlap: true;
660
+ `
661
+ });
662
+ map.addLayer(polygonLabelsLayer);
663
+ const pointLabelsLayer = new mapFeatureStream.MapLayer({
664
+ id: "map-annotations-point-labels",
665
+ type: "symbol",
666
+ source: annotationSource.id,
667
+ filter: `geometry-type() == 'Point' && to-boolean(@labelText) && coalesce(@visible, true)`,
668
+ interactive: false,
669
+ style: `
670
+ symbol-placement: 'point';
671
+ text-field: @labelText;
672
+ text-color: @labelColor;
673
+ text-size: @labelSize;
674
+ text-anchor: @labelAnchor;
675
+ text-offset: @labelOffset;
676
+ /* text-radial-offset: (@radius + 8) / coalesce(@labelSize, {{annotationsStyleDefaults.labelSize}}); */
677
+ text-justify: @labelJustify;
678
+ text-max-width: @labelMaxWidth;
679
+ text-allow-overlap: true;
680
+ `
681
+ });
682
+ map.addLayer(pointLabelsLayer);
683
+ const lineLabelsLayer = new mapFeatureStream.MapLayer({
684
+ id: "map-annotations-line-labels",
685
+ type: "symbol",
686
+ source: annotationSource.id,
687
+ filter: `geometry-type() == 'LineString' && to-boolean(@labelText) && coalesce(@visible, true)`,
688
+ interactive: false,
689
+ style: `
690
+ symbol-placement: 'line-center';
691
+ text-field: @labelText;
692
+ text-color: @labelColor;
693
+ text-anchor: @labelAnchor;
694
+ text-size: @labelSize;
695
+ /* text-offset: @labelOffset; */
696
+ text-justify: @labelJustify;
697
+ text-max-width: @labelMaxWidth;
698
+ text-allow-overlap: true;
699
+ text-ignore-placement: true;
700
+ `
701
+ });
702
+ map.addLayer(lineLabelsLayer);
703
+ const polygonSelectionLayer = new mapFeatureStream.MapLayer({
704
+ id: "map-annotations-polygon-selection",
705
+ type: "line",
706
+ source: annotationSource.id,
707
+ filter: `geometry-type() == 'Polygon' && coalesce(@visible, true)`,
708
+ interactive: false,
709
+ style: `
710
+ line-color: @@selected ? @selectionStrokeColor : @@hover ? @hoverStrokeColor : transparent;
711
+ line-width: @selectionWidth;
712
+ line-opacity: @selectionStrokeOpacity;
713
+ `
714
+ });
715
+ map.addLayer(polygonSelectionLayer);
716
+ const pointSelectionLayer = new mapFeatureStream.MapLayer({
717
+ id: "map-annotations-point-selection",
718
+ type: "circle",
719
+ source: annotationSource.id,
720
+ filter: `geometry-type() == 'Point' && coalesce(@visible, true)`,
721
+ interactive: false,
722
+ style: `
723
+ circle-radius: @radius + 1;
724
+ circle-color: transparent;
725
+ circle-stroke-color: @@selected ? @selectionStrokeColor : @@hover ? @hoverStrokeColor : transparent;
726
+ circle-stroke-width: @selectionWidth;
727
+ circle-stroke-opacity: @selectionStrokeOpacity;
728
+ `
729
+ });
730
+ map.addLayer(pointSelectionLayer);
731
+ const lineSelectionLayer = new mapFeatureStream.MapLayer({
732
+ id: "map-annotations-line-selection",
733
+ type: "line",
734
+ source: annotationSource.id,
735
+ filter: `geometry-type() == 'LineString' && coalesce(@visible, true)`,
736
+ interactive: false,
737
+ style: `
738
+ line-color: @@selected ? @selectionStrokeColor : @@hover ? @hoverStrokeColor : transparent;
739
+ line-opacity: @selectionStrokeOpacity;
740
+ line-width: @selectionWidth/2;
741
+ line-gap-width: @strokeWidth;
742
+ `
743
+ });
744
+ map.addLayer(lineSelectionLayer);
745
+ });
746
+ return map.getSource("map-annotations");
747
+ }
748
+
749
+ function createSupplementaryPointsForCircle(geojson) {
750
+ const { properties, geometry } = geojson;
751
+ if (properties.user_type !== "Circle")
752
+ return null;
753
+ const supplementaryPoints = [];
754
+ const vertices = geometry.coordinates[0].slice(0, -1);
755
+ for (let index = 0; index < vertices.length; index += Math.round(vertices.length / 4)) {
756
+ supplementaryPoints.push(MapboxDraw__default.lib.createVertex(properties.id, vertices[index], `0.${index}`, false));
757
+ }
758
+ return supplementaryPoints;
759
+ }
760
+
761
+ const DirectModeOverride = MapboxDraw__default.modes.direct_select;
762
+ const moveFeatures = MapboxDraw__default.lib.moveFeatures;
763
+ const constrainFeatureMovement = MapboxDraw__default.lib.constrainFeatureMovement;
764
+ const createSupplementaryPoints = MapboxDraw__default.lib.createSupplementaryPoints;
765
+ const Constants$1 = MapboxDraw__default.constants;
766
+ DirectModeOverride.dragFeature = function(state, e, delta) {
767
+ moveFeatures(this.getSelected(), delta);
768
+ this.getSelected().filter((feature) => feature.properties.type === "Circle").map((circle) => circle.properties.circleCenter).forEach((center) => {
769
+ center[0] += delta.lng;
770
+ center[1] += delta.lat;
771
+ });
772
+ state.dragMoveLocation = e.lngLat;
773
+ };
774
+ DirectModeOverride.dragVertex = function(state, e, delta) {
775
+ if (state.feature.properties.type === "Circle") {
776
+ const center = state.feature.properties.circleCenter;
777
+ const movedVertex = [e.lngLat.lng, e.lngLat.lat];
778
+ const radius = turfDistance__default(helpers.point(center), helpers.point(movedVertex), { units: "kilometers" });
779
+ const circleFeature = turfCircle__default(center, radius);
780
+ state.feature.incomingCoords(circleFeature.geometry.coordinates);
781
+ state.feature.properties.circleRadius = radius;
782
+ } else {
783
+ const selectedCoords = state.selectedCoordPaths.map((coord_path) => state.feature.getCoordinate(coord_path));
784
+ const selectedCoordPoints = selectedCoords.map((coords) => ({
785
+ type: Constants$1.geojsonTypes.FEATURE,
786
+ properties: {},
787
+ geometry: {
788
+ type: Constants$1.geojsonTypes.POINT,
789
+ coordinates: coords
790
+ }
791
+ }));
792
+ const constrainedDelta = constrainFeatureMovement(selectedCoordPoints, delta);
793
+ for (let i = 0; i < selectedCoords.length; i++) {
794
+ const coord = selectedCoords[i];
795
+ state.feature.updateCoordinate(state.selectedCoordPaths[i], coord[0] + constrainedDelta.lng, coord[1] + constrainedDelta.lat);
796
+ }
797
+ }
798
+ };
799
+ DirectModeOverride.toDisplayFeatures = function(state, geojson, push) {
800
+ if (state.featureId === geojson.properties.id) {
801
+ geojson.properties.active = Constants$1.activeStates.ACTIVE;
802
+ push(geojson);
803
+ const supplementaryPoints = geojson.properties.user_type === "Circle" ? createSupplementaryPointsForCircle(geojson) : createSupplementaryPoints(geojson, {
804
+ map: this.map,
805
+ midpoints: true,
806
+ selectedPaths: state.selectedCoordPaths
807
+ });
808
+ supplementaryPoints.forEach(push);
809
+ } else {
810
+ geojson.properties.active = Constants$1.activeStates.INACTIVE;
811
+ push(geojson);
812
+ }
813
+ this.fireActionable(state);
814
+ };
815
+ const DirectMode = DirectModeOverride;
816
+
817
+ const dragPan = {
818
+ enable(ctx) {
819
+ setTimeout(() => {
820
+ if (!ctx.map || !ctx.map.dragPan || !ctx._ctx || !ctx._ctx.store || !ctx._ctx.store.getInitialConfigValue)
821
+ return;
822
+ if (!ctx._ctx.store.getInitialConfigValue("dragPan"))
823
+ return;
824
+ ctx.map.dragPan.enable();
825
+ }, 0);
826
+ },
827
+ disable(ctx) {
828
+ setTimeout(() => {
829
+ if (!ctx.map || !ctx.map.doubleClickZoom)
830
+ return;
831
+ ctx.map.dragPan.disable();
832
+ }, 0);
833
+ }
834
+ };
835
+
836
+ const DragCircleMode = { ...MapboxDraw__default.modes.draw_polygon };
837
+ const Constants = MapboxDraw__default.constants;
838
+ DragCircleMode.onSetup = function(opts) {
839
+ const polygon = this.newFeature({
840
+ type: Constants.geojsonTypes.FEATURE,
841
+ properties: {
842
+ type: "Circle",
843
+ circleCenter: []
844
+ },
845
+ geometry: {
846
+ type: Constants.geojsonTypes.POLYGON,
847
+ coordinates: []
848
+ }
849
+ });
850
+ this.addFeature(polygon);
851
+ this.clearSelectedFeatures();
852
+ dragPan.disable(this);
853
+ this.updateUIClasses({ mouse: Constants.cursors.ADD });
854
+ this.activateUIButton(Constants.types.POLYGON);
855
+ this.setActionableState({
856
+ trash: true
857
+ });
858
+ return {
859
+ polygon,
860
+ currentVertexPosition: 0
861
+ };
862
+ };
863
+ DragCircleMode.onMouseDown = DragCircleMode.onTouchStart = function(state, e) {
864
+ const currentCenter = state.polygon.properties.circleCenter;
865
+ if (currentCenter.length === 0) {
866
+ state.polygon.properties.circleCenter = [e.lngLat.lng, e.lngLat.lat];
867
+ }
868
+ };
869
+ DragCircleMode.onDrag = DragCircleMode.onMouseMove = function(state, e) {
870
+ const center = state.polygon.properties.circleCenter;
871
+ if (center.length > 0) {
872
+ const distanceInKm = turfDistance__default(
873
+ helpers.point(center),
874
+ helpers.point([e.lngLat.lng, e.lngLat.lat]),
875
+ { units: "kilometers" }
876
+ );
877
+ const circleFeature = turfCircle__default(center, distanceInKm);
878
+ state.polygon.incomingCoords(circleFeature.geometry.coordinates);
879
+ state.polygon.properties.circleRadius = distanceInKm;
880
+ }
881
+ };
882
+ DragCircleMode.onMouseUp = DragCircleMode.onTouchEnd = function(state) {
883
+ dragPan.enable(this);
884
+ return this.changeMode(Constants.modes.SIMPLE_SELECT, { featureIds: [state.polygon.id] });
885
+ };
886
+ DragCircleMode.onClick = DragCircleMode.onTap = function(state) {
887
+ state.polygon.properties.circleCenter = [];
888
+ };
889
+ DragCircleMode.toDisplayFeatures = function(state, geojson, display) {
890
+ const isActivePolygon = geojson.properties.id === state.polygon.id;
891
+ geojson.properties.active = isActivePolygon ? Constants.activeStates.ACTIVE : Constants.activeStates.INACTIVE;
892
+ return display(geojson);
893
+ };
894
+ const DragCircleMode$1 = DragCircleMode;
895
+
896
+ var __defProp$3 = Object.defineProperty;
897
+ var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
898
+ var __publicField$3 = (obj, key, value) => {
899
+ __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
900
+ return value;
901
+ };
902
+ Debug__default("flow:annotation-plugin");
903
+ const _AnnotationPlugin = class _AnnotationPlugin extends MapPluginBase {
904
+ constructor(pluginManager, options) {
905
+ super(pluginManager, options);
906
+ __publicField$3(this, "name", "AnnotationPlugin");
907
+ // Feature data model
908
+ __publicField$3(this, "_features", /* @__PURE__ */ new Map());
909
+ __publicField$3(this, "_featureIds", []);
910
+ // Undo/redo stacks
911
+ __publicField$3(this, "_undoStack", []);
912
+ __publicField$3(this, "_redoStack", []);
913
+ // Editing state
914
+ __publicField$3(this, "_mode", "idle");
915
+ __publicField$3(this, "_activeFeatureId", null);
916
+ __publicField$3(this, "_activeFeatureType", null);
917
+ __publicField$3(this, "_onCommitCleanup", []);
918
+ __publicField$3(this, "_annotationDataSource");
919
+ __publicField$3(this, "_drawControl", null);
920
+ __publicField$3(this, "_removeKeyboardShortcuts", null);
921
+ this.options = { ..._AnnotationPlugin._defaultOptions, ...options };
922
+ this.options.defaultStyle = { ..._AnnotationPlugin._defaultOptions.defaultStyle, ...options?.defaultStyle };
923
+ }
924
+ initialize() {
925
+ this._annotationDataSource = addAnnotationLayers(this.map);
926
+ if (this.options.selectionOptions) {
927
+ this.map.getPlugin(SelectionPlugin).enableSelection(this._annotationDataSource.id, this.options.selectionOptions);
928
+ }
929
+ if (this.options.interactive) {
930
+ this._removeKeyboardShortcuts = this.pluginManager.addKeyboardShortcuts({
931
+ "Enter,Escape": () => {
932
+ this.commit();
933
+ },
934
+ "Delete,Backspace": () => this.deleteSelectedFeature(),
935
+ "Ctrl+KeyZ": () => {
936
+ this.undo();
937
+ },
938
+ "Ctrl+Shift+KeyZ": () => {
939
+ this.redo();
940
+ },
941
+ KeyP: () => this.createFeature("Polygon"),
942
+ KeyL: () => this.createFeature("LineString"),
943
+ KeyM: () => this.createFeature("Point"),
944
+ KeyC: () => this.createFeature("Circle")
945
+ });
946
+ }
947
+ }
948
+ destroy() {
949
+ if (this._removeKeyboardShortcuts)
950
+ this._removeKeyboardShortcuts();
951
+ }
952
+ clear() {
953
+ this.commit();
954
+ this._featureIds = [];
955
+ this._features = /* @__PURE__ */ new Map();
956
+ this._undoStack = [];
957
+ this._redoStack = [];
958
+ this._mode = "idle";
959
+ this._activeFeatureId = null;
960
+ this._activeFeatureType = null;
961
+ this.render();
962
+ return this;
963
+ }
964
+ undo() {
965
+ const operation = this._undoStack.pop();
966
+ if (operation) {
967
+ operation.undo();
968
+ this._redoStack.push(operation);
969
+ this.render();
970
+ }
971
+ return this;
972
+ }
973
+ /**
974
+ * Redo the last undone operation.
975
+ */
976
+ redo() {
977
+ const operation = this._redoStack.pop();
978
+ if (operation) {
979
+ operation.do();
980
+ this._undoStack.push(operation);
981
+ this.render();
982
+ }
983
+ return this;
984
+ }
985
+ getFeature(featureId) {
986
+ const feature = this._features.get(featureId);
987
+ if (!feature) {
988
+ throw new mapFeatureStream.FlowError(`<AnnotationPlugin>: No feature with id '${featureId}'`);
989
+ }
990
+ return feature;
991
+ }
992
+ getFeatures() {
993
+ return this._featureIds.map((id) => this._features.get(id));
994
+ }
995
+ setFeatures(features) {
996
+ this.commit();
997
+ const normalizedFeatures = features.map((f) => this.applyDefaults(f));
998
+ const oldFeatures = this._features;
999
+ const oldFeatureIds = this._featureIds;
1000
+ const operation = {
1001
+ do: () => {
1002
+ this._featureIds = normalizedFeatures.map((f) => f.id);
1003
+ this._features = new Map(normalizedFeatures.map((f) => [f.id, f]));
1004
+ },
1005
+ undo: () => {
1006
+ this._featureIds = oldFeatureIds;
1007
+ this._features = oldFeatures;
1008
+ }
1009
+ };
1010
+ this.performOperation(operation);
1011
+ return this;
1012
+ }
1013
+ addFeature(feature) {
1014
+ this.commit();
1015
+ const fullFeature = this.applyDefaults(feature);
1016
+ const operation = {
1017
+ do: () => {
1018
+ this._features.set(fullFeature.id, fullFeature);
1019
+ this._featureIds.push(fullFeature.id);
1020
+ },
1021
+ undo: () => {
1022
+ this._features.delete(fullFeature.id);
1023
+ const index = this._featureIds.indexOf(fullFeature.id);
1024
+ if (index !== -1) {
1025
+ this._featureIds.splice(index, 1);
1026
+ }
1027
+ }
1028
+ };
1029
+ this.performOperation(operation);
1030
+ return fullFeature;
1031
+ }
1032
+ deleteFeature(featureId) {
1033
+ this.commit();
1034
+ if (!featureId) {
1035
+ return this;
1036
+ }
1037
+ this.deselectFeature(featureId);
1038
+ const feature = this.getFeature(featureId);
1039
+ const operation = {
1040
+ do: () => {
1041
+ this._features.delete(featureId);
1042
+ const index = this._featureIds.indexOf(featureId);
1043
+ if (index !== -1) {
1044
+ this._featureIds.splice(index, 1);
1045
+ }
1046
+ },
1047
+ undo: () => {
1048
+ this._features.set(featureId, feature);
1049
+ this._featureIds.push(featureId);
1050
+ }
1051
+ };
1052
+ this.performOperation(operation);
1053
+ return this;
1054
+ }
1055
+ createFeature(featureType) {
1056
+ this.commit();
1057
+ this.startDrawing();
1058
+ this._drawControl.changeMode(this.drawModeForFeatureType(featureType));
1059
+ this._mode = "creating";
1060
+ this._activeFeatureId = null;
1061
+ this._activeFeatureType = featureType;
1062
+ this.emitStateChange();
1063
+ const commitChanges = () => {
1064
+ setTimeout(() => this.commit(), 0);
1065
+ };
1066
+ this.map.maplibreMap.once("draw.create", commitChanges);
1067
+ this.map.maplibreMap.once("draw.modechange", commitChanges);
1068
+ this._onCommitCleanup.push(() => {
1069
+ this.map.maplibreMap.off("draw.create", commitChanges);
1070
+ this.map.maplibreMap.off("draw.modechange", commitChanges);
1071
+ });
1072
+ }
1073
+ editFeature(featureId) {
1074
+ const feature = this.getFeature(featureId);
1075
+ this._mode = "editing";
1076
+ this._activeFeatureId = featureId;
1077
+ this._activeFeatureType = feature.properties.type;
1078
+ const commitChanges = () => {
1079
+ setTimeout(() => this.commit(), 0);
1080
+ };
1081
+ this.startDrawing();
1082
+ this._drawControl.add(feature);
1083
+ this.setFeatureProperty(featureId, "visible", false);
1084
+ this.render();
1085
+ switch (this.editModeForFeature(feature)) {
1086
+ case "direct_select":
1087
+ this._drawControl.changeMode("direct_select", {
1088
+ featureId
1089
+ });
1090
+ this.map.maplibreMap.once("draw.modechange", commitChanges);
1091
+ this._onCommitCleanup.push(() => this.map.maplibreMap.off("draw.modechange", commitChanges));
1092
+ break;
1093
+ case "simple_select":
1094
+ this._drawControl.changeMode("simple_select", {
1095
+ featureIds: [featureId]
1096
+ });
1097
+ this.map.maplibreMap.once("draw.selectionchange", commitChanges);
1098
+ this._onCommitCleanup.push(() => this.map.maplibreMap.off("draw.selectionchange", commitChanges));
1099
+ break;
1100
+ }
1101
+ }
1102
+ zoomToFeature(featureId, animationOptions) {
1103
+ const feature = this.getFeature(featureId);
1104
+ if (!feature)
1105
+ return this;
1106
+ const bbox = feature.properties.type === "Point" ? turfBBox__default(turfBuffer__default(feature, 50)) : turfBBox__default(feature);
1107
+ this.map.setBounds(bbox, animationOptions);
1108
+ return this;
1109
+ }
1110
+ setFeatureProperty(featureId, property, value) {
1111
+ const feature = this.getFeature(featureId);
1112
+ const featureCopy = {
1113
+ ...feature,
1114
+ properties: { ...feature.properties, [property]: value }
1115
+ };
1116
+ this._features.set(featureId, featureCopy);
1117
+ return this;
1118
+ }
1119
+ setFeatureProperties(featureId, properties) {
1120
+ const feature = this.getFeature(featureId);
1121
+ const featureCopy = {
1122
+ ...feature,
1123
+ properties: { ...feature.properties, ...properties }
1124
+ };
1125
+ this._features.set(featureId, featureCopy);
1126
+ return this;
1127
+ }
1128
+ commit() {
1129
+ this._onCommitCleanup.forEach((f) => f());
1130
+ this._onCommitCleanup = [];
1131
+ if (this._mode === "idle")
1132
+ return this;
1133
+ const drawControlFeature = this._drawControl.getAll().features[0];
1134
+ let operation = null;
1135
+ if (this._mode === "editing") {
1136
+ const mapFeature = this.getFeature(this._activeFeatureId);
1137
+ this.setFeatureProperty(mapFeature.id, "visible", true);
1138
+ if (!turfBooleanEqual__default(mapFeature.geometry, drawControlFeature.geometry)) {
1139
+ operation = {
1140
+ do: () => {
1141
+ this.setFeatureGeometry(mapFeature.id, drawControlFeature.geometry);
1142
+ if (drawControlFeature.properties.type === "Circle") {
1143
+ this.setFeatureProperty(mapFeature.id, "center", drawControlFeature.properties.circleCenter);
1144
+ this.setFeatureProperty(mapFeature.id, "radiusInKm", drawControlFeature.properties.circleRadius);
1145
+ }
1146
+ },
1147
+ undo: () => {
1148
+ this.setFeatureGeometry(mapFeature.id, mapFeature.geometry);
1149
+ if (mapFeature.properties.type === "Circle") {
1150
+ this.setFeatureProperty(mapFeature.id, "center", mapFeature.properties.circleCenter);
1151
+ this.setFeatureProperty(mapFeature.id, "radiusInKm", mapFeature.properties.circleRadius);
1152
+ }
1153
+ }
1154
+ };
1155
+ }
1156
+ } else if (this._mode === "creating") {
1157
+ if (this.isValidGeometry(drawControlFeature)) {
1158
+ let createdFeature = drawControlFeature;
1159
+ createdFeature.id = "";
1160
+ this.applyDefaults(createdFeature);
1161
+ operation = {
1162
+ do: () => {
1163
+ this._features.set(drawControlFeature.id, drawControlFeature);
1164
+ this._featureIds.push(drawControlFeature.id);
1165
+ if (this.options.selectionOptions?.mode === "single" || this.options.selectionOptions?.mode === "multi") {
1166
+ this.map.getPlugin(SelectionPlugin).selectFeatures(this._annotationDataSource.id, drawControlFeature.id);
1167
+ }
1168
+ },
1169
+ undo: () => {
1170
+ createdFeature = this._features.get(createdFeature.id);
1171
+ this._features.delete(createdFeature.id);
1172
+ const index = this._featureIds.indexOf(createdFeature.id);
1173
+ if (index !== -1) {
1174
+ this._featureIds.splice(index, 1);
1175
+ }
1176
+ }
1177
+ };
1178
+ }
1179
+ }
1180
+ if (operation) {
1181
+ this.performOperation(operation);
1182
+ }
1183
+ this._mode = "idle";
1184
+ this._activeFeatureId = null;
1185
+ this._activeFeatureType = null;
1186
+ this.endDrawing();
1187
+ this.render();
1188
+ return this;
1189
+ }
1190
+ cancel() {
1191
+ this._onCommitCleanup.forEach((f) => f());
1192
+ this._onCommitCleanup = [];
1193
+ if (this._mode === "idle")
1194
+ return this;
1195
+ if (this._mode === "editing") {
1196
+ this.setFeatureProperty(this._activeFeatureId, "visible", true);
1197
+ }
1198
+ this._activeFeatureId = null;
1199
+ this._activeFeatureType = null;
1200
+ this._mode = "idle";
1201
+ this.endDrawing();
1202
+ this.render();
1203
+ return this;
1204
+ }
1205
+ render() {
1206
+ const renderedFeatures = {
1207
+ type: "FeatureCollection",
1208
+ features: this._featureIds.map((id) => this._features.get(id))
1209
+ };
1210
+ this._annotationDataSource.setSrc(renderedFeatures);
1211
+ this.emitStateChange();
1212
+ return this;
1213
+ }
1214
+ handleDblClick(event) {
1215
+ if (!this.options.interactive) {
1216
+ return;
1217
+ }
1218
+ const clickedFeature = event.features[0];
1219
+ if (clickedFeature && clickedFeature.source === this._annotationDataSource.id) {
1220
+ this.editFeature(clickedFeature.id.toString());
1221
+ }
1222
+ }
1223
+ handleBeforeStyleChanged(event) {
1224
+ const { oldStyle, newStyle } = event;
1225
+ if (this._drawControl) {
1226
+ if (oldStyle.sources["mapbox-gl-draw"]) {
1227
+ newStyle.sources["mapbox-gl-draw"] = oldStyle.sources["mapbox-gl-draw"];
1228
+ }
1229
+ oldStyle.layers.filter((l) => l.id.startsWith("gl-draw")).forEach((l) => newStyle.layers.push(l));
1230
+ }
1231
+ return newStyle;
1232
+ }
1233
+ startDrawing() {
1234
+ if (this._drawControl) {
1235
+ return this._drawControl;
1236
+ }
1237
+ this.pluginManager.setExclusivePlugin(this);
1238
+ this._drawControl = new MapboxDraw__default({
1239
+ displayControlsDefault: false,
1240
+ keybindings: false,
1241
+ modes: {
1242
+ ...MapboxDraw__default.modes,
1243
+ drag_circle: DragCircleMode$1,
1244
+ direct_select: DirectMode
1245
+ //...options.modes
1246
+ },
1247
+ userProperties: true
1248
+ });
1249
+ this.map.maplibreMap.addControl(this._drawControl);
1250
+ return this._drawControl;
1251
+ }
1252
+ endDrawing() {
1253
+ this.pluginManager.removeExclusivePlugin(this);
1254
+ if (this._drawControl) {
1255
+ this.map.maplibreMap.removeControl(this._drawControl);
1256
+ this._drawControl = null;
1257
+ }
1258
+ }
1259
+ applyDefaults(feature) {
1260
+ feature.id = feature.properties.id = this.generateFeatureId(feature);
1261
+ feature.properties = {
1262
+ id: this.generateFeatureId(feature),
1263
+ name: this.generateFeatureName(feature),
1264
+ type: feature.properties.type ?? feature.geometry.type,
1265
+ selected: false,
1266
+ ...this.options.defaultStyle,
1267
+ ...feature.properties
1268
+ };
1269
+ feature.id = feature.properties.id;
1270
+ return feature;
1271
+ }
1272
+ generateFeatureId(feature) {
1273
+ if (stringUtils.isNumber(feature.id) || stringUtils.isStringFull(feature.id)) {
1274
+ return feature.id.toString();
1275
+ } else {
1276
+ return mapFeatureStream.randomId("feature");
1277
+ }
1278
+ }
1279
+ generateFeatureName(feature) {
1280
+ const type = feature.properties.type ?? feature.geometry.type;
1281
+ return `${type} ${this._featureIds.length}`;
1282
+ }
1283
+ performOperation(operation) {
1284
+ this._undoStack.push(operation);
1285
+ this._redoStack.length = 0;
1286
+ operation.do();
1287
+ }
1288
+ deselectFeature(featureId) {
1289
+ if (this.options.selectionOptions?.mode === "single" || this.options.selectionOptions?.mode === "multi") {
1290
+ this.map.getPlugin(SelectionPlugin).deselectFeatures(this._annotationDataSource.id, featureId);
1291
+ }
1292
+ }
1293
+ deleteSelectedFeature() {
1294
+ if (this.options.selectionOptions?.mode === "single" || this.options.selectionOptions?.mode === "multi") {
1295
+ const selected = this.map.getPlugin(SelectionPlugin).selectedFeatureIds(this._annotationDataSource.id);
1296
+ selected.forEach((id) => this.deleteFeature(id));
1297
+ this.render();
1298
+ }
1299
+ }
1300
+ editModeForFeature(feature) {
1301
+ switch (feature.geometry.type) {
1302
+ case "Point":
1303
+ return "simple_select";
1304
+ default:
1305
+ return "direct_select";
1306
+ }
1307
+ }
1308
+ drawModeForFeatureType(featureType) {
1309
+ switch (featureType) {
1310
+ case "Polygon":
1311
+ return "draw_polygon";
1312
+ case "LineString":
1313
+ return "draw_line_string";
1314
+ case "Point":
1315
+ return "draw_point";
1316
+ case "Circle":
1317
+ return "drag_circle";
1318
+ default:
1319
+ throw new Error(`Unrecognized feature type: ${featureType}`);
1320
+ }
1321
+ }
1322
+ setFeatureGeometry(featureId, geometry) {
1323
+ const feature = this.getFeature(featureId);
1324
+ const featureCopy = {
1325
+ ...feature,
1326
+ geometry
1327
+ };
1328
+ this._features.set(featureId, featureCopy);
1329
+ return featureCopy;
1330
+ }
1331
+ isValidGeometry(feature) {
1332
+ if (featureTypeChecks.isPolygon(feature)) {
1333
+ return feature.geometry.coordinates[0][0] !== null && feature.geometry.coordinates[0].length > 3 && turfArea__default(feature) > 0;
1334
+ } else if (featureTypeChecks.isLineString(feature)) {
1335
+ return feature.geometry.coordinates.length > 1 && turfLength__default(feature) > 0;
1336
+ } else if (featureTypeChecks.isPoint(feature)) {
1337
+ return feature.geometry.coordinates.length > 0;
1338
+ }
1339
+ return false;
1340
+ }
1341
+ emitStateChange() {
1342
+ const eventData = {
1343
+ mode: this._mode,
1344
+ canUndo: this._undoStack.length > 0,
1345
+ canRedo: this._redoStack.length > 0,
1346
+ activeFeatureId: this._activeFeatureId,
1347
+ activeFeatureType: this._activeFeatureType,
1348
+ features: this._featureIds.map((id) => this._features.get(id))
1349
+ };
1350
+ this.emit("annotationStateChanged", new AnnotationEvent("annotationStateChanged", this.map, eventData));
1351
+ }
1352
+ };
1353
+ __publicField$3(_AnnotationPlugin, "_defaultOptions", {
1354
+ interactive: true,
1355
+ defaultStyle: {
1356
+ labelSize: 10,
1357
+ labelColor: "#ffffff",
1358
+ labelMaxWidth: 10,
1359
+ labelOffset: [0, 0.5],
1360
+ labelJustify: "auto",
1361
+ labelAnchor: "top",
1362
+ polygonLabelAnchor: "center",
1363
+ radius: 5,
1364
+ fillColor: "rgba(204,204,204,0.65)",
1365
+ strokeWidth: 1,
1366
+ strokeColor: "#ffffff",
1367
+ selectionStrokeColor: "orange",
1368
+ selectionStrokeOpacity: 0.5,
1369
+ selectionWidth: 3,
1370
+ hoverStrokeColor: "transparent"
1371
+ }
1372
+ });
1373
+ let AnnotationPlugin = _AnnotationPlugin;
1374
+
1375
+ var __defProp$2 = Object.defineProperty;
1376
+ var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1377
+ var __publicField$2 = (obj, key, value) => {
1378
+ __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
1379
+ return value;
1380
+ };
1381
+ const debug$1 = Debug__default("flow:data-join-map-plugin");
1382
+ const _DataJoin = class _DataJoin {
1383
+ constructor(id, map, options) {
1384
+ this.id = id;
1385
+ this.map = map;
1386
+ __publicField$2(this, "autorunDisposer", null);
1387
+ __publicField$2(this, "dataExpression", null);
1388
+ __publicField$2(this, "options");
1389
+ __publicField$2(this, "parameterExpressions", {});
1390
+ this.options = {
1391
+ ..._DataJoin.defaultOptions,
1392
+ ...options
1393
+ };
1394
+ }
1395
+ get source() {
1396
+ return this.options.source;
1397
+ }
1398
+ start() {
1399
+ this.stop();
1400
+ if (stringUtils.isString(this.options.data)) {
1401
+ if (stringUtils.isURL(this.options.data))
1402
+ this.options.data = `'${this.options.data}'`;
1403
+ this.dataExpression = new mapFeatureStream.ReactiveExpression(this.options.data);
1404
+ this.dataExpression.bindState(this.map.context.state);
1405
+ } else {
1406
+ this.dataExpression = null;
1407
+ }
1408
+ if (stringUtils.isArrayFull(this.options.parameters)) {
1409
+ this.parameterExpressions = this.options.parameters.reduce((accum, param) => {
1410
+ const expr = new mapFeatureStream.ReactiveExpression(param.value.toString());
1411
+ expr.bindState(this.map.context.state);
1412
+ accum[param.name] = expr;
1413
+ return accum;
1414
+ }, {});
1415
+ }
1416
+ this.autorunDisposer = mobx.autorun(
1417
+ async () => {
1418
+ let data = this.dataExpression ? mobx.toJS(this.dataExpression.value) : this.options.data;
1419
+ const missingParams = this.options.parameters.map(
1420
+ (p) => p.required && stringUtils.isNil(this.parameterExpressions[p.name].value) ? p.name : void 0
1421
+ ).filter((p) => !!p);
1422
+ if (stringUtils.isNull(data)) {
1423
+ debug$1(`FlowMap<${this.map.id}>: Skipping data join '${this.id}' (null data)`);
1424
+ return;
1425
+ }
1426
+ if (missingParams.length) {
1427
+ debug$1(`FlowMap<${this.map.id}>: Skipping data join '${this.id}' (null required parameters: ${missingParams.join(", ")})`);
1428
+ return;
1429
+ }
1430
+ debug$1(`FlowMap<${this.map.id}>: Performing data join '${this.id}'`);
1431
+ if (stringUtils.isString(data)) {
1432
+ try {
1433
+ data = await this.loadData(data);
1434
+ } catch (e) {
1435
+ this.map.emitError(`Failed to load data for data join '${this.id}' - ${e.message}`, e);
1436
+ data = [];
1437
+ }
1438
+ }
1439
+ this.doDataJoin(data);
1440
+ },
1441
+ { name: `FlowDataJoin.${this.map.id}.${this.id})` }
1442
+ );
1443
+ }
1444
+ stop() {
1445
+ if (this.autorunDisposer) {
1446
+ this.autorunDisposer();
1447
+ this.autorunDisposer = null;
1448
+ }
1449
+ }
1450
+ doDataJoin(data) {
1451
+ const source = this.map.getSource(this.options.source);
1452
+ const sourceLayer = source.type === "vector" ? this.options.sourceLayer || "geometry" : void 0;
1453
+ if (this.options.clear) {
1454
+ this.map.removeFeatureState({ source: source.id, sourceLayer }, this.id);
1455
+ }
1456
+ const featureData = data.reduce((accum, d) => {
1457
+ accum[d[this.options.foreignKey]] = { [this.id]: d };
1458
+ return accum;
1459
+ }, {});
1460
+ this.map.setFeatureStateBulk({ source: source.id, sourceLayer }, featureData);
1461
+ }
1462
+ loadData(datasetOrUrl) {
1463
+ if (stringUtils.isURL(datasetOrUrl)) {
1464
+ const url = new URL(datasetOrUrl);
1465
+ const params = new URLSearchParams(url.searchParams);
1466
+ if (stringUtils.isArrayFull(this.options.parameters)) {
1467
+ this.options.parameters.forEach((p) => {
1468
+ params.append(p.name, this.parameterExpressions[p.name].value);
1469
+ });
1470
+ }
1471
+ url.search = params.toString();
1472
+ const headers = new Headers({ Accept: "application/json" });
1473
+ const request = new Request(url.toString(), {
1474
+ method: "GET",
1475
+ mode: "cors",
1476
+ headers,
1477
+ cache: "default"
1478
+ });
1479
+ return fetch(request).then((response) => {
1480
+ if (!response.ok) {
1481
+ throw new Error(`status=${response.status} ${response.statusText}`);
1482
+ }
1483
+ return response.json();
1484
+ });
1485
+ } else {
1486
+ const params = {};
1487
+ if (stringUtils.isArrayFull(this.options.parameters)) {
1488
+ this.options.parameters.forEach((p) => {
1489
+ params[p.name] = this.parameterExpressions[p.name].value;
1490
+ });
1491
+ }
1492
+ return this.map.context.flowClient.datasets.query(datasetOrUrl, {}, params);
1493
+ }
1494
+ }
1495
+ };
1496
+ __publicField$2(_DataJoin, "defaultOptions", {
1497
+ clear: false,
1498
+ parameters: []
1499
+ });
1500
+ let DataJoin = _DataJoin;
1501
+ class DataJoinPlugin extends MapPluginBase {
1502
+ constructor(pluginManager) {
1503
+ super(pluginManager);
1504
+ __publicField$2(this, "_joins", /* @__PURE__ */ new Map());
1505
+ __publicField$2(this, "name", "DataJoinPlugin");
1506
+ }
1507
+ addDataJoin(id, options) {
1508
+ const dataJoin = new DataJoin(id, this.map, options);
1509
+ this._joins.set(id, dataJoin);
1510
+ dataJoin.start();
1511
+ }
1512
+ bindState(state) {
1513
+ this._joins.forEach((join) => join.start());
1514
+ }
1515
+ destroy() {
1516
+ this._joins.forEach((join) => join.stop());
1517
+ this._joins.clear();
1518
+ }
1519
+ handleSourceRemoved(event) {
1520
+ this._joins.forEach((join) => {
1521
+ if (join.source === event.source) {
1522
+ join.stop();
1523
+ this._joins.delete(join.id);
1524
+ }
1525
+ });
1526
+ }
1527
+ removeDataJoin(id) {
1528
+ const dataJoin = this._joins.get(id);
1529
+ if (dataJoin) {
1530
+ dataJoin.stop();
1531
+ this._joins.delete(id);
1532
+ } else {
1533
+ throw new mapFeatureStream.FlowError(`Cannot remove unrecognized data join '${id}'`);
1534
+ }
1535
+ }
1536
+ }
1537
+
1538
+ var __defProp$1 = Object.defineProperty;
1539
+ var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1540
+ var __publicField$1 = (obj, key, value) => {
1541
+ __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
1542
+ return value;
1543
+ };
1544
+ class HoverEffectPlugin extends MapPluginBase {
1545
+ constructor(pluginManager) {
1546
+ super(pluginManager);
1547
+ __publicField$1(this, "hoveredFeature", null);
1548
+ __publicField$1(this, "name", "HoverEffectPlugin");
1549
+ }
1550
+ handleMouseMove(event) {
1551
+ const hoveredFeature = event.features[0];
1552
+ if (hoveredFeature) {
1553
+ this.map.maplibreMap._container.classList.add("feature-hovered");
1554
+ } else {
1555
+ this.map.maplibreMap._container.classList.remove("feature-hovered");
1556
+ }
1557
+ if (!this.compareFeatures(hoveredFeature, this.hoveredFeature)) {
1558
+ this.clearHover();
1559
+ if (isFeatureWithId(hoveredFeature) && stringUtils.isDefined(this.map.getSource(hoveredFeature.source)?.featureId)) {
1560
+ this.map.setFeatureState(hoveredFeature, { hover: true }, false);
1561
+ this.hoveredFeature = hoveredFeature;
1562
+ }
1563
+ }
1564
+ }
1565
+ handleMouseOut(event) {
1566
+ this.clearHover();
1567
+ }
1568
+ handleSetExclusivePlugin(exclusivePlugins) {
1569
+ if (exclusivePlugins.length) {
1570
+ this.clearHover();
1571
+ this.map.maplibreMap._container.classList.remove("feature-hovered");
1572
+ }
1573
+ }
1574
+ compareFeatures(f1, f2) {
1575
+ if (f1 === f2) {
1576
+ return true;
1577
+ }
1578
+ if (stringUtils.isObject(f1) && stringUtils.isObject(f2)) {
1579
+ return f1.id == f2.id && f1.source === f2.source && f1.sourceLayer == f2.sourceLayer;
1580
+ }
1581
+ return false;
1582
+ }
1583
+ clearHover() {
1584
+ if (this.hoveredFeature && this.map.getSource(this.hoveredFeature.source)) {
1585
+ this.map.removeFeatureState(this.hoveredFeature, "hover", false);
1586
+ this.hoveredFeature = null;
1587
+ }
1588
+ }
1589
+ }
1590
+
1591
+ var __defProp = Object.defineProperty;
1592
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
1593
+ var __publicField = (obj, key, value) => {
1594
+ __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
1595
+ return value;
1596
+ };
1597
+ const debug = Debug__default("flow:url-sync-plugin");
1598
+ class UrlSyncPlugin extends MapPluginBase {
1599
+ constructor(pluginManager) {
1600
+ super(pluginManager);
1601
+ __publicField(this, "name", "UrlSyncPlugin");
1602
+ }
1603
+ initialize() {
1604
+ const searchParams = new URLSearchParams(window.location.search);
1605
+ const hash = searchParams.get(this.map.id);
1606
+ if (hash) {
1607
+ const center = this.hashToMapState(hash);
1608
+ debug("Setting map position from URL", center);
1609
+ this.map.setCenter(center);
1610
+ }
1611
+ }
1612
+ handleMoveEnd(event) {
1613
+ const center = this.mapStateToHash(this.map.getCenter());
1614
+ const searchParams = new URLSearchParams(window.location.search);
1615
+ searchParams.set(this.map.id, center);
1616
+ const newUrl = `${location.pathname}?${searchParams.toString()}`;
1617
+ debug("Updating URL with map position", center);
1618
+ window.history.replaceState({}, "", newUrl);
1619
+ }
1620
+ mapStateToHash(mapCenter) {
1621
+ const state = {
1622
+ z: mapCenter.zoom.toFixed(3),
1623
+ x: mapCenter.lng.toFixed(3),
1624
+ y: mapCenter.lat.toFixed(3),
1625
+ pitch: mapCenter.pitch.toFixed(1),
1626
+ bearing: mapCenter.bearing.toFixed(1)
1627
+ };
1628
+ return `${state.z}_${state.x}_${state.y}_${state.pitch}_${state.bearing}`;
1629
+ }
1630
+ hashToMapState(hash) {
1631
+ const [zoom, x, y, pitch, bearing] = hash.split("_");
1632
+ return {
1633
+ lng: +x,
1634
+ lat: +y,
1635
+ zoom: +zoom,
1636
+ pitch: +pitch,
1637
+ bearing: +bearing
1638
+ };
1639
+ }
1640
+ }
1641
+
1642
+ exports.PluginManager = mapFeatureStream.PluginManager;
1643
+ exports.AnnotationEvent = AnnotationEvent;
1644
+ exports.AnnotationPlugin = AnnotationPlugin;
1645
+ exports.DataJoin = DataJoin;
1646
+ exports.DataJoinPlugin = DataJoinPlugin;
1647
+ exports.HoverEffectPlugin = HoverEffectPlugin;
1648
+ exports.MapPluginBase = MapPluginBase;
1649
+ exports.PopupPlugin = PopupPlugin;
1650
+ exports.SelectionEvent = SelectionEvent;
1651
+ exports.SelectionPlugin = SelectionPlugin;
1652
+ exports.UrlSyncPlugin = UrlSyncPlugin;