@vidro/map-handler 1.2.10 → 1.2.19

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 (43) hide show
  1. package/README.md +442 -32
  2. package/dist/map-handler.js +1 -1
  3. package/doc/animation.png +0 -0
  4. package/doc/confirmComponent.png +0 -0
  5. package/examples/full/apidemo.js +46 -43
  6. package/examples/full/cachedToken.dat +1 -1
  7. package/examples/full/cachedTokenData.dat +1 -1
  8. package/examples/full/docker/Docker_compose.yml +14 -0
  9. package/examples/full/docker/Dockerfile +27 -0
  10. package/examples/full/index.php +5 -4
  11. package/examples/full/tester.css +74 -0
  12. package/examples/full/tester.js +2 -2
  13. package/examples/react-next/README.md +282 -0
  14. package/examples/react-next/components/AuthComponent.js +88 -0
  15. package/examples/react-next/components/MapButtons.js +161 -0
  16. package/examples/react-next/components/MapFilters.js +120 -0
  17. package/examples/react-next/components/MapIframe.js +25 -0
  18. package/examples/react-next/components/MapInfo.js +36 -0
  19. package/examples/react-next/components/MapLayers.js +60 -0
  20. package/examples/react-next/components/MapList.js +43 -0
  21. package/examples/react-next/contexts/auth.js +101 -0
  22. package/examples/react-next/contexts/maps.js +158 -0
  23. package/examples/react-next/contexts/messages.js +340 -0
  24. package/examples/react-next/env.sample +3 -0
  25. package/examples/react-next/eslint.config.mjs +14 -0
  26. package/examples/react-next/hooks/useMapEvents.js +118 -0
  27. package/examples/react-next/jsconfig.json +7 -0
  28. package/examples/react-next/next.config.mjs +6 -0
  29. package/examples/react-next/package.json +24 -0
  30. package/examples/react-next/pages/_app.js +5 -0
  31. package/examples/react-next/pages/index.js +87 -0
  32. package/examples/react-next/postcss.config.mjs +8 -0
  33. package/examples/react-next/public/discord.svg +8 -0
  34. package/examples/react-next/public/favicon.ico +0 -0
  35. package/examples/react-next/public/file.svg +1 -0
  36. package/examples/react-next/public/logo.png +0 -0
  37. package/examples/react-next/public/next.svg +1 -0
  38. package/examples/react-next/shared/constants.js +47 -0
  39. package/examples/react-next/styles/globals.css +24 -0
  40. package/examples/react-next/tailwind.config.mjs +17 -0
  41. package/helpers.md +45 -0
  42. package/package.json +1 -1
  43. package/src/index.js +305 -20
@@ -0,0 +1,47 @@
1
+ export const INFO_EVENTS = {
2
+ NO_RESULTS: "no results",
3
+ NO_LAYER: "no layer",
4
+ INVALID_GEOMETRY: "invalid geometry",
5
+ ZOOM_OVERFLOW: "zoomlevel overflow",
6
+ NO_GEOJSON_RESULTS: "no geojson results",
7
+ };
8
+ export const COMMON = {
9
+ START: "start",
10
+ REJECT: "reject",
11
+ };
12
+ export const GEOLOCATION_EVENTS = {
13
+ ERROR: "geolocation error",
14
+ GEOLOCATING: "localizing",
15
+ GEOLOCATED: "localized",
16
+ ERROR_USER_DENIED: "user denied geolocation",
17
+ };
18
+
19
+ export const MEASURING_EVENTS = {
20
+ MEASURING: "measuring",
21
+ MEASURE_END: "measured",
22
+ };
23
+
24
+ export const MAP_EVENTS = {
25
+ INFO: "info",
26
+ COORDINATES: "coordinates",
27
+ GET_TOC: "getToc",
28
+ ZOOM_CHANGE: "onZoomChange",
29
+ CENTER_CHANGE: "onCenterChange",
30
+ LOADED: "loaded",
31
+ ERROR: "error",
32
+ AVAILABLE_WMS_LAYERS: "availableWMSLayers",
33
+ CAPABILITIES: "capabilities",
34
+ GISWATER_FILTERS_APPLIED: "GiswaterFiltersApplied",
35
+ GEOLOCATION: "geolocation",
36
+ END_MEASURE: "MeasureEnd",
37
+ START_MEASURE: "MeasureStart",
38
+ UNLOADED: "unloaded",
39
+ CENTER_CHANGE: "onCenterChange",
40
+ ACTIVE_LAYER: "activeLayer",
41
+ WMS_LAYERS: "availableWMSLayers",
42
+ STATUS: "status",
43
+ GEOM_ADDED: "geomAdded",
44
+ LAYERS: "layers",
45
+ VERSION: "version",
46
+ SCREENSHOT: "screenshot",
47
+ };
@@ -0,0 +1,24 @@
1
+ @tailwind base;
2
+ @tailwind components;
3
+ @tailwind utilities;
4
+
5
+ /* Update tailwind to hide input type number arrows */
6
+ @layer base {
7
+
8
+ input[type="number"]::-webkit-inner-spin-button,
9
+ input[type="number"]::-webkit-outer-spin-button {
10
+ -webkit-appearance: none;
11
+ margin: 0;
12
+ }
13
+ }
14
+
15
+ html,
16
+ body {
17
+ padding: 0;
18
+ margin: 0;
19
+ font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen,
20
+ Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif;
21
+ color: #666666;
22
+ min-height: 100vh;
23
+ background-color: white;
24
+ }
@@ -0,0 +1,17 @@
1
+ /** @type {import('tailwindcss').Config} */
2
+ export default {
3
+ content: [
4
+ "./pages/**/*.{js,ts,jsx,tsx,mdx}",
5
+ "./components/**/*.{js,ts,jsx,tsx,mdx}",
6
+ "./app/**/*.{js,ts,jsx,tsx,mdx}",
7
+ ],
8
+ theme: {
9
+ extend: {
10
+ colors: {
11
+ background: "var(--background)",
12
+ foreground: "var(--foreground)",
13
+ },
14
+ },
15
+ },
16
+ plugins: [],
17
+ };
package/helpers.md ADDED
@@ -0,0 +1,45 @@
1
+ ##### Image to ArrayBuffer
2
+
3
+
4
+ >Helper function to fetch image as ArrayBuffer
5
+
6
+ ```
7
+ const fetchImageAsArrayBuffer = async (path) => {
8
+ try {
9
+ const response = await fetch(path); // Fetch the image from the path
10
+ const buffer = await response.arrayBuffer(); // Convert response to ArrayBuffer
11
+ return buffer; // Return the binary data
12
+ } catch (error) {
13
+ console.error("Error fetching image:", error);
14
+ throw error;
15
+ }
16
+ };
17
+ ```
18
+
19
+ >Helper function to set image as ArrayBuffer with vanilla js
20
+
21
+
22
+ ```
23
+ // Simulate a call to Dropbox or other service that can
24
+ // return an image as an ArrayBuffer.
25
+ var xhr = new XMLHttpRequest();
26
+
27
+ // Use JSFiddle logo as a sample image to avoid complicating
28
+ // this example with cross-domain issues.
29
+ xhr.open( "GET", "http://fiddle.jshell.net/img/logo.png", true );
30
+
31
+ // Ask for the result as an ArrayBuffer.
32
+ xhr.responseType = "arraybuffer";
33
+
34
+ xhr.onload = function( e ) {
35
+ // Obtain a blob: URL for the image data.
36
+ var arrayBufferView = new Uint8Array( this.response );
37
+ var blob = new Blob( [ arrayBufferView ], { type: "image/jpeg" } );
38
+ var urlCreator = window.URL || window.webkitURL;
39
+ var imageUrl = urlCreator.createObjectURL( blob );
40
+ var img = document.querySelector( "#photo" );
41
+ img.src = imageUrl;
42
+ };
43
+
44
+ xhr.send();
45
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vidro/map-handler",
3
- "version": "1.2.10",
3
+ "version": "1.2.19",
4
4
  "description": "Tool to achieve the easiest way of communication with the map",
5
5
  "homepage": "https://github.com/Vidro-Software-SL/maphandler",
6
6
  "repository": {
package/src/index.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { EventEmitter } from "events";
2
2
  import { iframeCommunicator } from "./shared/iframe-communicator";
3
+
3
4
  class Communicator extends EventEmitter {
4
5
  constructor(data) {
5
6
  super();
@@ -15,19 +16,25 @@ class Communicator extends EventEmitter {
15
16
  this.sessionToken = data.sessionToken;
16
17
  }
17
18
 
19
+ removeListener(event, listener) {
20
+ super.removeListener(event, listener);
21
+ }
18
22
  onMessageReceived = (e) => {
19
23
  switch (e.data.type) {
20
24
  case "onZoomChange":
21
- this.emitEvent("onZoomChange", e.data.zoom, e.data.domId);
25
+ this.emitEvent("onZoomChange", e.data, e.data.domId);
26
+ break;
27
+ case "onCenterChange":
28
+ this.emitEvent("onCenterChange", e.data, e.data.domId);
22
29
  break;
23
30
  case "geomAdded":
24
- this.emitEvent("geomAdded", e.data.geom_astext, e.data.domId);
31
+ this.emitEvent("geomAdded", e.data, e.data.domId);
25
32
  break;
26
33
  case "layers":
27
- this.emitEvent("layers", e.data.layers, e.data.domId);
34
+ this.emitEvent("layers", e.data, e.data.domId);
28
35
  break;
29
36
  case "geoJSONlayers":
30
- this.emitEvent("geoJSONlayers", e.data.layers, e.data.domId);
37
+ this.emitEvent("geoJSONlayers", e.data, e.data.domId);
31
38
  break;
32
39
  case "info":
33
40
  this.emitEvent("info", e.data, e.data.domId);
@@ -82,6 +89,22 @@ class Communicator extends EventEmitter {
82
89
  case "status":
83
90
  this.emitEvent("status", e.data, e.data.domId);
84
91
  break;
92
+ case "MeasureEnd":
93
+ this.emitEvent("MeasureEnd", e.data, e.data.domId);
94
+ break;
95
+ case "queue":
96
+ this.emitEvent("queue", e.data, e.data.domId);
97
+ break;
98
+ case "version":
99
+ this.emitEvent("version", e.data, e.data.domId);
100
+ break;
101
+ case "hover":
102
+ this.emitEvent("hover", e.data, e.data.domId);
103
+ break;
104
+ case "screenshot":
105
+ this.emitEvent("screenshot", e.data, e.data.domId);
106
+ break;
107
+
85
108
  //case "getLegend": this.emitEvent("getLegend", e.data,e.data.domId); break;
86
109
  }
87
110
  };
@@ -107,37 +130,74 @@ class Communicator extends EventEmitter {
107
130
  });
108
131
  };
109
132
 
110
- AddGeom = (geomtype) => {
133
+ AddGeom = (geomtype, options) => {
111
134
  this.com.sendMessageToMap({
112
135
  type: "AddGeom",
113
136
  geom: geomtype,
137
+ texts: options?.texts,
138
+ style: options?.style,
139
+ drawOnEnd: options?.drawOnEnd,
140
+ showConfirm: options?.showConfirm,
114
141
  sessionToken: this.sessionToken,
115
142
  });
116
143
  };
117
144
 
145
+ CancelAddGeom = (s) => {
146
+ this.com.sendMessageToMap({
147
+ type: "CancelAddGeom",
148
+ });
149
+ };
150
+
151
+ loadMultipleLayers = (layers) => {
152
+ if (typeof layers !== "undefined") {
153
+ this.com.sendMessageToMap({
154
+ type: "loadMultipleLayers",
155
+ layers: layers,
156
+ });
157
+ } else {
158
+ this.emit("error", { error: "no layers" });
159
+ }
160
+ };
161
+
162
+ toggleGroup = (layers) => {
163
+ this.com.sendMessageToMap({
164
+ type: "toggleGroup",
165
+ layers,
166
+ });
167
+ };
168
+
118
169
  toggleLayer = (layer, properties) => {
119
170
  if (typeof properties === "undefined") {
120
171
  properties = {
121
172
  gutter: null,
122
173
  transparent: null,
123
174
  singletile: null,
175
+ zIndex: null,
124
176
  };
125
177
  }
126
178
 
127
179
  if (properties.singletile !== null) {
128
180
  if (typeof properties.singletile !== "boolean") {
129
181
  properties.singletile = null;
130
- this.emit("error", { error: "singleTile must be a Boolean" });
182
+ this.emit("error", {
183
+ error: "singletile must be a Boolean",
184
+ type: "error",
185
+ });
131
186
  }
132
187
  }
133
- if (properties.gutter !== "" && properties.gutter !== null) {
188
+ if (
189
+ properties.gutter !== "" &&
190
+ properties.gutter !== null &&
191
+ !properties.singletile
192
+ ) {
134
193
  if (isNaN(parseInt(properties.gutter))) {
135
194
  properties.gutter = null;
136
- this.emit("error", { error: "Gutter must be a number" });
195
+ this.emit("error", { type: "error", error: "Gutter must be a number" });
137
196
  }
138
197
  if (properties.singletile) {
139
198
  properties.gutter = null;
140
199
  this.emit("error", {
200
+ type: "error",
141
201
  error:
142
202
  "Gutter can only be user with multitile layers; set singletile to false",
143
203
  });
@@ -147,7 +207,10 @@ class Communicator extends EventEmitter {
147
207
  if (properties.transparent !== null) {
148
208
  if (typeof properties.transparent !== "boolean") {
149
209
  properties.transparent = null;
150
- this.emit("error", { error: "transparent must be a Boolean" });
210
+ this.emit("error", {
211
+ type: "error",
212
+ error: "transparent must be a Boolean",
213
+ });
151
214
  }
152
215
  }
153
216
  this.com.sendMessageToMap({
@@ -159,9 +222,27 @@ class Communicator extends EventEmitter {
159
222
  transparent: properties.transparent,
160
223
  singletile: properties.singletile,
161
224
  sessionToken: this.sessionToken,
225
+ zIndex: !isNaN(parseInt(properties.zIndex))
226
+ ? parseInt(properties.zIndex)
227
+ : null,
228
+ });
229
+ };
230
+
231
+ removeLayer = (layer) => {
232
+ this.com.sendMessageToMap({
233
+ type: "removeLayer",
234
+ layer: layer,
235
+ sessionToken: this.sessionToken,
162
236
  });
163
237
  };
164
238
 
239
+ displayLayer = (layer) => {
240
+ this.com.sendMessageToMap({
241
+ type: "displayLayer",
242
+ layer: layer,
243
+ sessionToken: this.sessionToken,
244
+ });
245
+ };
165
246
  setActiveLayer = (layer) => {
166
247
  this.com.sendMessageToMap({
167
248
  type: "setActiveLayer",
@@ -177,6 +258,22 @@ class Communicator extends EventEmitter {
177
258
  });
178
259
  };
179
260
 
261
+ bringLayerToTop = (layer) => {
262
+ this.com.sendMessageToMap({
263
+ type: "bringLayerToTop",
264
+ layer: layer,
265
+ sessionToken: this.sessionToken,
266
+ });
267
+ };
268
+
269
+ bringLayerToBottom = (layer) => {
270
+ this.com.sendMessageToMap({
271
+ type: "bringLayerToBottom",
272
+ layer: layer,
273
+ sessionToken: this.sessionToken,
274
+ });
275
+ };
276
+
180
277
  loadWMSAvailableLayers = () => {
181
278
  this.com.sendMessageToMap({
182
279
  type: "loadWMSAvailableLayers",
@@ -196,11 +293,69 @@ class Communicator extends EventEmitter {
196
293
  type: "highlight",
197
294
  geom: options.geom,
198
295
  zoom: options.zoom,
296
+ metadata: options?.data,
297
+ center: options?.center !== undefined ? options.center : false,
298
+ animate: options?.animate,
299
+ style: options?.style,
199
300
  sessionToken: this.sessionToken,
200
301
  });
201
302
  };
202
303
 
203
- DrawGeometry = (geom, styles, name) => {
304
+ DrawGeometries = (geoms) => {
305
+ if (typeof geoms !== "undefined") {
306
+ this.com.sendMessageToMap({
307
+ type: "DrawGeometries",
308
+ geoms: geoms,
309
+ });
310
+ } else {
311
+ this.emit("error", { type: "error", error: "no geoms" });
312
+ }
313
+ };
314
+
315
+ RemoveGeometriesByProperty = (layer, property, value) => {
316
+ if (
317
+ typeof layer !== "undefined" &&
318
+ typeof property !== "undefined" &&
319
+ typeof value !== "undefined"
320
+ ) {
321
+ this.com.sendMessageToMap({
322
+ type: "RemoveGeometriesByProperty",
323
+ layer,
324
+ property,
325
+ value,
326
+ });
327
+ } else {
328
+ this.emit("error", {
329
+ type: "error",
330
+ error: "no layer, property or value",
331
+ });
332
+ }
333
+ };
334
+
335
+ UpdateGeometriesByProperty = (layer, property, value, style) => {
336
+ if (
337
+ typeof layer !== "undefined" &&
338
+ typeof property !== "undefined" &&
339
+ typeof style !== "undefined" &&
340
+ typeof value !== "undefined"
341
+ ) {
342
+ this.com.sendMessageToMap({
343
+ type: "UpdateGeometriesByProperty",
344
+ layer,
345
+ property,
346
+ value,
347
+ style,
348
+ });
349
+ } else {
350
+ this.emit("error", {
351
+ type: "error",
352
+ error: "no layer, property or value",
353
+ });
354
+ }
355
+ };
356
+
357
+ DrawGeometry = (geom, styles, name, id) => {
358
+ console.warn("DrawGeometry is deprecated. Use DrawGeometries");
204
359
  const sty = {
205
360
  stroke_color: styles.stroke_color ? styles.stroke_color : null,
206
361
  fill_color: styles.fill_color ? styles.fill_color : null,
@@ -212,7 +367,7 @@ class Communicator extends EventEmitter {
212
367
  //text
213
368
  font_color: styles.font_color ? styles.font_color : null,
214
369
  font: styles.font ? styles.font : null,
215
- fontSize: styles.fontSize ? styles.fontSize : null,
370
+ font_size: styles.font_size ? styles.font_size : null,
216
371
  placement: styles.placement ? styles.placement : null,
217
372
  fontFillColor: styles.fontFillColor ? styles.fontFillColor : null,
218
373
  fontStrokeColor: styles.fontStrokeColor ? styles.fontStrokeColor : null,
@@ -220,6 +375,7 @@ class Communicator extends EventEmitter {
220
375
  baseline: styles.baseline ? styles.baseline : null,
221
376
  align: styles.align ? styles.align : null,
222
377
  display: styles.display ? styles.display : null,
378
+ offsetY: styles.offsetY ? styles.offsetY : null,
223
379
  };
224
380
 
225
381
  this.com.sendMessageToMap({
@@ -227,10 +383,25 @@ class Communicator extends EventEmitter {
227
383
  geom: geom,
228
384
  style: sty,
229
385
  name: name ? name : "highlight",
386
+ id: id ? id : Math.floor(Math.random() * 1000) + 1,
230
387
  sessionToken: this.sessionToken,
231
388
  });
232
389
  };
233
390
 
391
+ RemoveGeometry = (id, layer = null) => {
392
+ const _id = typeof id == "undefined" ? null : id;
393
+ if (!_id) {
394
+ console.error("No element id");
395
+ this.emit("error", { type: "error", error: "No element id" });
396
+ return;
397
+ }
398
+ this.com.sendMessageToMap({
399
+ type: "removeGeometry",
400
+ layer,
401
+ id: _id,
402
+ });
403
+ };
404
+
234
405
  zoomToExtent = () => {
235
406
  this.com.sendMessageToMap({
236
407
  type: "zoomToExtent",
@@ -238,6 +409,37 @@ class Communicator extends EventEmitter {
238
409
  });
239
410
  };
240
411
 
412
+ zoomToScale = (scale) => {
413
+ const allowedScales = [
414
+ "1:100",
415
+ "1:200",
416
+ "1:400",
417
+ "1:500",
418
+ "1:1000",
419
+ "1:2000",
420
+ "1:5000",
421
+ "1:10000",
422
+ "1:50000",
423
+ ];
424
+
425
+ if (!allowedScales.includes(scale)) {
426
+ console.error(
427
+ `Invalid scale: ${scale}. Allowed values are: ${allowedScales.join(
428
+ ", "
429
+ )}`
430
+ );
431
+ this.emit("error", {
432
+ type: "error",
433
+ error: `Invalid scale: ${scale}`,
434
+ });
435
+ return;
436
+ }
437
+ this.com.sendMessageToMap({
438
+ type: "zoomToScale",
439
+ sessionToken: this.sessionToken,
440
+ scale: scale,
441
+ });
442
+ };
241
443
  zoomToCoordinates = (lat, lon, zoomLevel) => {
242
444
  if (!isNaN(parseInt(zoomLevel))) {
243
445
  this.com.sendMessageToMap({
@@ -249,6 +451,15 @@ class Communicator extends EventEmitter {
249
451
  }
250
452
  };
251
453
 
454
+ zoomToGeometry = (geom, limits) => {
455
+ this.com.sendMessageToMap({
456
+ type: "zoomToGeometry",
457
+ sessionToken: this.sessionToken,
458
+ geom,
459
+ limits,
460
+ });
461
+ };
462
+
252
463
  infoFromCoordinates = (type, layer, hitTolerance, format) => {
253
464
  const _layer = typeof layer == "undefined" ? null : layer;
254
465
  const _hitTolerance =
@@ -294,10 +505,11 @@ class Communicator extends EventEmitter {
294
505
  });
295
506
  };
296
507
 
297
- Geolocalize = (toggle) => {
508
+ Geolocalize = (toggle, options) => {
298
509
  this.com.sendMessageToMap({
299
510
  type: "Geolocalize",
300
511
  toggle: toggle,
512
+ options: options,
301
513
  sessionToken: this.sessionToken,
302
514
  });
303
515
  };
@@ -305,7 +517,7 @@ class Communicator extends EventEmitter {
305
517
  /* deprecated since v1.1.19 */
306
518
  toggleGiswaterTiled = (toggle, tiled) => {
307
519
  this.com.sendMessageToMap({
308
- type: "toggleGiswaterTiled",
520
+ type: "toggleTiled",
309
521
  toggle: toggle,
310
522
  tiled: tiled,
311
523
  sessionToken: this.sessionToken,
@@ -362,7 +574,7 @@ class Communicator extends EventEmitter {
362
574
  sessionToken: this.sessionToken,
363
575
  });
364
576
  } else {
365
- this.emit("error", { error: "No geoJSON data" });
577
+ this.emit("error", { type: "error", error: "No geoJSON data" });
366
578
  return;
367
579
  }
368
580
  };
@@ -382,7 +594,7 @@ class Communicator extends EventEmitter {
382
594
  sessionToken: this.sessionToken,
383
595
  });
384
596
  } else {
385
- this.emit("error", { error: "No geoJSON data" });
597
+ this.emit("error", { type: "error", error: "No geoJSON data" });
386
598
  return;
387
599
  }
388
600
  };
@@ -397,7 +609,10 @@ class Communicator extends EventEmitter {
397
609
  try {
398
610
  filtersJson = JSON.parse(filters);
399
611
  } catch (e) {
400
- this.emit("error", { error: "Filters is not a valid JSON" });
612
+ this.emit("error", {
613
+ type: "error",
614
+ error: "Filters is not a valid JSON",
615
+ });
401
616
  return;
402
617
  }
403
618
  }
@@ -408,7 +623,7 @@ class Communicator extends EventEmitter {
408
623
  sessionToken: this.sessionToken,
409
624
  });
410
625
  } else {
411
- this.emit("error", { error: "No filters" });
626
+ this.emit("error", { type: "error", error: "No filters" });
412
627
  return;
413
628
  }
414
629
  };
@@ -423,18 +638,30 @@ class Communicator extends EventEmitter {
423
638
  try {
424
639
  filtersJson = JSON.parse(filters);
425
640
  } catch (e) {
426
- this.emit("error", { error: "Filters is not a valid JSON" });
641
+ this.emit("error", {
642
+ type: "error",
643
+ error: "Filters is not a valid JSON",
644
+ });
427
645
  return;
428
646
  }
429
647
  }
648
+ const isValid = filtersJson.every((item) => Array.isArray(item.filters));
430
649
 
650
+ // isValid will be true if all elements have "filters" property that is an array
651
+ if (!isValid) {
652
+ this.emit("error", {
653
+ type: "error",
654
+ error: "Filters is not a valid JSON - missing filters array",
655
+ });
656
+ return;
657
+ }
431
658
  return this.com.sendMessageToMap({
432
659
  type: "setFilters",
433
660
  filters: filtersJson,
434
661
  sessionToken: this.sessionToken,
435
662
  });
436
663
  } else {
437
- this.emit("error", { error: "No filters" });
664
+ this.emit("error", { type: "error", error: "No filters" });
438
665
  return;
439
666
  }
440
667
  };
@@ -447,7 +674,7 @@ class Communicator extends EventEmitter {
447
674
  sessionToken: this.sessionToken,
448
675
  });
449
676
  } else {
450
- this.emit("error", { error: "No layer_name" });
677
+ this.emit("error", { type: "error", error: "No layer_name" });
451
678
  return;
452
679
  }
453
680
  };
@@ -551,6 +778,64 @@ class Communicator extends EventEmitter {
551
778
  sessionToken: this.sessionToken,
552
779
  });
553
780
  };
781
+
782
+ setBboxSize = (bbox) => {
783
+ if (!isNaN(parseInt(bbox))) {
784
+ this.com.sendMessageToMap({
785
+ type: "setBoundingBoxSize",
786
+ bbox: bbox,
787
+ sessionToken: this.sessionToken,
788
+ });
789
+ } else {
790
+ console.error("bbox is not a integer");
791
+ }
792
+ };
793
+ addIcon = ({ icon, coordinates }) => {
794
+ // Validate icon
795
+ if (!(icon instanceof ArrayBuffer)) {
796
+ this.emit("error", {
797
+ type: "error",
798
+ error: "Invalid icon: Expected an ArrayBuffer.",
799
+ });
800
+ }
801
+
802
+ // Validate coordinates
803
+ if (!Array.isArray(coordinates)) {
804
+ this.emit("error", {
805
+ type: "error",
806
+ error: "Invalid coordinates: Expected an array [longitude, latitude].",
807
+ });
808
+ }
809
+
810
+ // Ensure coordinates contain exactly two numeric values
811
+ if (
812
+ coordinates.length !== 2 ||
813
+ typeof coordinates[0] !== "number" ||
814
+ typeof coordinates[1] !== "number"
815
+ ) {
816
+ this.emit("error", {
817
+ type: "error",
818
+ error:
819
+ "Invalid coordinates: Expected an array with two numeric values [longitude, latitude].",
820
+ });
821
+ }
822
+
823
+ // Send the message to the map
824
+ this.com.sendMessageToMap({
825
+ type: "AddIcon",
826
+ icon,
827
+ coordinates,
828
+ sessionToken: this.sessionToken,
829
+ });
830
+ };
831
+
832
+ screenshot = (options) => {
833
+ this.com.sendMessageToMap({
834
+ type: "screenshot",
835
+ options,
836
+ sessionToken: this.sessionToken,
837
+ });
838
+ };
554
839
  }
555
840
 
556
841
  export { Communicator };