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