@dxos/react-ui-geo 0.8.4-main.1da679c → 0.8.4-main.21d9917
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 +367 -450
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +367 -450
- 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.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +3 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +7 -10
- package/dist/types/src/components/Map/Map.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.stories.d.ts +3 -1
- 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/hooks/context.d.ts +1 -1
- package/dist/types/src/hooks/context.d.ts.map +1 -1
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
- 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/tsconfig.tsbuildinfo +1 -1
- package/package.json +27 -24
- package/src/components/Globe/Globe.stories.tsx +6 -5
- package/src/components/Globe/Globe.tsx +6 -5
- package/src/components/Map/Map.stories.tsx +5 -4
- package/src/components/Map/Map.tsx +19 -49
- package/src/components/Toolbar/Controls.tsx +12 -14
- package/src/hooks/context.tsx +14 -8
- package/src/hooks/useGlobeZoomHandler.ts +8 -2
- package/src/hooks/useTour.ts +1 -0
- package/src/index.ts +1 -0
- package/src/translations.ts +20 -0
|
@@ -3,42 +3,42 @@ import {
|
|
|
3
3
|
} from "./chunk-GMWLKTLN.mjs";
|
|
4
4
|
|
|
5
5
|
// src/components/Globe/Globe.tsx
|
|
6
|
-
import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
|
|
7
6
|
import { easeLinear, easeSinOut, geoMercator, geoOrthographic, geoPath as geoPath2, geoTransverseMercator, interpolateNumber, transition } from "d3";
|
|
8
7
|
import React3, { forwardRef, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
9
8
|
import { useResizeDetector } from "react-resize-detector";
|
|
10
9
|
import { useDynamicRef, useThemeContext } from "@dxos/react-ui";
|
|
11
|
-
import { mx } from "@dxos/
|
|
10
|
+
import { mx } from "@dxos/ui-theme";
|
|
12
11
|
|
|
13
12
|
// src/hooks/context.tsx
|
|
14
|
-
import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
|
|
15
13
|
import React, { createContext, useContext } from "react";
|
|
16
14
|
import { raise } from "@dxos/debug";
|
|
17
15
|
import { useControlledState } from "@dxos/react-ui";
|
|
16
|
+
var defaults = {
|
|
17
|
+
center: {
|
|
18
|
+
lat: 51,
|
|
19
|
+
lng: 0
|
|
20
|
+
},
|
|
21
|
+
zoom: 4
|
|
22
|
+
};
|
|
18
23
|
var GlobeContext = /* @__PURE__ */ createContext(void 0);
|
|
19
|
-
var GlobeContextProvider = ({ children, size, center:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
}
|
|
38
|
-
}, children);
|
|
39
|
-
} finally {
|
|
40
|
-
_effect.f();
|
|
41
|
-
}
|
|
24
|
+
var GlobeContextProvider = ({ children, size, center: centerProp = defaults.center, zoom: zoomProp = defaults.zoom, translation: translationProp, rotation: rotationProp }) => {
|
|
25
|
+
const [center, setCenter] = useControlledState(centerProp);
|
|
26
|
+
const [zoom, setZoom] = useControlledState(zoomProp);
|
|
27
|
+
const [translation, setTranslation] = useControlledState(translationProp);
|
|
28
|
+
const [rotation, setRotation] = useControlledState(rotationProp);
|
|
29
|
+
return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
|
|
30
|
+
value: {
|
|
31
|
+
size,
|
|
32
|
+
center,
|
|
33
|
+
zoom,
|
|
34
|
+
translation,
|
|
35
|
+
rotation,
|
|
36
|
+
setCenter,
|
|
37
|
+
setZoom,
|
|
38
|
+
setTranslation,
|
|
39
|
+
setRotation
|
|
40
|
+
}
|
|
41
|
+
}, children);
|
|
42
42
|
};
|
|
43
43
|
var useGlobeContext = () => {
|
|
44
44
|
return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
|
|
@@ -376,8 +376,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
376
376
|
generator.pointRadius(value * scale);
|
|
377
377
|
} else {
|
|
378
378
|
context[key] = value;
|
|
379
|
-
fill
|
|
380
|
-
stroke
|
|
379
|
+
fill ||= key === "fillStyle";
|
|
380
|
+
stroke ||= key === "strokeStyle";
|
|
381
381
|
}
|
|
382
382
|
});
|
|
383
383
|
}
|
|
@@ -427,6 +427,7 @@ var cancelDrag = (node) => node.on(".drag", null);
|
|
|
427
427
|
|
|
428
428
|
// src/hooks/useGlobeZoomHandler.ts
|
|
429
429
|
import { useCallback } from "react";
|
|
430
|
+
var ZOOM_FACTOR = 0.1;
|
|
430
431
|
var useGlobeZoomHandler = (controller) => {
|
|
431
432
|
return useCallback((event) => {
|
|
432
433
|
if (!controller) {
|
|
@@ -434,11 +435,15 @@ var useGlobeZoomHandler = (controller) => {
|
|
|
434
435
|
}
|
|
435
436
|
switch (event) {
|
|
436
437
|
case "zoom-in": {
|
|
437
|
-
controller.setZoom((zoom) =>
|
|
438
|
+
controller.setZoom((zoom) => {
|
|
439
|
+
return zoom * (1 + ZOOM_FACTOR);
|
|
440
|
+
});
|
|
438
441
|
break;
|
|
439
442
|
}
|
|
440
443
|
case "zoom-out": {
|
|
441
|
-
controller.setZoom((zoom) =>
|
|
444
|
+
controller.setZoom((zoom) => {
|
|
445
|
+
return zoom * (1 - ZOOM_FACTOR);
|
|
446
|
+
});
|
|
442
447
|
break;
|
|
443
448
|
}
|
|
444
449
|
}
|
|
@@ -619,9 +624,25 @@ var useTour = (controller, points, options = {}) => {
|
|
|
619
624
|
};
|
|
620
625
|
|
|
621
626
|
// src/components/Toolbar/Controls.tsx
|
|
622
|
-
import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
|
|
623
627
|
import React2 from "react";
|
|
624
|
-
import { IconButton, Toolbar } from "@dxos/react-ui";
|
|
628
|
+
import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
|
|
629
|
+
|
|
630
|
+
// src/translations.ts
|
|
631
|
+
var translationKey = "@dxos/react-ui-geo";
|
|
632
|
+
var translations = [
|
|
633
|
+
{
|
|
634
|
+
"en-US": {
|
|
635
|
+
[translationKey]: {
|
|
636
|
+
"zoom in icon button": "Zoom in",
|
|
637
|
+
"zoom out icon button": "Zoom out",
|
|
638
|
+
"start icon button": "Start",
|
|
639
|
+
"toggle icon button": "Toggle"
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
];
|
|
644
|
+
|
|
645
|
+
// src/components/Toolbar/Controls.tsx
|
|
625
646
|
var controlPositions = {
|
|
626
647
|
topleft: "top-2 left-2",
|
|
627
648
|
topright: "top-2 right-2",
|
|
@@ -629,58 +650,42 @@ var controlPositions = {
|
|
|
629
650
|
bottomright: "bottom-2 right-2"
|
|
630
651
|
};
|
|
631
652
|
var ZoomControls = ({ classNames, onAction }) => {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
iconOnly: true,
|
|
650
|
-
size: 5,
|
|
651
|
-
classNames: "px-0 aspect-square",
|
|
652
|
-
onClick: () => onAction?.("zoom-out")
|
|
653
|
-
}));
|
|
654
|
-
} finally {
|
|
655
|
-
_effect.f();
|
|
656
|
-
}
|
|
653
|
+
const { t } = useTranslation(translationKey);
|
|
654
|
+
return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
|
|
655
|
+
classNames: [
|
|
656
|
+
"gap-2",
|
|
657
|
+
classNames
|
|
658
|
+
]
|
|
659
|
+
}, /* @__PURE__ */ React2.createElement(IconButton, {
|
|
660
|
+
icon: "ph--plus--regular",
|
|
661
|
+
iconOnly: true,
|
|
662
|
+
label: t("zoom in icon button"),
|
|
663
|
+
onClick: () => onAction?.("zoom-in")
|
|
664
|
+
}), /* @__PURE__ */ React2.createElement(IconButton, {
|
|
665
|
+
icon: "ph--minus--regular",
|
|
666
|
+
iconOnly: true,
|
|
667
|
+
label: t("zoom out icon button"),
|
|
668
|
+
onClick: () => onAction?.("zoom-out")
|
|
669
|
+
}));
|
|
657
670
|
};
|
|
658
671
|
var ActionControls = ({ classNames, onAction }) => {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
iconOnly: true,
|
|
677
|
-
size: 5,
|
|
678
|
-
classNames: "px-0 aspect-square",
|
|
679
|
-
onClick: () => onAction?.("toggle")
|
|
680
|
-
}));
|
|
681
|
-
} finally {
|
|
682
|
-
_effect.f();
|
|
683
|
-
}
|
|
672
|
+
const { t } = useTranslation(translationKey);
|
|
673
|
+
return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
|
|
674
|
+
classNames: [
|
|
675
|
+
"gap-2",
|
|
676
|
+
classNames
|
|
677
|
+
]
|
|
678
|
+
}, /* @__PURE__ */ React2.createElement(IconButton, {
|
|
679
|
+
icon: "ph--path--regular",
|
|
680
|
+
iconOnly: true,
|
|
681
|
+
label: t("start icon button"),
|
|
682
|
+
onClick: () => onAction?.("start")
|
|
683
|
+
}), /* @__PURE__ */ React2.createElement(IconButton, {
|
|
684
|
+
icon: "ph--globe-hemisphere-west--regular",
|
|
685
|
+
iconOnly: true,
|
|
686
|
+
label: t("toggle icon button"),
|
|
687
|
+
onClick: () => onAction?.("toggle")
|
|
688
|
+
}));
|
|
684
689
|
};
|
|
685
690
|
|
|
686
691
|
// src/components/Globe/Globe.tsx
|
|
@@ -739,185 +744,146 @@ var getProjection = (type = "orthographic") => {
|
|
|
739
744
|
return type ?? geoOrthographic();
|
|
740
745
|
};
|
|
741
746
|
var GlobeRoot = ({ classNames, children, ...props }) => {
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
...props
|
|
754
|
-
}, children));
|
|
755
|
-
} finally {
|
|
756
|
-
_effect.f();
|
|
757
|
-
}
|
|
747
|
+
const { ref, width, height } = useResizeDetector();
|
|
748
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
749
|
+
ref,
|
|
750
|
+
className: mx("relative flex grow overflow-hidden", classNames)
|
|
751
|
+
}, /* @__PURE__ */ React3.createElement(GlobeContextProvider, {
|
|
752
|
+
size: {
|
|
753
|
+
width,
|
|
754
|
+
height
|
|
755
|
+
},
|
|
756
|
+
...props
|
|
757
|
+
}, children));
|
|
758
758
|
};
|
|
759
|
-
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection:
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
useImperativeHandle(forwardRef3, () => {
|
|
791
|
-
return {
|
|
792
|
-
canvas,
|
|
793
|
-
projection,
|
|
794
|
-
center,
|
|
795
|
-
get zoom() {
|
|
796
|
-
return zoomRef.current;
|
|
797
|
-
},
|
|
798
|
-
translation,
|
|
799
|
-
rotation,
|
|
800
|
-
setCenter,
|
|
801
|
-
setZoom: (s) => {
|
|
802
|
-
if (typeof s === "function") {
|
|
803
|
-
const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
|
|
804
|
-
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
805
|
-
zooming.current = false;
|
|
806
|
-
});
|
|
807
|
-
} else {
|
|
808
|
-
setZoom(s);
|
|
809
|
-
}
|
|
810
|
-
},
|
|
811
|
-
setTranslation,
|
|
812
|
-
setRotation
|
|
813
|
-
};
|
|
814
|
-
}, [
|
|
815
|
-
canvas
|
|
816
|
-
]);
|
|
817
|
-
const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
|
|
818
|
-
alpha: false
|
|
819
|
-
})), [
|
|
759
|
+
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: projectionProp, topology, features, styles: stylesProp }, forwardRef3) => {
|
|
760
|
+
const { themeMode } = useThemeContext();
|
|
761
|
+
const styles = useMemo2(() => stylesProp ?? defaultStyles[themeMode], [
|
|
762
|
+
stylesProp,
|
|
763
|
+
themeMode
|
|
764
|
+
]);
|
|
765
|
+
const [canvas, setCanvas] = useState3(null);
|
|
766
|
+
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
767
|
+
const projection = useMemo2(() => getProjection(projectionProp), [
|
|
768
|
+
projectionProp
|
|
769
|
+
]);
|
|
770
|
+
const layers = useMemo2(() => {
|
|
771
|
+
return timer(() => createLayers(topology, features, styles));
|
|
772
|
+
}, [
|
|
773
|
+
topology,
|
|
774
|
+
features,
|
|
775
|
+
styles
|
|
776
|
+
]);
|
|
777
|
+
const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
|
|
778
|
+
const zoomRef = useDynamicRef(zoom);
|
|
779
|
+
useEffect4(() => {
|
|
780
|
+
if (center) {
|
|
781
|
+
setZoom(1);
|
|
782
|
+
setRotation(positionToRotation(geoToPosition(center)));
|
|
783
|
+
}
|
|
784
|
+
}, [
|
|
785
|
+
center
|
|
786
|
+
]);
|
|
787
|
+
const zooming = useRef(false);
|
|
788
|
+
useImperativeHandle(forwardRef3, () => {
|
|
789
|
+
return {
|
|
820
790
|
canvas,
|
|
821
|
-
projection
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
827
|
-
size.width / 2 + (translation?.x ?? 0),
|
|
828
|
-
size.height / 2 + (translation?.y ?? 0)
|
|
829
|
-
]).rotate(rotation ?? [
|
|
830
|
-
0,
|
|
831
|
-
0,
|
|
832
|
-
0
|
|
833
|
-
]);
|
|
834
|
-
renderLayers(generator, layers, zoom, styles);
|
|
835
|
-
});
|
|
836
|
-
}
|
|
837
|
-
}, [
|
|
838
|
-
generator,
|
|
839
|
-
size,
|
|
840
|
-
zoom,
|
|
791
|
+
projection,
|
|
792
|
+
center,
|
|
793
|
+
get zoom() {
|
|
794
|
+
return zoomRef.current;
|
|
795
|
+
},
|
|
841
796
|
translation,
|
|
842
797
|
rotation,
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
798
|
+
setCenter,
|
|
799
|
+
setZoom: (s) => {
|
|
800
|
+
if (typeof s === "function") {
|
|
801
|
+
const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
|
|
802
|
+
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
803
|
+
zooming.current = false;
|
|
804
|
+
});
|
|
805
|
+
} else {
|
|
806
|
+
setZoom(s);
|
|
807
|
+
}
|
|
808
|
+
},
|
|
809
|
+
setTranslation,
|
|
810
|
+
setRotation
|
|
811
|
+
};
|
|
812
|
+
}, [
|
|
813
|
+
canvas
|
|
814
|
+
]);
|
|
815
|
+
const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
|
|
816
|
+
alpha: false
|
|
817
|
+
})), [
|
|
818
|
+
canvas,
|
|
819
|
+
projection
|
|
820
|
+
]);
|
|
821
|
+
useEffect4(() => {
|
|
822
|
+
if (canvas && projection) {
|
|
823
|
+
timer(() => {
|
|
824
|
+
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
825
|
+
size.width / 2 + (translation?.x ?? 0),
|
|
826
|
+
size.height / 2 + (translation?.y ?? 0)
|
|
827
|
+
]).rotate(rotation ?? [
|
|
828
|
+
0,
|
|
829
|
+
0,
|
|
830
|
+
0
|
|
831
|
+
]);
|
|
832
|
+
renderLayers(generator, layers, zoom, styles);
|
|
833
|
+
});
|
|
847
834
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
835
|
+
}, [
|
|
836
|
+
generator,
|
|
837
|
+
size,
|
|
838
|
+
zoom,
|
|
839
|
+
translation,
|
|
840
|
+
rotation,
|
|
841
|
+
layers
|
|
842
|
+
]);
|
|
843
|
+
if (!size.width || !size.height) {
|
|
844
|
+
return null;
|
|
855
845
|
}
|
|
846
|
+
return /* @__PURE__ */ React3.createElement("canvas", {
|
|
847
|
+
ref: canvasRef,
|
|
848
|
+
width: size.width,
|
|
849
|
+
height: size.height
|
|
850
|
+
});
|
|
856
851
|
});
|
|
857
852
|
var GlobeDebug = ({ position = "topleft" }) => {
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
rotation
|
|
870
|
-
}, null, 2)));
|
|
871
|
-
} finally {
|
|
872
|
-
_effect.f();
|
|
873
|
-
}
|
|
853
|
+
const { size, zoom, translation, rotation } = useGlobeContext();
|
|
854
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
855
|
+
className: mx("z-10 absolute is-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
|
|
856
|
+
}, /* @__PURE__ */ React3.createElement("pre", {
|
|
857
|
+
className: "font-mono text-xs text-green-700"
|
|
858
|
+
}, JSON.stringify({
|
|
859
|
+
size,
|
|
860
|
+
zoom,
|
|
861
|
+
translation,
|
|
862
|
+
rotation
|
|
863
|
+
}, null, 2)));
|
|
874
864
|
};
|
|
875
865
|
var GlobePanel = ({ position, classNames, children }) => {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
880
|
-
}, children);
|
|
881
|
-
} finally {
|
|
882
|
-
_effect.f();
|
|
883
|
-
}
|
|
866
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
867
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
868
|
+
}, children);
|
|
884
869
|
};
|
|
885
870
|
var CustomControl = ({ position, children }) => {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
890
|
-
}, children);
|
|
891
|
-
} finally {
|
|
892
|
-
_effect.f();
|
|
893
|
-
}
|
|
894
|
-
};
|
|
895
|
-
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
|
|
896
|
-
var _effect = _useSignals3();
|
|
897
|
-
try {
|
|
898
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
899
|
-
position,
|
|
900
|
-
...props
|
|
901
|
-
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
902
|
-
onAction
|
|
903
|
-
}));
|
|
904
|
-
} finally {
|
|
905
|
-
_effect.f();
|
|
906
|
-
}
|
|
907
|
-
};
|
|
908
|
-
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
|
|
909
|
-
var _effect = _useSignals3();
|
|
910
|
-
try {
|
|
911
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
912
|
-
position,
|
|
913
|
-
...props
|
|
914
|
-
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
915
|
-
onAction
|
|
916
|
-
}));
|
|
917
|
-
} finally {
|
|
918
|
-
_effect.f();
|
|
919
|
-
}
|
|
871
|
+
return /* @__PURE__ */ React3.createElement("div", {
|
|
872
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
873
|
+
}, children);
|
|
920
874
|
};
|
|
875
|
+
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
876
|
+
position,
|
|
877
|
+
...props
|
|
878
|
+
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
879
|
+
onAction
|
|
880
|
+
}));
|
|
881
|
+
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
882
|
+
position,
|
|
883
|
+
...props
|
|
884
|
+
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
885
|
+
onAction
|
|
886
|
+
}));
|
|
921
887
|
var Globe = {
|
|
922
888
|
Root: GlobeRoot,
|
|
923
889
|
Canvas: GlobeCanvas,
|
|
@@ -928,17 +894,15 @@ var Globe = {
|
|
|
928
894
|
};
|
|
929
895
|
|
|
930
896
|
// src/components/Map/Map.tsx
|
|
931
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
932
897
|
import "leaflet/dist/leaflet.css";
|
|
933
898
|
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
934
899
|
import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
|
|
935
900
|
import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useRef as useRef2, useState as useState4 } from "react";
|
|
936
901
|
import { createRoot } from "react-dom/client";
|
|
937
|
-
import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
|
|
938
|
-
import { debounce } from "@dxos/async";
|
|
902
|
+
import { MapContainer, Marker, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
939
903
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
|
940
|
-
import { defaultTx, mx as mx2 } from "@dxos/
|
|
941
|
-
var
|
|
904
|
+
import { defaultTx, mx as mx2 } from "@dxos/ui-theme";
|
|
905
|
+
var defaults2 = {
|
|
942
906
|
center: {
|
|
943
907
|
lat: 51,
|
|
944
908
|
lng: 0
|
|
@@ -946,213 +910,164 @@ var defaults = {
|
|
|
946
910
|
zoom: 4
|
|
947
911
|
};
|
|
948
912
|
var [MapContextProvier, useMapContext] = createContext2("Map");
|
|
949
|
-
var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
if (!map) {
|
|
990
|
-
return;
|
|
991
|
-
}
|
|
992
|
-
if (attention) {
|
|
993
|
-
map.scrollWheelZoom.enable();
|
|
994
|
-
} else {
|
|
995
|
-
map.scrollWheelZoom.disable();
|
|
996
|
-
}
|
|
997
|
-
}, [
|
|
998
|
-
map,
|
|
999
|
-
attention
|
|
1000
|
-
]);
|
|
1001
|
-
return /* @__PURE__ */ React4.createElement(MapContextProvier, {
|
|
1002
|
-
attention
|
|
1003
|
-
}, /* @__PURE__ */ React4.createElement(MapContainer, {
|
|
1004
|
-
...props,
|
|
1005
|
-
ref: mapRef,
|
|
1006
|
-
className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
|
|
1007
|
-
attributionControl: false,
|
|
1008
|
-
zoomControl: false,
|
|
1009
|
-
scrollWheelZoom,
|
|
1010
|
-
doubleClickZoom,
|
|
1011
|
-
touchZoom,
|
|
1012
|
-
center,
|
|
1013
|
-
zoom
|
|
1014
|
-
}));
|
|
1015
|
-
} finally {
|
|
1016
|
-
_effect.f();
|
|
1017
|
-
}
|
|
913
|
+
var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center, zoom, onChange, ...props }, forwardedRef) => {
|
|
914
|
+
const [attention, setAttention] = useState4(false);
|
|
915
|
+
const mapRef = useRef2(null);
|
|
916
|
+
const map = mapRef.current;
|
|
917
|
+
useImperativeHandle2(forwardedRef, () => ({
|
|
918
|
+
setCenter: (center2, zoom2) => {
|
|
919
|
+
mapRef.current?.setView(center2, zoom2);
|
|
920
|
+
},
|
|
921
|
+
setZoom: (cb) => {
|
|
922
|
+
mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
|
|
923
|
+
}
|
|
924
|
+
}), []);
|
|
925
|
+
useEffect5(() => {
|
|
926
|
+
if (!map) {
|
|
927
|
+
return;
|
|
928
|
+
}
|
|
929
|
+
if (attention) {
|
|
930
|
+
map.scrollWheelZoom.enable();
|
|
931
|
+
} else {
|
|
932
|
+
map.scrollWheelZoom.disable();
|
|
933
|
+
}
|
|
934
|
+
}, [
|
|
935
|
+
map,
|
|
936
|
+
attention
|
|
937
|
+
]);
|
|
938
|
+
return /* @__PURE__ */ React4.createElement(MapContextProvier, {
|
|
939
|
+
attention,
|
|
940
|
+
onChange
|
|
941
|
+
}, /* @__PURE__ */ React4.createElement(MapContainer, {
|
|
942
|
+
...props,
|
|
943
|
+
ref: mapRef,
|
|
944
|
+
className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
|
|
945
|
+
attributionControl: false,
|
|
946
|
+
zoomControl: false,
|
|
947
|
+
scrollWheelZoom,
|
|
948
|
+
doubleClickZoom,
|
|
949
|
+
touchZoom,
|
|
950
|
+
center: center ?? defaults2.center,
|
|
951
|
+
zoom: zoom ?? defaults2.zoom
|
|
952
|
+
}));
|
|
1018
953
|
});
|
|
1019
954
|
MapRoot.displayName = "Map.Root";
|
|
1020
955
|
var MapTiles = (_props) => {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
}
|
|
1029
|
-
}
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
956
|
+
const ref = useRef2(null);
|
|
957
|
+
const { onChange } = useMapContext(MapTiles.displayName);
|
|
958
|
+
useMapEvents({
|
|
959
|
+
zoomstart: (ev) => {
|
|
960
|
+
onChange?.({
|
|
961
|
+
center: ev.target.getCenter(),
|
|
962
|
+
zoom: ev.target.getZoom()
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
const { attention } = useMapContext(MapTiles.displayName);
|
|
967
|
+
useEffect5(() => {
|
|
968
|
+
if (ref.current) {
|
|
969
|
+
ref.current.getContainer().dataset.attention = attention ? "1" : "0";
|
|
970
|
+
}
|
|
971
|
+
}, [
|
|
972
|
+
attention
|
|
973
|
+
]);
|
|
974
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
|
|
975
|
+
ref,
|
|
976
|
+
"data-attention": attention,
|
|
977
|
+
detectRetina: true,
|
|
978
|
+
className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
|
|
979
|
+
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
980
|
+
keepBuffer: 4
|
|
981
|
+
}));
|
|
1043
982
|
};
|
|
1044
983
|
MapTiles.displayName = "Map.Tiles";
|
|
1045
984
|
var MapMarkers = ({ selected, markers }) => {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
}, title && /* @__PURE__ */ React4.createElement(Popup, null, title));
|
|
1092
|
-
}));
|
|
1093
|
-
} finally {
|
|
1094
|
-
_effect.f();
|
|
1095
|
-
}
|
|
985
|
+
const map = useMap();
|
|
986
|
+
useEffect5(() => {
|
|
987
|
+
if (markers.length > 0) {
|
|
988
|
+
const bounds = latLngBounds(markers.map((marker) => marker.location));
|
|
989
|
+
map.fitBounds(bounds);
|
|
990
|
+
} else {
|
|
991
|
+
map.setView(defaults2.center, defaults2.zoom);
|
|
992
|
+
}
|
|
993
|
+
}, [
|
|
994
|
+
markers
|
|
995
|
+
]);
|
|
996
|
+
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
|
|
997
|
+
return /* @__PURE__ */ React4.createElement(Marker, {
|
|
998
|
+
key: id,
|
|
999
|
+
position: {
|
|
1000
|
+
lat,
|
|
1001
|
+
lng
|
|
1002
|
+
},
|
|
1003
|
+
icon: (
|
|
1004
|
+
// TODO(burdon): Create custom icon from bundled assets.
|
|
1005
|
+
// TODO(burdon): Selection state.
|
|
1006
|
+
new L.Icon({
|
|
1007
|
+
iconUrl: "https://dxos.network/marker-icon.png",
|
|
1008
|
+
iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
|
|
1009
|
+
shadowUrl: "https://dxos.network/marker-shadow.png",
|
|
1010
|
+
iconSize: [
|
|
1011
|
+
25,
|
|
1012
|
+
41
|
|
1013
|
+
],
|
|
1014
|
+
iconAnchor: [
|
|
1015
|
+
12,
|
|
1016
|
+
41
|
|
1017
|
+
],
|
|
1018
|
+
popupAnchor: [
|
|
1019
|
+
1,
|
|
1020
|
+
-34
|
|
1021
|
+
],
|
|
1022
|
+
shadowSize: [
|
|
1023
|
+
41,
|
|
1024
|
+
41
|
|
1025
|
+
]
|
|
1026
|
+
})
|
|
1027
|
+
)
|
|
1028
|
+
}, title && /* @__PURE__ */ React4.createElement(Popup, null, title));
|
|
1029
|
+
}));
|
|
1096
1030
|
};
|
|
1097
1031
|
MapMarkers.displayName = "Map.Markers";
|
|
1098
1032
|
var CustomControl2 = ({ position, children }) => {
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
const
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
control.
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
]);
|
|
1125
|
-
return null;
|
|
1126
|
-
} finally {
|
|
1127
|
-
_effect.f();
|
|
1128
|
-
}
|
|
1129
|
-
};
|
|
1130
|
-
var MapZoom = ({ onAction, position = "bottomleft", ...props }) => {
|
|
1131
|
-
var _effect = _useSignals4();
|
|
1132
|
-
try {
|
|
1133
|
-
return /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1134
|
-
position,
|
|
1135
|
-
...props
|
|
1136
|
-
}, /* @__PURE__ */ React4.createElement(ZoomControls, {
|
|
1137
|
-
onAction
|
|
1138
|
-
}));
|
|
1139
|
-
} finally {
|
|
1140
|
-
_effect.f();
|
|
1141
|
-
}
|
|
1142
|
-
};
|
|
1143
|
-
var MapAction = ({ onAction, position = "bottomright", ...props }) => {
|
|
1144
|
-
var _effect = _useSignals4();
|
|
1145
|
-
try {
|
|
1146
|
-
return /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1147
|
-
position,
|
|
1148
|
-
...props
|
|
1149
|
-
}, /* @__PURE__ */ React4.createElement(ActionControls, {
|
|
1150
|
-
onAction
|
|
1151
|
-
}));
|
|
1152
|
-
} finally {
|
|
1153
|
-
_effect.f();
|
|
1154
|
-
}
|
|
1033
|
+
const map = useMap();
|
|
1034
|
+
useEffect5(() => {
|
|
1035
|
+
const control = new Control({
|
|
1036
|
+
position
|
|
1037
|
+
});
|
|
1038
|
+
control.onAdd = () => {
|
|
1039
|
+
const container = DomUtil.create("div", mx2("!m-0", controlPositions[position]));
|
|
1040
|
+
DomEvent.disableClickPropagation(container);
|
|
1041
|
+
DomEvent.disableScrollPropagation(container);
|
|
1042
|
+
const root = createRoot(container);
|
|
1043
|
+
root.render(/* @__PURE__ */ React4.createElement(ThemeProvider, {
|
|
1044
|
+
tx: defaultTx
|
|
1045
|
+
}, /* @__PURE__ */ React4.createElement(Tooltip.Provider, null, children)));
|
|
1046
|
+
return container;
|
|
1047
|
+
};
|
|
1048
|
+
control.addTo(map);
|
|
1049
|
+
return () => {
|
|
1050
|
+
control.remove();
|
|
1051
|
+
};
|
|
1052
|
+
}, [
|
|
1053
|
+
map,
|
|
1054
|
+
position,
|
|
1055
|
+
children
|
|
1056
|
+
]);
|
|
1057
|
+
return null;
|
|
1155
1058
|
};
|
|
1059
|
+
var MapZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1060
|
+
position,
|
|
1061
|
+
...props
|
|
1062
|
+
}, /* @__PURE__ */ React4.createElement(ZoomControls, {
|
|
1063
|
+
onAction
|
|
1064
|
+
}));
|
|
1065
|
+
var MapAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React4.createElement(CustomControl2, {
|
|
1066
|
+
position,
|
|
1067
|
+
...props
|
|
1068
|
+
}, /* @__PURE__ */ React4.createElement(ActionControls, {
|
|
1069
|
+
onAction
|
|
1070
|
+
}));
|
|
1156
1071
|
var Map = {
|
|
1157
1072
|
Root: MapRoot,
|
|
1158
1073
|
Tiles: MapTiles,
|
|
@@ -1180,6 +1095,8 @@ export {
|
|
|
1180
1095
|
renderLayers,
|
|
1181
1096
|
restrictAxis,
|
|
1182
1097
|
timer,
|
|
1098
|
+
translationKey,
|
|
1099
|
+
translations,
|
|
1183
1100
|
useDrag,
|
|
1184
1101
|
useGlobeContext,
|
|
1185
1102
|
useGlobeZoomHandler,
|