@openremote/or-map 1.8.0-snapshot.20250725120002 → 1.8.0-snapshot.20250728102340

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/mapwidget.js CHANGED
@@ -1,885 +1 @@
1
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
- return new (P || (P = Promise))(function (resolve, reject) {
4
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
- step((generator = generator.apply(thisArg, _arguments || [])).next());
8
- });
9
- };
10
- import manager, { DefaultColor4 } from "@openremote/core";
11
- import maplibregl, { GeolocateControl, Marker as MarkerGL, NavigationControl, } from "maplibre-gl";
12
- import MaplibreGeocoder from "@maplibre/maplibre-gl-geocoder";
13
- import "@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css";
14
- import { debounce } from "lodash";
15
- import { OrMapClickedEvent, OrMapGeocoderChangeEvent, OrMapLoadedEvent, OrMapLongPressEvent, } from "./index";
16
- import { getLatLngBounds, getLngLat } from "./util";
17
- import { isMapboxURL, transformMapboxUrl } from "./mapbox-url-utils";
18
- const mapboxJsStyles = require("mapbox.js/dist/mapbox.css");
19
- const maplibreGlStyles = require("maplibre-gl/dist/maplibre-gl.css");
20
- const maplibreGeoCoderStyles = require("@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css");
21
- // TODO: fix any type
22
- const metersToPixelsAtMaxZoom = (meters, latitude) => meters / 0.075 / Math.cos(latitude * Math.PI / 180);
23
- let pkey;
24
- export class MapWidget {
25
- constructor(type, styleParent, mapContainer, showGeoCodingControl = false, showBoundaryBox = false, useZoomControls = true, showGeoJson = true) {
26
- this._loaded = false;
27
- this._markersJs = new Map();
28
- this._markersGl = new Map();
29
- this._geoJsonSources = [];
30
- this._geoJsonLayers = new Map();
31
- this._showGeoCodingControl = false;
32
- this._showBoundaryBox = false;
33
- this._useZoomControls = true;
34
- this._showGeoJson = true;
35
- this._clickHandlers = new Map();
36
- this._type = type;
37
- this._styleParent = styleParent;
38
- this._mapContainer = mapContainer;
39
- this._showGeoCodingControl = showGeoCodingControl;
40
- this._showBoundaryBox = showBoundaryBox;
41
- this._useZoomControls = useZoomControls;
42
- this._showGeoJson = showGeoJson;
43
- }
44
- setCenter(center) {
45
- this._center = getLngLat(center);
46
- switch (this._type) {
47
- case "RASTER" /* MapType.RASTER */:
48
- if (this._mapJs) {
49
- const latLng = getLngLat(this._center) || (this._viewSettings ? getLngLat(this._viewSettings.center) : undefined);
50
- if (latLng) {
51
- this._mapJs.setView(latLng, undefined, { pan: { animate: false }, zoom: { animate: false } });
52
- }
53
- }
54
- break;
55
- case "VECTOR" /* MapType.VECTOR */:
56
- if (this._mapGl && this._center) {
57
- this._mapGl.setCenter(this._center);
58
- }
59
- break;
60
- }
61
- return this;
62
- }
63
- flyTo(coordinates, zoom) {
64
- switch (this._type) {
65
- case "RASTER" /* MapType.RASTER */:
66
- if (this._mapJs) {
67
- // TODO implement fylTo
68
- }
69
- break;
70
- case "VECTOR" /* MapType.VECTOR */:
71
- if (!coordinates) {
72
- coordinates = this._center ? this._center : this._viewSettings ? this._viewSettings.center : undefined;
73
- }
74
- if (!zoom) {
75
- zoom = this._zoom ? this._zoom : this._viewSettings && this._viewSettings.zoom ? this._viewSettings.zoom : undefined;
76
- }
77
- if (this._mapGl) {
78
- // Only do flyTo if it has valid LngLat value
79
- if (coordinates) {
80
- this._mapGl.flyTo({
81
- center: coordinates,
82
- zoom: zoom
83
- });
84
- }
85
- }
86
- else {
87
- this._center = coordinates;
88
- this._zoom = zoom;
89
- }
90
- break;
91
- }
92
- return this;
93
- }
94
- resize() {
95
- switch (this._type) {
96
- case "RASTER" /* MapType.RASTER */:
97
- if (this._mapJs) {
98
- }
99
- break;
100
- case "VECTOR" /* MapType.VECTOR */:
101
- if (this._mapGl) {
102
- this._mapGl.resize();
103
- }
104
- break;
105
- }
106
- return this;
107
- }
108
- setZoom(zoom) {
109
- this._zoom = zoom;
110
- switch (this._type) {
111
- case "RASTER" /* MapType.RASTER */:
112
- if (this._mapJs && this._zoom) {
113
- this._mapJs.setZoom(this._zoom, { animate: false });
114
- }
115
- break;
116
- case "VECTOR" /* MapType.VECTOR */:
117
- if (this._mapGl && this._zoom) {
118
- this._mapGl.setZoom(this._zoom);
119
- }
120
- break;
121
- }
122
- return this;
123
- }
124
- setControls(controls) {
125
- this._controls = controls;
126
- if (this._mapGl) {
127
- if (this._controls) {
128
- this._controls.forEach((control) => {
129
- if (Array.isArray(control)) {
130
- const controlAndPosition = control;
131
- this._mapGl.addControl(controlAndPosition[0], controlAndPosition[1]);
132
- }
133
- else {
134
- this._mapGl.addControl(control);
135
- }
136
- });
137
- }
138
- else {
139
- // Add zoom and rotation controls to the map
140
- this._mapGl.addControl(new NavigationControl());
141
- }
142
- }
143
- return this;
144
- }
145
- setGeoJson(geoJsonConfig) {
146
- var _a;
147
- this._geoJsonConfig = geoJsonConfig;
148
- if (this._mapGl) {
149
- if (this._geoJsonConfig) {
150
- this.loadGeoJSON(this._geoJsonConfig);
151
- }
152
- else {
153
- this.loadGeoJSON((_a = this._viewSettings) === null || _a === void 0 ? void 0 : _a.geoJson);
154
- }
155
- }
156
- return this;
157
- }
158
- loadViewSettings() {
159
- return __awaiter(this, void 0, void 0, function* () {
160
- var _a;
161
- let settingsResponse;
162
- if (this._type === "RASTER" /* MapType.RASTER */) {
163
- settingsResponse = yield manager.rest.api.MapResource.getSettingsJs();
164
- }
165
- else {
166
- settingsResponse = yield manager.rest.api.MapResource.getSettings();
167
- }
168
- const settings = settingsResponse.data;
169
- if (settings.override) {
170
- return settings.override;
171
- }
172
- // Load options for current realm or fallback to default if exist
173
- const realmName = manager.displayRealm || "default";
174
- this._viewSettings = settings.options ? settings.options[realmName] ? settings.options[realmName] : settings.options.default : null;
175
- if (this._viewSettings) {
176
- // If Map was already present, so only ran during updates such as realm switches
177
- if (this._mapGl) {
178
- this._mapGl.setMinZoom(this._viewSettings.minZoom);
179
- this._mapGl.setMaxZoom(this._viewSettings.maxZoom);
180
- if (this._viewSettings.bounds) {
181
- this._mapGl.setMaxBounds(this._viewSettings.bounds);
182
- }
183
- // Unload all GeoJSON that is present, and load new layers if present
184
- if (this._geoJsonConfig) {
185
- yield this.loadGeoJSON(this._geoJsonConfig);
186
- }
187
- else {
188
- yield this.loadGeoJSON((_a = this._viewSettings) === null || _a === void 0 ? void 0 : _a.geoJson);
189
- }
190
- }
191
- if (!this._center) {
192
- this.setCenter(this._viewSettings.center);
193
- }
194
- else {
195
- this.setCenter(this._center);
196
- }
197
- }
198
- return settings;
199
- });
200
- }
201
- load() {
202
- return __awaiter(this, void 0, void 0, function* () {
203
- var _a;
204
- if (this._loaded) {
205
- return;
206
- }
207
- if (this._type === "RASTER" /* MapType.RASTER */) {
208
- // Add style to shadow root
209
- const style = document.createElement("style");
210
- style.id = "mapboxJsStyle";
211
- style.textContent = mapboxJsStyles;
212
- this._styleParent.appendChild(style);
213
- const settings = yield this.loadViewSettings();
214
- let options;
215
- if (this._viewSettings) {
216
- options = {};
217
- // JS zoom is out compared to GL
218
- options.zoom = this._viewSettings.zoom ? this._viewSettings.zoom + 1 : undefined;
219
- if (this._useZoomControls) {
220
- options.maxZoom = this._viewSettings.maxZoom ? this._viewSettings.maxZoom - 1 : undefined;
221
- options.minZoom = this._viewSettings.minZoom ? this._viewSettings.minZoom + 1 : undefined;
222
- }
223
- options.boxZoom = this._viewSettings.boxZoom;
224
- // JS uses lat then lng unlike GL
225
- if (this._viewSettings.bounds) {
226
- options.maxBounds = getLatLngBounds(this._viewSettings.bounds);
227
- }
228
- if (this._viewSettings.center) {
229
- const lngLat = getLngLat(this._viewSettings.center);
230
- options.center = lngLat ? L.latLng(lngLat.lat, lngLat.lng) : undefined;
231
- }
232
- if (this._center) {
233
- const lngLat = getLngLat(this._center);
234
- options.center = lngLat ? L.latLng(lngLat.lat, lngLat.lng) : undefined;
235
- }
236
- if (this._zoom) {
237
- options.zoom = this._zoom + 1;
238
- }
239
- }
240
- this._mapJs = L.mapbox.map(this._mapContainer, settings, options);
241
- this._mapJs.on("click", (e) => {
242
- this._onMapClick(e.latlng);
243
- });
244
- if (options && options.maxBounds) {
245
- const minZoom = this._mapJs.getBoundsZoom(options.maxBounds, true);
246
- if (!options.minZoom || options.minZoom < minZoom) {
247
- this._mapJs.setMinZoom(minZoom);
248
- }
249
- }
250
- }
251
- else {
252
- // Add style to shadow root
253
- let style = document.createElement("style");
254
- style.id = "maplibreGlStyle";
255
- style.textContent = maplibreGlStyles;
256
- this._styleParent.appendChild(style);
257
- style = document.createElement("style");
258
- style.id = "maplibreGeoCoderStyles";
259
- style.textContent = maplibreGeoCoderStyles;
260
- this._styleParent.appendChild(style);
261
- const map = yield import(/* webpackChunkName: "maplibre-gl" */ "maplibre-gl");
262
- const settings = yield this.loadViewSettings();
263
- const options = {
264
- attributionControl: { compact: true },
265
- container: this._mapContainer,
266
- style: settings,
267
- transformRequest: (url, resourceType) => {
268
- if (!pkey) {
269
- pkey = new URL(url).searchParams.get("access_token") || '';
270
- }
271
- if (isMapboxURL(url)) {
272
- return transformMapboxUrl(url, pkey, resourceType);
273
- }
274
- // Cross-domain tile servers usually have the following headers specified "access-control-allow-methods GET", "access-control-allow-origin *", "allow GET,HEAD". The "Access-Control-Request-Headers: Authorization" may not be set e.g. with Mapbox tile servers. The CORS preflight request (OPTION) will in this case fail if the "authorization" header is being requested cross-domain. The only headers allowed are so called "simple request" headers, see https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests.
275
- const headers = new URL(window.origin).hostname === new URL(url).hostname
276
- ? { Authorization: manager.getAuthorizationHeader() } : {};
277
- return {
278
- headers,
279
- url
280
- };
281
- }
282
- };
283
- if (this._viewSettings) {
284
- if (this._useZoomControls) {
285
- options.maxZoom = this._viewSettings.maxZoom;
286
- options.minZoom = this._viewSettings.minZoom;
287
- }
288
- if (this._viewSettings.bounds && !this._showBoundaryBox) {
289
- options.maxBounds = this._viewSettings.bounds;
290
- }
291
- options.boxZoom = this._viewSettings.boxZoom;
292
- options.zoom = this._viewSettings.zoom;
293
- options.center = this._viewSettings.center;
294
- }
295
- this._center = this._center || (this._viewSettings ? this._viewSettings.center : undefined);
296
- options.center = this._center;
297
- if (this._zoom) {
298
- options.zoom = this._zoom;
299
- }
300
- this._mapGl = new map.Map(options);
301
- yield this.styleLoaded();
302
- this._mapGl.on("click", (e) => {
303
- this._onMapClick(e.lngLat);
304
- });
305
- this._mapGl.on("dblclick", (e) => {
306
- this._onMapClick(e.lngLat, true);
307
- });
308
- if (this._showGeoCodingControl && this._viewSettings && this._viewSettings.geocodeUrl) {
309
- this._geocoder = new MaplibreGeocoder({ forwardGeocode: this._forwardGeocode.bind(this), reverseGeocode: this._reverseGeocode }, { maplibregl: maplibregl, showResultsWhileTyping: true });
310
- // Override the _onKeyDown function from MaplibreGeocoder which has a bug getting the value from the input element
311
- this._geocoder._onKeyDown = debounce((e) => {
312
- var ESC_KEY_CODE = 27, TAB_KEY_CODE = 9;
313
- if (e.keyCode === ESC_KEY_CODE && this._geocoder.options.clearAndBlurOnEsc) {
314
- this._geocoder._clear(e);
315
- return this._geocoder._inputEl.blur();
316
- }
317
- // if target has shadowRoot, then get the actual active element inside the shadowRoot
318
- var value = this._geocoder._inputEl.value || e.key;
319
- if (!value) {
320
- this._geocoder.fresh = true;
321
- // the user has removed all the text
322
- if (e.keyCode !== TAB_KEY_CODE)
323
- this._geocoder.clear(e);
324
- return (this._geocoder._clearEl.style.display = "none");
325
- }
326
- // TAB, ESC, LEFT, RIGHT, UP, DOWN
327
- if (e.metaKey ||
328
- [TAB_KEY_CODE, ESC_KEY_CODE, 37, 39, 38, 40].indexOf(e.keyCode) !== -1)
329
- return;
330
- // ENTER
331
- if (e.keyCode === 13) {
332
- if (!this._geocoder.options.showResultsWhileTyping) {
333
- if (!this._geocoder._typeahead.list.selectingListItem)
334
- this._geocoder._geocode(value);
335
- }
336
- else {
337
- if (this._geocoder.options.showResultMarkers) {
338
- this._geocoder._fitBoundsForMarkers();
339
- }
340
- this._geocoder._inputEl.value = this._geocoder._typeahead.query;
341
- this._geocoder.lastSelected = null;
342
- this._geocoder._typeahead.selected = null;
343
- return;
344
- }
345
- }
346
- if (value.length >= this._geocoder.options.minLength &&
347
- this._geocoder.options.showResultsWhileTyping) {
348
- this._geocoder._geocode(value);
349
- }
350
- }, 300);
351
- this._mapGl.addControl(this._geocoder, 'top-left');
352
- // There's no callback parameter in the options of the MaplibreGeocoder,
353
- // so this is how we get the selected result.
354
- this._geocoder._inputEl.addEventListener("change", () => {
355
- var selected = this._geocoder._typeahead.selected;
356
- this._onGeocodeChange(selected);
357
- });
358
- }
359
- // Add custom controls
360
- if (this._controls) {
361
- this._controls.forEach((control) => {
362
- if (Array.isArray(control)) {
363
- const controlAndPosition = control;
364
- this._mapGl.addControl(controlAndPosition[0], controlAndPosition[1]);
365
- }
366
- else {
367
- this._mapGl.addControl(control);
368
- }
369
- });
370
- }
371
- else {
372
- // Add zoom and rotation controls to the map
373
- this._mapGl.addControl(new NavigationControl());
374
- // Add current location controls to the map
375
- this._mapGl.addControl(new GeolocateControl({
376
- positionOptions: {
377
- enableHighAccuracy: true
378
- },
379
- showAccuracyCircle: true,
380
- showUserLocation: true
381
- }));
382
- }
383
- // Unload all GeoJSON that is present, and load new layers if present
384
- if (this._geoJsonConfig) {
385
- yield this.loadGeoJSON(this._geoJsonConfig);
386
- }
387
- else {
388
- yield this.loadGeoJSON((_a = this._viewSettings) === null || _a === void 0 ? void 0 : _a.geoJson);
389
- }
390
- this._initLongPressEvent();
391
- }
392
- this._mapContainer.dispatchEvent(new OrMapLoadedEvent());
393
- this._loaded = true;
394
- this.createBoundaryBox();
395
- });
396
- }
397
- styleLoaded() {
398
- return new Promise(resolve => {
399
- if (this._mapGl) {
400
- this._mapGl.once('style.load', () => {
401
- resolve();
402
- });
403
- }
404
- });
405
- }
406
- // Clean up of internal resources associated with the map.
407
- // Normally used during disconnectedCallback
408
- unload() {
409
- if (this._mapGl) {
410
- this._mapGl.remove();
411
- this._mapGl = undefined;
412
- }
413
- if (this._mapJs) {
414
- this._mapJs.remove();
415
- this._mapJs = undefined;
416
- }
417
- }
418
- _onMapClick(lngLat, doubleClicked = false) {
419
- this._mapContainer.dispatchEvent(new OrMapClickedEvent(lngLat, doubleClicked));
420
- }
421
- loadGeoJSON(geoJsonConfig) {
422
- return __awaiter(this, void 0, void 0, function* () {
423
- // Remove old layers
424
- if (this._geoJsonLayers.size > 0) {
425
- this._geoJsonLayers.forEach((layer, layerId) => this._mapGl.removeLayer(layerId));
426
- this._geoJsonLayers = new Map();
427
- }
428
- // Remove old sources
429
- if (this._geoJsonSources.length > 0) {
430
- this._geoJsonSources.forEach((sourceId) => this._mapGl.removeSource(sourceId));
431
- this._geoJsonSources = [];
432
- }
433
- // Add new ones if present
434
- if (this._showGeoJson && geoJsonConfig) {
435
- // If array of features (most of the GeoJSONs use this)
436
- if (geoJsonConfig.source.type == "FeatureCollection") {
437
- const groupedSources = this.groupSourcesByGeometryType(geoJsonConfig.source);
438
- groupedSources === null || groupedSources === void 0 ? void 0 : groupedSources.forEach((features, type) => {
439
- const newSource = {
440
- type: "geojson",
441
- data: {
442
- type: "FeatureCollection",
443
- features: features
444
- }
445
- };
446
- const sourceInfo = this.addGeoJSONSource(newSource);
447
- if (sourceInfo) {
448
- this.addGeoJSONLayer(type, sourceInfo.sourceId);
449
- }
450
- });
451
- // Or only 1 feature is added
452
- }
453
- else if (geoJsonConfig.source.type == "Feature") {
454
- const sourceInfo = this.addGeoJSONSource(geoJsonConfig.source);
455
- if (sourceInfo) {
456
- this.addGeoJSONLayer(sourceInfo.source.type, sourceInfo.sourceId);
457
- }
458
- }
459
- else {
460
- console.error("Could not create layer since source type is neither 'FeatureCollection' nor 'Feature'.");
461
- }
462
- }
463
- });
464
- }
465
- groupSourcesByGeometryType(sources) {
466
- const groupedSources = new Map();
467
- sources.features.forEach((feature) => {
468
- let sources = groupedSources.get(feature.geometry.type);
469
- if (sources == undefined) {
470
- sources = [];
471
- }
472
- sources.push(feature);
473
- groupedSources.set(feature.geometry.type, sources);
474
- });
475
- return groupedSources;
476
- }
477
- addGeoJSONSource(source) {
478
- if (!this._mapGl) {
479
- console.error("mapGl instance not found!");
480
- return;
481
- }
482
- const id = Date.now() + "-" + (this._geoJsonSources.length + 1);
483
- this._mapGl.addSource(id, source);
484
- this._geoJsonSources.push(id);
485
- return {
486
- source: source,
487
- sourceId: id
488
- };
489
- }
490
- addGeoJSONLayer(typeString, sourceId) {
491
- if (!this._mapGl) {
492
- console.error("mapGl instance not found!");
493
- return;
494
- }
495
- const type = typeString;
496
- const layerId = sourceId + "-" + type;
497
- // If layer is not added yet
498
- if (this._geoJsonLayers.get(layerId) == undefined) {
499
- // Get realm color by getting value from CSS
500
- let realmColor = getComputedStyle(this._mapContainer).getPropertyValue('--or-app-color4');
501
- if (realmColor == undefined || realmColor.length == 0) {
502
- realmColor = DefaultColor4;
503
- }
504
- let layer = {
505
- id: layerId,
506
- source: sourceId
507
- };
508
- // Set styling based on type
509
- switch (type) {
510
- case "Point":
511
- case "MultiPoint": {
512
- layer.type = "circle";
513
- layer.paint = {
514
- 'circle-radius': 12,
515
- 'circle-color': realmColor
516
- };
517
- this._geoJsonLayers.set(layerId, layer);
518
- this._mapGl.addLayer(layer);
519
- break;
520
- }
521
- case "LineString":
522
- case "MultiLineString": {
523
- layer.type = "line";
524
- layer.paint = {
525
- 'line-color': realmColor,
526
- 'line-width': 4
527
- };
528
- this._geoJsonLayers.set(layerId, layer);
529
- this._mapGl.addLayer(layer);
530
- break;
531
- }
532
- case "Polygon":
533
- case "MultiPolygon": {
534
- layer.type = "fill";
535
- layer.paint = {
536
- 'fill-color': realmColor,
537
- 'fill-opacity': 0.3
538
- };
539
- this._geoJsonLayers.set(layerId, layer);
540
- this._mapGl.addLayer(layer);
541
- // Add extra layer with outline
542
- const outlineId = layerId + "-outline";
543
- const outlineLayer = {
544
- id: outlineId,
545
- source: sourceId,
546
- type: "line",
547
- paint: {
548
- 'line-color': realmColor,
549
- 'line-width': 2
550
- },
551
- };
552
- this._geoJsonLayers.set(outlineId, outlineLayer);
553
- this._mapGl.addLayer(outlineLayer);
554
- break;
555
- }
556
- case "GeometryCollection": {
557
- console.error("GeometryCollection GeoJSON is not implemented yet!");
558
- return;
559
- }
560
- }
561
- }
562
- }
563
- addMarker(marker) {
564
- if (marker.hasPosition()) {
565
- this._updateMarkerElement(marker, true);
566
- }
567
- }
568
- removeMarker(marker) {
569
- this._removeMarkerRadius(marker);
570
- this._updateMarkerElement(marker, false);
571
- }
572
- onMarkerChanged(marker, prop) {
573
- if (!this._loaded) {
574
- return;
575
- }
576
- switch (prop) {
577
- case "lat":
578
- case "lng":
579
- case "radius":
580
- if (marker.hasPosition()) {
581
- if (marker._actualMarkerElement) {
582
- this._updateMarkerPosition(marker);
583
- }
584
- else {
585
- this._updateMarkerElement(marker, true);
586
- }
587
- }
588
- else if (marker._actualMarkerElement) {
589
- this._updateMarkerElement(marker, false);
590
- }
591
- break;
592
- }
593
- }
594
- _updateMarkerPosition(marker) {
595
- switch (this._type) {
596
- case "RASTER" /* MapType.RASTER */:
597
- const m = this._markersJs.get(marker);
598
- if (m) {
599
- m.setLatLng([marker.lat, marker.lng]);
600
- }
601
- break;
602
- case "VECTOR" /* MapType.VECTOR */:
603
- const mGl = this._markersGl.get(marker);
604
- if (mGl) {
605
- mGl.setLngLat([marker.lng, marker.lat]);
606
- }
607
- break;
608
- }
609
- this._createMarkerRadius(marker);
610
- }
611
- _updateMarkerElement(marker, doAdd) {
612
- switch (this._type) {
613
- case "RASTER" /* MapType.RASTER */:
614
- let m = this._markersJs.get(marker);
615
- if (m) {
616
- this._removeMarkerClickHandler(marker, marker.markerContainer);
617
- marker._actualMarkerElement = undefined;
618
- m.removeFrom(this._mapJs);
619
- this._markersJs.delete(marker);
620
- }
621
- if (doAdd) {
622
- const elem = marker._createMarkerElement();
623
- if (elem) {
624
- const icon = L.divIcon({ html: elem.outerHTML, className: "or-marker-raster" });
625
- m = L.marker([marker.lat, marker.lng], { icon: icon, clickable: marker.interactive });
626
- m.addTo(this._mapJs);
627
- marker._actualMarkerElement = m.getElement() ? m.getElement().firstElementChild : undefined;
628
- if (marker.interactive) {
629
- this._addMarkerClickHandler(marker, marker.markerContainer);
630
- }
631
- this._markersJs.set(marker, m);
632
- }
633
- if (marker.radius) {
634
- this._createMarkerRadius(marker);
635
- }
636
- }
637
- break;
638
- case "VECTOR" /* MapType.VECTOR */:
639
- let mGl = this._markersGl.get(marker);
640
- if (mGl) {
641
- marker._actualMarkerElement = undefined;
642
- this._removeMarkerClickHandler(marker, mGl.getElement());
643
- mGl.remove();
644
- this._markersGl.delete(marker);
645
- }
646
- if (doAdd) {
647
- const elem = marker._createMarkerElement();
648
- if (elem) {
649
- mGl = new MarkerGL({
650
- element: elem,
651
- anchor: "top-left"
652
- })
653
- .setLngLat([marker.lng, marker.lat])
654
- .addTo(this._mapGl);
655
- this._markersGl.set(marker, mGl);
656
- marker._actualMarkerElement = mGl.getElement();
657
- if (marker.interactive) {
658
- this._addMarkerClickHandler(marker, mGl.getElement());
659
- }
660
- }
661
- if (marker.radius) {
662
- this._createMarkerRadius(marker);
663
- }
664
- }
665
- break;
666
- }
667
- }
668
- _removeMarkerRadius(marker) {
669
- if (this._mapGl && this._loaded && marker.radius && marker.lat && marker.lng) {
670
- if (this._mapGl.getSource('circleData')) {
671
- this._mapGl.removeLayer('marker-radius-circle');
672
- this._mapGl.removeSource('circleData');
673
- }
674
- }
675
- }
676
- _createMarkerRadius(marker) {
677
- if (this._mapGl && this._loaded && marker.radius && marker.lat && marker.lng) {
678
- this._removeMarkerRadius(marker);
679
- this._mapGl.addSource('circleData', {
680
- type: 'geojson',
681
- data: {
682
- type: 'FeatureCollection',
683
- features: [{
684
- type: "Feature",
685
- geometry: {
686
- "type": "Point",
687
- "coordinates": [marker.lng, marker.lat]
688
- },
689
- properties: {
690
- "title": "You Found Me",
691
- }
692
- }]
693
- }
694
- });
695
- this._mapGl.addLayer({
696
- "id": "marker-radius-circle",
697
- "type": "circle",
698
- "source": "circleData",
699
- "paint": {
700
- "circle-radius": [
701
- "interpolate",
702
- ["linear"],
703
- ["zoom"],
704
- 0, 0,
705
- 20, metersToPixelsAtMaxZoom(marker.radius, marker.lat)
706
- ],
707
- "circle-color": "red",
708
- "circle-opacity": 0.3
709
- }
710
- });
711
- }
712
- }
713
- createBoundaryBox(boundsArray = []) {
714
- var _a, _b;
715
- if (this._mapGl && this._loaded && this._showBoundaryBox && ((_a = this._viewSettings) === null || _a === void 0 ? void 0 : _a.bounds)) {
716
- if (this._mapGl.getSource('bounds')) {
717
- this._mapGl.removeLayer('bounds');
718
- this._mapGl.removeSource('bounds');
719
- }
720
- if (boundsArray.length !== 4) {
721
- boundsArray = (_b = this._viewSettings) === null || _b === void 0 ? void 0 : _b.bounds.toString().split(",");
722
- }
723
- var req = [
724
- [
725
- [boundsArray[0], boundsArray[3]],
726
- [boundsArray[2], boundsArray[3]],
727
- [boundsArray[2], boundsArray[1]],
728
- [boundsArray[0], boundsArray[1]],
729
- [boundsArray[0], boundsArray[3]]
730
- ]
731
- ];
732
- this._mapGl.fitBounds([
733
- parseFloat(boundsArray[0]) + .01,
734
- parseFloat(boundsArray[1]) - .01,
735
- parseFloat(boundsArray[2]) - .01,
736
- parseFloat(boundsArray[3]) + .01,
737
- ]);
738
- this._mapGl.addSource('bounds', {
739
- 'type': 'geojson',
740
- 'data': {
741
- 'type': 'Feature',
742
- 'properties': {},
743
- 'geometry': {
744
- 'type': 'Polygon',
745
- // @ts-ignore
746
- 'coordinates': req
747
- }
748
- }
749
- });
750
- this._mapGl.addLayer({
751
- 'id': 'bounds',
752
- 'type': 'fill',
753
- 'source': 'bounds',
754
- 'paint': {
755
- 'fill-color': '#FF0000',
756
- 'fill-opacity': .4
757
- }
758
- });
759
- }
760
- }
761
- _addMarkerClickHandler(marker, elem) {
762
- if (elem) {
763
- const handler = (ev) => {
764
- ev.stopPropagation();
765
- marker._onClick(ev);
766
- };
767
- this._clickHandlers.set(marker, handler);
768
- elem.addEventListener("click", handler);
769
- }
770
- }
771
- _removeMarkerClickHandler(marker, elem) {
772
- const handler = this._clickHandlers.get(marker);
773
- if (handler && elem) {
774
- elem.removeEventListener("click", handler);
775
- this._clickHandlers.delete(marker);
776
- }
777
- }
778
- _forwardGeocode(config) {
779
- return __awaiter(this, void 0, void 0, function* () {
780
- const features = [];
781
- try {
782
- let request = this._viewSettings.geocodeUrl + '/search?q=' + config.query + '&format=geojson&polygon_geojson=1&addressdetails=1';
783
- const response = yield fetch(request);
784
- const geojson = yield response.json();
785
- for (let feature of geojson.features) {
786
- let center = [feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2, feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2];
787
- let point = {
788
- type: 'Feature',
789
- geometry: {
790
- type: 'Point',
791
- coordinates: center
792
- },
793
- place_name: feature.properties.display_name,
794
- properties: feature.properties,
795
- text: feature.properties.display_name,
796
- place_type: ['place'],
797
- center: center
798
- };
799
- features.push(point);
800
- }
801
- }
802
- catch (e) {
803
- console.error(`Failed to forwardGeocode with error: ${e}`);
804
- }
805
- return {
806
- features: features
807
- };
808
- });
809
- }
810
- _reverseGeocode(config) {
811
- return __awaiter(this, void 0, void 0, function* () {
812
- const features = [];
813
- try {
814
- let request = this._viewSettings.geocodeUrl + '/reverse?lat=' + config.lat + '&lon=' + config.lon + '&format=geojson&polygon_geojson=1&addressdetails=1';
815
- const response = yield fetch(request);
816
- const geojson = yield response.json();
817
- for (let feature of geojson.features) {
818
- let center = [feature.bbox[0] + (feature.bbox[2] - feature.bbox[0]) / 2, feature.bbox[1] + (feature.bbox[3] - feature.bbox[1]) / 2];
819
- let point = {
820
- type: 'Feature',
821
- geometry: {
822
- type: 'Point',
823
- coordinates: center
824
- },
825
- place_name: feature.properties.display_name,
826
- properties: feature.properties,
827
- text: feature.properties.display_name,
828
- place_type: ['place'],
829
- center: center
830
- };
831
- features.push(point);
832
- }
833
- }
834
- catch (e) {
835
- console.error(`Failed to reverseGeocode with error: ${e}`);
836
- }
837
- return {
838
- features: features
839
- };
840
- });
841
- }
842
- _initLongPressEvent() {
843
- if (this._mapGl) {
844
- let pressTimeout;
845
- let pos;
846
- let clearTimeoutFunc = () => { if (pressTimeout)
847
- clearTimeout(pressTimeout); pressTimeout = null; };
848
- this._mapGl.on('touchstart', (e) => {
849
- if (e.originalEvent.touches.length > 1) {
850
- return;
851
- }
852
- pos = e.lngLat;
853
- pressTimeout = setTimeout(() => {
854
- this._onLongPress(pos);
855
- }, 500);
856
- });
857
- this._mapGl.on('mousedown', (e) => {
858
- if (!pressTimeout) {
859
- pos = e.lngLat;
860
- pressTimeout = setTimeout(() => {
861
- this._onLongPress(pos);
862
- pressTimeout = null;
863
- }, 500);
864
- }
865
- });
866
- this._mapGl.on('dragstart', clearTimeoutFunc);
867
- this._mapGl.on('mouseup', clearTimeoutFunc);
868
- this._mapGl.on('touchend', clearTimeoutFunc);
869
- this._mapGl.on('touchcancel', clearTimeoutFunc);
870
- this._mapGl.on('touchmove', clearTimeoutFunc);
871
- this._mapGl.on('moveend', clearTimeoutFunc);
872
- this._mapGl.on('gesturestart', clearTimeoutFunc);
873
- this._mapGl.on('gesturechange', clearTimeoutFunc);
874
- this._mapGl.on('gestureend', clearTimeoutFunc);
875
- }
876
- }
877
- ;
878
- _onLongPress(lngLat) {
879
- this._mapContainer.dispatchEvent(new OrMapLongPressEvent(lngLat));
880
- }
881
- _onGeocodeChange(geocode) {
882
- this._mapContainer.dispatchEvent(new OrMapGeocoderChangeEvent(geocode));
883
- }
884
- }
885
- //# sourceMappingURL=mapwidget.js.map
1
+ let pkey;var __awaiter=this&&this.__awaiter||function(e,t,o,i){return new(o||(o=Promise))(function(s,r){function a(e){try{l(i.next(e))}catch(e){r(e)}}function n(e){try{l(i.throw(e))}catch(e){r(e)}}function l(e){var t;e.done?s(e.value):((t=e.value)instanceof o?t:new o(function(e){e(t)})).then(a,n)}l((i=i.apply(e,t||[])).next())})};import e,{DefaultColor4 as t}from"@openremote/core";import o,{GeolocateControl as i,Marker as s,NavigationControl as r}from"maplibre-gl";import a from"@maplibre/maplibre-gl-geocoder";import"@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css";import{debounce as n}from"lodash";import{OrMapClickedEvent as l,OrMapGeocoderChangeEvent as h,OrMapLoadedEvent as d,OrMapLongPressEvent as _}from"./index";import{getLatLngBounds as c,getLngLat as m}from"./util";import{isMapboxURL as p,transformMapboxUrl as u}from"./mapbox-url-utils";let mapboxJsStyles=require("mapbox.js/dist/mapbox.css"),maplibreGlStyles=require("maplibre-gl/dist/maplibre-gl.css"),maplibreGeoCoderStyles=require("@maplibre/maplibre-gl-geocoder/dist/maplibre-gl-geocoder.css"),metersToPixelsAtMaxZoom=(e,t)=>e/.075/Math.cos(t*Math.PI/180);export class MapWidget{constructor(e,t,o,i=!1,s=!1,r=!0,a=!0){this._loaded=!1,this._markersJs=new Map,this._markersGl=new Map,this._geoJsonSources=[],this._geoJsonLayers=new Map,this._showGeoCodingControl=!1,this._showBoundaryBox=!1,this._useZoomControls=!0,this._showGeoJson=!0,this._clickHandlers=new Map,this._type=e,this._styleParent=t,this._mapContainer=o,this._showGeoCodingControl=i,this._showBoundaryBox=s,this._useZoomControls=r,this._showGeoJson=a}setCenter(e){switch(this._center=m(e),this._type){case"RASTER":if(this._mapJs){let e=m(this._center)||(this._viewSettings?m(this._viewSettings.center):void 0);e&&this._mapJs.setView(e,void 0,{pan:{animate:!1},zoom:{animate:!1}})}break;case"VECTOR":this._mapGl&&this._center&&this._mapGl.setCenter(this._center)}return this}flyTo(e,t){switch(this._type){case"RASTER":this._mapJs;break;case"VECTOR":e||(e=this._center?this._center:this._viewSettings?this._viewSettings.center:void 0),t||(t=this._zoom?this._zoom:this._viewSettings&&this._viewSettings.zoom?this._viewSettings.zoom:void 0),this._mapGl?e&&this._mapGl.flyTo({center:e,zoom:t}):(this._center=e,this._zoom=t)}return this}resize(){switch(this._type){case"RASTER":this._mapJs;break;case"VECTOR":this._mapGl&&this._mapGl.resize()}return this}setZoom(e){switch(this._zoom=e,this._type){case"RASTER":this._mapJs&&this._zoom&&this._mapJs.setZoom(this._zoom,{animate:!1});break;case"VECTOR":this._mapGl&&this._zoom&&this._mapGl.setZoom(this._zoom)}return this}setControls(e){return this._controls=e,this._mapGl&&(this._controls?this._controls.forEach(e=>{Array.isArray(e)?this._mapGl.addControl(e[0],e[1]):this._mapGl.addControl(e)}):this._mapGl.addControl(new r)),this}setGeoJson(e){var t;return this._geoJsonConfig=e,this._mapGl&&(this._geoJsonConfig?this.loadGeoJSON(this._geoJsonConfig):this.loadGeoJSON(null==(t=this._viewSettings)?void 0:t.geoJson)),this}loadViewSettings(){return __awaiter(this,void 0,void 0,function*(){var t;let o=("RASTER"===this._type?yield e.rest.api.MapResource.getSettingsJs():yield e.rest.api.MapResource.getSettings()).data;if(o.override)return o.override;let i=e.displayRealm||"default";return this._viewSettings=o.options?o.options[i]?o.options[i]:o.options.default:null,this._viewSettings&&(this._mapGl&&(this._mapGl.setMinZoom(this._viewSettings.minZoom),this._mapGl.setMaxZoom(this._viewSettings.maxZoom),this._viewSettings.bounds&&this._mapGl.setMaxBounds(this._viewSettings.bounds),this._geoJsonConfig?yield this.loadGeoJSON(this._geoJsonConfig):yield this.loadGeoJSON(null==(t=this._viewSettings)?void 0:t.geoJson)),this._center?this.setCenter(this._center):this.setCenter(this._viewSettings.center)),o})}load(){return __awaiter(this,void 0,void 0,function*(){var t;if(!this._loaded){if("RASTER"===this._type){let e,t=document.createElement("style");t.id="mapboxJsStyle",t.textContent=mapboxJsStyles,this._styleParent.appendChild(t);let o=yield this.loadViewSettings();if(this._viewSettings){if((e={}).zoom=this._viewSettings.zoom?this._viewSettings.zoom+1:void 0,this._useZoomControls&&(e.maxZoom=this._viewSettings.maxZoom?this._viewSettings.maxZoom-1:void 0,e.minZoom=this._viewSettings.minZoom?this._viewSettings.minZoom+1:void 0),e.boxZoom=this._viewSettings.boxZoom,this._viewSettings.bounds&&(e.maxBounds=c(this._viewSettings.bounds)),this._viewSettings.center){let t=m(this._viewSettings.center);e.center=t?L.latLng(t.lat,t.lng):void 0}if(this._center){let t=m(this._center);e.center=t?L.latLng(t.lat,t.lng):void 0}this._zoom&&(e.zoom=this._zoom+1)}if(this._mapJs=L.mapbox.map(this._mapContainer,o,e),this._mapJs.on("click",e=>{this._onMapClick(e.latlng)}),e&&e.maxBounds){let t=this._mapJs.getBoundsZoom(e.maxBounds,!0);(!e.minZoom||e.minZoom<t)&&this._mapJs.setMinZoom(t)}}else{let s=document.createElement("style");s.id="maplibreGlStyle",s.textContent=maplibreGlStyles,this._styleParent.appendChild(s),(s=document.createElement("style")).id="maplibreGeoCoderStyles",s.textContent=maplibreGeoCoderStyles,this._styleParent.appendChild(s);let l=yield import("maplibre-gl"),h=yield this.loadViewSettings(),d={attributionControl:{compact:!0},container:this._mapContainer,style:h,transformRequest:(t,o)=>(pkey||(pkey=new URL(t).searchParams.get("access_token")||""),p(t))?u(t,pkey,o):{headers:new URL(window.origin).hostname===new URL(t).hostname?{Authorization:e.getAuthorizationHeader()}:{},url:t}};this._viewSettings&&(this._useZoomControls&&(d.maxZoom=this._viewSettings.maxZoom,d.minZoom=this._viewSettings.minZoom),this._viewSettings.bounds&&!this._showBoundaryBox&&(d.maxBounds=this._viewSettings.bounds),d.boxZoom=this._viewSettings.boxZoom,d.zoom=this._viewSettings.zoom,d.center=this._viewSettings.center),this._center=this._center||(this._viewSettings?this._viewSettings.center:void 0),d.center=this._center,this._zoom&&(d.zoom=this._zoom),this._mapGl=new l.Map(d),yield this.styleLoaded(),this._mapGl.on("click",e=>{this._onMapClick(e.lngLat)}),this._mapGl.on("dblclick",e=>{this._onMapClick(e.lngLat,!0)}),this._showGeoCodingControl&&this._viewSettings&&this._viewSettings.geocodeUrl&&(this._geocoder=new a({forwardGeocode:this._forwardGeocode.bind(this),reverseGeocode:this._reverseGeocode},{maplibregl:o,showResultsWhileTyping:!0}),this._geocoder._onKeyDown=n(e=>{if(27===e.keyCode&&this._geocoder.options.clearAndBlurOnEsc)return this._geocoder._clear(e),this._geocoder._inputEl.blur();var t=this._geocoder._inputEl.value||e.key;if(!t)return this._geocoder.fresh=!0,9!==e.keyCode&&this._geocoder.clear(e),this._geocoder._clearEl.style.display="none";if(!e.metaKey&&-1===[9,27,37,39,38,40].indexOf(e.keyCode)){if(13===e.keyCode)if(this._geocoder.options.showResultsWhileTyping){this._geocoder.options.showResultMarkers&&this._geocoder._fitBoundsForMarkers(),this._geocoder._inputEl.value=this._geocoder._typeahead.query,this._geocoder.lastSelected=null,this._geocoder._typeahead.selected=null;return}else this._geocoder._typeahead.list.selectingListItem||this._geocoder._geocode(t);t.length>=this._geocoder.options.minLength&&this._geocoder.options.showResultsWhileTyping&&this._geocoder._geocode(t)}},300),this._mapGl.addControl(this._geocoder,"top-left"),this._geocoder._inputEl.addEventListener("change",()=>{var e=this._geocoder._typeahead.selected;this._onGeocodeChange(e)})),this._controls?this._controls.forEach(e=>{Array.isArray(e)?this._mapGl.addControl(e[0],e[1]):this._mapGl.addControl(e)}):(this._mapGl.addControl(new r),this._mapGl.addControl(new i({positionOptions:{enableHighAccuracy:!0},showAccuracyCircle:!0,showUserLocation:!0}))),this._geoJsonConfig?yield this.loadGeoJSON(this._geoJsonConfig):yield this.loadGeoJSON(null==(t=this._viewSettings)?void 0:t.geoJson),this._initLongPressEvent()}this._mapContainer.dispatchEvent(new d),this._loaded=!0,this.createBoundaryBox()}})}styleLoaded(){return new Promise(e=>{this._mapGl&&this._mapGl.once("style.load",()=>{e()})})}unload(){this._mapGl&&(this._mapGl.remove(),this._mapGl=void 0),this._mapJs&&(this._mapJs.remove(),this._mapJs=void 0)}_onMapClick(e,t=!1){this._mapContainer.dispatchEvent(new l(e,t))}loadGeoJSON(e){return __awaiter(this,void 0,void 0,function*(){if(this._geoJsonLayers.size>0&&(this._geoJsonLayers.forEach((e,t)=>this._mapGl.removeLayer(t)),this._geoJsonLayers=new Map),this._geoJsonSources.length>0&&(this._geoJsonSources.forEach(e=>this._mapGl.removeSource(e)),this._geoJsonSources=[]),this._showGeoJson&&e)if("FeatureCollection"==e.source.type){let t=this.groupSourcesByGeometryType(e.source);null==t||t.forEach((e,t)=>{let o=this.addGeoJSONSource({type:"geojson",data:{type:"FeatureCollection",features:e}});o&&this.addGeoJSONLayer(t,o.sourceId)})}else if("Feature"==e.source.type){let t=this.addGeoJSONSource(e.source);t&&this.addGeoJSONLayer(t.source.type,t.sourceId)}else console.error("Could not create layer since source type is neither 'FeatureCollection' nor 'Feature'.")})}groupSourcesByGeometryType(e){let t=new Map;return e.features.forEach(e=>{let o=t.get(e.geometry.type);void 0==o&&(o=[]),o.push(e),t.set(e.geometry.type,o)}),t}addGeoJSONSource(e){if(!this._mapGl)return void console.error("mapGl instance not found!");let t=Date.now()+"-"+(this._geoJsonSources.length+1);return this._mapGl.addSource(t,e),this._geoJsonSources.push(t),{source:e,sourceId:t}}addGeoJSONLayer(e,o){if(!this._mapGl)return void console.error("mapGl instance not found!");let i=o+"-"+e;if(void 0==this._geoJsonLayers.get(i)){let s=getComputedStyle(this._mapContainer).getPropertyValue("--or-app-color4");(void 0==s||0==s.length)&&(s=t);let r={id:i,source:o};switch(e){case"Point":case"MultiPoint":r.type="circle",r.paint={"circle-radius":12,"circle-color":s},this._geoJsonLayers.set(i,r),this._mapGl.addLayer(r);break;case"LineString":case"MultiLineString":r.type="line",r.paint={"line-color":s,"line-width":4},this._geoJsonLayers.set(i,r),this._mapGl.addLayer(r);break;case"Polygon":case"MultiPolygon":{r.type="fill",r.paint={"fill-color":s,"fill-opacity":.3},this._geoJsonLayers.set(i,r),this._mapGl.addLayer(r);let e=i+"-outline",t={id:e,source:o,type:"line",paint:{"line-color":s,"line-width":2}};this._geoJsonLayers.set(e,t),this._mapGl.addLayer(t);break}case"GeometryCollection":return void console.error("GeometryCollection GeoJSON is not implemented yet!")}}}addMarker(e){e.hasPosition()&&this._updateMarkerElement(e,!0)}removeMarker(e){this._removeMarkerRadius(e),this._updateMarkerElement(e,!1)}onMarkerChanged(e,t){if(this._loaded)switch(t){case"lat":case"lng":case"radius":e.hasPosition()?e._actualMarkerElement?this._updateMarkerPosition(e):this._updateMarkerElement(e,!0):e._actualMarkerElement&&this._updateMarkerElement(e,!1)}}_updateMarkerPosition(e){switch(this._type){case"RASTER":let t=this._markersJs.get(e);t&&t.setLatLng([e.lat,e.lng]);break;case"VECTOR":let o=this._markersGl.get(e);o&&o.setLngLat([e.lng,e.lat])}this._createMarkerRadius(e)}_updateMarkerElement(e,t){switch(this._type){case"RASTER":let o=this._markersJs.get(e);if(o&&(this._removeMarkerClickHandler(e,e.markerContainer),e._actualMarkerElement=void 0,o.removeFrom(this._mapJs),this._markersJs.delete(e)),t){let t=e._createMarkerElement();if(t){let i=L.divIcon({html:t.outerHTML,className:"or-marker-raster"});(o=L.marker([e.lat,e.lng],{icon:i,clickable:e.interactive})).addTo(this._mapJs),e._actualMarkerElement=o.getElement()?o.getElement().firstElementChild:void 0,e.interactive&&this._addMarkerClickHandler(e,e.markerContainer),this._markersJs.set(e,o)}e.radius&&this._createMarkerRadius(e)}break;case"VECTOR":let i=this._markersGl.get(e);if(i&&(e._actualMarkerElement=void 0,this._removeMarkerClickHandler(e,i.getElement()),i.remove(),this._markersGl.delete(e)),t){let t=e._createMarkerElement();t&&(i=new s({element:t,anchor:"top-left"}).setLngLat([e.lng,e.lat]).addTo(this._mapGl),this._markersGl.set(e,i),e._actualMarkerElement=i.getElement(),e.interactive&&this._addMarkerClickHandler(e,i.getElement())),e.radius&&this._createMarkerRadius(e)}}}_removeMarkerRadius(e){this._mapGl&&this._loaded&&e.radius&&e.lat&&e.lng&&this._mapGl.getSource("circleData")&&(this._mapGl.removeLayer("marker-radius-circle"),this._mapGl.removeSource("circleData"))}_createMarkerRadius(e){this._mapGl&&this._loaded&&e.radius&&e.lat&&e.lng&&(this._removeMarkerRadius(e),this._mapGl.addSource("circleData",{type:"geojson",data:{type:"FeatureCollection",features:[{type:"Feature",geometry:{type:"Point",coordinates:[e.lng,e.lat]},properties:{title:"You Found Me"}}]}}),this._mapGl.addLayer({id:"marker-radius-circle",type:"circle",source:"circleData",paint:{"circle-radius":["interpolate",["linear"],["zoom"],0,0,20,metersToPixelsAtMaxZoom(e.radius,e.lat)],"circle-color":"red","circle-opacity":.3}}))}createBoundaryBox(e=[]){var t,o;if(this._mapGl&&this._loaded&&this._showBoundaryBox&&(null==(t=this._viewSettings)?void 0:t.bounds)){this._mapGl.getSource("bounds")&&(this._mapGl.removeLayer("bounds"),this._mapGl.removeSource("bounds")),4!==e.length&&(e=null==(o=this._viewSettings)?void 0:o.bounds.toString().split(","));var i=[[[e[0],e[3]],[e[2],e[3]],[e[2],e[1]],[e[0],e[1]],[e[0],e[3]]]];this._mapGl.fitBounds([parseFloat(e[0])+.01,parseFloat(e[1])-.01,parseFloat(e[2])-.01,parseFloat(e[3])+.01]),this._mapGl.addSource("bounds",{type:"geojson",data:{type:"Feature",properties:{},geometry:{type:"Polygon",coordinates:i}}}),this._mapGl.addLayer({id:"bounds",type:"fill",source:"bounds",paint:{"fill-color":"#FF0000","fill-opacity":.4}})}}_addMarkerClickHandler(e,t){if(t){let o=t=>{t.stopPropagation(),e._onClick(t)};this._clickHandlers.set(e,o),t.addEventListener("click",o)}}_removeMarkerClickHandler(e,t){let o=this._clickHandlers.get(e);o&&t&&(t.removeEventListener("click",o),this._clickHandlers.delete(e))}_forwardGeocode(e){return __awaiter(this,void 0,void 0,function*(){let t=[];try{let o=this._viewSettings.geocodeUrl+"/search?q="+e.query+"&format=geojson&polygon_geojson=1&addressdetails=1",i=yield fetch(o);for(let e of(yield i.json()).features){let o=[e.bbox[0]+(e.bbox[2]-e.bbox[0])/2,e.bbox[1]+(e.bbox[3]-e.bbox[1])/2],i={type:"Feature",geometry:{type:"Point",coordinates:o},place_name:e.properties.display_name,properties:e.properties,text:e.properties.display_name,place_type:["place"],center:o};t.push(i)}}catch(e){console.error(`Failed to forwardGeocode with error: ${e}`)}return{features:t}})}_reverseGeocode(e){return __awaiter(this,void 0,void 0,function*(){let t=[];try{let o=this._viewSettings.geocodeUrl+"/reverse?lat="+e.lat+"&lon="+e.lon+"&format=geojson&polygon_geojson=1&addressdetails=1",i=yield fetch(o);for(let e of(yield i.json()).features){let o=[e.bbox[0]+(e.bbox[2]-e.bbox[0])/2,e.bbox[1]+(e.bbox[3]-e.bbox[1])/2],i={type:"Feature",geometry:{type:"Point",coordinates:o},place_name:e.properties.display_name,properties:e.properties,text:e.properties.display_name,place_type:["place"],center:o};t.push(i)}}catch(e){console.error(`Failed to reverseGeocode with error: ${e}`)}return{features:t}})}_initLongPressEvent(){if(this._mapGl){let e,t,o=()=>{e&&clearTimeout(e),e=null};this._mapGl.on("touchstart",o=>{o.originalEvent.touches.length>1||(t=o.lngLat,e=setTimeout(()=>{this._onLongPress(t)},500))}),this._mapGl.on("mousedown",o=>{e||(t=o.lngLat,e=setTimeout(()=>{this._onLongPress(t),e=null},500))}),this._mapGl.on("dragstart",o),this._mapGl.on("mouseup",o),this._mapGl.on("touchend",o),this._mapGl.on("touchcancel",o),this._mapGl.on("touchmove",o),this._mapGl.on("moveend",o),this._mapGl.on("gesturestart",o),this._mapGl.on("gesturechange",o),this._mapGl.on("gestureend",o)}}_onLongPress(e){this._mapContainer.dispatchEvent(new _(e))}_onGeocodeChange(e){this._mapContainer.dispatchEvent(new h(e))}}