react-bkoi-gl 2.0.0 → 2.1.0

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 (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +1429 -176
  3. package/dist/index.cjs +1299 -266
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +870 -0
  6. package/dist/index.d.ts +870 -2
  7. package/dist/index.js +2420 -2
  8. package/dist/index.js.map +1 -1
  9. package/dist/styles/react-bkoi-gl.css +95 -1
  10. package/package.json +83 -31
  11. package/dist/components/attribution-control.d.ts +0 -9
  12. package/dist/components/attribution-control.js +0 -20
  13. package/dist/components/attribution-control.js.map +0 -1
  14. package/dist/components/fullscreen-control.d.ts +0 -12
  15. package/dist/components/fullscreen-control.js +0 -21
  16. package/dist/components/fullscreen-control.js.map +0 -1
  17. package/dist/components/geolocate-control.d.ts +0 -21
  18. package/dist/components/geolocate-control.js +0 -46
  19. package/dist/components/geolocate-control.js.map +0 -1
  20. package/dist/components/layer.d.ts +0 -18
  21. package/dist/components/layer.js +0 -98
  22. package/dist/components/layer.js.map +0 -1
  23. package/dist/components/logo-control.d.ts +0 -9
  24. package/dist/components/logo-control.js +0 -28
  25. package/dist/components/logo-control.js.map +0 -1
  26. package/dist/components/map.d.ts +0 -27
  27. package/dist/components/map.js +0 -108
  28. package/dist/components/map.js.map +0 -1
  29. package/dist/components/marker.d.ts +0 -18
  30. package/dist/components/marker.js +0 -105
  31. package/dist/components/marker.js.map +0 -1
  32. package/dist/components/navigation-control.d.ts +0 -9
  33. package/dist/components/navigation-control.js +0 -19
  34. package/dist/components/navigation-control.js.map +0 -1
  35. package/dist/components/popup.d.ts +0 -15
  36. package/dist/components/popup.js +0 -68
  37. package/dist/components/popup.js.map +0 -1
  38. package/dist/components/scale-control.d.ts +0 -11
  39. package/dist/components/scale-control.js +0 -31
  40. package/dist/components/scale-control.js.map +0 -1
  41. package/dist/components/source.d.ts +0 -6
  42. package/dist/components/source.js +0 -95
  43. package/dist/components/source.js.map +0 -1
  44. package/dist/components/terrain-control.d.ts +0 -10
  45. package/dist/components/terrain-control.js +0 -19
  46. package/dist/components/terrain-control.js.map +0 -1
  47. package/dist/components/use-control.d.ts +0 -9
  48. package/dist/components/use-control.js +0 -30
  49. package/dist/components/use-control.js.map +0 -1
  50. package/dist/components/use-map.d.ts +0 -19
  51. package/dist/components/use-map.js +0 -54
  52. package/dist/components/use-map.js.map +0 -1
  53. package/dist/exports-maplibre-gl.d.ts +0 -33
  54. package/dist/exports-maplibre-gl.js +0 -21
  55. package/dist/exports-maplibre-gl.js.map +0 -1
  56. package/dist/maplibre/create-ref.d.ts +0 -9
  57. package/dist/maplibre/create-ref.js +0 -30
  58. package/dist/maplibre/create-ref.js.map +0 -1
  59. package/dist/maplibre/maplibre.d.ts +0 -81
  60. package/dist/maplibre/maplibre.js +0 -387
  61. package/dist/maplibre/maplibre.js.map +0 -1
  62. package/dist/styles.d.js +0 -2
  63. package/dist/styles.d.js.map +0 -1
  64. package/dist/tsconfig.build.tsbuildinfo +0 -1
  65. package/dist/types/common.d.ts +0 -20
  66. package/dist/types/common.js +0 -2
  67. package/dist/types/common.js.map +0 -1
  68. package/dist/types/events.d.ts +0 -80
  69. package/dist/types/events.js +0 -2
  70. package/dist/types/events.js.map +0 -1
  71. package/dist/types/internal.d.ts +0 -14
  72. package/dist/types/internal.js +0 -2
  73. package/dist/types/internal.js.map +0 -1
  74. package/dist/types/lib.d.ts +0 -40
  75. package/dist/types/lib.js +0 -2
  76. package/dist/types/lib.js.map +0 -1
  77. package/dist/types/style-spec.d.ts +0 -1
  78. package/dist/types/style-spec.js +0 -2
  79. package/dist/types/style-spec.js.map +0 -1
  80. package/dist/utils/apply-react-style.d.ts +0 -2
  81. package/dist/utils/apply-react-style.js +0 -16
  82. package/dist/utils/apply-react-style.js.map +0 -1
  83. package/dist/utils/assert.d.ts +0 -1
  84. package/dist/utils/assert.js +0 -6
  85. package/dist/utils/assert.js.map +0 -1
  86. package/dist/utils/compare-class-names.d.ts +0 -2
  87. package/dist/utils/compare-class-names.js +0 -23
  88. package/dist/utils/compare-class-names.js.map +0 -1
  89. package/dist/utils/deep-equal.d.ts +0 -15
  90. package/dist/utils/deep-equal.js +0 -46
  91. package/dist/utils/deep-equal.js.map +0 -1
  92. package/dist/utils/set-globals.d.ts +0 -20
  93. package/dist/utils/set-globals.js +0 -31
  94. package/dist/utils/set-globals.js.map +0 -1
  95. package/dist/utils/style-utils.d.ts +0 -3
  96. package/dist/utils/style-utils.js +0 -42
  97. package/dist/utils/style-utils.js.map +0 -1
  98. package/dist/utils/transform.d.ts +0 -18
  99. package/dist/utils/transform.js +0 -33
  100. package/dist/utils/transform.js.map +0 -1
  101. package/dist/utils/use-isomorphic-layout-effect.d.ts +0 -3
  102. package/dist/utils/use-isomorphic-layout-effect.js +0 -4
  103. package/dist/utils/use-isomorphic-layout-effect.js.map +0 -1
  104. package/src/components/attribution-control.ts +0 -56
  105. package/src/components/fullscreen-control.ts +0 -40
  106. package/src/components/geolocate-control.ts +0 -96
  107. package/src/components/layer.ts +0 -141
  108. package/src/components/logo-control.ts +0 -44
  109. package/src/components/map.tsx +0 -166
  110. package/src/components/marker.ts +0 -155
  111. package/src/components/navigation-control.ts +0 -28
  112. package/src/components/popup.ts +0 -113
  113. package/src/components/scale-control.ts +0 -44
  114. package/src/components/source.ts +0 -159
  115. package/src/components/terrain-control.ts +0 -29
  116. package/src/components/use-control.ts +0 -68
  117. package/src/components/use-map.tsx +0 -71
  118. package/src/exports-maplibre-gl.ts +0 -37
  119. package/src/index.ts +0 -3
  120. package/src/maplibre/create-ref.ts +0 -70
  121. package/src/maplibre/maplibre.ts +0 -624
  122. package/src/styles.d.ts +0 -4
  123. package/src/types/common.ts +0 -34
  124. package/src/types/events.ts +0 -133
  125. package/src/types/internal.ts +0 -26
  126. package/src/types/lib.ts +0 -84
  127. package/src/types/style-spec.ts +0 -34
  128. package/src/utils/apply-react-style.ts +0 -24
  129. package/src/utils/assert.ts +0 -5
  130. package/src/utils/compare-class-names.ts +0 -29
  131. package/src/utils/deep-equal.ts +0 -61
  132. package/src/utils/set-globals.ts +0 -51
  133. package/src/utils/style-utils.ts +0 -68
  134. package/src/utils/transform.ts +0 -58
  135. package/src/utils/use-isomorphic-layout-effect.ts +0 -8
package/dist/index.js CHANGED
@@ -1,3 +1,2421 @@
1
- export * from "./exports-maplibre-gl.js";
2
- export { default } from "./exports-maplibre-gl.js";
1
+ // src/components/map.tsx
2
+ import * as React2 from "react";
3
+ import { useState as useState2, useRef, useEffect as useEffect5, useContext as useContext3, useMemo as useMemo3, useImperativeHandle } from "react";
4
+
5
+ // src/components/use-map.tsx
6
+ import * as React from "react";
7
+ import { useState, useCallback, useMemo, useContext } from "react";
8
+ var MountedMapsContext = React.createContext(null);
9
+ var MapProvider = (props) => {
10
+ const [maps, setMaps] = useState({});
11
+ const onMapMount = useCallback((map, id = "default") => {
12
+ setMaps((currMaps) => {
13
+ if (id === "current") {
14
+ throw new Error("'current' cannot be used as map id");
15
+ }
16
+ if (currMaps[id]) {
17
+ throw new Error(`Multiple maps with the same id: ${id}`);
18
+ }
19
+ return { ...currMaps, [id]: map };
20
+ });
21
+ }, []);
22
+ const onMapUnmount = useCallback((id = "default") => {
23
+ setMaps((currMaps) => {
24
+ if (currMaps[id]) {
25
+ const nextMaps = { ...currMaps };
26
+ delete nextMaps[id];
27
+ return nextMaps;
28
+ }
29
+ return currMaps;
30
+ });
31
+ }, []);
32
+ return /* @__PURE__ */ React.createElement(
33
+ MountedMapsContext.Provider,
34
+ {
35
+ value: {
36
+ maps,
37
+ onMapMount,
38
+ onMapUnmount
39
+ }
40
+ },
41
+ props.children
42
+ );
43
+ };
44
+ function useMap() {
45
+ const maps = useContext(MountedMapsContext)?.maps;
46
+ const currentMap = useContext(MapContext);
47
+ const mapsWithCurrent = useMemo(() => {
48
+ const current = currentMap?.map || (maps ? Object.values(maps)[0] : void 0);
49
+ return { ...maps, current };
50
+ }, [maps, currentMap]);
51
+ return mapsWithCurrent;
52
+ }
53
+
54
+ // src/utils/deep-equal.ts
55
+ function arePointsEqual(a, b) {
56
+ const ax = Array.isArray(a) ? a[0] : a ? a.x : 0;
57
+ const ay = Array.isArray(a) ? a[1] : a ? a.y : 0;
58
+ const bx = Array.isArray(b) ? b[0] : b ? b.x : 0;
59
+ const by = Array.isArray(b) ? b[1] : b ? b.y : 0;
60
+ return ax === bx && ay === by;
61
+ }
62
+ function deepEqual(a, b) {
63
+ if (a === b) {
64
+ return true;
65
+ }
66
+ if (!a || !b) {
67
+ return false;
68
+ }
69
+ if (Array.isArray(a)) {
70
+ if (!Array.isArray(b) || a.length !== b.length) {
71
+ return false;
72
+ }
73
+ for (let i = 0; i < a.length; i++) {
74
+ if (!deepEqual(a[i], b[i])) {
75
+ return false;
76
+ }
77
+ }
78
+ return true;
79
+ } else if (Array.isArray(b)) {
80
+ return false;
81
+ }
82
+ if (typeof a === "object" && typeof b === "object") {
83
+ const aKeys = Object.keys(a);
84
+ const bKeys = Object.keys(b);
85
+ if (aKeys.length !== bKeys.length) {
86
+ return false;
87
+ }
88
+ for (const key of aKeys) {
89
+ if (!Object.prototype.hasOwnProperty.call(b, key)) {
90
+ return false;
91
+ }
92
+ if (!deepEqual(a[key], b[key])) {
93
+ return false;
94
+ }
95
+ }
96
+ return true;
97
+ }
98
+ return false;
99
+ }
100
+
101
+ // src/utils/transform.ts
102
+ function transformToViewState(tr) {
103
+ return {
104
+ longitude: tr.center.lng,
105
+ latitude: tr.center.lat,
106
+ zoom: tr.zoom,
107
+ pitch: tr.pitch,
108
+ bearing: tr.bearing,
109
+ padding: tr.padding
110
+ };
111
+ }
112
+ function applyViewStateToTransform(tr, props) {
113
+ const v = props.viewState || props;
114
+ const changes = {};
115
+ if ("longitude" in v && "latitude" in v && (v.longitude !== tr.center.lng || v.latitude !== tr.center.lat)) {
116
+ const LngLat = tr.center.constructor;
117
+ changes.center = new LngLat(v.longitude, v.latitude);
118
+ }
119
+ if ("zoom" in v && v.zoom !== tr.zoom) {
120
+ changes.zoom = v.zoom;
121
+ }
122
+ if ("bearing" in v && v.bearing !== tr.bearing) {
123
+ changes.bearing = v.bearing;
124
+ }
125
+ if ("pitch" in v && v.pitch !== tr.pitch) {
126
+ changes.pitch = v.pitch;
127
+ }
128
+ if (v.padding && tr.padding && !deepEqual(v.padding, tr.padding)) {
129
+ changes.padding = v.padding;
130
+ }
131
+ return changes;
132
+ }
133
+
134
+ // src/utils/style-utils.ts
135
+ var refProps = ["type", "source", "source-layer", "minzoom", "maxzoom", "filter", "layout"];
136
+ function normalizeStyle(style) {
137
+ if (!style) {
138
+ return null;
139
+ }
140
+ if (typeof style === "string") {
141
+ return style;
142
+ }
143
+ if ("toJS" in style) {
144
+ style = style.toJS();
145
+ }
146
+ if (!style.layers) {
147
+ return style;
148
+ }
149
+ const layerIndex = {};
150
+ for (const layer of style.layers) {
151
+ layerIndex[layer.id] = layer;
152
+ }
153
+ const layers = style.layers.map((layer) => {
154
+ const legacyLayer = layer;
155
+ let normalizedLayer = null;
156
+ if ("interactive" in legacyLayer) {
157
+ normalizedLayer = Object.assign({}, legacyLayer);
158
+ delete normalizedLayer.interactive;
159
+ }
160
+ const layerRef = layerIndex[legacyLayer.ref];
161
+ if (layerRef) {
162
+ normalizedLayer = normalizedLayer || Object.assign({}, legacyLayer);
163
+ delete normalizedLayer.ref;
164
+ for (const propName of refProps) {
165
+ if (propName in layerRef) {
166
+ normalizedLayer[propName] = layerRef[propName];
167
+ }
168
+ }
169
+ }
170
+ return normalizedLayer || layer;
171
+ });
172
+ return { ...style, layers };
173
+ }
174
+
175
+ // src/maplibre/maplibre.ts
176
+ var DEFAULT_STYLE = {
177
+ version: 8,
178
+ sources: {},
179
+ layers: []
180
+ };
181
+ var pointerEvents = {
182
+ mousedown: "onMouseDown",
183
+ mouseup: "onMouseUp",
184
+ mouseover: "onMouseOver",
185
+ mousemove: "onMouseMove",
186
+ click: "onClick",
187
+ dblclick: "onDblClick",
188
+ mouseenter: "onMouseEnter",
189
+ mouseleave: "onMouseLeave",
190
+ mouseout: "onMouseOut",
191
+ contextmenu: "onContextMenu",
192
+ touchstart: "onTouchStart",
193
+ touchend: "onTouchEnd",
194
+ touchmove: "onTouchMove",
195
+ touchcancel: "onTouchCancel"
196
+ };
197
+ var cameraEvents = {
198
+ movestart: "onMoveStart",
199
+ move: "onMove",
200
+ moveend: "onMoveEnd",
201
+ dragstart: "onDragStart",
202
+ drag: "onDrag",
203
+ dragend: "onDragEnd",
204
+ zoomstart: "onZoomStart",
205
+ zoom: "onZoom",
206
+ zoomend: "onZoomEnd",
207
+ rotatestart: "onRotateStart",
208
+ rotate: "onRotate",
209
+ rotateend: "onRotateEnd",
210
+ pitchstart: "onPitchStart",
211
+ pitch: "onPitch",
212
+ pitchend: "onPitchEnd"
213
+ };
214
+ var otherEvents = {
215
+ wheel: "onWheel",
216
+ boxzoomstart: "onBoxZoomStart",
217
+ boxzoomend: "onBoxZoomEnd",
218
+ boxzoomcancel: "onBoxZoomCancel",
219
+ resize: "onResize",
220
+ load: "onLoad",
221
+ render: "onRender",
222
+ idle: "onIdle",
223
+ remove: "onRemove",
224
+ data: "onData",
225
+ styledata: "onStyleData",
226
+ sourcedata: "onSourceData",
227
+ error: "onError"
228
+ };
229
+ var settingNames = [
230
+ "minZoom",
231
+ "maxZoom",
232
+ "minPitch",
233
+ "maxPitch",
234
+ "maxBounds",
235
+ "projection",
236
+ "renderWorldCopies"
237
+ ];
238
+ var handlerNames = [
239
+ "scrollZoom",
240
+ "boxZoom",
241
+ "dragRotate",
242
+ "dragPan",
243
+ "keyboard",
244
+ "doubleClickZoom",
245
+ "touchZoomRotate",
246
+ "touchPitch"
247
+ ];
248
+ var Maplibre = class _Maplibre {
249
+ constructor(MapClass, props, container) {
250
+ // mapboxgl.Map instance
251
+ this._map = null;
252
+ // Internal states
253
+ this._internalUpdate = false;
254
+ this._hoveredFeatures = null;
255
+ this._propsedCameraUpdate = null;
256
+ this._styleComponents = {};
257
+ this._onEvent = (e) => {
258
+ const handlerName = otherEvents[e.type];
259
+ const cb = this.props[handlerName];
260
+ if (cb) {
261
+ cb(e);
262
+ } else if (e.type === "error") {
263
+ console.error(e.error);
264
+ }
265
+ };
266
+ this._onCameraEvent = (e) => {
267
+ if (this._internalUpdate) {
268
+ return;
269
+ }
270
+ e.viewState = this._propsedCameraUpdate || transformToViewState(this._map.transform);
271
+ const handlerName = cameraEvents[e.type];
272
+ const cb = this.props[handlerName];
273
+ if (cb) {
274
+ cb(e);
275
+ }
276
+ };
277
+ this._onCameraUpdate = (tr) => {
278
+ if (this._internalUpdate) {
279
+ return tr;
280
+ }
281
+ this._propsedCameraUpdate = transformToViewState(tr);
282
+ return applyViewStateToTransform(tr, this.props);
283
+ };
284
+ this._onPointerEvent = (e) => {
285
+ if (e.type === "mousemove" || e.type === "mouseout") {
286
+ this._updateHover(e);
287
+ }
288
+ const handlerName = pointerEvents[e.type];
289
+ const cb = this.props[handlerName];
290
+ if (cb) {
291
+ if (this.props.interactiveLayerIds && e.type !== "mouseover" && e.type !== "mouseout") {
292
+ e.features = this._hoveredFeatures || this._queryRenderedFeatures(e.point);
293
+ }
294
+ cb(e);
295
+ delete e.features;
296
+ }
297
+ };
298
+ this._MapClass = MapClass;
299
+ this.props = props;
300
+ this._initialize(container);
301
+ }
302
+ static {
303
+ this.savedMaps = [];
304
+ }
305
+ get map() {
306
+ return this._map;
307
+ }
308
+ setProps(props) {
309
+ const oldProps = this.props;
310
+ this.props = props;
311
+ const settingsChanged = this._updateSettings(props, oldProps);
312
+ const sizeChanged = this._updateSize(props);
313
+ const viewStateChanged = this._updateViewState(props);
314
+ this._updateStyle(props, oldProps);
315
+ this._updateStyleComponents(props);
316
+ this._updateHandlers(props, oldProps);
317
+ if (settingsChanged || sizeChanged || viewStateChanged && !this._map.isMoving()) {
318
+ this.redraw();
319
+ }
320
+ }
321
+ static reuse(props, container) {
322
+ const that = _Maplibre.savedMaps.pop();
323
+ if (!that) {
324
+ return null;
325
+ }
326
+ const map = that.map;
327
+ const oldContainer = map.getContainer();
328
+ container.className = oldContainer.className;
329
+ while (oldContainer.childNodes.length > 0) {
330
+ container.appendChild(oldContainer.childNodes[0]);
331
+ }
332
+ const mapInternal = map;
333
+ mapInternal._container = container;
334
+ const resizeObserver = mapInternal._resizeObserver;
335
+ if (resizeObserver) {
336
+ resizeObserver.disconnect();
337
+ resizeObserver.observe(container);
338
+ }
339
+ that.setProps({ ...props, styleDiffing: false });
340
+ map.resize();
341
+ const { initialViewState } = props;
342
+ if (initialViewState) {
343
+ if (initialViewState.bounds) {
344
+ map.fitBounds(initialViewState.bounds, {
345
+ ...initialViewState.fitBoundsOptions,
346
+ duration: 0
347
+ });
348
+ } else {
349
+ that._updateViewState(initialViewState);
350
+ }
351
+ }
352
+ if (map.isStyleLoaded()) {
353
+ map.fire("load");
354
+ } else {
355
+ map.once("style.load", () => map.fire("load"));
356
+ }
357
+ const mapInternalForUpdate = map;
358
+ mapInternalForUpdate._update();
359
+ return that;
360
+ }
361
+ _initialize(container) {
362
+ const { props } = this;
363
+ const { mapStyle = DEFAULT_STYLE } = props;
364
+ const mapOptions = {
365
+ ...props,
366
+ ...props.initialViewState,
367
+ container,
368
+ style: normalizeStyle(mapStyle)
369
+ };
370
+ const viewState = mapOptions.initialViewState || mapOptions.viewState || mapOptions;
371
+ Object.assign(mapOptions, {
372
+ center: [viewState.longitude || 0, viewState.latitude || 0],
373
+ zoom: viewState.zoom || 0,
374
+ pitch: viewState.pitch || 0,
375
+ bearing: viewState.bearing || 0
376
+ });
377
+ if (props.gl) {
378
+ const getContext = HTMLCanvasElement.prototype.getContext;
379
+ HTMLCanvasElement.prototype.getContext = () => {
380
+ HTMLCanvasElement.prototype.getContext = getContext;
381
+ return props.gl;
382
+ };
383
+ }
384
+ const map = new this._MapClass(mapOptions);
385
+ if (viewState.padding) {
386
+ map.setPadding(viewState.padding);
387
+ }
388
+ if (props.cursor) {
389
+ map.getCanvas().style.cursor = props.cursor;
390
+ }
391
+ map.transformCameraUpdate = this._onCameraUpdate;
392
+ map.on("style.load", () => {
393
+ const mapWithProjection = map;
394
+ this._styleComponents = {
395
+ light: map.getLight(),
396
+ sky: map.getSky(),
397
+ projection: mapWithProjection.getProjection?.(),
398
+ terrain: map.getTerrain()
399
+ };
400
+ this._updateStyleComponents(this.props);
401
+ });
402
+ map.on("sourcedata", () => {
403
+ this._updateStyleComponents(this.props);
404
+ });
405
+ for (const eventName in pointerEvents) {
406
+ map.on(eventName, this._onPointerEvent);
407
+ }
408
+ for (const eventName in cameraEvents) {
409
+ map.on(eventName, this._onCameraEvent);
410
+ }
411
+ for (const eventName in otherEvents) {
412
+ map.on(eventName, this._onEvent);
413
+ }
414
+ this._map = map;
415
+ }
416
+ recycle() {
417
+ const container = this.map.getContainer();
418
+ const children = container.querySelector("[mapboxgl-children]");
419
+ children?.remove();
420
+ _Maplibre.savedMaps.push(this);
421
+ }
422
+ destroy() {
423
+ this._map.remove();
424
+ }
425
+ // Force redraw the map now. Typically resize() and jumpTo() is reflected in the next
426
+ // render cycle, which is managed by Mapbox's animation loop.
427
+ // This removes the synchronization issue caused by requestAnimationFrame.
428
+ redraw() {
429
+ const map = this._map;
430
+ if (map.style) {
431
+ if (map._frame) {
432
+ map._frame.cancel();
433
+ map._frame = null;
434
+ }
435
+ map._render();
436
+ }
437
+ }
438
+ /* Trigger map resize if size is controlled
439
+ @param {object} nextProps
440
+ @returns {bool} true if size has changed
441
+ */
442
+ _updateSize(nextProps) {
443
+ const { viewState } = nextProps;
444
+ if (viewState) {
445
+ const map = this._map;
446
+ if (viewState.width !== map.transform.width || viewState.height !== map.transform.height) {
447
+ map.resize();
448
+ return true;
449
+ }
450
+ }
451
+ return false;
452
+ }
453
+ // Adapted from map.jumpTo
454
+ /* Update camera to match props
455
+ @param {object} nextProps
456
+ @param {bool} triggerEvents - should fire camera events
457
+ @returns {bool} true if anything is changed
458
+ */
459
+ _updateViewState(nextProps) {
460
+ const map = this._map;
461
+ const tr = map.transform;
462
+ const isMoving = map.isMoving();
463
+ if (!isMoving) {
464
+ const changes = applyViewStateToTransform(tr, nextProps);
465
+ if (Object.keys(changes).length > 0) {
466
+ this._internalUpdate = true;
467
+ map.jumpTo(changes);
468
+ this._internalUpdate = false;
469
+ return true;
470
+ }
471
+ }
472
+ return false;
473
+ }
474
+ /* Update camera constraints and projection settings to match props
475
+ @param {object} nextProps
476
+ @param {object} currProps
477
+ @returns {bool} true if anything is changed
478
+ */
479
+ _updateSettings(nextProps, currProps) {
480
+ const map = this._map;
481
+ let changed = false;
482
+ for (const propName of settingNames) {
483
+ if (propName in nextProps && !deepEqual(nextProps[propName], currProps[propName])) {
484
+ changed = true;
485
+ const setter = map[`set${propName[0].toUpperCase()}${propName.slice(1)}`];
486
+ setter?.call(map, nextProps[propName]);
487
+ }
488
+ }
489
+ return changed;
490
+ }
491
+ /* Update map style to match props */
492
+ _updateStyle(nextProps, currProps) {
493
+ if (nextProps.cursor !== currProps.cursor) {
494
+ this._map.getCanvas().style.cursor = nextProps.cursor || "";
495
+ }
496
+ if (nextProps.mapStyle !== currProps.mapStyle) {
497
+ const { mapStyle = DEFAULT_STYLE, styleDiffing = true } = nextProps;
498
+ const options = {
499
+ diff: styleDiffing
500
+ };
501
+ if ("localIdeographFontFamily" in nextProps) {
502
+ options.localIdeographFontFamily = nextProps.localIdeographFontFamily;
503
+ }
504
+ this._map.setStyle(normalizeStyle(mapStyle), options);
505
+ }
506
+ }
507
+ /* Update fog, light, projection and terrain to match props
508
+ * These props are special because
509
+ * 1. They can not be applied right away. Certain conditions (style loaded, source loaded, etc.) must be met
510
+ * 2. They can be overwritten by mapStyle
511
+ */
512
+ _updateStyleComponents({ light, projection, sky, terrain }) {
513
+ const map = this._map;
514
+ const currProps = this._styleComponents;
515
+ const mapWithProjection = map;
516
+ if (map.style._loaded) {
517
+ if (light && !deepEqual(light, currProps.light)) {
518
+ currProps.light = light;
519
+ map.setLight(light);
520
+ }
521
+ if (projection && !deepEqual(projection, currProps.projection) && projection !== currProps.projection?.type) {
522
+ currProps.projection = typeof projection === "string" ? { type: projection } : projection;
523
+ mapWithProjection.setProjection?.(currProps.projection);
524
+ }
525
+ if (sky && !deepEqual(sky, currProps.sky)) {
526
+ currProps.sky = sky;
527
+ map.setSky(sky);
528
+ }
529
+ if (terrain !== void 0 && !deepEqual(terrain, currProps.terrain)) {
530
+ if (!terrain || map.getSource(terrain.source)) {
531
+ currProps.terrain = terrain;
532
+ map.setTerrain(terrain);
533
+ }
534
+ }
535
+ }
536
+ }
537
+ /* Update interaction handlers to match props */
538
+ _updateHandlers(nextProps, currProps) {
539
+ const map = this._map;
540
+ for (const propName of handlerNames) {
541
+ const newValue = nextProps[propName] ?? true;
542
+ const oldValue = currProps[propName] ?? true;
543
+ if (!deepEqual(newValue, oldValue)) {
544
+ if (newValue) {
545
+ map[propName].enable(newValue);
546
+ } else {
547
+ map[propName].disable();
548
+ }
549
+ }
550
+ }
551
+ }
552
+ _queryRenderedFeatures(point) {
553
+ const map = this._map;
554
+ const { interactiveLayerIds = [] } = this.props;
555
+ try {
556
+ return map.queryRenderedFeatures(point, {
557
+ layers: interactiveLayerIds.filter(map.getLayer.bind(map))
558
+ });
559
+ } catch {
560
+ return [];
561
+ }
562
+ }
563
+ _updateHover(e) {
564
+ const { props } = this;
565
+ const shouldTrackHoveredFeatures = props.interactiveLayerIds && (props.onMouseMove || props.onMouseEnter || props.onMouseLeave);
566
+ if (shouldTrackHoveredFeatures) {
567
+ const eventType = e.type;
568
+ const wasHovering = this._hoveredFeatures?.length > 0;
569
+ const features = this._queryRenderedFeatures(e.point);
570
+ const isHovering = features.length > 0;
571
+ if (!isHovering && wasHovering) {
572
+ e.type = "mouseleave";
573
+ this._onPointerEvent(e);
574
+ }
575
+ this._hoveredFeatures = features;
576
+ if (isHovering && !wasHovering) {
577
+ e.type = "mouseenter";
578
+ this._onPointerEvent(e);
579
+ }
580
+ e.type = eventType;
581
+ } else {
582
+ this._hoveredFeatures = null;
583
+ }
584
+ }
585
+ };
586
+
587
+ // src/maplibre/create-ref.ts
588
+ var skipMethods = [
589
+ "setMaxBounds",
590
+ "setMinZoom",
591
+ "setMaxZoom",
592
+ "setMinPitch",
593
+ "setMaxPitch",
594
+ "setRenderWorldCopies",
595
+ "setProjection",
596
+ "setStyle",
597
+ "addSource",
598
+ "removeSource",
599
+ "addLayer",
600
+ "removeLayer",
601
+ "setLayerZoomRange",
602
+ "setFilter",
603
+ "setPaintProperty",
604
+ "setLayoutProperty",
605
+ "setLight",
606
+ "setTerrain",
607
+ "setFog",
608
+ "remove"
609
+ ];
610
+ function createRef(mapInstance) {
611
+ if (!mapInstance) {
612
+ return null;
613
+ }
614
+ const map = mapInstance.map;
615
+ const result = {
616
+ getMap: () => map
617
+ };
618
+ for (const key of getMethodNames(map)) {
619
+ if (!(key in result) && !skipMethods.includes(key)) {
620
+ result[key] = map[key].bind(map);
621
+ }
622
+ }
623
+ return result;
624
+ }
625
+ function getMethodNames(obj) {
626
+ const result = /* @__PURE__ */ new Set();
627
+ let proto = obj;
628
+ while (proto) {
629
+ for (const key of Object.getOwnPropertyNames(proto)) {
630
+ if (key[0] !== "_" && typeof obj[key] === "function" && key !== "fire" && key !== "setEventedParent") {
631
+ result.add(key);
632
+ }
633
+ }
634
+ proto = Object.getPrototypeOf(proto);
635
+ }
636
+ return Array.from(result);
637
+ }
638
+
639
+ // src/utils/use-isomorphic-layout-effect.ts
640
+ import { useEffect, useLayoutEffect } from "react";
641
+ var useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffect : useEffect;
642
+ var use_isomorphic_layout_effect_default = useIsomorphicLayoutEffect;
643
+
644
+ // src/utils/set-globals.ts
645
+ var validateUrl = (url, settingName) => {
646
+ try {
647
+ const parsed = new URL(url);
648
+ if (!["http:", "https:"].includes(parsed.protocol)) {
649
+ console.warn(`${settingName}: Only http/https protocols are allowed, got: ${parsed.protocol}`);
650
+ return false;
651
+ }
652
+ return true;
653
+ } catch {
654
+ console.warn(`${settingName}: Invalid URL format: ${url}`);
655
+ return false;
656
+ }
657
+ };
658
+ function setGlobals(mapLib, props) {
659
+ const { RTLTextPlugin, maxParallelImageRequests, workerCount, workerUrl } = props;
660
+ if (RTLTextPlugin && mapLib.getRTLTextPluginStatus && mapLib.getRTLTextPluginStatus() === "unavailable") {
661
+ const { pluginUrl, lazy = true } = typeof RTLTextPlugin === "string" ? { pluginUrl: RTLTextPlugin } : RTLTextPlugin;
662
+ if (validateUrl(pluginUrl, "RTLTextPlugin")) {
663
+ mapLib.setRTLTextPlugin(
664
+ pluginUrl,
665
+ (error) => {
666
+ if (error) {
667
+ console.error(error);
668
+ }
669
+ },
670
+ lazy
671
+ );
672
+ }
673
+ }
674
+ if (maxParallelImageRequests !== void 0) {
675
+ mapLib.setMaxParallelImageRequests(maxParallelImageRequests);
676
+ }
677
+ if (workerCount !== void 0) {
678
+ mapLib.setWorkerCount(workerCount);
679
+ }
680
+ if (workerUrl !== void 0) {
681
+ if (validateUrl(workerUrl, "workerUrl")) {
682
+ mapLib.setWorkerUrl(workerUrl);
683
+ }
684
+ }
685
+ }
686
+
687
+ // src/components/logo-control.ts
688
+ import { useEffect as useEffect3, memo } from "react";
689
+
690
+ // src/utils/apply-react-style.ts
691
+ var unitlessNumber = /box|flex|grid|column|lineHeight|fontWeight|opacity|order|tabSize|zIndex/;
692
+ function applyReactStyle(element, styles) {
693
+ if (!element || !styles) {
694
+ return;
695
+ }
696
+ const style = element.style;
697
+ for (const key in styles) {
698
+ const value = styles[key];
699
+ if (Number.isFinite(value) && !unitlessNumber.test(key)) {
700
+ style[key] = `${value}px`;
701
+ } else {
702
+ style[key] = value;
703
+ }
704
+ }
705
+ }
706
+
707
+ // src/components/use-control.ts
708
+ import { useContext as useContext2, useMemo as useMemo2, useEffect as useEffect2 } from "react";
709
+ function useControl(onCreate, arg1, arg2, arg3) {
710
+ const context = useContext2(MapContext);
711
+ if (!context) {
712
+ throw new Error("useControl must be used within a Map component");
713
+ }
714
+ const ctrl = useMemo2(() => onCreate(context), []);
715
+ useEffect2(() => {
716
+ const opts = arg3 || arg2 || arg1;
717
+ const onAdd = typeof arg1 === "function" && typeof arg2 === "function" ? arg1 : null;
718
+ const onRemove = typeof arg2 === "function" ? arg2 : typeof arg1 === "function" ? arg1 : null;
719
+ const { map } = context;
720
+ const ctrlAsIControl = ctrl;
721
+ if (!map.hasControl(ctrlAsIControl)) {
722
+ map.addControl(ctrlAsIControl, opts?.position);
723
+ if (onAdd) {
724
+ onAdd(context);
725
+ }
726
+ }
727
+ return () => {
728
+ if (onRemove) {
729
+ onRemove(context);
730
+ }
731
+ if (map.hasControl(ctrlAsIControl)) {
732
+ map.removeControl(ctrlAsIControl);
733
+ }
734
+ };
735
+ }, []);
736
+ return ctrl;
737
+ }
738
+
739
+ // src/components/logo-control.ts
740
+ function _LogoControl(props) {
741
+ const ctrl = useControl(
742
+ () => {
743
+ const control = {
744
+ onAdd: (map) => {
745
+ if (map.getContainer) {
746
+ const existingLogo = map.getContainer().querySelector('a.maplibregl-ctrl-logo[href="https://www.barikoi.com"]');
747
+ if (existingLogo) {
748
+ existingLogo.remove();
749
+ }
750
+ }
751
+ const container = document.createElement("a");
752
+ container.className = "maplibregl-ctrl-logo";
753
+ container.href = "https://www.barikoi.com";
754
+ container.target = "_blank";
755
+ container.setAttribute("alt", "Barikoi");
756
+ container.setAttribute("aria-label", "Barikoi logo");
757
+ container.setAttribute("rel", "noopener nofollow");
758
+ control._container = container;
759
+ return container;
760
+ },
761
+ onRemove: () => {
762
+ delete control._container;
763
+ }
764
+ };
765
+ return control;
766
+ },
767
+ { position: props.position }
768
+ );
769
+ useEffect3(() => {
770
+ applyReactStyle(ctrl._container, props.style);
771
+ }, [props.style, ctrl._container]);
772
+ return null;
773
+ }
774
+ var LogoControl = memo(_LogoControl);
775
+
776
+ // src/components/attribution-control.ts
777
+ import { useEffect as useEffect4, memo as memo2 } from "react";
778
+ function _AttributionControl(props) {
779
+ const { current: map } = useMap();
780
+ const ctrl = useControl(
781
+ ({ mapLib }) => new mapLib.AttributionControl({
782
+ compact: true,
783
+ ...props
784
+ }),
785
+ { position: props.position }
786
+ );
787
+ useEffect4(() => {
788
+ applyReactStyle(ctrl._container, props.style);
789
+ if (!ctrl._container || !map) return;
790
+ const onLoad = () => {
791
+ setTimeout(() => {
792
+ const inner = ctrl._container.querySelector(".maplibregl-ctrl-attrib-inner");
793
+ if (inner) {
794
+ inner.textContent = "";
795
+ const createLink = (text, href) => {
796
+ const a = document.createElement("a");
797
+ a.href = href;
798
+ a.target = "_blank";
799
+ a.rel = "noopener noreferrer";
800
+ a.textContent = text;
801
+ return a;
802
+ };
803
+ inner.appendChild(createLink("Barikoi", "https://barikoi.com"));
804
+ inner.appendChild(document.createTextNode(" \xA9 "));
805
+ inner.appendChild(createLink("OpenMapTiles", "https://openmaptiles.org"));
806
+ inner.appendChild(document.createTextNode(" \xA9 "));
807
+ inner.appendChild(
808
+ createLink("OpenStreetMap contributors", "https://www.openstreetmap.org/copyright")
809
+ );
810
+ }
811
+ }, 0);
812
+ };
813
+ if (map.loaded()) {
814
+ onLoad();
815
+ } else {
816
+ map.once("load", onLoad);
817
+ }
818
+ return () => {
819
+ map.off("load", onLoad);
820
+ };
821
+ }, [props.style, ctrl._container, map]);
822
+ return null;
823
+ }
824
+ var AttributionControl = memo2(_AttributionControl);
825
+
826
+ // src/components/map.tsx
827
+ var MapContext = React2.createContext(null);
828
+ function _Map(props, ref) {
829
+ const mountedMapsContext = useContext3(MountedMapsContext);
830
+ const [mapInstance, setMapInstance] = useState2(null);
831
+ const containerRef = useRef();
832
+ const { current: contextValue } = useRef({
833
+ mapLib: null,
834
+ map: null
835
+ });
836
+ useEffect5(() => {
837
+ const mapLib = props.mapLib;
838
+ let isMounted = true;
839
+ let maplibre = null;
840
+ Promise.resolve(mapLib || import("maplibre-gl")).then((module) => {
841
+ if (!isMounted) {
842
+ return;
843
+ }
844
+ if (!module) {
845
+ throw new Error("Invalid mapLib");
846
+ }
847
+ const mapboxgl = "Map" in module ? module : module.default;
848
+ if (!mapboxgl.Map) {
849
+ throw new Error("Invalid mapLib");
850
+ }
851
+ setGlobals(mapboxgl, props);
852
+ if (props.reuseMaps) {
853
+ maplibre = Maplibre.reuse(props, containerRef.current);
854
+ }
855
+ if (!maplibre) {
856
+ maplibre = new Maplibre(
857
+ mapboxgl.Map,
858
+ {
859
+ ...props,
860
+ attributionControl: false
861
+ },
862
+ containerRef.current
863
+ );
864
+ }
865
+ if (maplibre) {
866
+ contextValue.map = createRef(maplibre);
867
+ contextValue.mapLib = mapboxgl;
868
+ setMapInstance(maplibre);
869
+ }
870
+ mountedMapsContext?.onMapMount(contextValue.map, props.id);
871
+ }).catch((error) => {
872
+ const { onError } = props;
873
+ if (onError) {
874
+ onError({
875
+ type: "error",
876
+ target: null,
877
+ originalEvent: null,
878
+ error
879
+ });
880
+ } else {
881
+ console.error(error);
882
+ }
883
+ });
884
+ return () => {
885
+ isMounted = false;
886
+ if (maplibre) {
887
+ mountedMapsContext?.onMapUnmount(props.id);
888
+ if (props.reuseMaps) {
889
+ maplibre.recycle();
890
+ } else {
891
+ maplibre.destroy();
892
+ }
893
+ }
894
+ };
895
+ }, []);
896
+ use_isomorphic_layout_effect_default(() => {
897
+ if (mapInstance) {
898
+ mapInstance.setProps(props);
899
+ }
900
+ });
901
+ useImperativeHandle(ref, () => contextValue.map, [mapInstance]);
902
+ const style = useMemo3(
903
+ () => ({
904
+ position: "relative",
905
+ width: "100%",
906
+ height: "100%",
907
+ ...props.style
908
+ }),
909
+ [props.style]
910
+ );
911
+ const CHILD_CONTAINER_STYLE = {
912
+ height: "100%"
913
+ };
914
+ return /* @__PURE__ */ React2.createElement("div", { id: props.id, ref: containerRef, style }, mapInstance && /* @__PURE__ */ React2.createElement(MapContext.Provider, { value: contextValue }, /* @__PURE__ */ React2.createElement("div", { style: CHILD_CONTAINER_STYLE }, /* @__PURE__ */ React2.createElement(LogoControl, { position: "bottom-left" }), /* @__PURE__ */ React2.createElement(AttributionControl, { position: "bottom-right" }), props.children)));
915
+ }
916
+ var Map = React2.forwardRef(_Map);
917
+
918
+ // src/components/marker.ts
919
+ import * as React3 from "react";
920
+ import { createPortal } from "react-dom";
921
+ import {
922
+ useImperativeHandle as useImperativeHandle2,
923
+ useEffect as useEffect6,
924
+ useMemo as useMemo4,
925
+ useRef as useRef2,
926
+ useContext as useContext4,
927
+ forwardRef as forwardRef2,
928
+ memo as memo3
929
+ } from "react";
930
+
931
+ // src/utils/compare-class-names.ts
932
+ function compareClassNames(prevClassName, nextClassName) {
933
+ if (prevClassName === nextClassName) {
934
+ return null;
935
+ }
936
+ const prevClassList = getClassList(prevClassName);
937
+ const nextClassList = getClassList(nextClassName);
938
+ const diff = [];
939
+ for (const c of nextClassList) {
940
+ if (!prevClassList.has(c)) {
941
+ diff.push(c);
942
+ }
943
+ }
944
+ for (const c of prevClassList) {
945
+ if (!nextClassList.has(c)) {
946
+ diff.push(c);
947
+ }
948
+ }
949
+ return diff.length === 0 ? null : diff;
950
+ }
951
+ function getClassList(className) {
952
+ return new Set(className ? className.trim().split(/\s+/) : []);
953
+ }
954
+
955
+ // src/components/marker.ts
956
+ var Marker = memo3(
957
+ forwardRef2((props, ref) => {
958
+ const { map, mapLib } = useContext4(MapContext);
959
+ const callbackRef = useRef2({});
960
+ const marker = useMemo4(() => {
961
+ let hasChildren = false;
962
+ React3.Children.forEach(props.children, (el) => {
963
+ if (el) {
964
+ hasChildren = true;
965
+ }
966
+ });
967
+ const options = {
968
+ ...props,
969
+ element: hasChildren ? document.createElement("div") : void 0
970
+ };
971
+ const mk = new mapLib.Marker(options);
972
+ mk.setLngLat([props.longitude, props.latitude]);
973
+ return mk;
974
+ }, []);
975
+ useEffect6(() => {
976
+ callbackRef.current = {
977
+ onClick: props.onClick,
978
+ onDragStart: props.onDragStart,
979
+ onDrag: props.onDrag,
980
+ onDragEnd: props.onDragEnd
981
+ };
982
+ });
983
+ useEffect6(() => {
984
+ const clickHandler = (e) => {
985
+ callbackRef.current.onClick?.({
986
+ type: "click",
987
+ target: marker,
988
+ originalEvent: e
989
+ });
990
+ };
991
+ marker.getElement().addEventListener("click", clickHandler);
992
+ const dragStartHandler = (e) => {
993
+ e.lngLat = marker.getLngLat();
994
+ callbackRef.current.onDragStart?.(e);
995
+ };
996
+ const dragHandler = (e) => {
997
+ e.lngLat = marker.getLngLat();
998
+ callbackRef.current.onDrag?.(e);
999
+ };
1000
+ const dragEndHandler = (e) => {
1001
+ e.lngLat = marker.getLngLat();
1002
+ callbackRef.current.onDragEnd?.(e);
1003
+ };
1004
+ marker.on("dragstart", dragStartHandler);
1005
+ marker.on("drag", dragHandler);
1006
+ marker.on("dragend", dragEndHandler);
1007
+ marker.addTo(map.getMap());
1008
+ return () => {
1009
+ marker.getElement().removeEventListener("click", clickHandler);
1010
+ marker.off("dragstart", dragStartHandler);
1011
+ marker.off("drag", dragHandler);
1012
+ marker.off("dragend", dragEndHandler);
1013
+ marker.remove();
1014
+ };
1015
+ }, []);
1016
+ const {
1017
+ longitude,
1018
+ latitude,
1019
+ offset,
1020
+ style,
1021
+ draggable = false,
1022
+ popup = null,
1023
+ rotation = 0,
1024
+ rotationAlignment = "auto",
1025
+ pitchAlignment = "auto",
1026
+ className
1027
+ } = props;
1028
+ useEffect6(() => {
1029
+ applyReactStyle(marker.getElement(), style);
1030
+ }, [style]);
1031
+ useImperativeHandle2(ref, () => marker, []);
1032
+ const prevClassNameRef = useRef2(className);
1033
+ useEffect6(() => {
1034
+ if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) {
1035
+ marker.setLngLat([longitude, latitude]);
1036
+ }
1037
+ if (offset && !arePointsEqual(marker.getOffset(), offset)) {
1038
+ marker.setOffset(offset);
1039
+ }
1040
+ if (marker.isDraggable() !== draggable) {
1041
+ marker.setDraggable(draggable);
1042
+ }
1043
+ if (marker.getRotation() !== rotation) {
1044
+ marker.setRotation(rotation);
1045
+ }
1046
+ if (marker.getRotationAlignment() !== rotationAlignment) {
1047
+ marker.setRotationAlignment(rotationAlignment);
1048
+ }
1049
+ if (marker.getPitchAlignment() !== pitchAlignment) {
1050
+ marker.setPitchAlignment(pitchAlignment);
1051
+ }
1052
+ if (marker.getPopup() !== popup) {
1053
+ marker.setPopup(popup);
1054
+ }
1055
+ const classNameDiff = compareClassNames(prevClassNameRef.current, className);
1056
+ if (classNameDiff) {
1057
+ for (const c of classNameDiff) {
1058
+ marker.toggleClassName(c);
1059
+ }
1060
+ }
1061
+ prevClassNameRef.current = className;
1062
+ });
1063
+ return createPortal(props.children, marker.getElement());
1064
+ })
1065
+ );
1066
+
1067
+ // src/components/popup.ts
1068
+ import { createPortal as createPortal2 } from "react-dom";
1069
+ import { useImperativeHandle as useImperativeHandle3, useEffect as useEffect7, useMemo as useMemo5, useContext as useContext5, forwardRef as forwardRef3, memo as memo4 } from "react";
1070
+ var Popup = memo4(
1071
+ forwardRef3((props, ref) => {
1072
+ const { map, mapLib } = useContext5(MapContext);
1073
+ const container = useMemo5(() => {
1074
+ return document.createElement("div");
1075
+ }, []);
1076
+ const popup = useMemo5(() => {
1077
+ const options = { ...props };
1078
+ const pp = new mapLib.Popup(options);
1079
+ pp.setLngLat([props.longitude, props.latitude]);
1080
+ return pp;
1081
+ }, []);
1082
+ useImperativeHandle3(ref, () => popup, []);
1083
+ useEffect7(() => {
1084
+ const onOpen = (e) => {
1085
+ props.onOpen?.(e);
1086
+ };
1087
+ const onClose = (e) => {
1088
+ props.onClose?.(e);
1089
+ };
1090
+ popup.on("open", onOpen);
1091
+ popup.on("close", onClose);
1092
+ popup.setDOMContent(container).addTo(map.getMap());
1093
+ return () => {
1094
+ popup.off("open", onOpen);
1095
+ popup.off("close", onClose);
1096
+ if (popup.isOpen()) {
1097
+ popup.remove();
1098
+ }
1099
+ };
1100
+ }, []);
1101
+ useEffect7(() => {
1102
+ applyReactStyle(popup.getElement(), props.style);
1103
+ }, [props.style]);
1104
+ useEffect7(() => {
1105
+ if (popup.isOpen()) {
1106
+ if (popup.getLngLat().lng !== props.longitude || popup.getLngLat().lat !== props.latitude) {
1107
+ popup.setLngLat([props.longitude, props.latitude]);
1108
+ }
1109
+ }
1110
+ }, [props.longitude, props.latitude]);
1111
+ useEffect7(() => {
1112
+ if (popup.isOpen() && props.offset) {
1113
+ popup.setOffset(props.offset);
1114
+ }
1115
+ }, [props.offset]);
1116
+ useEffect7(() => {
1117
+ if (popup.isOpen() && props.maxWidth !== void 0) {
1118
+ popup.setMaxWidth(props.maxWidth);
1119
+ }
1120
+ }, [props.maxWidth]);
1121
+ useEffect7(() => {
1122
+ if (popup.isOpen() && props.className) {
1123
+ const currentClassName = popup.options.className || "";
1124
+ const classNameDiff = compareClassNames(currentClassName, props.className);
1125
+ if (classNameDiff) {
1126
+ for (const c of classNameDiff) {
1127
+ popup.toggleClassName(c);
1128
+ }
1129
+ }
1130
+ }
1131
+ }, [props.className]);
1132
+ return createPortal2(props.children, container);
1133
+ })
1134
+ );
1135
+
1136
+ // src/components/fullscreen-control.ts
1137
+ import { useEffect as useEffect8, memo as memo5 } from "react";
1138
+ function _FullscreenControl(props) {
1139
+ const ctrl = useControl(
1140
+ ({ mapLib }) => new mapLib.FullscreenControl({
1141
+ container: props.containerId && document.getElementById(props.containerId)
1142
+ }),
1143
+ { position: props.position }
1144
+ );
1145
+ useEffect8(() => {
1146
+ applyReactStyle(ctrl._controlContainer, props.style);
1147
+ }, [props.style]);
1148
+ return null;
1149
+ }
1150
+ var FullscreenControl = memo5(_FullscreenControl);
1151
+
1152
+ // src/components/geolocate-control.ts
1153
+ import { useImperativeHandle as useImperativeHandle4, useRef as useRef3, useEffect as useEffect9, forwardRef as forwardRef4, memo as memo6 } from "react";
1154
+ function _GeolocateControl(props, ref) {
1155
+ const thisRef = useRef3({ props });
1156
+ const ctrl = useControl(
1157
+ ({ mapLib }) => {
1158
+ const gc = new mapLib.GeolocateControl(props);
1159
+ const setupUI = gc._setupUI;
1160
+ gc._setupUI = () => {
1161
+ if (!gc._container.hasChildNodes()) {
1162
+ setupUI();
1163
+ }
1164
+ };
1165
+ gc.on("geolocate", (e) => {
1166
+ thisRef.current.props.onGeolocate?.(e);
1167
+ });
1168
+ gc.on("error", (e) => {
1169
+ thisRef.current.props.onError?.(e);
1170
+ });
1171
+ gc.on("outofmaxbounds", (e) => {
1172
+ thisRef.current.props.onOutOfMaxBounds?.(e);
1173
+ });
1174
+ gc.on("trackuserlocationstart", (e) => {
1175
+ thisRef.current.props.onTrackUserLocationStart?.(e);
1176
+ });
1177
+ gc.on("trackuserlocationend", (e) => {
1178
+ thisRef.current.props.onTrackUserLocationEnd?.(e);
1179
+ });
1180
+ return gc;
1181
+ },
1182
+ { position: props.position }
1183
+ );
1184
+ thisRef.current.props = props;
1185
+ useImperativeHandle4(ref, () => ctrl, []);
1186
+ useEffect9(() => {
1187
+ applyReactStyle(ctrl._container, props.style);
1188
+ }, [props.style]);
1189
+ return null;
1190
+ }
1191
+ var GeolocateControl = memo6(forwardRef4(_GeolocateControl));
1192
+
1193
+ // src/components/navigation-control.ts
1194
+ import { useEffect as useEffect10, memo as memo7 } from "react";
1195
+ function _NavigationControl(props) {
1196
+ const ctrl = useControl(({ mapLib }) => new mapLib.NavigationControl(props), {
1197
+ position: props.position
1198
+ });
1199
+ useEffect10(() => {
1200
+ applyReactStyle(ctrl._container, props.style);
1201
+ }, [props.style]);
1202
+ return null;
1203
+ }
1204
+ var NavigationControl = memo7(_NavigationControl);
1205
+
1206
+ // src/components/scale-control.ts
1207
+ import { useEffect as useEffect11, useRef as useRef4, memo as memo8 } from "react";
1208
+ function _ScaleControl(props) {
1209
+ const ctrl = useControl(({ mapLib }) => new mapLib.ScaleControl(props), {
1210
+ position: props.position
1211
+ });
1212
+ const propsRef = useRef4(props);
1213
+ const prevProps = propsRef.current;
1214
+ propsRef.current = props;
1215
+ const { style, maxWidth, unit } = props;
1216
+ useEffect11(() => {
1217
+ if (maxWidth !== void 0 && maxWidth !== prevProps.maxWidth) {
1218
+ ctrl.options.maxWidth = maxWidth;
1219
+ }
1220
+ if (unit !== void 0 && unit !== prevProps.unit) {
1221
+ ctrl.setUnit(unit);
1222
+ }
1223
+ }, [ctrl, maxWidth, unit, prevProps.maxWidth, prevProps.unit]);
1224
+ useEffect11(() => {
1225
+ applyReactStyle(ctrl._container, style);
1226
+ }, [ctrl, style]);
1227
+ return null;
1228
+ }
1229
+ var ScaleControl = memo8(_ScaleControl);
1230
+
1231
+ // src/components/terrain-control.ts
1232
+ import { useEffect as useEffect12, memo as memo9 } from "react";
1233
+ function _TerrainControl(props) {
1234
+ const ctrl = useControl(({ mapLib }) => new mapLib.TerrainControl(props), {
1235
+ position: props.position
1236
+ });
1237
+ useEffect12(() => {
1238
+ applyReactStyle(ctrl._container, props.style);
1239
+ }, [props.style]);
1240
+ return null;
1241
+ }
1242
+ var TerrainControl = memo9(_TerrainControl);
1243
+
1244
+ // src/components/source.ts
1245
+ import * as React4 from "react";
1246
+ import {
1247
+ useContext as useContext6,
1248
+ useEffect as useEffect13,
1249
+ useMemo as useMemo6,
1250
+ useState as useState3,
1251
+ useRef as useRef5,
1252
+ cloneElement,
1253
+ memo as memo10,
1254
+ useId,
1255
+ useImperativeHandle as useImperativeHandle5
1256
+ } from "react";
1257
+
1258
+ // src/utils/assert.ts
1259
+ function assert(condition, message) {
1260
+ if (!condition) {
1261
+ throw new Error(message);
1262
+ }
1263
+ }
1264
+
1265
+ // src/components/source.ts
1266
+ function createSource(map, id, props) {
1267
+ const mapInternal = map;
1268
+ if (mapInternal.style && mapInternal.style._loaded) {
1269
+ const options = { ...props };
1270
+ delete options.id;
1271
+ delete options.children;
1272
+ map.addSource(id, options);
1273
+ return map.getSource(id);
1274
+ }
1275
+ return null;
1276
+ }
1277
+ function updateSource(source, props, prevProps) {
1278
+ assert(props.id === prevProps.id, "source id changed");
1279
+ assert(props.type === prevProps.type, "source type changed");
1280
+ let changedKey = "";
1281
+ let changedKeyCount = 0;
1282
+ for (const key in props) {
1283
+ if (key !== "children" && key !== "id" && !deepEqual(prevProps[key], props[key])) {
1284
+ changedKey = key;
1285
+ changedKeyCount++;
1286
+ }
1287
+ }
1288
+ if (!changedKeyCount) {
1289
+ return;
1290
+ }
1291
+ const type = props.type;
1292
+ if (type === "geojson") {
1293
+ ;
1294
+ source.setData(props.data);
1295
+ } else if (type === "image") {
1296
+ ;
1297
+ source.updateImage({
1298
+ url: props.url,
1299
+ coordinates: props.coordinates
1300
+ });
1301
+ } else {
1302
+ const sourceWithMethods = source;
1303
+ const propsWithOptional = props;
1304
+ switch (changedKey) {
1305
+ case "coordinates":
1306
+ sourceWithMethods.setCoordinates?.(propsWithOptional.coordinates);
1307
+ break;
1308
+ case "url":
1309
+ sourceWithMethods.setUrl?.(propsWithOptional.url);
1310
+ break;
1311
+ case "tiles":
1312
+ sourceWithMethods.setTiles?.(propsWithOptional.tiles);
1313
+ break;
1314
+ default:
1315
+ console.warn(`Unable to update <Source> prop: ${changedKey}`);
1316
+ }
1317
+ }
1318
+ }
1319
+ function _Source(props, ref) {
1320
+ const map = useContext6(MapContext).map.getMap();
1321
+ const propsRef = useRef5(props);
1322
+ const sourceRef = useRef5(null);
1323
+ const [, setStyleLoaded] = useState3(0);
1324
+ const generatedId = useId();
1325
+ const id = useMemo6(
1326
+ () => props.id || `jsx-source-${generatedId.replace(/:/g, "-")}`,
1327
+ // Empty deps - id is set once on mount and should not change
1328
+ []
1329
+ );
1330
+ useEffect13(() => {
1331
+ if (map) {
1332
+ const forceUpdate = () => setTimeout(() => setStyleLoaded((version) => version + 1), 0);
1333
+ map.on("styledata", forceUpdate);
1334
+ forceUpdate();
1335
+ return () => {
1336
+ map.off("styledata", forceUpdate);
1337
+ const mapInternal2 = map;
1338
+ if (mapInternal2.style && mapInternal2.style._loaded && map.getSource(id)) {
1339
+ const allLayers = map.getStyle()?.layers;
1340
+ if (allLayers) {
1341
+ for (const layer of allLayers) {
1342
+ const layerWithSource = layer;
1343
+ if (layerWithSource.source === id) {
1344
+ map.removeLayer(layer.id);
1345
+ }
1346
+ }
1347
+ }
1348
+ map.removeSource(id);
1349
+ }
1350
+ };
1351
+ }
1352
+ return void 0;
1353
+ }, [map]);
1354
+ const mapInternal = map;
1355
+ let source = map && mapInternal.style && map.getSource(id);
1356
+ if (source) {
1357
+ updateSource(source, props, propsRef.current);
1358
+ } else {
1359
+ source = createSource(map, id, props);
1360
+ }
1361
+ sourceRef.current = source;
1362
+ propsRef.current = props;
1363
+ useImperativeHandle5(ref, () => sourceRef.current, [source]);
1364
+ return source && React4.Children.map(
1365
+ props.children,
1366
+ (child) => child && cloneElement(child, {
1367
+ source: id
1368
+ })
1369
+ ) || null;
1370
+ }
1371
+ var Source = memo10(React4.forwardRef(_Source));
1372
+
1373
+ // src/components/canvas-source.ts
1374
+ import * as React5 from "react";
1375
+ import { useContext as useContext7, useEffect as useEffect14, useMemo as useMemo7, useRef as useRef6, memo as memo11 } from "react";
1376
+ function _CanvasSource(props) {
1377
+ const map = useContext7(MapContext).map.getMap();
1378
+ const propsRef = useRef6(props);
1379
+ const id = useMemo7(() => props.id || `canvas-source-${Date.now()}`, [props.id]);
1380
+ useEffect14(() => {
1381
+ if (!map) return void 0;
1382
+ const mapInternal2 = map;
1383
+ let source = null;
1384
+ const addSource = () => {
1385
+ if (!mapInternal2.style || !mapInternal2.style._loaded) return;
1386
+ if (map.getSource(id)) return;
1387
+ const { coordinates, canvas, animate } = props;
1388
+ map.addSource(id, {
1389
+ type: "canvas",
1390
+ coordinates,
1391
+ canvas,
1392
+ animate: animate || false
1393
+ });
1394
+ source = map.getSource(id);
1395
+ };
1396
+ const updateSource2 = () => {
1397
+ if (!source) return;
1398
+ const { coordinates, canvas } = props;
1399
+ const prevProps = propsRef.current;
1400
+ if (JSON.stringify(coordinates) !== JSON.stringify(prevProps.coordinates)) {
1401
+ const sourceWithMethods = source;
1402
+ sourceWithMethods.setCoordinates?.(coordinates);
1403
+ }
1404
+ };
1405
+ if (mapInternal2.style && mapInternal2.style._loaded) {
1406
+ addSource();
1407
+ } else {
1408
+ map.once("styledata", addSource);
1409
+ }
1410
+ return () => {
1411
+ map.off("styledata", addSource);
1412
+ const mapInternalForCleanup = map;
1413
+ if (mapInternalForCleanup.style && mapInternalForCleanup.style._loaded && map.getSource(id)) {
1414
+ const allLayers = map.getStyle()?.layers;
1415
+ if (allLayers) {
1416
+ for (const layer of allLayers) {
1417
+ if (layer.source === id) {
1418
+ map.removeLayer(layer.id);
1419
+ }
1420
+ }
1421
+ }
1422
+ map.removeSource(id);
1423
+ }
1424
+ };
1425
+ }, [map, id]);
1426
+ useEffect14(() => {
1427
+ if (!map) return;
1428
+ const source = map.getSource(id);
1429
+ if (!source) return;
1430
+ const { coordinates } = props;
1431
+ const prevProps = propsRef.current;
1432
+ if (JSON.stringify(coordinates) !== JSON.stringify(prevProps.coordinates)) {
1433
+ const sourceWithMethods = source;
1434
+ sourceWithMethods.setCoordinates?.(coordinates);
1435
+ }
1436
+ propsRef.current = props;
1437
+ }, [map, id, props.coordinates, props.canvas]);
1438
+ if (!map) return null;
1439
+ const mapInternal = map;
1440
+ if (!mapInternal.style || !mapInternal.style._loaded || !map.getSource(id)) {
1441
+ return null;
1442
+ }
1443
+ return props.children && React5.Children.map(
1444
+ props.children,
1445
+ (child) => child && React5.cloneElement(child, {
1446
+ source: id
1447
+ })
1448
+ ) || null;
1449
+ }
1450
+ var CanvasSource = memo11(_CanvasSource);
1451
+
1452
+ // src/components/layer.ts
1453
+ import { useContext as useContext8, useEffect as useEffect15, useMemo as useMemo8, useState as useState5, useRef as useRef7, memo as memo12, useId as useId2 } from "react";
1454
+ function updateLayer(map, id, props, prevProps) {
1455
+ assert(props.id === prevProps.id, "layer id changed");
1456
+ assert(props.type === prevProps.type, "layer type changed");
1457
+ if (props.type === "custom" || prevProps.type === "custom") {
1458
+ return;
1459
+ }
1460
+ const propsWithFilter = props;
1461
+ const prevPropsWithFilter = prevProps;
1462
+ const { layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId } = propsWithFilter;
1463
+ if (beforeId !== prevPropsWithFilter.beforeId) {
1464
+ map.moveLayer(id, beforeId);
1465
+ }
1466
+ if (layout !== prevPropsWithFilter.layout) {
1467
+ const prevLayout = prevPropsWithFilter.layout || {};
1468
+ for (const key in layout) {
1469
+ if (!deepEqual(layout[key], prevLayout[key])) {
1470
+ map.setLayoutProperty(id, key, layout[key]);
1471
+ }
1472
+ }
1473
+ for (const key in prevLayout) {
1474
+ if (!Object.prototype.hasOwnProperty.call(layout, key)) {
1475
+ map.setLayoutProperty(id, key, void 0);
1476
+ }
1477
+ }
1478
+ }
1479
+ if (paint !== prevPropsWithFilter.paint) {
1480
+ const prevPaint = prevPropsWithFilter.paint || {};
1481
+ for (const key in paint) {
1482
+ if (!deepEqual(paint[key], prevPaint[key])) {
1483
+ map.setPaintProperty(id, key, paint[key]);
1484
+ }
1485
+ }
1486
+ for (const key in prevPaint) {
1487
+ if (!Object.prototype.hasOwnProperty.call(paint, key)) {
1488
+ map.setPaintProperty(id, key, void 0);
1489
+ }
1490
+ }
1491
+ }
1492
+ if (!deepEqual(filter, prevPropsWithFilter.filter)) {
1493
+ map.setFilter(id, filter ?? null);
1494
+ }
1495
+ if (minzoom !== prevPropsWithFilter.minzoom || maxzoom !== prevPropsWithFilter.maxzoom) {
1496
+ map.setLayerZoomRange(id, minzoom, maxzoom);
1497
+ }
1498
+ }
1499
+ function createLayer(map, id, props) {
1500
+ const mapInternal = map;
1501
+ if (mapInternal.style && mapInternal.style._loaded && (!("source" in props) || map.getSource(props.source))) {
1502
+ const options = { ...props, id };
1503
+ delete options.beforeId;
1504
+ map.addLayer(options, props.beforeId);
1505
+ }
1506
+ }
1507
+ function _Layer(props) {
1508
+ const map = useContext8(MapContext).map.getMap();
1509
+ const propsRef = useRef7(props);
1510
+ const [, setStyleLoaded] = useState5(0);
1511
+ const generatedId = useId2();
1512
+ const id = useMemo8(
1513
+ () => props.id || `jsx-layer-${generatedId.replace(/:/g, "-")}`,
1514
+ // Empty deps - id is set once on mount and should not change
1515
+ []
1516
+ );
1517
+ const {
1518
+ onClick,
1519
+ onMouseEnter,
1520
+ onMouseLeave,
1521
+ onMouseMove,
1522
+ onMouseDown,
1523
+ onMouseUp,
1524
+ onContextMenu,
1525
+ onDoubleClick
1526
+ } = props;
1527
+ const callbacksRef = useRef7({
1528
+ onClick,
1529
+ onMouseEnter,
1530
+ onMouseLeave,
1531
+ onMouseMove,
1532
+ onMouseDown,
1533
+ onMouseUp,
1534
+ onContextMenu,
1535
+ onDoubleClick
1536
+ });
1537
+ useEffect15(() => {
1538
+ callbacksRef.current = {
1539
+ onClick,
1540
+ onMouseEnter,
1541
+ onMouseLeave,
1542
+ onMouseMove,
1543
+ onMouseDown,
1544
+ onMouseUp,
1545
+ onContextMenu,
1546
+ onDoubleClick
1547
+ };
1548
+ }, [
1549
+ onClick,
1550
+ onMouseEnter,
1551
+ onMouseLeave,
1552
+ onMouseMove,
1553
+ onMouseDown,
1554
+ onMouseUp,
1555
+ onContextMenu,
1556
+ onDoubleClick
1557
+ ]);
1558
+ useEffect15(() => {
1559
+ if (map) {
1560
+ const forceUpdate = () => setStyleLoaded((version) => version + 1);
1561
+ map.on("styledata", forceUpdate);
1562
+ forceUpdate();
1563
+ return () => {
1564
+ map.off("styledata", forceUpdate);
1565
+ const mapInternal2 = map;
1566
+ if (mapInternal2.style && mapInternal2.style._loaded && map.getLayer(id)) {
1567
+ map.removeLayer(id);
1568
+ }
1569
+ };
1570
+ }
1571
+ return void 0;
1572
+ }, [map]);
1573
+ useEffect15(() => {
1574
+ if (!map) return void 0;
1575
+ const hasEventHandler = onClick || onMouseEnter || onMouseLeave || onMouseMove || onMouseDown || onMouseUp || onContextMenu || onDoubleClick;
1576
+ if (!hasEventHandler) return void 0;
1577
+ const handleClick = (e) => {
1578
+ callbacksRef.current.onClick?.(e);
1579
+ };
1580
+ const handleMouseEnter = (e) => {
1581
+ callbacksRef.current.onMouseEnter?.(e);
1582
+ if (callbacksRef.current.onClick) {
1583
+ map.getCanvas().style.cursor = "pointer";
1584
+ }
1585
+ };
1586
+ const handleMouseLeave = () => {
1587
+ callbacksRef.current.onMouseLeave?.();
1588
+ map.getCanvas().style.cursor = "";
1589
+ };
1590
+ const handleMouseMove = (e) => {
1591
+ callbacksRef.current.onMouseMove?.(e);
1592
+ };
1593
+ const handleMouseDown = (e) => {
1594
+ callbacksRef.current.onMouseDown?.(e);
1595
+ };
1596
+ const handleMouseUp = (e) => {
1597
+ callbacksRef.current.onMouseUp?.(e);
1598
+ };
1599
+ const handleContextMenu = (e) => {
1600
+ callbacksRef.current.onContextMenu?.(e);
1601
+ };
1602
+ const handleDoubleClick = (e) => {
1603
+ callbacksRef.current.onDoubleClick?.(e);
1604
+ };
1605
+ if (onClick) map.on("click", id, handleClick);
1606
+ if (onMouseEnter) map.on("mouseenter", id, handleMouseEnter);
1607
+ if (onMouseLeave) map.on("mouseleave", id, handleMouseLeave);
1608
+ if (onMouseMove) map.on("mousemove", id, handleMouseMove);
1609
+ if (onMouseDown) map.on("mousedown", id, handleMouseDown);
1610
+ if (onMouseUp) map.on("mouseup", id, handleMouseUp);
1611
+ if (onContextMenu) map.on("contextmenu", id, handleContextMenu);
1612
+ if (onDoubleClick) map.on("dblclick", id, handleDoubleClick);
1613
+ return () => {
1614
+ if (onClick) map.off("click", id, handleClick);
1615
+ if (onMouseEnter) map.off("mouseenter", id, handleMouseEnter);
1616
+ if (onMouseLeave) map.off("mouseleave", id, handleMouseLeave);
1617
+ if (onMouseMove) map.off("mousemove", id, handleMouseMove);
1618
+ if (onMouseDown) map.off("mousedown", id, handleMouseDown);
1619
+ if (onMouseUp) map.off("mouseup", id, handleMouseUp);
1620
+ if (onContextMenu) map.off("contextmenu", id, handleContextMenu);
1621
+ if (onDoubleClick) map.off("dblclick", id, handleDoubleClick);
1622
+ };
1623
+ }, [
1624
+ map,
1625
+ id,
1626
+ onClick,
1627
+ onMouseEnter,
1628
+ onMouseLeave,
1629
+ onMouseMove,
1630
+ onMouseDown,
1631
+ onMouseUp,
1632
+ onContextMenu,
1633
+ onDoubleClick
1634
+ ]);
1635
+ const mapInternal = map;
1636
+ const layer = map && mapInternal.style && map.getLayer(id);
1637
+ if (layer) {
1638
+ try {
1639
+ updateLayer(map, id, props, propsRef.current);
1640
+ } catch (error) {
1641
+ console.warn(error);
1642
+ }
1643
+ } else {
1644
+ createLayer(map, id, props);
1645
+ }
1646
+ propsRef.current = props;
1647
+ return null;
1648
+ }
1649
+ var Layer = memo12(_Layer);
1650
+
1651
+ // src/components/draw-control.ts
1652
+ import { useEffect as useEffect16, useMemo as useMemo9, memo as memo13, useRef as useRef8, useContext as useContext9 } from "react";
1653
+ import MapboxDraw from "maplibre-gl-draw";
1654
+ var defaultDrawOptions = {
1655
+ displayControlsDefault: false,
1656
+ controls: {
1657
+ polygon: true,
1658
+ trash: true
1659
+ }
1660
+ };
1661
+ function _DrawControl(props) {
1662
+ const {
1663
+ position,
1664
+ style,
1665
+ onDrawCreate,
1666
+ onDrawDelete,
1667
+ onDrawUpdate,
1668
+ onDrawSelectionChange,
1669
+ onDrawModeChange,
1670
+ onDrawCombine,
1671
+ onDrawUncombine,
1672
+ onDrawRender,
1673
+ ...drawOptions
1674
+ } = props;
1675
+ const context = useContext9(MapContext);
1676
+ if (!context) {
1677
+ throw new Error("DrawControl must be used within a Map component");
1678
+ }
1679
+ const options = useMemo9(
1680
+ () => ({
1681
+ ...defaultDrawOptions,
1682
+ ...drawOptions,
1683
+ controls: {
1684
+ ...defaultDrawOptions.controls,
1685
+ ...drawOptions.controls
1686
+ }
1687
+ }),
1688
+ [
1689
+ drawOptions.displayControlsDefault,
1690
+ drawOptions.controls,
1691
+ drawOptions.styles,
1692
+ drawOptions.modes,
1693
+ drawOptions.defaultMode
1694
+ ]
1695
+ );
1696
+ const optionsKey = useMemo9(() => JSON.stringify(options), [options]);
1697
+ const callbacksRef = useRef8({
1698
+ onDrawCreate,
1699
+ onDrawDelete,
1700
+ onDrawUpdate,
1701
+ onDrawSelectionChange,
1702
+ onDrawModeChange,
1703
+ onDrawCombine,
1704
+ onDrawUncombine,
1705
+ onDrawRender
1706
+ });
1707
+ useEffect16(() => {
1708
+ callbacksRef.current = {
1709
+ onDrawCreate,
1710
+ onDrawDelete,
1711
+ onDrawUpdate,
1712
+ onDrawSelectionChange,
1713
+ onDrawModeChange,
1714
+ onDrawCombine,
1715
+ onDrawUncombine,
1716
+ onDrawRender
1717
+ };
1718
+ }, [
1719
+ onDrawCreate,
1720
+ onDrawDelete,
1721
+ onDrawUpdate,
1722
+ onDrawSelectionChange,
1723
+ onDrawModeChange,
1724
+ onDrawCombine,
1725
+ onDrawUncombine,
1726
+ onDrawRender
1727
+ ]);
1728
+ const ctrlRef = useRef8(null);
1729
+ const listenersRef = useRef8({});
1730
+ useEffect16(() => {
1731
+ const { map } = context;
1732
+ if (!map) return;
1733
+ const mapInstance = map.getMap();
1734
+ if (!mapInstance) return;
1735
+ const DrawClass = MapboxDraw;
1736
+ const resetCursorIfNeeded = () => {
1737
+ if (ctrlRef.current) {
1738
+ const currentMode = ctrlRef.current.getMode();
1739
+ if (currentMode === "simple_select") {
1740
+ mapInstance.getCanvas().style.cursor = "";
1741
+ }
1742
+ }
1743
+ };
1744
+ const handleCreate = (e) => {
1745
+ resetCursorIfNeeded();
1746
+ callbacksRef.current.onDrawCreate?.(e);
1747
+ };
1748
+ const handleUpdate = (e) => {
1749
+ resetCursorIfNeeded();
1750
+ callbacksRef.current.onDrawUpdate?.(e);
1751
+ };
1752
+ const handleDelete = (e) => {
1753
+ resetCursorIfNeeded();
1754
+ callbacksRef.current.onDrawDelete?.(e);
1755
+ };
1756
+ const handleSelectionChange = (e) => {
1757
+ resetCursorIfNeeded();
1758
+ callbacksRef.current.onDrawSelectionChange?.(e);
1759
+ };
1760
+ const handleModeChange = (e) => {
1761
+ resetCursorIfNeeded();
1762
+ callbacksRef.current.onDrawModeChange?.(e);
1763
+ };
1764
+ const handleCombine = (e) => {
1765
+ callbacksRef.current.onDrawCombine?.(e);
1766
+ };
1767
+ const handleUncombine = (e) => {
1768
+ callbacksRef.current.onDrawUncombine?.(e);
1769
+ };
1770
+ const handleRender = (e) => {
1771
+ callbacksRef.current.onDrawRender?.(e);
1772
+ };
1773
+ const ctrl = new DrawClass(options);
1774
+ ctrlRef.current = ctrl;
1775
+ map.addControl(ctrl, position);
1776
+ listenersRef.current = {
1777
+ handleCreate,
1778
+ handleUpdate,
1779
+ handleDelete,
1780
+ handleSelectionChange,
1781
+ handleModeChange,
1782
+ handleCombine,
1783
+ handleUncombine,
1784
+ handleRender
1785
+ };
1786
+ mapInstance.on("draw.create", handleCreate);
1787
+ mapInstance.on("draw.update", handleUpdate);
1788
+ mapInstance.on("draw.delete", handleDelete);
1789
+ mapInstance.on("draw.selectionchange", handleSelectionChange);
1790
+ mapInstance.on("draw.modechange", handleModeChange);
1791
+ mapInstance.on("draw.combine", handleCombine);
1792
+ mapInstance.on("draw.uncombine", handleUncombine);
1793
+ mapInstance.on("draw.render", handleRender);
1794
+ return () => {
1795
+ if (listenersRef.current.handleCreate) {
1796
+ mapInstance.off("draw.create", listenersRef.current.handleCreate);
1797
+ }
1798
+ if (listenersRef.current.handleUpdate) {
1799
+ mapInstance.off("draw.update", listenersRef.current.handleUpdate);
1800
+ }
1801
+ if (listenersRef.current.handleDelete) {
1802
+ mapInstance.off("draw.delete", listenersRef.current.handleDelete);
1803
+ }
1804
+ if (listenersRef.current.handleSelectionChange) {
1805
+ mapInstance.off("draw.selectionchange", listenersRef.current.handleSelectionChange);
1806
+ }
1807
+ if (listenersRef.current.handleModeChange) {
1808
+ mapInstance.off("draw.modechange", listenersRef.current.handleModeChange);
1809
+ }
1810
+ if (listenersRef.current.handleCombine) {
1811
+ mapInstance.off("draw.combine", listenersRef.current.handleCombine);
1812
+ }
1813
+ if (listenersRef.current.handleUncombine) {
1814
+ mapInstance.off("draw.uncombine", listenersRef.current.handleUncombine);
1815
+ }
1816
+ if (listenersRef.current.handleRender) {
1817
+ mapInstance.off("draw.render", listenersRef.current.handleRender);
1818
+ }
1819
+ if (ctrlRef.current && map.hasControl(ctrlRef.current)) {
1820
+ map.removeControl(ctrlRef.current);
1821
+ }
1822
+ ctrlRef.current = null;
1823
+ };
1824
+ }, [context, optionsKey, position]);
1825
+ return null;
1826
+ }
1827
+ var DrawControl = memo13(_DrawControl);
1828
+
1829
+ // src/components/globe-control.ts
1830
+ import { useEffect as useEffect17, memo as memo14, useRef as useRef9 } from "react";
1831
+ var GLOBE_SVG = `<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2">
1832
+ <circle cx="12" cy="12" r="9" fill="none"/>
1833
+ <path d="M12 21a9 9-9 0 0-9 9-9 0 0 9h0c2.2a8.2 2.3 5.1 5.8-5.5c-.4-.4-.5-.9-.5-1.5v-1.3c0-2.3 1.8-4.2 4-4.5V5.5c-1.8.5-3.5 2-4.5 2.8 0 5.2 2.3 5.2 5 0z"/>
1834
+ <path d="M12 3c-2.8 0-5.2 2.3-5.2 5h2c0-1.5.1-1.1.5-1.5L5.8 9 2.3 5.1 8.2 2c.4 0 .9-.5 1.5-.5h1.3c2.3 0 4.2-1.8 4.5-4h-2c0 1.5-1.8 3.5-4 4.5V21c2.8 0 5.2-2.3 5.2-5h-2c0 1.5-.1 1.1-.5 1.5L18.2 15 14.8l2.7-5.1c-.4 0-.9.5-1.5.5h-1.3c-2.3 0-4.2 1.8-4.5 4h2c0-1.5 1.8-3.5 4-4.5V3z"/>
1835
+ </svg>`;
1836
+ var MAP_SVG = `<svg viewBox="0 0 24 24" width="24" height="24" stroke="currentColor" stroke-width="2">
1837
+ <rect x="3" y="3" width="18" height="18" rx="2" fill="none"/>
1838
+ <path d="M3 9h18M3 15h18M9 3v18M15 3v18"/>
1839
+ </svg>`;
1840
+ var GlobeControlImpl = class {
1841
+ constructor(options, callbacks) {
1842
+ this._map = null;
1843
+ this._isGlobe = false;
1844
+ this._options = options;
1845
+ this._onProjectionChange = callbacks.onProjectionChange;
1846
+ this._container = document.createElement("div");
1847
+ this._container.className = "maplibregl-ctrl maplibregl-ctrl-group";
1848
+ this._button = this._createButton();
1849
+ this._container.appendChild(this._button);
1850
+ }
1851
+ _createButton() {
1852
+ const button = this._options.buttonElement || document.createElement("button");
1853
+ if (!this._options.buttonElement) {
1854
+ button.className = this._options.buttonClassName || "maplibregl-ctrl-globe";
1855
+ button.type = "button";
1856
+ button.title = this._options.buttonTitle || "Toggle Globe View";
1857
+ button.setAttribute("aria-label", "Toggle Globe View");
1858
+ button.innerHTML = this._isGlobe ? MAP_SVG : GLOBE_SVG;
1859
+ Object.assign(button.style, {
1860
+ padding: "5px",
1861
+ border: "none",
1862
+ background: "white",
1863
+ cursor: "pointer",
1864
+ borderRadius: "4px",
1865
+ display: "flex",
1866
+ alignItems: "center",
1867
+ justifyContent: "center",
1868
+ ...this._options.buttonStyle
1869
+ });
1870
+ }
1871
+ button.addEventListener("click", () => this._toggleGlobe());
1872
+ return button;
1873
+ }
1874
+ _toggleGlobe() {
1875
+ if (!this._map) return;
1876
+ this._isGlobe = !this._isGlobe;
1877
+ this._button.innerHTML = this._isGlobe ? MAP_SVG : GLOBE_SVG;
1878
+ this._button.title = this._isGlobe ? "Switch to Map View" : "Switch to Globe View";
1879
+ try {
1880
+ const projection = this._isGlobe ? { type: "globe" } : { type: "mercator" };
1881
+ this._map.setProjection(projection);
1882
+ this._onProjectionChange?.(this._isGlobe);
1883
+ } catch (error) {
1884
+ console.warn("GlobeControl: setProjection not available", error);
1885
+ }
1886
+ }
1887
+ onAdd(map) {
1888
+ this._map = map;
1889
+ try {
1890
+ const currentProjection = map.getProjection?.();
1891
+ this._isGlobe = currentProjection?.type === "globe";
1892
+ this._button.innerHTML = this._isGlobe ? MAP_SVG : GLOBE_SVG;
1893
+ } catch {
1894
+ this._isGlobe = false;
1895
+ }
1896
+ return this._container;
1897
+ }
1898
+ onRemove() {
1899
+ this._container.parentNode?.removeChild(this._container);
1900
+ this._map = null;
1901
+ }
1902
+ /**
1903
+ * Check if currently in globe view
1904
+ */
1905
+ isGlobe() {
1906
+ return this._isGlobe;
1907
+ }
1908
+ /**
1909
+ * Set the projection programmatically
1910
+ */
1911
+ setGlobe(isGlobe) {
1912
+ if (this._isGlobe !== isGlobe) {
1913
+ this._toggleGlobe();
1914
+ }
1915
+ }
1916
+ };
1917
+ function _GlobeControl(props) {
1918
+ const { position, onProjectionChange, ...options } = props;
1919
+ const callbacksRef = useRef9({ onProjectionChange });
1920
+ useEffect17(() => {
1921
+ callbacksRef.current = { onProjectionChange };
1922
+ }, [onProjectionChange]);
1923
+ useControl(
1924
+ () => {
1925
+ return new GlobeControlImpl(options, {
1926
+ onProjectionChange: (isGlobe) => callbacksRef.current.onProjectionChange?.(isGlobe)
1927
+ });
1928
+ },
1929
+ { position }
1930
+ );
1931
+ return null;
1932
+ }
1933
+ var GlobeControl = memo14(_GlobeControl);
1934
+
1935
+ // src/components/minimap-control.ts
1936
+ import { memo as memo15 } from "react";
1937
+ import {
1938
+ Map as Map2
1939
+ } from "maplibre-gl";
1940
+ var DEFAULT_ZOOM_ADJUST = -4;
1941
+ var DEFAULT_COLLAPSED_SIZE = "29px";
1942
+ var DEFAULT_BORDER_RADIUS = "3px";
1943
+ var TRANSITION_DURATION_MS = 600;
1944
+ var RESIZE_DEBOUNCE_MS = 100;
1945
+ var DEFAULT_WIDTH = "400px";
1946
+ var DEFAULT_HEIGHT = "300px";
1947
+ var defaultInteractions = {
1948
+ dragPan: true,
1949
+ scrollZoom: false,
1950
+ boxZoom: false,
1951
+ dragRotate: false,
1952
+ keyboard: false,
1953
+ doubleClickZoom: false,
1954
+ touchZoomRotate: false
1955
+ };
1956
+ var DEFAULT_ICON = `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17.6 18L8 8.4V17H6V5h12v2H9.4l9.6 9.6l-1.4 1.4Z" /></svg>`;
1957
+ function getRandomUUID() {
1958
+ if (typeof crypto !== "undefined" && crypto.randomUUID) {
1959
+ return crypto.randomUUID();
1960
+ }
1961
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
1962
+ const array = new Uint8Array(1);
1963
+ crypto.getRandomValues(array);
1964
+ const r = array[0] % 16;
1965
+ const v = c === "x" ? r : r & 3 | 8;
1966
+ return v.toString(16);
1967
+ });
1968
+ }
1969
+ function sanitizeSVG(svgString) {
1970
+ const svgPattern = /^<svg[^>]*>[\s\S]*<\/svg>$/i;
1971
+ if (!svgPattern.test(svgString)) {
1972
+ console.warn("Invalid SVG format, using default icon");
1973
+ return DEFAULT_ICON;
1974
+ }
1975
+ return svgString.replace(/<script[\s\S]*?<\/script>/gi, "").replace(/\s*on\w+\s*=\s*["'][^"']*["']/gi, "").replace(/javascript:/gi, "");
1976
+ }
1977
+ var Minimap = class {
1978
+ constructor(options = {}) {
1979
+ this.differentStyle = false;
1980
+ this.isMinimized = false;
1981
+ this.id = `minimap-${getRandomUUID()}`;
1982
+ if (options.style !== void 0) {
1983
+ this.differentStyle = true;
1984
+ }
1985
+ const interactions = { ...defaultInteractions, ...options.interactions ?? {} };
1986
+ const containerStyle = this.validateContainerStyle(options.containerStyle);
1987
+ this.options = {
1988
+ zoomAdjust: DEFAULT_ZOOM_ADJUST,
1989
+ position: "top-right",
1990
+ pitchAdjust: false,
1991
+ attributionControl: false,
1992
+ logoPosition: "bottom-left",
1993
+ toggleable: true,
1994
+ initialMinimized: false,
1995
+ collapsedWidth: DEFAULT_COLLAPSED_SIZE,
1996
+ collapsedHeight: DEFAULT_COLLAPSED_SIZE,
1997
+ borderRadius: DEFAULT_BORDER_RADIUS,
1998
+ hideText: "Hide minimap",
1999
+ showText: "Show minimap",
2000
+ responsive: true,
2001
+ responsiveWidth: "20vw",
2002
+ responsiveHeight: "20vh",
2003
+ minWidth: "200px",
2004
+ minHeight: "150px",
2005
+ maxWidth: DEFAULT_WIDTH,
2006
+ maxHeight: DEFAULT_HEIGHT,
2007
+ interactions,
2008
+ ...options,
2009
+ containerStyle
2010
+ };
2011
+ if (options.lockZoom !== void 0) {
2012
+ this.options.minZoom = options.lockZoom;
2013
+ this.options.maxZoom = options.lockZoom;
2014
+ }
2015
+ this.isMinimized = this.options.initialMinimized ?? false;
2016
+ }
2017
+ onAdd(parentMap) {
2018
+ this.parentMap = parentMap;
2019
+ this.container = this.createContainer();
2020
+ this.options.container = this.container;
2021
+ this.options.zoom = parentMap.getZoom() + (this.options.zoomAdjust ?? DEFAULT_ZOOM_ADJUST);
2022
+ this.options.center ??= parentMap.getCenter().toArray();
2023
+ this.options.bearing = parentMap.getBearing();
2024
+ this.options.pitch = this.options.pitchAdjust ? parentMap.getPitch() : 0;
2025
+ if (!this.differentStyle) {
2026
+ this.options.style = parentMap.getStyle();
2027
+ }
2028
+ this.map = new Map2(this.options);
2029
+ this.map.once("style.load", () => {
2030
+ this.map.resize();
2031
+ });
2032
+ this.map.once("load", () => {
2033
+ this.configureInteractions();
2034
+ this.addParentRect(this.options.parentRect);
2035
+ this.desync = this.syncMaps();
2036
+ this.setupToggleButton();
2037
+ this.setupResponsiveSizing();
2038
+ });
2039
+ return this.container;
2040
+ }
2041
+ onRemove() {
2042
+ if (this.resizeHandler) {
2043
+ window.removeEventListener("resize", this.resizeHandler);
2044
+ this.resizeHandler = void 0;
2045
+ }
2046
+ this.toggleButtonCleanup?.();
2047
+ this.desync?.();
2048
+ this.container.remove();
2049
+ }
2050
+ createContainer() {
2051
+ const container = document.createElement("div");
2052
+ container.id = this.id;
2053
+ container.className = "maplibregl-ctrl maplibregl-ctrl-group maplibregl-ctrl-minimap custom-ctrl-minimap";
2054
+ if (this.isMinimized) {
2055
+ container.classList.add("minimized");
2056
+ }
2057
+ const styleEl = document.createElement("style");
2058
+ styleEl.innerHTML = this.getContainerStyles();
2059
+ container.appendChild(styleEl);
2060
+ if (this.options.containerStyle) {
2061
+ for (const [key, value] of Object.entries(this.options.containerStyle)) {
2062
+ container.style.setProperty(key, value);
2063
+ }
2064
+ }
2065
+ if (this.isMinimized) {
2066
+ container.style.width = this.options.collapsedWidth || DEFAULT_COLLAPSED_SIZE;
2067
+ container.style.height = this.options.collapsedHeight || DEFAULT_COLLAPSED_SIZE;
2068
+ }
2069
+ const preventDefault = (e) => e.preventDefault();
2070
+ container.addEventListener("contextmenu", preventDefault);
2071
+ return container;
2072
+ }
2073
+ getContainerStyles() {
2074
+ const width = this.options.containerStyle?.width || DEFAULT_WIDTH;
2075
+ const height = this.options.containerStyle?.height || DEFAULT_HEIGHT;
2076
+ const collapsedWidth = this.options.collapsedWidth || DEFAULT_COLLAPSED_SIZE;
2077
+ const collapsedHeight = this.options.collapsedHeight || DEFAULT_COLLAPSED_SIZE;
2078
+ const borderRadius = this.options.borderRadius || DEFAULT_BORDER_RADIUS;
2079
+ return `
2080
+ #${this.id}.custom-ctrl-minimap {
2081
+ cursor: default !important;
2082
+ box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
2083
+ transition: width 0.6s ease-in, height 0.6s ease-in, border-color 0s ease-in;
2084
+ border-style: solid;
2085
+ border-radius: ${borderRadius};
2086
+ border-width: 4px;
2087
+ border-color: white;
2088
+ width: ${width};
2089
+ height: ${height};
2090
+ overflow: hidden;
2091
+ background: #fff;
2092
+ position: relative;
2093
+ }
2094
+ #${this.id}.minimized {
2095
+ border-radius: 3px !important;
2096
+ width: ${collapsedWidth};
2097
+ height: ${collapsedHeight};
2098
+ }
2099
+ #${this.id} canvas {
2100
+ width: 100% !important;
2101
+ height: 100% !important;
2102
+ display: block;
2103
+ }
2104
+ @media (prefers-color-scheme: dark) {
2105
+ #${this.id}.custom-ctrl-minimap {
2106
+ border-color: hsl(0, 0%, 15.2%);
2107
+ }
2108
+ }
2109
+ `;
2110
+ }
2111
+ validateContainerStyle(style) {
2112
+ const defaults = { border: "1px solid #000", width: DEFAULT_WIDTH, height: DEFAULT_HEIGHT };
2113
+ if (!style) return defaults;
2114
+ const validated = {};
2115
+ if (style.width) {
2116
+ validated.width = CSS.supports("width", style.width) ? style.width : defaults.width;
2117
+ } else {
2118
+ validated.width = defaults.width;
2119
+ }
2120
+ if (style.height) {
2121
+ validated.height = CSS.supports("height", style.height) ? style.height : defaults.height;
2122
+ } else {
2123
+ validated.height = defaults.height;
2124
+ }
2125
+ for (const [key, value] of Object.entries(style)) {
2126
+ if (key !== "width" && key !== "height") {
2127
+ validated[key] = value;
2128
+ }
2129
+ }
2130
+ return validated;
2131
+ }
2132
+ configureInteractions() {
2133
+ const interactions = this.options.interactions || defaultInteractions;
2134
+ for (const [interaction, enabled] of Object.entries(interactions)) {
2135
+ if (!enabled) {
2136
+ const interactionMethod = interaction;
2137
+ const interactionObj = this.map[interactionMethod];
2138
+ interactionObj?.disable();
2139
+ }
2140
+ }
2141
+ }
2142
+ setupToggleButton() {
2143
+ if (!this.options.toggleable) return;
2144
+ const el = document.createElement("button");
2145
+ const elId = "btn-" + getRandomUUID();
2146
+ el.innerHTML = sanitizeSVG(this.options.toggleButton?.icon || DEFAULT_ICON);
2147
+ el.setAttribute("id", elId);
2148
+ el.setAttribute("type", "button");
2149
+ el.setAttribute("aria-label", this.options.hideText || "Hide minimap");
2150
+ el.setAttribute("title", this.options.hideText || "Hide minimap");
2151
+ if (this.options.toggleButton?.className) {
2152
+ const classes = this.options.toggleButton.className.split(" ");
2153
+ classes.forEach((cls) => el.classList.add(cls));
2154
+ }
2155
+ const iconBackgroundColor = this.options.toggleButton?.iconBackgroundColor || "black";
2156
+ const hoverColor = this.options.toggleButton?.hoverColor || "#e5e7e3";
2157
+ const styleEl = document.createElement("style");
2158
+ styleEl.innerHTML = `
2159
+ button#${elId} {
2160
+ border-radius: 0 !important;
2161
+ color: black;
2162
+ background-color: ${iconBackgroundColor};
2163
+ border: none;
2164
+ display: flex;
2165
+ align-items: center;
2166
+ justify-content: center;
2167
+ cursor: pointer;
2168
+ transition: all 0.2s ease-in;
2169
+ position: absolute;
2170
+ width: 24px;
2171
+ height: 24px;
2172
+ z-index: 2;
2173
+ padding: 0;
2174
+ left: 0;
2175
+ top: 0;
2176
+ }
2177
+ button#${elId}:hover {
2178
+ background-color: ${hoverColor} !important;
2179
+ }
2180
+ button#${elId} svg {
2181
+ fill: white;
2182
+ width: 16px;
2183
+ height: 16px;
2184
+ }
2185
+ .minimized > button#${elId} > * {
2186
+ transform: rotate(-180deg);
2187
+ }
2188
+ `;
2189
+ const clickHandler = () => {
2190
+ this.toggle();
2191
+ const minimized = this.container.classList.contains("minimized");
2192
+ const text = minimized ? this.options.showText || "Show minimap" : this.options.hideText || "Hide minimap";
2193
+ el.setAttribute("aria-label", text);
2194
+ el.setAttribute("title", text);
2195
+ };
2196
+ el.addEventListener("click", clickHandler);
2197
+ document.head.appendChild(styleEl);
2198
+ this.container.appendChild(el);
2199
+ this.toggleButtonCleanup = () => {
2200
+ el.removeEventListener("click", clickHandler);
2201
+ styleEl.remove();
2202
+ this.container.removeChild(el);
2203
+ };
2204
+ }
2205
+ setupResponsiveSizing() {
2206
+ if (!this.options.responsive) return;
2207
+ const updateSize = () => {
2208
+ if (this.isMinimized) return;
2209
+ const vw = window.innerWidth / 100;
2210
+ const vh = window.innerHeight / 100;
2211
+ const responsiveWidth = this.options.responsiveWidth || "20vw";
2212
+ const responsiveHeight = this.options.responsiveHeight || "20vh";
2213
+ let width;
2214
+ let height;
2215
+ if (responsiveWidth.endsWith("vw")) {
2216
+ width = parseFloat(responsiveWidth) * vw;
2217
+ } else if (responsiveWidth.endsWith("%")) {
2218
+ width = parseFloat(responsiveWidth) / 100 * window.innerWidth;
2219
+ } else {
2220
+ width = parseFloat(responsiveWidth);
2221
+ }
2222
+ if (responsiveHeight.endsWith("vh")) {
2223
+ height = parseFloat(responsiveHeight) * vh;
2224
+ } else if (responsiveHeight.endsWith("%")) {
2225
+ height = parseFloat(responsiveHeight) / 100 * window.innerHeight;
2226
+ } else {
2227
+ height = parseFloat(responsiveHeight);
2228
+ }
2229
+ const minW = parseFloat(this.options.minWidth || "200px");
2230
+ const minH = parseFloat(this.options.minHeight || "150px");
2231
+ const maxW = parseFloat(this.options.maxWidth || DEFAULT_WIDTH);
2232
+ const maxH = parseFloat(this.options.maxHeight || DEFAULT_HEIGHT);
2233
+ width = Math.max(minW, Math.min(maxW, width));
2234
+ height = Math.max(minH, Math.min(maxH, height));
2235
+ this.container.style.width = `${width}px`;
2236
+ this.container.style.height = `${height}px`;
2237
+ this.map.resize();
2238
+ this.setParentBounds();
2239
+ };
2240
+ updateSize();
2241
+ let resizeTimeout;
2242
+ this.resizeHandler = () => {
2243
+ clearTimeout(resizeTimeout);
2244
+ resizeTimeout = setTimeout(updateSize, RESIZE_DEBOUNCE_MS);
2245
+ };
2246
+ window.addEventListener("resize", this.resizeHandler);
2247
+ }
2248
+ toggle() {
2249
+ this.isMinimized = !this.isMinimized;
2250
+ const collapsedWidth = this.options.collapsedWidth || DEFAULT_COLLAPSED_SIZE;
2251
+ const collapsedHeight = this.options.collapsedHeight || DEFAULT_COLLAPSED_SIZE;
2252
+ if (this.isMinimized) {
2253
+ this.container.classList.add("minimized");
2254
+ this.container.style.width = collapsedWidth;
2255
+ this.container.style.height = collapsedHeight;
2256
+ } else {
2257
+ this.container.classList.remove("minimized");
2258
+ if (this.options.responsive && this.resizeHandler) {
2259
+ this.resizeHandler();
2260
+ } else {
2261
+ const expandedWidth = this.options.containerStyle?.width || DEFAULT_WIDTH;
2262
+ const expandedHeight = this.options.containerStyle?.height || DEFAULT_HEIGHT;
2263
+ this.container.style.width = expandedWidth;
2264
+ this.container.style.height = expandedHeight;
2265
+ }
2266
+ }
2267
+ this.options.onToggle?.(this.isMinimized);
2268
+ setTimeout(() => {
2269
+ this.map.resize();
2270
+ this.setParentBounds();
2271
+ }, TRANSITION_DURATION_MS);
2272
+ }
2273
+ isMinimizedState() {
2274
+ return this.isMinimized;
2275
+ }
2276
+ addParentRect(rect) {
2277
+ if (rect === void 0 || rect.linePaint === void 0 && rect.fillPaint === void 0) {
2278
+ return;
2279
+ }
2280
+ this.parentRect = {
2281
+ type: "Feature",
2282
+ properties: { name: "parentRect" },
2283
+ geometry: {
2284
+ type: "Polygon",
2285
+ coordinates: [[[], [], [], [], []]]
2286
+ }
2287
+ };
2288
+ this.map.addSource("parentRect", {
2289
+ type: "geojson",
2290
+ data: this.parentRect
2291
+ });
2292
+ if (rect.lineLayout !== void 0 || rect.linePaint !== void 0) {
2293
+ this.map.addLayer({
2294
+ id: "parentRectOutline",
2295
+ type: "line",
2296
+ source: "parentRect",
2297
+ layout: { ...rect.lineLayout || {} },
2298
+ paint: {
2299
+ "line-color": "#FFF",
2300
+ "line-width": 1,
2301
+ "line-opacity": 0.85,
2302
+ ...rect.linePaint || {}
2303
+ }
2304
+ });
2305
+ }
2306
+ if (rect.fillPaint !== void 0) {
2307
+ this.map.addLayer({
2308
+ id: "parentRectFill",
2309
+ type: "fill",
2310
+ source: "parentRect",
2311
+ layout: {},
2312
+ paint: {
2313
+ "fill-color": "#08F",
2314
+ "fill-opacity": 0.135,
2315
+ ...rect.fillPaint || {}
2316
+ }
2317
+ });
2318
+ }
2319
+ this.setParentBounds();
2320
+ }
2321
+ setParentBounds() {
2322
+ if (this.parentRect === void 0 || this.isMinimized) return;
2323
+ const { devicePixelRatio } = window;
2324
+ const canvas = this.parentMap.getCanvas();
2325
+ const width = canvas.width / devicePixelRatio;
2326
+ const height = canvas.height / devicePixelRatio;
2327
+ const unproject = this.parentMap.unproject.bind(this.parentMap);
2328
+ const northWest = unproject([0, 0]);
2329
+ const northEast = unproject([width, 0]);
2330
+ const southWest = unproject([0, height]);
2331
+ const southEast = unproject([width, height]);
2332
+ this.parentRect.geometry.coordinates = [
2333
+ [
2334
+ southWest.toArray(),
2335
+ southEast.toArray(),
2336
+ northEast.toArray(),
2337
+ northWest.toArray(),
2338
+ southWest.toArray()
2339
+ ]
2340
+ ];
2341
+ const source = this.map.getSource("parentRect");
2342
+ if (source !== void 0) {
2343
+ source.setData(this.parentRect);
2344
+ }
2345
+ }
2346
+ syncMaps() {
2347
+ const { pitchAdjust } = this.options;
2348
+ const parentCallback = () => {
2349
+ if (!this.isMinimized) {
2350
+ sync("parent");
2351
+ }
2352
+ };
2353
+ const minimapCallback = () => {
2354
+ if (!this.isMinimized) {
2355
+ sync("minimap");
2356
+ }
2357
+ };
2358
+ const on = () => {
2359
+ this.parentMap.on("move", parentCallback);
2360
+ this.map.on("move", minimapCallback);
2361
+ };
2362
+ const off = () => {
2363
+ this.parentMap.off("move", parentCallback);
2364
+ this.map.off("move", minimapCallback);
2365
+ };
2366
+ const sync = (which) => {
2367
+ off();
2368
+ const from = which === "parent" ? this.parentMap : this.map;
2369
+ const to = which === "parent" ? this.map : this.parentMap;
2370
+ const center = from.getCenter();
2371
+ const zoom = from.getZoom() + (this.options.zoomAdjust ?? DEFAULT_ZOOM_ADJUST) * (which === "parent" ? 1 : -1);
2372
+ const bearing = from.getBearing();
2373
+ const pitch = from.getPitch();
2374
+ to.jumpTo({
2375
+ center,
2376
+ zoom,
2377
+ bearing,
2378
+ pitch: pitchAdjust ? pitch : 0
2379
+ });
2380
+ this.setParentBounds();
2381
+ on();
2382
+ };
2383
+ on();
2384
+ return () => {
2385
+ off();
2386
+ };
2387
+ }
2388
+ };
2389
+ function _MinimapControl(props) {
2390
+ const { position, ...options } = props;
2391
+ useControl(() => new Minimap(options), { position });
2392
+ return null;
2393
+ }
2394
+ var MinimapControl = memo15(_MinimapControl);
2395
+
2396
+ // src/exports-maplibre-gl.ts
2397
+ var exports_maplibre_gl_default = Map;
2398
+ export {
2399
+ AttributionControl,
2400
+ CanvasSource,
2401
+ DrawControl,
2402
+ FullscreenControl,
2403
+ GeolocateControl,
2404
+ GlobeControl,
2405
+ Layer,
2406
+ LogoControl,
2407
+ Map,
2408
+ MapProvider,
2409
+ Marker,
2410
+ Minimap,
2411
+ MinimapControl,
2412
+ NavigationControl,
2413
+ Popup,
2414
+ ScaleControl,
2415
+ Source,
2416
+ TerrainControl,
2417
+ exports_maplibre_gl_default as default,
2418
+ useControl,
2419
+ useMap
2420
+ };
3
2421
  //# sourceMappingURL=index.js.map