@dxos/react-ui-geo 0.8.4-main.3a94e84 → 0.8.4-main.3c1ae3b
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/dist/lib/browser/index.mjs +214 -177
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +214 -177
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +25 -9
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +27 -17
- package/dist/types/src/components/Map/Map.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.stories.d.ts +14 -8
- package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
- package/dist/types/src/components/index.d.ts +0 -1
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/hooks/context.d.ts +7 -7
- package/dist/types/src/hooks/context.d.ts.map +1 -1
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +1 -1
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useSpinner.d.ts +1 -1
- package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
- package/dist/types/src/hooks/useTour.d.ts +4 -3
- package/dist/types/src/hooks/useTour.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +1 -0
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +12 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/types.d.ts +2 -1
- package/dist/types/src/types.d.ts.map +1 -1
- package/dist/types/src/util/path.d.ts +5 -8
- package/dist/types/src/util/path.d.ts.map +1 -1
- package/dist/types/src/util/render.d.ts +4 -4
- package/dist/types/src/util/render.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +22 -19
- package/src/components/Globe/Globe.stories.tsx +82 -34
- package/src/components/Globe/Globe.tsx +55 -34
- package/src/components/Map/Map.stories.tsx +25 -14
- package/src/components/Map/Map.tsx +180 -95
- package/src/components/Toolbar/Controls.tsx +14 -20
- package/src/components/index.ts +0 -2
- package/src/hooks/context.tsx +22 -16
- package/src/hooks/useGlobeZoomHandler.ts +9 -3
- package/src/hooks/useMapZoomHandler.ts +1 -1
- package/src/hooks/useSpinner.ts +2 -1
- package/src/hooks/useTour.ts +10 -8
- package/src/index.ts +1 -0
- package/src/translations.ts +20 -0
- package/src/types.ts +3 -1
- package/src/util/inertia.ts +1 -1
- package/src/util/path.ts +5 -6
- package/src/util/render.ts +5 -3
- package/dist/types/src/components/types.d.ts +0 -15
- package/dist/types/src/components/types.d.ts.map +0 -1
- package/src/components/types.ts +0 -19
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
|
|
5
5
|
// src/components/Globe/Globe.tsx
|
|
6
6
|
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
7
|
-
import { geoMercator, geoOrthographic, geoPath as geoPath2, geoTransverseMercator, interpolateNumber, transition
|
|
7
|
+
import { easeLinear, easeSinOut, geoMercator, geoOrthographic, geoPath as geoPath2, geoTransverseMercator, interpolateNumber, transition } from "d3";
|
|
8
8
|
import React3, { forwardRef, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
9
9
|
import { useResizeDetector } from "react-resize-detector";
|
|
10
10
|
import { useDynamicRef, useThemeContext } from "@dxos/react-ui";
|
|
@@ -15,23 +15,30 @@ import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
|
15
15
|
import React, { createContext, useContext } from "react";
|
|
16
16
|
import { raise } from "@dxos/debug";
|
|
17
17
|
import { useControlledState } from "@dxos/react-ui";
|
|
18
|
+
var defaults = {
|
|
19
|
+
center: {
|
|
20
|
+
lat: 51,
|
|
21
|
+
lng: 0
|
|
22
|
+
},
|
|
23
|
+
zoom: 4
|
|
24
|
+
};
|
|
18
25
|
var GlobeContext = /* @__PURE__ */ createContext(void 0);
|
|
19
|
-
var GlobeContextProvider = ({ children, size, center:
|
|
26
|
+
var GlobeContextProvider = ({ children, size, center: centerParam = defaults.center, zoom: zoomParam = defaults.zoom, translation: translationParam, rotation: rotationParam }) => {
|
|
20
27
|
var _effect = _useSignals();
|
|
21
28
|
try {
|
|
22
|
-
const [center, setCenter] = useControlledState(
|
|
23
|
-
const [
|
|
24
|
-
const [translation, setTranslation] = useControlledState(
|
|
25
|
-
const [rotation, setRotation] = useControlledState(
|
|
29
|
+
const [center, setCenter] = useControlledState(centerParam);
|
|
30
|
+
const [zoom, setZoom] = useControlledState(zoomParam);
|
|
31
|
+
const [translation, setTranslation] = useControlledState(translationParam);
|
|
32
|
+
const [rotation, setRotation] = useControlledState(rotationParam);
|
|
26
33
|
return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
|
|
27
34
|
value: {
|
|
28
35
|
size,
|
|
29
36
|
center,
|
|
30
|
-
|
|
37
|
+
zoom,
|
|
31
38
|
translation,
|
|
32
39
|
rotation,
|
|
33
40
|
setCenter,
|
|
34
|
-
|
|
41
|
+
setZoom,
|
|
35
42
|
setTranslation,
|
|
36
43
|
setRotation
|
|
37
44
|
}
|
|
@@ -64,7 +71,7 @@ var timer = (cb) => {
|
|
|
64
71
|
};
|
|
65
72
|
|
|
66
73
|
// src/util/inertia.ts
|
|
67
|
-
import {
|
|
74
|
+
import { drag, select, timer as timer2 } from "d3";
|
|
68
75
|
import versor from "versor";
|
|
69
76
|
var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
|
|
70
77
|
var geoInertiaDrag = (target, render, projection, options) => {
|
|
@@ -427,6 +434,7 @@ var cancelDrag = (node) => node.on(".drag", null);
|
|
|
427
434
|
|
|
428
435
|
// src/hooks/useGlobeZoomHandler.ts
|
|
429
436
|
import { useCallback } from "react";
|
|
437
|
+
var ZOOM_FACTOR = 0.1;
|
|
430
438
|
var useGlobeZoomHandler = (controller) => {
|
|
431
439
|
return useCallback((event) => {
|
|
432
440
|
if (!controller) {
|
|
@@ -434,11 +442,15 @@ var useGlobeZoomHandler = (controller) => {
|
|
|
434
442
|
}
|
|
435
443
|
switch (event) {
|
|
436
444
|
case "zoom-in": {
|
|
437
|
-
controller.
|
|
445
|
+
controller.setZoom((zoom) => {
|
|
446
|
+
return zoom * (1 + ZOOM_FACTOR);
|
|
447
|
+
});
|
|
438
448
|
break;
|
|
439
449
|
}
|
|
440
450
|
case "zoom-out": {
|
|
441
|
-
controller.
|
|
451
|
+
controller.setZoom((zoom) => {
|
|
452
|
+
return zoom * (1 - ZOOM_FACTOR);
|
|
453
|
+
});
|
|
442
454
|
break;
|
|
443
455
|
}
|
|
444
456
|
}
|
|
@@ -523,8 +535,8 @@ var useSpinner = (controller, options = {}) => {
|
|
|
523
535
|
};
|
|
524
536
|
|
|
525
537
|
// src/hooks/useTour.ts
|
|
526
|
-
import {
|
|
527
|
-
import { useEffect as useEffect3, useState as useState2
|
|
538
|
+
import { selection as d3Selection, geoDistance, geoInterpolate, geoPath } from "d3";
|
|
539
|
+
import { useEffect as useEffect3, useMemo, useState as useState2 } from "react";
|
|
528
540
|
import versor2 from "versor";
|
|
529
541
|
var TRANSITION_NAME = "globe-tour";
|
|
530
542
|
var defaultDuration = 1500;
|
|
@@ -571,7 +583,7 @@ var useTour = (controller, points, options = {}) => {
|
|
|
571
583
|
{
|
|
572
584
|
context.beginPath();
|
|
573
585
|
context.strokeStyle = options?.styles?.arc?.strokeStyle ?? "yellow";
|
|
574
|
-
context.lineWidth = (options?.styles?.arc?.lineWidth ?? 1.5) * (controller?.
|
|
586
|
+
context.lineWidth = (options?.styles?.arc?.lineWidth ?? 1.5) * (controller?.zoom ?? 1);
|
|
575
587
|
context.setLineDash(options?.styles?.arc?.lineDash ?? []);
|
|
576
588
|
path({
|
|
577
589
|
type: "LineString",
|
|
@@ -583,7 +595,7 @@ var useTour = (controller, points, options = {}) => {
|
|
|
583
595
|
context.stroke();
|
|
584
596
|
context.beginPath();
|
|
585
597
|
context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
|
|
586
|
-
path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.
|
|
598
|
+
path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.zoom ?? 1));
|
|
587
599
|
path({
|
|
588
600
|
type: "Point",
|
|
589
601
|
coordinates: ip(t22)
|
|
@@ -597,7 +609,7 @@ var useTour = (controller, points, options = {}) => {
|
|
|
597
609
|
await transition2.end();
|
|
598
610
|
last = next;
|
|
599
611
|
}
|
|
600
|
-
} catch
|
|
612
|
+
} catch {
|
|
601
613
|
} finally {
|
|
602
614
|
setRunning(false);
|
|
603
615
|
}
|
|
@@ -621,7 +633,24 @@ var useTour = (controller, points, options = {}) => {
|
|
|
621
633
|
// src/components/Toolbar/Controls.tsx
|
|
622
634
|
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
623
635
|
import React2 from "react";
|
|
624
|
-
import { IconButton, Toolbar } from "@dxos/react-ui";
|
|
636
|
+
import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
|
|
637
|
+
|
|
638
|
+
// src/translations.ts
|
|
639
|
+
var translationKey = "react-ui-geo";
|
|
640
|
+
var translations = [
|
|
641
|
+
{
|
|
642
|
+
"en-US": {
|
|
643
|
+
[translationKey]: {
|
|
644
|
+
"zoom in icon button": "Zoom in",
|
|
645
|
+
"zoom out icon button": "Zoom out",
|
|
646
|
+
"start icon button": "Start",
|
|
647
|
+
"toggle icon button": "Toggle"
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
];
|
|
652
|
+
|
|
653
|
+
// src/components/Toolbar/Controls.tsx
|
|
625
654
|
var controlPositions = {
|
|
626
655
|
topleft: "top-2 left-2",
|
|
627
656
|
topright: "top-2 right-2",
|
|
@@ -631,26 +660,21 @@ var controlPositions = {
|
|
|
631
660
|
var ZoomControls = ({ classNames, onAction }) => {
|
|
632
661
|
var _effect = _useSignals2();
|
|
633
662
|
try {
|
|
663
|
+
const { t } = useTranslation(translationKey);
|
|
634
664
|
return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
|
|
635
665
|
classNames: [
|
|
636
|
-
"gap-
|
|
666
|
+
"gap-2",
|
|
637
667
|
classNames
|
|
638
668
|
]
|
|
639
669
|
}, /* @__PURE__ */ React2.createElement(IconButton, {
|
|
640
|
-
//
|
|
641
670
|
icon: "ph--plus--regular",
|
|
642
|
-
label: "zoom in",
|
|
643
671
|
iconOnly: true,
|
|
644
|
-
|
|
645
|
-
classNames: "px-0 aspect-square",
|
|
672
|
+
label: t("zoom in icon button"),
|
|
646
673
|
onClick: () => onAction?.("zoom-in")
|
|
647
674
|
}), /* @__PURE__ */ React2.createElement(IconButton, {
|
|
648
|
-
//
|
|
649
675
|
icon: "ph--minus--regular",
|
|
650
|
-
label: "zoom out",
|
|
651
676
|
iconOnly: true,
|
|
652
|
-
|
|
653
|
-
classNames: "px-0 aspect-square",
|
|
677
|
+
label: t("zoom out icon button"),
|
|
654
678
|
onClick: () => onAction?.("zoom-out")
|
|
655
679
|
}));
|
|
656
680
|
} finally {
|
|
@@ -660,26 +684,21 @@ var ZoomControls = ({ classNames, onAction }) => {
|
|
|
660
684
|
var ActionControls = ({ classNames, onAction }) => {
|
|
661
685
|
var _effect = _useSignals2();
|
|
662
686
|
try {
|
|
687
|
+
const { t } = useTranslation(translationKey);
|
|
663
688
|
return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
|
|
664
689
|
classNames: [
|
|
665
|
-
"gap-
|
|
690
|
+
"gap-2",
|
|
666
691
|
classNames
|
|
667
692
|
]
|
|
668
693
|
}, /* @__PURE__ */ React2.createElement(IconButton, {
|
|
669
|
-
|
|
670
|
-
icon: "ph--play--regular",
|
|
671
|
-
label: "start",
|
|
694
|
+
icon: "ph--path--regular",
|
|
672
695
|
iconOnly: true,
|
|
673
|
-
|
|
674
|
-
classNames: "px-0 aspect-square",
|
|
696
|
+
label: t("start icon button"),
|
|
675
697
|
onClick: () => onAction?.("start")
|
|
676
698
|
}), /* @__PURE__ */ React2.createElement(IconButton, {
|
|
677
|
-
//
|
|
678
699
|
icon: "ph--globe-hemisphere-west--regular",
|
|
679
|
-
label: "toggle",
|
|
680
700
|
iconOnly: true,
|
|
681
|
-
|
|
682
|
-
classNames: "px-0 aspect-square",
|
|
701
|
+
label: t("toggle icon button"),
|
|
683
702
|
onClick: () => onAction?.("toggle")
|
|
684
703
|
}));
|
|
685
704
|
} finally {
|
|
@@ -760,18 +779,18 @@ var GlobeRoot = ({ classNames, children, ...props }) => {
|
|
|
760
779
|
_effect.f();
|
|
761
780
|
}
|
|
762
781
|
};
|
|
763
|
-
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection:
|
|
782
|
+
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: projectionParam, topology, features, styles: stylesParam }, forwardRef3) => {
|
|
764
783
|
var _effect = _useSignals3();
|
|
765
784
|
try {
|
|
766
785
|
const { themeMode } = useThemeContext();
|
|
767
|
-
const styles = useMemo2(() =>
|
|
768
|
-
|
|
786
|
+
const styles = useMemo2(() => stylesParam ?? defaultStyles[themeMode], [
|
|
787
|
+
stylesParam,
|
|
769
788
|
themeMode
|
|
770
789
|
]);
|
|
771
790
|
const [canvas, setCanvas] = useState3(null);
|
|
772
791
|
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
773
|
-
const projection = useMemo2(() => getProjection(
|
|
774
|
-
|
|
792
|
+
const projection = useMemo2(() => getProjection(projectionParam), [
|
|
793
|
+
projectionParam
|
|
775
794
|
]);
|
|
776
795
|
const layers = useMemo2(() => {
|
|
777
796
|
return timer(() => createLayers(topology, features, styles));
|
|
@@ -780,11 +799,11 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
|
|
|
780
799
|
features,
|
|
781
800
|
styles
|
|
782
801
|
]);
|
|
783
|
-
const { size, center,
|
|
784
|
-
const
|
|
802
|
+
const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
|
|
803
|
+
const zoomRef = useDynamicRef(zoom);
|
|
785
804
|
useEffect4(() => {
|
|
786
805
|
if (center) {
|
|
787
|
-
|
|
806
|
+
setZoom(1);
|
|
788
807
|
setRotation(positionToRotation(geoToPosition(center)));
|
|
789
808
|
}
|
|
790
809
|
}, [
|
|
@@ -796,20 +815,20 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
|
|
|
796
815
|
canvas,
|
|
797
816
|
projection,
|
|
798
817
|
center,
|
|
799
|
-
get
|
|
800
|
-
return
|
|
818
|
+
get zoom() {
|
|
819
|
+
return zoomRef.current;
|
|
801
820
|
},
|
|
802
821
|
translation,
|
|
803
822
|
rotation,
|
|
804
823
|
setCenter,
|
|
805
|
-
|
|
824
|
+
setZoom: (s) => {
|
|
806
825
|
if (typeof s === "function") {
|
|
807
|
-
const is = interpolateNumber(
|
|
808
|
-
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) =>
|
|
826
|
+
const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
|
|
827
|
+
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
809
828
|
zooming.current = false;
|
|
810
829
|
});
|
|
811
830
|
} else {
|
|
812
|
-
|
|
831
|
+
setZoom(s);
|
|
813
832
|
}
|
|
814
833
|
},
|
|
815
834
|
setTranslation,
|
|
@@ -827,7 +846,7 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
|
|
|
827
846
|
useEffect4(() => {
|
|
828
847
|
if (canvas && projection) {
|
|
829
848
|
timer(() => {
|
|
830
|
-
projection.scale(Math.min(size.width, size.height) / 2 *
|
|
849
|
+
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
831
850
|
size.width / 2 + (translation?.x ?? 0),
|
|
832
851
|
size.height / 2 + (translation?.y ?? 0)
|
|
833
852
|
]).rotate(rotation ?? [
|
|
@@ -835,13 +854,13 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
|
|
|
835
854
|
0,
|
|
836
855
|
0
|
|
837
856
|
]);
|
|
838
|
-
renderLayers(generator, layers,
|
|
857
|
+
renderLayers(generator, layers, zoom, styles);
|
|
839
858
|
});
|
|
840
859
|
}
|
|
841
860
|
}, [
|
|
842
861
|
generator,
|
|
843
862
|
size,
|
|
844
|
-
|
|
863
|
+
zoom,
|
|
845
864
|
translation,
|
|
846
865
|
rotation,
|
|
847
866
|
layers
|
|
@@ -861,14 +880,14 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
|
|
|
861
880
|
var GlobeDebug = ({ position = "topleft" }) => {
|
|
862
881
|
var _effect = _useSignals3();
|
|
863
882
|
try {
|
|
864
|
-
const { size,
|
|
883
|
+
const { size, zoom, translation, rotation } = useGlobeContext();
|
|
865
884
|
return /* @__PURE__ */ React3.createElement("div", {
|
|
866
|
-
className: mx("z-10 absolute
|
|
885
|
+
className: mx("z-10 absolute is-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
|
|
867
886
|
}, /* @__PURE__ */ React3.createElement("pre", {
|
|
868
887
|
className: "font-mono text-xs text-green-700"
|
|
869
888
|
}, JSON.stringify({
|
|
870
889
|
size,
|
|
871
|
-
|
|
890
|
+
zoom,
|
|
872
891
|
translation,
|
|
873
892
|
rotation
|
|
874
893
|
}, null, 2)));
|
|
@@ -896,35 +915,37 @@ var CustomControl = ({ position, children }) => {
|
|
|
896
915
|
_effect.f();
|
|
897
916
|
}
|
|
898
917
|
};
|
|
918
|
+
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
|
|
919
|
+
var _effect = _useSignals3();
|
|
920
|
+
try {
|
|
921
|
+
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
922
|
+
position,
|
|
923
|
+
...props
|
|
924
|
+
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
925
|
+
onAction
|
|
926
|
+
}));
|
|
927
|
+
} finally {
|
|
928
|
+
_effect.f();
|
|
929
|
+
}
|
|
930
|
+
};
|
|
931
|
+
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
|
|
932
|
+
var _effect = _useSignals3();
|
|
933
|
+
try {
|
|
934
|
+
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
935
|
+
position,
|
|
936
|
+
...props
|
|
937
|
+
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
938
|
+
onAction
|
|
939
|
+
}));
|
|
940
|
+
} finally {
|
|
941
|
+
_effect.f();
|
|
942
|
+
}
|
|
943
|
+
};
|
|
899
944
|
var Globe = {
|
|
900
945
|
Root: GlobeRoot,
|
|
901
946
|
Canvas: GlobeCanvas,
|
|
902
|
-
Zoom:
|
|
903
|
-
|
|
904
|
-
try {
|
|
905
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
906
|
-
position,
|
|
907
|
-
...props
|
|
908
|
-
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
909
|
-
onAction
|
|
910
|
-
}));
|
|
911
|
-
} finally {
|
|
912
|
-
_effect.f();
|
|
913
|
-
}
|
|
914
|
-
},
|
|
915
|
-
Action: ({ onAction, position = "bottomright", ...props }) => {
|
|
916
|
-
var _effect = _useSignals3();
|
|
917
|
-
try {
|
|
918
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
919
|
-
position,
|
|
920
|
-
...props
|
|
921
|
-
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
922
|
-
onAction
|
|
923
|
-
}));
|
|
924
|
-
} finally {
|
|
925
|
-
_effect.f();
|
|
926
|
-
}
|
|
927
|
-
},
|
|
947
|
+
Zoom: GlobeZoom,
|
|
948
|
+
Action: GlobeAction,
|
|
928
949
|
Debug: GlobeDebug,
|
|
929
950
|
Panel: GlobePanel
|
|
930
951
|
};
|
|
@@ -932,108 +953,117 @@ var Globe = {
|
|
|
932
953
|
// src/components/Map/Map.tsx
|
|
933
954
|
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
934
955
|
import "leaflet/dist/leaflet.css";
|
|
956
|
+
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
935
957
|
import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
|
|
936
|
-
import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2 } from "react";
|
|
958
|
+
import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useRef as useRef2, useState as useState4 } from "react";
|
|
937
959
|
import { createRoot } from "react-dom/client";
|
|
938
|
-
import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
|
|
939
|
-
import { useResizeDetector as useResizeDetector2 } from "react-resize-detector";
|
|
940
|
-
import { debounce } from "@dxos/async";
|
|
960
|
+
import { MapContainer, Marker, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
941
961
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
|
942
962
|
import { defaultTx, mx as mx2 } from "@dxos/react-ui-theme";
|
|
943
|
-
var
|
|
944
|
-
// TODO(burdon): Guess location.
|
|
963
|
+
var defaults2 = {
|
|
945
964
|
center: {
|
|
946
965
|
lat: 51,
|
|
947
966
|
lng: 0
|
|
948
967
|
},
|
|
949
968
|
zoom: 4
|
|
950
969
|
};
|
|
951
|
-
var
|
|
970
|
+
var [MapContextProvier, useMapContext] = createContext2("Map");
|
|
971
|
+
var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center, zoom, onChange, ...props }, forwardedRef) => {
|
|
952
972
|
var _effect = _useSignals4();
|
|
953
973
|
try {
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
// TODO(burdon): Only if attention.
|
|
958
|
-
scrollWheelZoom: true,
|
|
959
|
-
zoomControl: false,
|
|
960
|
-
center,
|
|
961
|
-
zoom,
|
|
962
|
-
...props
|
|
963
|
-
});
|
|
964
|
-
} finally {
|
|
965
|
-
_effect.f();
|
|
966
|
-
}
|
|
967
|
-
};
|
|
968
|
-
var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }, forwardedRef) => {
|
|
969
|
-
var _effect = _useSignals4();
|
|
970
|
-
try {
|
|
971
|
-
const { ref, width, height } = useResizeDetector2({
|
|
972
|
-
refreshRate: 200
|
|
973
|
-
});
|
|
974
|
-
const map = useMap();
|
|
974
|
+
const [attention, setAttention] = useState4(false);
|
|
975
|
+
const mapRef = useRef2(null);
|
|
976
|
+
const map = mapRef.current;
|
|
975
977
|
useImperativeHandle2(forwardedRef, () => ({
|
|
976
978
|
setCenter: (center2, zoom2) => {
|
|
977
|
-
|
|
979
|
+
mapRef.current?.setView(center2, zoom2);
|
|
978
980
|
},
|
|
979
981
|
setZoom: (cb) => {
|
|
980
|
-
|
|
982
|
+
mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
|
|
981
983
|
}
|
|
982
|
-
}), [
|
|
983
|
-
map
|
|
984
|
-
]);
|
|
984
|
+
}), []);
|
|
985
985
|
useEffect5(() => {
|
|
986
|
-
if (
|
|
987
|
-
|
|
986
|
+
if (!map) {
|
|
987
|
+
return;
|
|
988
988
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
useEffect5(() => {
|
|
994
|
-
if (center) {
|
|
995
|
-
map.setView(center, zoom);
|
|
996
|
-
} else if (zoom !== void 0) {
|
|
997
|
-
map.setZoom(zoom);
|
|
989
|
+
if (attention) {
|
|
990
|
+
map.scrollWheelZoom.enable();
|
|
991
|
+
} else {
|
|
992
|
+
map.scrollWheelZoom.disable();
|
|
998
993
|
}
|
|
999
994
|
}, [
|
|
1000
|
-
|
|
1001
|
-
|
|
995
|
+
map,
|
|
996
|
+
attention
|
|
1002
997
|
]);
|
|
1003
|
-
|
|
1004
|
-
|
|
998
|
+
return /* @__PURE__ */ React4.createElement(MapContextProvier, {
|
|
999
|
+
attention,
|
|
1000
|
+
onChange
|
|
1001
|
+
}, /* @__PURE__ */ React4.createElement(MapContainer, {
|
|
1002
|
+
...props,
|
|
1003
|
+
ref: mapRef,
|
|
1004
|
+
className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
|
|
1005
|
+
attributionControl: false,
|
|
1006
|
+
zoomControl: false,
|
|
1007
|
+
scrollWheelZoom,
|
|
1008
|
+
doubleClickZoom,
|
|
1009
|
+
touchZoom,
|
|
1010
|
+
center: center ?? defaults2.center,
|
|
1011
|
+
zoom: zoom ?? defaults2.zoom
|
|
1012
|
+
}));
|
|
1013
|
+
} finally {
|
|
1014
|
+
_effect.f();
|
|
1015
|
+
}
|
|
1016
|
+
});
|
|
1017
|
+
MapRoot.displayName = "Map.Root";
|
|
1018
|
+
var MapTiles = (_props) => {
|
|
1019
|
+
var _effect = _useSignals4();
|
|
1020
|
+
try {
|
|
1021
|
+
const ref = useRef2(null);
|
|
1022
|
+
const { onChange } = useMapContext(MapTiles.displayName);
|
|
1023
|
+
useMapEvents({
|
|
1024
|
+
zoomstart: (ev) => {
|
|
1005
1025
|
onChange?.({
|
|
1006
|
-
center:
|
|
1007
|
-
zoom:
|
|
1026
|
+
center: ev.target.getCenter(),
|
|
1027
|
+
zoom: ev.target.getZoom()
|
|
1008
1028
|
});
|
|
1009
|
-
}
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
}
|
|
1029
|
+
}
|
|
1030
|
+
});
|
|
1031
|
+
const { attention } = useMapContext(MapTiles.displayName);
|
|
1032
|
+
useEffect5(() => {
|
|
1033
|
+
if (ref.current) {
|
|
1034
|
+
ref.current.getContainer().dataset.attention = attention ? "1" : "0";
|
|
1035
|
+
}
|
|
1016
1036
|
}, [
|
|
1017
|
-
|
|
1018
|
-
onChange
|
|
1037
|
+
attention
|
|
1019
1038
|
]);
|
|
1039
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
|
|
1040
|
+
ref,
|
|
1041
|
+
"data-attention": attention,
|
|
1042
|
+
detectRetina: true,
|
|
1043
|
+
className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
|
|
1044
|
+
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
1045
|
+
keepBuffer: 4
|
|
1046
|
+
}));
|
|
1047
|
+
} finally {
|
|
1048
|
+
_effect.f();
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
MapTiles.displayName = "Map.Tiles";
|
|
1052
|
+
var MapMarkers = ({ selected, markers }) => {
|
|
1053
|
+
var _effect = _useSignals4();
|
|
1054
|
+
try {
|
|
1055
|
+
const map = useMap();
|
|
1020
1056
|
useEffect5(() => {
|
|
1021
1057
|
if (markers.length > 0) {
|
|
1022
1058
|
const bounds = latLngBounds(markers.map((marker) => marker.location));
|
|
1023
1059
|
map.fitBounds(bounds);
|
|
1024
1060
|
} else {
|
|
1025
|
-
map.setView(
|
|
1061
|
+
map.setView(defaults2.center, defaults2.zoom);
|
|
1026
1062
|
}
|
|
1027
1063
|
}, [
|
|
1028
1064
|
markers
|
|
1029
1065
|
]);
|
|
1030
|
-
return /* @__PURE__ */ React4.createElement(
|
|
1031
|
-
ref,
|
|
1032
|
-
className: "flex w-full h-full overflow-hidden bg-baseSurface"
|
|
1033
|
-
}, /* @__PURE__ */ React4.createElement(TileLayer, {
|
|
1034
|
-
className: "dark:filter dark:grayscale dark:invert",
|
|
1035
|
-
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
1036
|
-
}), markers?.map(({ id, title, location: { lat, lng } }) => {
|
|
1066
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
|
|
1037
1067
|
return /* @__PURE__ */ React4.createElement(Marker, {
|
|
1038
1068
|
key: id,
|
|
1039
1069
|
position: {
|
|
@@ -1042,6 +1072,7 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
|
|
|
1042
1072
|
},
|
|
1043
1073
|
icon: (
|
|
1044
1074
|
// TODO(burdon): Create custom icon from bundled assets.
|
|
1075
|
+
// TODO(burdon): Selection state.
|
|
1045
1076
|
new L.Icon({
|
|
1046
1077
|
iconUrl: "https://dxos.network/marker-icon.png",
|
|
1047
1078
|
iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
|
|
@@ -1069,7 +1100,8 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
|
|
|
1069
1100
|
} finally {
|
|
1070
1101
|
_effect.f();
|
|
1071
1102
|
}
|
|
1072
|
-
}
|
|
1103
|
+
};
|
|
1104
|
+
MapMarkers.displayName = "Map.Markers";
|
|
1073
1105
|
var CustomControl2 = ({ position, children }) => {
|
|
1074
1106
|
var _effect = _useSignals4();
|
|
1075
1107
|
try {
|
|
@@ -1102,35 +1134,38 @@ var CustomControl2 = ({ position, children }) => {
|
|
|
1102
1134
|
_effect.f();
|
|
1103
1135
|
}
|
|
1104
1136
|
};
|
|
1137
|
+
var MapZoom = ({ onAction, position = "bottomleft", ...props }) => {
|
|
1138
|
+
var _effect = _useSignals4();
|
|
1139
|
+
try {
|
|
1140
|
+
return /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1141
|
+
position,
|
|
1142
|
+
...props
|
|
1143
|
+
}, /* @__PURE__ */ React4.createElement(ZoomControls, {
|
|
1144
|
+
onAction
|
|
1145
|
+
}));
|
|
1146
|
+
} finally {
|
|
1147
|
+
_effect.f();
|
|
1148
|
+
}
|
|
1149
|
+
};
|
|
1150
|
+
var MapAction = ({ onAction, position = "bottomright", ...props }) => {
|
|
1151
|
+
var _effect = _useSignals4();
|
|
1152
|
+
try {
|
|
1153
|
+
return /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1154
|
+
position,
|
|
1155
|
+
...props
|
|
1156
|
+
}, /* @__PURE__ */ React4.createElement(ActionControls, {
|
|
1157
|
+
onAction
|
|
1158
|
+
}));
|
|
1159
|
+
} finally {
|
|
1160
|
+
_effect.f();
|
|
1161
|
+
}
|
|
1162
|
+
};
|
|
1105
1163
|
var Map = {
|
|
1106
1164
|
Root: MapRoot,
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
return /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1112
|
-
position,
|
|
1113
|
-
...props
|
|
1114
|
-
}, /* @__PURE__ */ React4.createElement(ZoomControls, {
|
|
1115
|
-
onAction
|
|
1116
|
-
}));
|
|
1117
|
-
} finally {
|
|
1118
|
-
_effect.f();
|
|
1119
|
-
}
|
|
1120
|
-
},
|
|
1121
|
-
Action: ({ onAction, position = "bottomright", ...props }) => {
|
|
1122
|
-
var _effect = _useSignals4();
|
|
1123
|
-
try {
|
|
1124
|
-
return /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1125
|
-
position,
|
|
1126
|
-
...props
|
|
1127
|
-
}, /* @__PURE__ */ React4.createElement(ActionControls, {
|
|
1128
|
-
onAction
|
|
1129
|
-
}));
|
|
1130
|
-
} finally {
|
|
1131
|
-
_effect.f();
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1165
|
+
Tiles: MapTiles,
|
|
1166
|
+
Markers: MapMarkers,
|
|
1167
|
+
Zoom: MapZoom,
|
|
1168
|
+
Action: MapAction
|
|
1134
1169
|
};
|
|
1135
1170
|
export {
|
|
1136
1171
|
ActionControls,
|
|
@@ -1152,6 +1187,8 @@ export {
|
|
|
1152
1187
|
renderLayers,
|
|
1153
1188
|
restrictAxis,
|
|
1154
1189
|
timer,
|
|
1190
|
+
translationKey,
|
|
1191
|
+
translations,
|
|
1155
1192
|
useDrag,
|
|
1156
1193
|
useGlobeContext,
|
|
1157
1194
|
useGlobeZoomHandler,
|