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