react-bkoi-gl 2.0.1 → 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.
- package/README.md +1420 -176
- package/dist/index.cjs +1181 -174
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +548 -48
- package/dist/index.d.ts +548 -48
- package/dist/index.js +1189 -203
- package/dist/index.js.map +1 -1
- package/dist/styles/react-bkoi-gl.css +95 -1
- package/package.json +28 -8
package/dist/index.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
// src/components/map.tsx
|
|
2
2
|
import * as React2 from "react";
|
|
3
|
-
import {
|
|
4
|
-
useState as useState2,
|
|
5
|
-
useRef,
|
|
6
|
-
useEffect as useEffect5,
|
|
7
|
-
useContext as useContext3,
|
|
8
|
-
useMemo as useMemo3,
|
|
9
|
-
useImperativeHandle
|
|
10
|
-
} from "react";
|
|
3
|
+
import { useState as useState2, useRef, useEffect as useEffect5, useContext as useContext3, useMemo as useMemo3, useImperativeHandle } from "react";
|
|
11
4
|
|
|
12
5
|
// src/components/use-map.tsx
|
|
13
6
|
import * as React from "react";
|
|
@@ -52,7 +45,8 @@ function useMap() {
|
|
|
52
45
|
const maps = useContext(MountedMapsContext)?.maps;
|
|
53
46
|
const currentMap = useContext(MapContext);
|
|
54
47
|
const mapsWithCurrent = useMemo(() => {
|
|
55
|
-
|
|
48
|
+
const current = currentMap?.map || (maps ? Object.values(maps)[0] : void 0);
|
|
49
|
+
return { ...maps, current };
|
|
56
50
|
}, [maps, currentMap]);
|
|
57
51
|
return mapsWithCurrent;
|
|
58
52
|
}
|
|
@@ -138,15 +132,7 @@ function applyViewStateToTransform(tr, props) {
|
|
|
138
132
|
}
|
|
139
133
|
|
|
140
134
|
// src/utils/style-utils.ts
|
|
141
|
-
var refProps = [
|
|
142
|
-
"type",
|
|
143
|
-
"source",
|
|
144
|
-
"source-layer",
|
|
145
|
-
"minzoom",
|
|
146
|
-
"maxzoom",
|
|
147
|
-
"filter",
|
|
148
|
-
"layout"
|
|
149
|
-
];
|
|
135
|
+
var refProps = ["type", "source", "source-layer", "minzoom", "maxzoom", "filter", "layout"];
|
|
150
136
|
function normalizeStyle(style) {
|
|
151
137
|
if (!style) {
|
|
152
138
|
return null;
|
|
@@ -165,14 +151,15 @@ function normalizeStyle(style) {
|
|
|
165
151
|
layerIndex[layer.id] = layer;
|
|
166
152
|
}
|
|
167
153
|
const layers = style.layers.map((layer) => {
|
|
154
|
+
const legacyLayer = layer;
|
|
168
155
|
let normalizedLayer = null;
|
|
169
|
-
if ("interactive" in
|
|
170
|
-
normalizedLayer = Object.assign({},
|
|
156
|
+
if ("interactive" in legacyLayer) {
|
|
157
|
+
normalizedLayer = Object.assign({}, legacyLayer);
|
|
171
158
|
delete normalizedLayer.interactive;
|
|
172
159
|
}
|
|
173
|
-
const layerRef = layerIndex[
|
|
160
|
+
const layerRef = layerIndex[legacyLayer.ref];
|
|
174
161
|
if (layerRef) {
|
|
175
|
-
normalizedLayer = normalizedLayer || Object.assign({},
|
|
162
|
+
normalizedLayer = normalizedLayer || Object.assign({}, legacyLayer);
|
|
176
163
|
delete normalizedLayer.ref;
|
|
177
164
|
for (const propName of refProps) {
|
|
178
165
|
if (propName in layerRef) {
|
|
@@ -268,7 +255,8 @@ var Maplibre = class _Maplibre {
|
|
|
268
255
|
this._propsedCameraUpdate = null;
|
|
269
256
|
this._styleComponents = {};
|
|
270
257
|
this._onEvent = (e) => {
|
|
271
|
-
const
|
|
258
|
+
const handlerName = otherEvents[e.type];
|
|
259
|
+
const cb = this.props[handlerName];
|
|
272
260
|
if (cb) {
|
|
273
261
|
cb(e);
|
|
274
262
|
} else if (e.type === "error") {
|
|
@@ -280,7 +268,8 @@ var Maplibre = class _Maplibre {
|
|
|
280
268
|
return;
|
|
281
269
|
}
|
|
282
270
|
e.viewState = this._propsedCameraUpdate || transformToViewState(this._map.transform);
|
|
283
|
-
const
|
|
271
|
+
const handlerName = cameraEvents[e.type];
|
|
272
|
+
const cb = this.props[handlerName];
|
|
284
273
|
if (cb) {
|
|
285
274
|
cb(e);
|
|
286
275
|
}
|
|
@@ -296,7 +285,8 @@ var Maplibre = class _Maplibre {
|
|
|
296
285
|
if (e.type === "mousemove" || e.type === "mouseout") {
|
|
297
286
|
this._updateHover(e);
|
|
298
287
|
}
|
|
299
|
-
const
|
|
288
|
+
const handlerName = pointerEvents[e.type];
|
|
289
|
+
const cb = this.props[handlerName];
|
|
300
290
|
if (cb) {
|
|
301
291
|
if (this.props.interactiveLayerIds && e.type !== "mouseover" && e.type !== "mouseout") {
|
|
302
292
|
e.features = this._hoveredFeatures || this._queryRenderedFeatures(e.point);
|
|
@@ -310,7 +300,6 @@ var Maplibre = class _Maplibre {
|
|
|
310
300
|
this._initialize(container);
|
|
311
301
|
}
|
|
312
302
|
static {
|
|
313
|
-
// eslint-disable-next-line no-use-before-define
|
|
314
303
|
this.savedMaps = [];
|
|
315
304
|
}
|
|
316
305
|
get map() {
|
|
@@ -340,8 +329,9 @@ var Maplibre = class _Maplibre {
|
|
|
340
329
|
while (oldContainer.childNodes.length > 0) {
|
|
341
330
|
container.appendChild(oldContainer.childNodes[0]);
|
|
342
331
|
}
|
|
343
|
-
|
|
344
|
-
|
|
332
|
+
const mapInternal = map;
|
|
333
|
+
mapInternal._container = container;
|
|
334
|
+
const resizeObserver = mapInternal._resizeObserver;
|
|
345
335
|
if (resizeObserver) {
|
|
346
336
|
resizeObserver.disconnect();
|
|
347
337
|
resizeObserver.observe(container);
|
|
@@ -364,10 +354,10 @@ var Maplibre = class _Maplibre {
|
|
|
364
354
|
} else {
|
|
365
355
|
map.once("style.load", () => map.fire("load"));
|
|
366
356
|
}
|
|
367
|
-
map
|
|
357
|
+
const mapInternalForUpdate = map;
|
|
358
|
+
mapInternalForUpdate._update();
|
|
368
359
|
return that;
|
|
369
360
|
}
|
|
370
|
-
/* eslint-disable complexity,max-statements */
|
|
371
361
|
_initialize(container) {
|
|
372
362
|
const { props } = this;
|
|
373
363
|
const { mapStyle = DEFAULT_STYLE } = props;
|
|
@@ -400,11 +390,11 @@ var Maplibre = class _Maplibre {
|
|
|
400
390
|
}
|
|
401
391
|
map.transformCameraUpdate = this._onCameraUpdate;
|
|
402
392
|
map.on("style.load", () => {
|
|
393
|
+
const mapWithProjection = map;
|
|
403
394
|
this._styleComponents = {
|
|
404
395
|
light: map.getLight(),
|
|
405
396
|
sky: map.getSky(),
|
|
406
|
-
|
|
407
|
-
projection: map.getProjection?.(),
|
|
397
|
+
projection: mapWithProjection.getProjection?.(),
|
|
408
398
|
terrain: map.getTerrain()
|
|
409
399
|
};
|
|
410
400
|
this._updateStyleComponents(this.props);
|
|
@@ -423,7 +413,6 @@ var Maplibre = class _Maplibre {
|
|
|
423
413
|
}
|
|
424
414
|
this._map = map;
|
|
425
415
|
}
|
|
426
|
-
/* eslint-enable complexity,max-statements */
|
|
427
416
|
recycle() {
|
|
428
417
|
const container = this.map.getContainer();
|
|
429
418
|
const children = container.querySelector("[mapboxgl-children]");
|
|
@@ -520,14 +509,10 @@ var Maplibre = class _Maplibre {
|
|
|
520
509
|
* 1. They can not be applied right away. Certain conditions (style loaded, source loaded, etc.) must be met
|
|
521
510
|
* 2. They can be overwritten by mapStyle
|
|
522
511
|
*/
|
|
523
|
-
_updateStyleComponents({
|
|
524
|
-
light,
|
|
525
|
-
projection,
|
|
526
|
-
sky,
|
|
527
|
-
terrain
|
|
528
|
-
}) {
|
|
512
|
+
_updateStyleComponents({ light, projection, sky, terrain }) {
|
|
529
513
|
const map = this._map;
|
|
530
514
|
const currProps = this._styleComponents;
|
|
515
|
+
const mapWithProjection = map;
|
|
531
516
|
if (map.style._loaded) {
|
|
532
517
|
if (light && !deepEqual(light, currProps.light)) {
|
|
533
518
|
currProps.light = light;
|
|
@@ -535,7 +520,7 @@ var Maplibre = class _Maplibre {
|
|
|
535
520
|
}
|
|
536
521
|
if (projection && !deepEqual(projection, currProps.projection) && projection !== currProps.projection?.type) {
|
|
537
522
|
currProps.projection = typeof projection === "string" ? { type: projection } : projection;
|
|
538
|
-
|
|
523
|
+
mapWithProjection.setProjection?.(currProps.projection);
|
|
539
524
|
}
|
|
540
525
|
if (sky && !deepEqual(sky, currProps.sky)) {
|
|
541
526
|
currProps.sky = sky;
|
|
@@ -657,19 +642,34 @@ var useIsomorphicLayoutEffect = typeof document !== "undefined" ? useLayoutEffec
|
|
|
657
642
|
var use_isomorphic_layout_effect_default = useIsomorphicLayoutEffect;
|
|
658
643
|
|
|
659
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
|
+
};
|
|
660
658
|
function setGlobals(mapLib, props) {
|
|
661
659
|
const { RTLTextPlugin, maxParallelImageRequests, workerCount, workerUrl } = props;
|
|
662
660
|
if (RTLTextPlugin && mapLib.getRTLTextPluginStatus && mapLib.getRTLTextPluginStatus() === "unavailable") {
|
|
663
661
|
const { pluginUrl, lazy = true } = typeof RTLTextPlugin === "string" ? { pluginUrl: RTLTextPlugin } : RTLTextPlugin;
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
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
673
|
}
|
|
674
674
|
if (maxParallelImageRequests !== void 0) {
|
|
675
675
|
mapLib.setMaxParallelImageRequests(maxParallelImageRequests);
|
|
@@ -678,7 +678,9 @@ function setGlobals(mapLib, props) {
|
|
|
678
678
|
mapLib.setWorkerCount(workerCount);
|
|
679
679
|
}
|
|
680
680
|
if (workerUrl !== void 0) {
|
|
681
|
-
|
|
681
|
+
if (validateUrl(workerUrl, "workerUrl")) {
|
|
682
|
+
mapLib.setWorkerUrl(workerUrl);
|
|
683
|
+
}
|
|
682
684
|
}
|
|
683
685
|
}
|
|
684
686
|
|
|
@@ -706,14 +708,18 @@ function applyReactStyle(element, styles) {
|
|
|
706
708
|
import { useContext as useContext2, useMemo as useMemo2, useEffect as useEffect2 } from "react";
|
|
707
709
|
function useControl(onCreate, arg1, arg2, arg3) {
|
|
708
710
|
const context = useContext2(MapContext);
|
|
711
|
+
if (!context) {
|
|
712
|
+
throw new Error("useControl must be used within a Map component");
|
|
713
|
+
}
|
|
709
714
|
const ctrl = useMemo2(() => onCreate(context), []);
|
|
710
715
|
useEffect2(() => {
|
|
711
716
|
const opts = arg3 || arg2 || arg1;
|
|
712
717
|
const onAdd = typeof arg1 === "function" && typeof arg2 === "function" ? arg1 : null;
|
|
713
718
|
const onRemove = typeof arg2 === "function" ? arg2 : typeof arg1 === "function" ? arg1 : null;
|
|
714
719
|
const { map } = context;
|
|
715
|
-
|
|
716
|
-
|
|
720
|
+
const ctrlAsIControl = ctrl;
|
|
721
|
+
if (!map.hasControl(ctrlAsIControl)) {
|
|
722
|
+
map.addControl(ctrlAsIControl, opts?.position);
|
|
717
723
|
if (onAdd) {
|
|
718
724
|
onAdd(context);
|
|
719
725
|
}
|
|
@@ -722,8 +728,8 @@ function useControl(onCreate, arg1, arg2, arg3) {
|
|
|
722
728
|
if (onRemove) {
|
|
723
729
|
onRemove(context);
|
|
724
730
|
}
|
|
725
|
-
if (map.hasControl(
|
|
726
|
-
map.removeControl(
|
|
731
|
+
if (map.hasControl(ctrlAsIControl)) {
|
|
732
|
+
map.removeControl(ctrlAsIControl);
|
|
727
733
|
}
|
|
728
734
|
};
|
|
729
735
|
}, []);
|
|
@@ -783,11 +789,24 @@ function _AttributionControl(props) {
|
|
|
783
789
|
if (!ctrl._container || !map) return;
|
|
784
790
|
const onLoad = () => {
|
|
785
791
|
setTimeout(() => {
|
|
786
|
-
const inner = ctrl._container.querySelector(
|
|
787
|
-
".maplibregl-ctrl-attrib-inner"
|
|
788
|
-
);
|
|
792
|
+
const inner = ctrl._container.querySelector(".maplibregl-ctrl-attrib-inner");
|
|
789
793
|
if (inner) {
|
|
790
|
-
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
|
+
);
|
|
791
810
|
}
|
|
792
811
|
}, 0);
|
|
793
812
|
};
|
|
@@ -817,7 +836,7 @@ function _Map(props, ref) {
|
|
|
817
836
|
useEffect5(() => {
|
|
818
837
|
const mapLib = props.mapLib;
|
|
819
838
|
let isMounted = true;
|
|
820
|
-
let maplibre;
|
|
839
|
+
let maplibre = null;
|
|
821
840
|
Promise.resolve(mapLib || import("maplibre-gl")).then((module) => {
|
|
822
841
|
if (!isMounted) {
|
|
823
842
|
return;
|
|
@@ -838,15 +857,16 @@ function _Map(props, ref) {
|
|
|
838
857
|
mapboxgl.Map,
|
|
839
858
|
{
|
|
840
859
|
...props,
|
|
841
|
-
// @ts-ignore - attributionControl is not in the type definition but is supported by maplibre-gl
|
|
842
860
|
attributionControl: false
|
|
843
861
|
},
|
|
844
862
|
containerRef.current
|
|
845
863
|
);
|
|
846
864
|
}
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
865
|
+
if (maplibre) {
|
|
866
|
+
contextValue.map = createRef(maplibre);
|
|
867
|
+
contextValue.mapLib = mapboxgl;
|
|
868
|
+
setMapInstance(maplibre);
|
|
869
|
+
}
|
|
850
870
|
mountedMapsContext?.onMapMount(contextValue.map, props.id);
|
|
851
871
|
}).catch((error) => {
|
|
852
872
|
const { onError } = props;
|
|
@@ -891,7 +911,7 @@ function _Map(props, ref) {
|
|
|
891
911
|
const CHILD_CONTAINER_STYLE = {
|
|
892
912
|
height: "100%"
|
|
893
913
|
};
|
|
894
|
-
return /* @__PURE__ */ React2.createElement("div", { id: props.id, ref: containerRef, style }, mapInstance && /* @__PURE__ */ React2.createElement(MapContext.Provider, { value: contextValue }, /* @__PURE__ */ React2.createElement("div", {
|
|
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)));
|
|
895
915
|
}
|
|
896
916
|
var Map = React2.forwardRef(_Map);
|
|
897
917
|
|
|
@@ -936,7 +956,7 @@ function getClassList(className) {
|
|
|
936
956
|
var Marker = memo3(
|
|
937
957
|
forwardRef2((props, ref) => {
|
|
938
958
|
const { map, mapLib } = useContext4(MapContext);
|
|
939
|
-
const
|
|
959
|
+
const callbackRef = useRef2({});
|
|
940
960
|
const marker = useMemo4(() => {
|
|
941
961
|
let hasChildren = false;
|
|
942
962
|
React3.Children.forEach(props.children, (el) => {
|
|
@@ -950,33 +970,46 @@ var Marker = memo3(
|
|
|
950
970
|
};
|
|
951
971
|
const mk = new mapLib.Marker(options);
|
|
952
972
|
mk.setLngLat([props.longitude, props.latitude]);
|
|
953
|
-
mk.getElement().addEventListener("click", (e) => {
|
|
954
|
-
thisRef.current.props.onClick?.({
|
|
955
|
-
type: "click",
|
|
956
|
-
target: mk,
|
|
957
|
-
originalEvent: e
|
|
958
|
-
});
|
|
959
|
-
});
|
|
960
|
-
mk.on("dragstart", (e) => {
|
|
961
|
-
const evt = e;
|
|
962
|
-
evt.lngLat = marker.getLngLat();
|
|
963
|
-
thisRef.current.props.onDragStart?.(evt);
|
|
964
|
-
});
|
|
965
|
-
mk.on("drag", (e) => {
|
|
966
|
-
const evt = e;
|
|
967
|
-
evt.lngLat = marker.getLngLat();
|
|
968
|
-
thisRef.current.props.onDrag?.(evt);
|
|
969
|
-
});
|
|
970
|
-
mk.on("dragend", (e) => {
|
|
971
|
-
const evt = e;
|
|
972
|
-
evt.lngLat = marker.getLngLat();
|
|
973
|
-
thisRef.current.props.onDragEnd?.(evt);
|
|
974
|
-
});
|
|
975
973
|
return mk;
|
|
976
974
|
}, []);
|
|
977
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);
|
|
978
1007
|
marker.addTo(map.getMap());
|
|
979
1008
|
return () => {
|
|
1009
|
+
marker.getElement().removeEventListener("click", clickHandler);
|
|
1010
|
+
marker.off("dragstart", dragStartHandler);
|
|
1011
|
+
marker.off("drag", dragHandler);
|
|
1012
|
+
marker.off("dragend", dragEndHandler);
|
|
980
1013
|
marker.remove();
|
|
981
1014
|
};
|
|
982
1015
|
}, []);
|
|
@@ -989,82 +1022,76 @@ var Marker = memo3(
|
|
|
989
1022
|
popup = null,
|
|
990
1023
|
rotation = 0,
|
|
991
1024
|
rotationAlignment = "auto",
|
|
992
|
-
pitchAlignment = "auto"
|
|
1025
|
+
pitchAlignment = "auto",
|
|
1026
|
+
className
|
|
993
1027
|
} = props;
|
|
994
1028
|
useEffect6(() => {
|
|
995
1029
|
applyReactStyle(marker.getElement(), style);
|
|
996
1030
|
}, [style]);
|
|
997
1031
|
useImperativeHandle2(ref, () => marker, []);
|
|
998
|
-
const
|
|
999
|
-
|
|
1000
|
-
marker.
|
|
1001
|
-
|
|
1002
|
-
if (offset && !arePointsEqual(marker.getOffset(), offset)) {
|
|
1003
|
-
marker.setOffset(offset);
|
|
1004
|
-
}
|
|
1005
|
-
if (marker.isDraggable() !== draggable) {
|
|
1006
|
-
marker.setDraggable(draggable);
|
|
1007
|
-
}
|
|
1008
|
-
if (marker.getRotation() !== rotation) {
|
|
1009
|
-
marker.setRotation(rotation);
|
|
1010
|
-
}
|
|
1011
|
-
if (marker.getRotationAlignment() !== rotationAlignment) {
|
|
1012
|
-
marker.setRotationAlignment(rotationAlignment);
|
|
1013
|
-
}
|
|
1014
|
-
if (marker.getPitchAlignment() !== pitchAlignment) {
|
|
1015
|
-
marker.setPitchAlignment(pitchAlignment);
|
|
1016
|
-
}
|
|
1017
|
-
if (marker.getPopup() !== popup) {
|
|
1018
|
-
marker.setPopup(popup);
|
|
1019
|
-
}
|
|
1020
|
-
const classNameDiff = compareClassNames(
|
|
1021
|
-
oldProps.className,
|
|
1022
|
-
props.className
|
|
1023
|
-
);
|
|
1024
|
-
if (classNameDiff) {
|
|
1025
|
-
for (const c of classNameDiff) {
|
|
1026
|
-
marker.toggleClassName(c);
|
|
1032
|
+
const prevClassNameRef = useRef2(className);
|
|
1033
|
+
useEffect6(() => {
|
|
1034
|
+
if (marker.getLngLat().lng !== longitude || marker.getLngLat().lat !== latitude) {
|
|
1035
|
+
marker.setLngLat([longitude, latitude]);
|
|
1027
1036
|
}
|
|
1028
|
-
|
|
1029
|
-
|
|
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
|
+
});
|
|
1030
1063
|
return createPortal(props.children, marker.getElement());
|
|
1031
1064
|
})
|
|
1032
1065
|
);
|
|
1033
1066
|
|
|
1034
1067
|
// src/components/popup.ts
|
|
1035
1068
|
import { createPortal as createPortal2 } from "react-dom";
|
|
1036
|
-
import {
|
|
1037
|
-
useImperativeHandle as useImperativeHandle3,
|
|
1038
|
-
useEffect as useEffect7,
|
|
1039
|
-
useMemo as useMemo5,
|
|
1040
|
-
useRef as useRef3,
|
|
1041
|
-
useContext as useContext5,
|
|
1042
|
-
forwardRef as forwardRef3,
|
|
1043
|
-
memo as memo4
|
|
1044
|
-
} from "react";
|
|
1069
|
+
import { useImperativeHandle as useImperativeHandle3, useEffect as useEffect7, useMemo as useMemo5, useContext as useContext5, forwardRef as forwardRef3, memo as memo4 } from "react";
|
|
1045
1070
|
var Popup = memo4(
|
|
1046
1071
|
forwardRef3((props, ref) => {
|
|
1047
1072
|
const { map, mapLib } = useContext5(MapContext);
|
|
1048
1073
|
const container = useMemo5(() => {
|
|
1049
1074
|
return document.createElement("div");
|
|
1050
1075
|
}, []);
|
|
1051
|
-
const thisRef = useRef3({ props });
|
|
1052
1076
|
const popup = useMemo5(() => {
|
|
1053
1077
|
const options = { ...props };
|
|
1054
1078
|
const pp = new mapLib.Popup(options);
|
|
1055
1079
|
pp.setLngLat([props.longitude, props.latitude]);
|
|
1056
|
-
pp.once("open", (e) => {
|
|
1057
|
-
thisRef.current.props.onOpen?.(e);
|
|
1058
|
-
});
|
|
1059
1080
|
return pp;
|
|
1060
1081
|
}, []);
|
|
1082
|
+
useImperativeHandle3(ref, () => popup, []);
|
|
1061
1083
|
useEffect7(() => {
|
|
1084
|
+
const onOpen = (e) => {
|
|
1085
|
+
props.onOpen?.(e);
|
|
1086
|
+
};
|
|
1062
1087
|
const onClose = (e) => {
|
|
1063
|
-
|
|
1088
|
+
props.onClose?.(e);
|
|
1064
1089
|
};
|
|
1090
|
+
popup.on("open", onOpen);
|
|
1065
1091
|
popup.on("close", onClose);
|
|
1066
1092
|
popup.setDOMContent(container).addTo(map.getMap());
|
|
1067
1093
|
return () => {
|
|
1094
|
+
popup.off("open", onOpen);
|
|
1068
1095
|
popup.off("close", onClose);
|
|
1069
1096
|
if (popup.isOpen()) {
|
|
1070
1097
|
popup.remove();
|
|
@@ -1074,30 +1101,34 @@ var Popup = memo4(
|
|
|
1074
1101
|
useEffect7(() => {
|
|
1075
1102
|
applyReactStyle(popup.getElement(), props.style);
|
|
1076
1103
|
}, [props.style]);
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
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
|
+
}
|
|
1082
1109
|
}
|
|
1083
|
-
|
|
1110
|
+
}, [props.longitude, props.latitude]);
|
|
1111
|
+
useEffect7(() => {
|
|
1112
|
+
if (popup.isOpen() && props.offset) {
|
|
1084
1113
|
popup.setOffset(props.offset);
|
|
1085
1114
|
}
|
|
1086
|
-
|
|
1087
|
-
|
|
1115
|
+
}, [props.offset]);
|
|
1116
|
+
useEffect7(() => {
|
|
1117
|
+
if (popup.isOpen() && props.maxWidth !== void 0) {
|
|
1088
1118
|
popup.setMaxWidth(props.maxWidth);
|
|
1089
1119
|
}
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
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
|
+
}
|
|
1097
1129
|
}
|
|
1098
1130
|
}
|
|
1099
|
-
|
|
1100
|
-
}
|
|
1131
|
+
}, [props.className]);
|
|
1101
1132
|
return createPortal2(props.children, container);
|
|
1102
1133
|
})
|
|
1103
1134
|
);
|
|
@@ -1119,15 +1150,9 @@ function _FullscreenControl(props) {
|
|
|
1119
1150
|
var FullscreenControl = memo5(_FullscreenControl);
|
|
1120
1151
|
|
|
1121
1152
|
// src/components/geolocate-control.ts
|
|
1122
|
-
import {
|
|
1123
|
-
useImperativeHandle as useImperativeHandle4,
|
|
1124
|
-
useRef as useRef4,
|
|
1125
|
-
useEffect as useEffect9,
|
|
1126
|
-
forwardRef as forwardRef4,
|
|
1127
|
-
memo as memo6
|
|
1128
|
-
} from "react";
|
|
1153
|
+
import { useImperativeHandle as useImperativeHandle4, useRef as useRef3, useEffect as useEffect9, forwardRef as forwardRef4, memo as memo6 } from "react";
|
|
1129
1154
|
function _GeolocateControl(props, ref) {
|
|
1130
|
-
const thisRef =
|
|
1155
|
+
const thisRef = useRef3({ props });
|
|
1131
1156
|
const ctrl = useControl(
|
|
1132
1157
|
({ mapLib }) => {
|
|
1133
1158
|
const gc = new mapLib.GeolocateControl(props);
|
|
@@ -1163,9 +1188,7 @@ function _GeolocateControl(props, ref) {
|
|
|
1163
1188
|
}, [props.style]);
|
|
1164
1189
|
return null;
|
|
1165
1190
|
}
|
|
1166
|
-
var GeolocateControl = memo6(
|
|
1167
|
-
forwardRef4(_GeolocateControl)
|
|
1168
|
-
);
|
|
1191
|
+
var GeolocateControl = memo6(forwardRef4(_GeolocateControl));
|
|
1169
1192
|
|
|
1170
1193
|
// src/components/navigation-control.ts
|
|
1171
1194
|
import { useEffect as useEffect10, memo as memo7 } from "react";
|
|
@@ -1181,24 +1204,26 @@ function _NavigationControl(props) {
|
|
|
1181
1204
|
var NavigationControl = memo7(_NavigationControl);
|
|
1182
1205
|
|
|
1183
1206
|
// src/components/scale-control.ts
|
|
1184
|
-
import { useEffect as useEffect11, useRef as
|
|
1207
|
+
import { useEffect as useEffect11, useRef as useRef4, memo as memo8 } from "react";
|
|
1185
1208
|
function _ScaleControl(props) {
|
|
1186
1209
|
const ctrl = useControl(({ mapLib }) => new mapLib.ScaleControl(props), {
|
|
1187
1210
|
position: props.position
|
|
1188
1211
|
});
|
|
1189
|
-
const propsRef =
|
|
1212
|
+
const propsRef = useRef4(props);
|
|
1190
1213
|
const prevProps = propsRef.current;
|
|
1191
1214
|
propsRef.current = props;
|
|
1192
|
-
const { style } = props;
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
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]);
|
|
1199
1224
|
useEffect11(() => {
|
|
1200
1225
|
applyReactStyle(ctrl._container, style);
|
|
1201
|
-
}, [style]);
|
|
1226
|
+
}, [ctrl, style]);
|
|
1202
1227
|
return null;
|
|
1203
1228
|
}
|
|
1204
1229
|
var ScaleControl = memo8(_ScaleControl);
|
|
@@ -1223,8 +1248,11 @@ import {
|
|
|
1223
1248
|
useEffect as useEffect13,
|
|
1224
1249
|
useMemo as useMemo6,
|
|
1225
1250
|
useState as useState3,
|
|
1226
|
-
useRef as
|
|
1227
|
-
cloneElement
|
|
1251
|
+
useRef as useRef5,
|
|
1252
|
+
cloneElement,
|
|
1253
|
+
memo as memo10,
|
|
1254
|
+
useId,
|
|
1255
|
+
useImperativeHandle as useImperativeHandle5
|
|
1228
1256
|
} from "react";
|
|
1229
1257
|
|
|
1230
1258
|
// src/utils/assert.ts
|
|
@@ -1235,9 +1263,9 @@ function assert(condition, message) {
|
|
|
1235
1263
|
}
|
|
1236
1264
|
|
|
1237
1265
|
// src/components/source.ts
|
|
1238
|
-
var sourceCounter = 0;
|
|
1239
1266
|
function createSource(map, id, props) {
|
|
1240
|
-
|
|
1267
|
+
const mapInternal = map;
|
|
1268
|
+
if (mapInternal.style && mapInternal.style._loaded) {
|
|
1241
1269
|
const options = { ...props };
|
|
1242
1270
|
delete options.id;
|
|
1243
1271
|
delete options.children;
|
|
@@ -1262,33 +1290,43 @@ function updateSource(source, props, prevProps) {
|
|
|
1262
1290
|
}
|
|
1263
1291
|
const type = props.type;
|
|
1264
1292
|
if (type === "geojson") {
|
|
1293
|
+
;
|
|
1265
1294
|
source.setData(props.data);
|
|
1266
1295
|
} else if (type === "image") {
|
|
1296
|
+
;
|
|
1267
1297
|
source.updateImage({
|
|
1268
1298
|
url: props.url,
|
|
1269
1299
|
coordinates: props.coordinates
|
|
1270
1300
|
});
|
|
1271
1301
|
} else {
|
|
1302
|
+
const sourceWithMethods = source;
|
|
1303
|
+
const propsWithOptional = props;
|
|
1272
1304
|
switch (changedKey) {
|
|
1273
1305
|
case "coordinates":
|
|
1274
|
-
|
|
1306
|
+
sourceWithMethods.setCoordinates?.(propsWithOptional.coordinates);
|
|
1275
1307
|
break;
|
|
1276
1308
|
case "url":
|
|
1277
|
-
|
|
1309
|
+
sourceWithMethods.setUrl?.(propsWithOptional.url);
|
|
1278
1310
|
break;
|
|
1279
1311
|
case "tiles":
|
|
1280
|
-
|
|
1312
|
+
sourceWithMethods.setTiles?.(propsWithOptional.tiles);
|
|
1281
1313
|
break;
|
|
1282
1314
|
default:
|
|
1283
1315
|
console.warn(`Unable to update <Source> prop: ${changedKey}`);
|
|
1284
1316
|
}
|
|
1285
1317
|
}
|
|
1286
1318
|
}
|
|
1287
|
-
function
|
|
1319
|
+
function _Source(props, ref) {
|
|
1288
1320
|
const map = useContext6(MapContext).map.getMap();
|
|
1289
|
-
const propsRef =
|
|
1321
|
+
const propsRef = useRef5(props);
|
|
1322
|
+
const sourceRef = useRef5(null);
|
|
1290
1323
|
const [, setStyleLoaded] = useState3(0);
|
|
1291
|
-
const
|
|
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
|
+
);
|
|
1292
1330
|
useEffect13(() => {
|
|
1293
1331
|
if (map) {
|
|
1294
1332
|
const forceUpdate = () => setTimeout(() => setStyleLoaded((version) => version + 1), 0);
|
|
@@ -1296,11 +1334,13 @@ function Source(props) {
|
|
|
1296
1334
|
forceUpdate();
|
|
1297
1335
|
return () => {
|
|
1298
1336
|
map.off("styledata", forceUpdate);
|
|
1299
|
-
|
|
1337
|
+
const mapInternal2 = map;
|
|
1338
|
+
if (mapInternal2.style && mapInternal2.style._loaded && map.getSource(id)) {
|
|
1300
1339
|
const allLayers = map.getStyle()?.layers;
|
|
1301
1340
|
if (allLayers) {
|
|
1302
1341
|
for (const layer of allLayers) {
|
|
1303
|
-
|
|
1342
|
+
const layerWithSource = layer;
|
|
1343
|
+
if (layerWithSource.source === id) {
|
|
1304
1344
|
map.removeLayer(layer.id);
|
|
1305
1345
|
}
|
|
1306
1346
|
}
|
|
@@ -1311,13 +1351,16 @@ function Source(props) {
|
|
|
1311
1351
|
}
|
|
1312
1352
|
return void 0;
|
|
1313
1353
|
}, [map]);
|
|
1314
|
-
|
|
1354
|
+
const mapInternal = map;
|
|
1355
|
+
let source = map && mapInternal.style && map.getSource(id);
|
|
1315
1356
|
if (source) {
|
|
1316
1357
|
updateSource(source, props, propsRef.current);
|
|
1317
1358
|
} else {
|
|
1318
1359
|
source = createSource(map, id, props);
|
|
1319
1360
|
}
|
|
1361
|
+
sourceRef.current = source;
|
|
1320
1362
|
propsRef.current = props;
|
|
1363
|
+
useImperativeHandle5(ref, () => sourceRef.current, [source]);
|
|
1321
1364
|
return source && React4.Children.map(
|
|
1322
1365
|
props.children,
|
|
1323
1366
|
(child) => child && cloneElement(child, {
|
|
@@ -1325,21 +1368,103 @@ function Source(props) {
|
|
|
1325
1368
|
})
|
|
1326
1369
|
) || null;
|
|
1327
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);
|
|
1328
1451
|
|
|
1329
1452
|
// src/components/layer.ts
|
|
1330
|
-
import { useContext as
|
|
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";
|
|
1331
1454
|
function updateLayer(map, id, props, prevProps) {
|
|
1332
1455
|
assert(props.id === prevProps.id, "layer id changed");
|
|
1333
1456
|
assert(props.type === prevProps.type, "layer type changed");
|
|
1334
1457
|
if (props.type === "custom" || prevProps.type === "custom") {
|
|
1335
1458
|
return;
|
|
1336
1459
|
}
|
|
1337
|
-
const
|
|
1338
|
-
|
|
1460
|
+
const propsWithFilter = props;
|
|
1461
|
+
const prevPropsWithFilter = prevProps;
|
|
1462
|
+
const { layout = {}, paint = {}, filter, minzoom, maxzoom, beforeId } = propsWithFilter;
|
|
1463
|
+
if (beforeId !== prevPropsWithFilter.beforeId) {
|
|
1339
1464
|
map.moveLayer(id, beforeId);
|
|
1340
1465
|
}
|
|
1341
|
-
if (layout !==
|
|
1342
|
-
const prevLayout =
|
|
1466
|
+
if (layout !== prevPropsWithFilter.layout) {
|
|
1467
|
+
const prevLayout = prevPropsWithFilter.layout || {};
|
|
1343
1468
|
for (const key in layout) {
|
|
1344
1469
|
if (!deepEqual(layout[key], prevLayout[key])) {
|
|
1345
1470
|
map.setLayoutProperty(id, key, layout[key]);
|
|
@@ -1351,8 +1476,8 @@ function updateLayer(map, id, props, prevProps) {
|
|
|
1351
1476
|
}
|
|
1352
1477
|
}
|
|
1353
1478
|
}
|
|
1354
|
-
if (paint !==
|
|
1355
|
-
const prevPaint =
|
|
1479
|
+
if (paint !== prevPropsWithFilter.paint) {
|
|
1480
|
+
const prevPaint = prevPropsWithFilter.paint || {};
|
|
1356
1481
|
for (const key in paint) {
|
|
1357
1482
|
if (!deepEqual(paint[key], prevPaint[key])) {
|
|
1358
1483
|
map.setPaintProperty(id, key, paint[key]);
|
|
@@ -1364,41 +1489,151 @@ function updateLayer(map, id, props, prevProps) {
|
|
|
1364
1489
|
}
|
|
1365
1490
|
}
|
|
1366
1491
|
}
|
|
1367
|
-
if (!deepEqual(filter,
|
|
1368
|
-
map.setFilter(id, filter);
|
|
1492
|
+
if (!deepEqual(filter, prevPropsWithFilter.filter)) {
|
|
1493
|
+
map.setFilter(id, filter ?? null);
|
|
1369
1494
|
}
|
|
1370
|
-
if (minzoom !==
|
|
1495
|
+
if (minzoom !== prevPropsWithFilter.minzoom || maxzoom !== prevPropsWithFilter.maxzoom) {
|
|
1371
1496
|
map.setLayerZoomRange(id, minzoom, maxzoom);
|
|
1372
1497
|
}
|
|
1373
1498
|
}
|
|
1374
1499
|
function createLayer(map, id, props) {
|
|
1375
|
-
|
|
1500
|
+
const mapInternal = map;
|
|
1501
|
+
if (mapInternal.style && mapInternal.style._loaded && (!("source" in props) || map.getSource(props.source))) {
|
|
1376
1502
|
const options = { ...props, id };
|
|
1377
1503
|
delete options.beforeId;
|
|
1378
1504
|
map.addLayer(options, props.beforeId);
|
|
1379
1505
|
}
|
|
1380
1506
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
const map = useContext7(MapContext).map.getMap();
|
|
1507
|
+
function _Layer(props) {
|
|
1508
|
+
const map = useContext8(MapContext).map.getMap();
|
|
1384
1509
|
const propsRef = useRef7(props);
|
|
1385
|
-
const [, setStyleLoaded] =
|
|
1386
|
-
const
|
|
1387
|
-
|
|
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(() => {
|
|
1388
1559
|
if (map) {
|
|
1389
1560
|
const forceUpdate = () => setStyleLoaded((version) => version + 1);
|
|
1390
1561
|
map.on("styledata", forceUpdate);
|
|
1391
1562
|
forceUpdate();
|
|
1392
1563
|
return () => {
|
|
1393
1564
|
map.off("styledata", forceUpdate);
|
|
1394
|
-
|
|
1565
|
+
const mapInternal2 = map;
|
|
1566
|
+
if (mapInternal2.style && mapInternal2.style._loaded && map.getLayer(id)) {
|
|
1395
1567
|
map.removeLayer(id);
|
|
1396
1568
|
}
|
|
1397
1569
|
};
|
|
1398
1570
|
}
|
|
1399
1571
|
return void 0;
|
|
1400
1572
|
}, [map]);
|
|
1401
|
-
|
|
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);
|
|
1402
1637
|
if (layer) {
|
|
1403
1638
|
try {
|
|
1404
1639
|
updateLayer(map, id, props, propsRef.current);
|
|
@@ -1411,18 +1646,769 @@ function Layer(props) {
|
|
|
1411
1646
|
propsRef.current = props;
|
|
1412
1647
|
return null;
|
|
1413
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);
|
|
1414
2395
|
|
|
1415
2396
|
// src/exports-maplibre-gl.ts
|
|
1416
2397
|
var exports_maplibre_gl_default = Map;
|
|
1417
2398
|
export {
|
|
1418
2399
|
AttributionControl,
|
|
2400
|
+
CanvasSource,
|
|
2401
|
+
DrawControl,
|
|
1419
2402
|
FullscreenControl,
|
|
1420
2403
|
GeolocateControl,
|
|
2404
|
+
GlobeControl,
|
|
1421
2405
|
Layer,
|
|
1422
2406
|
LogoControl,
|
|
1423
2407
|
Map,
|
|
1424
2408
|
MapProvider,
|
|
1425
2409
|
Marker,
|
|
2410
|
+
Minimap,
|
|
2411
|
+
MinimapControl,
|
|
1426
2412
|
NavigationControl,
|
|
1427
2413
|
Popup,
|
|
1428
2414
|
ScaleControl,
|