@dxos/react-ui-geo 0.8.4-main.dedc0f3 → 0.8.4-main.e250131250
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 +382 -457
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +382 -457
- 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 +9 -3
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +13 -5
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +18 -11
- 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 -3
- 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 +28 -24
- package/src/components/Globe/Globe.stories.tsx +10 -9
- package/src/components/Globe/Globe.tsx +55 -28
- package/src/components/Map/Map.stories.tsx +12 -9
- package/src/components/Map/Map.tsx +82 -71
- package/src/components/Toolbar/Controls.tsx +12 -14
- package/src/hooks/context.tsx +6 -29
- 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,43 +3,16 @@ 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
|
-
import
|
|
7
|
+
import React2, { forwardRef, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
9
8
|
import { useResizeDetector } from "react-resize-detector";
|
|
10
|
-
import { useDynamicRef, useThemeContext } from "@dxos/react-ui";
|
|
11
|
-
import { mx } from "@dxos/
|
|
9
|
+
import { useComposedRefs, useControlledState, useDynamicRef, useThemeContext } from "@dxos/react-ui";
|
|
10
|
+
import { composable, composableProps, mx } from "@dxos/ui-theme";
|
|
12
11
|
|
|
13
12
|
// src/hooks/context.tsx
|
|
14
|
-
import {
|
|
15
|
-
import React, { createContext, useContext } from "react";
|
|
13
|
+
import { createContext, useContext } from "react";
|
|
16
14
|
import { raise } from "@dxos/debug";
|
|
17
|
-
import { useControlledState } from "@dxos/react-ui";
|
|
18
15
|
var GlobeContext = /* @__PURE__ */ createContext(void 0);
|
|
19
|
-
var GlobeContextProvider = ({ children, size, center: _center, zoom: _zoom, translation: _translation, rotation: _rotation }) => {
|
|
20
|
-
var _effect = _useSignals();
|
|
21
|
-
try {
|
|
22
|
-
const [center, setCenter] = useControlledState(_center);
|
|
23
|
-
const [zoom, setZoom] = useControlledState(_zoom);
|
|
24
|
-
const [translation, setTranslation] = useControlledState(_translation);
|
|
25
|
-
const [rotation, setRotation] = useControlledState(_rotation);
|
|
26
|
-
return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
|
|
27
|
-
value: {
|
|
28
|
-
size,
|
|
29
|
-
center,
|
|
30
|
-
zoom,
|
|
31
|
-
translation,
|
|
32
|
-
rotation,
|
|
33
|
-
setCenter,
|
|
34
|
-
setZoom,
|
|
35
|
-
setTranslation,
|
|
36
|
-
setRotation
|
|
37
|
-
}
|
|
38
|
-
}, children);
|
|
39
|
-
} finally {
|
|
40
|
-
_effect.f();
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
16
|
var useGlobeContext = () => {
|
|
44
17
|
return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
|
|
45
18
|
};
|
|
@@ -376,8 +349,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
376
349
|
generator.pointRadius(value * scale);
|
|
377
350
|
} else {
|
|
378
351
|
context[key] = value;
|
|
379
|
-
fill
|
|
380
|
-
stroke
|
|
352
|
+
fill ||= key === "fillStyle";
|
|
353
|
+
stroke ||= key === "strokeStyle";
|
|
381
354
|
}
|
|
382
355
|
});
|
|
383
356
|
}
|
|
@@ -427,6 +400,7 @@ var cancelDrag = (node) => node.on(".drag", null);
|
|
|
427
400
|
|
|
428
401
|
// src/hooks/useGlobeZoomHandler.ts
|
|
429
402
|
import { useCallback } from "react";
|
|
403
|
+
var ZOOM_FACTOR = 0.1;
|
|
430
404
|
var useGlobeZoomHandler = (controller) => {
|
|
431
405
|
return useCallback((event) => {
|
|
432
406
|
if (!controller) {
|
|
@@ -434,11 +408,15 @@ var useGlobeZoomHandler = (controller) => {
|
|
|
434
408
|
}
|
|
435
409
|
switch (event) {
|
|
436
410
|
case "zoom-in": {
|
|
437
|
-
controller.setZoom((zoom) =>
|
|
411
|
+
controller.setZoom((zoom) => {
|
|
412
|
+
return zoom * (1 + ZOOM_FACTOR);
|
|
413
|
+
});
|
|
438
414
|
break;
|
|
439
415
|
}
|
|
440
416
|
case "zoom-out": {
|
|
441
|
-
controller.setZoom((zoom) =>
|
|
417
|
+
controller.setZoom((zoom) => {
|
|
418
|
+
return zoom * (1 - ZOOM_FACTOR);
|
|
419
|
+
});
|
|
442
420
|
break;
|
|
443
421
|
}
|
|
444
422
|
}
|
|
@@ -619,9 +597,25 @@ var useTour = (controller, points, options = {}) => {
|
|
|
619
597
|
};
|
|
620
598
|
|
|
621
599
|
// src/components/Toolbar/Controls.tsx
|
|
622
|
-
import
|
|
623
|
-
import
|
|
624
|
-
|
|
600
|
+
import React from "react";
|
|
601
|
+
import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
|
|
602
|
+
|
|
603
|
+
// src/translations.ts
|
|
604
|
+
var translationKey = "@dxos/react-ui-geo";
|
|
605
|
+
var translations = [
|
|
606
|
+
{
|
|
607
|
+
"en-US": {
|
|
608
|
+
[translationKey]: {
|
|
609
|
+
"zoom in icon button": "Zoom in",
|
|
610
|
+
"zoom out icon button": "Zoom out",
|
|
611
|
+
"start icon button": "Start",
|
|
612
|
+
"toggle icon button": "Toggle"
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
];
|
|
617
|
+
|
|
618
|
+
// src/components/Toolbar/Controls.tsx
|
|
625
619
|
var controlPositions = {
|
|
626
620
|
topleft: "top-2 left-2",
|
|
627
621
|
topright: "top-2 right-2",
|
|
@@ -629,58 +623,42 @@ var controlPositions = {
|
|
|
629
623
|
bottomright: "bottom-2 right-2"
|
|
630
624
|
};
|
|
631
625
|
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
|
-
}
|
|
626
|
+
const { t } = useTranslation(translationKey);
|
|
627
|
+
return /* @__PURE__ */ React.createElement(Toolbar.Root, {
|
|
628
|
+
classNames: [
|
|
629
|
+
"gap-2",
|
|
630
|
+
classNames
|
|
631
|
+
]
|
|
632
|
+
}, /* @__PURE__ */ React.createElement(IconButton, {
|
|
633
|
+
icon: "ph--plus--regular",
|
|
634
|
+
iconOnly: true,
|
|
635
|
+
label: t("zoom in icon button"),
|
|
636
|
+
onClick: () => onAction?.("zoom-in")
|
|
637
|
+
}), /* @__PURE__ */ React.createElement(IconButton, {
|
|
638
|
+
icon: "ph--minus--regular",
|
|
639
|
+
iconOnly: true,
|
|
640
|
+
label: t("zoom out icon button"),
|
|
641
|
+
onClick: () => onAction?.("zoom-out")
|
|
642
|
+
}));
|
|
657
643
|
};
|
|
658
644
|
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
|
-
}
|
|
645
|
+
const { t } = useTranslation(translationKey);
|
|
646
|
+
return /* @__PURE__ */ React.createElement(Toolbar.Root, {
|
|
647
|
+
classNames: [
|
|
648
|
+
"gap-2",
|
|
649
|
+
classNames
|
|
650
|
+
]
|
|
651
|
+
}, /* @__PURE__ */ React.createElement(IconButton, {
|
|
652
|
+
icon: "ph--path--regular",
|
|
653
|
+
iconOnly: true,
|
|
654
|
+
label: t("start icon button"),
|
|
655
|
+
onClick: () => onAction?.("start")
|
|
656
|
+
}), /* @__PURE__ */ React.createElement(IconButton, {
|
|
657
|
+
icon: "ph--globe-hemisphere-west--regular",
|
|
658
|
+
iconOnly: true,
|
|
659
|
+
label: t("toggle icon button"),
|
|
660
|
+
onClick: () => onAction?.("toggle")
|
|
661
|
+
}));
|
|
684
662
|
};
|
|
685
663
|
|
|
686
664
|
// src/components/Globe/Globe.tsx
|
|
@@ -738,186 +716,166 @@ var getProjection = (type = "orthographic") => {
|
|
|
738
716
|
}
|
|
739
717
|
return type ?? geoOrthographic();
|
|
740
718
|
};
|
|
741
|
-
var GlobeRoot = ({
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
719
|
+
var GlobeRoot = composable(({ children, center: centerProp, zoom: zoomProp, translation: translationProp, rotation: rotationProp, ...props }, forwardedRef) => {
|
|
720
|
+
const localRef = useRef(null);
|
|
721
|
+
const composedRef = useComposedRefs(localRef, forwardedRef);
|
|
722
|
+
const { width, height } = useResizeDetector({
|
|
723
|
+
targetRef: localRef
|
|
724
|
+
});
|
|
725
|
+
const [center, setCenter] = useControlledState(centerProp);
|
|
726
|
+
const [zoom, setZoom] = useControlledState(zoomProp ?? 4);
|
|
727
|
+
const [translation, setTranslation] = useControlledState(translationProp);
|
|
728
|
+
const [rotation, setRotation] = useControlledState(rotationProp);
|
|
729
|
+
return /* @__PURE__ */ React2.createElement(GlobeContext.Provider, {
|
|
730
|
+
value: {
|
|
749
731
|
size: {
|
|
750
732
|
width,
|
|
751
733
|
height
|
|
752
734
|
},
|
|
753
|
-
|
|
754
|
-
}, children));
|
|
755
|
-
} finally {
|
|
756
|
-
_effect.f();
|
|
757
|
-
}
|
|
758
|
-
};
|
|
759
|
-
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topology, features, styles: _styles }, forwardRef3) => {
|
|
760
|
-
var _effect = _useSignals3();
|
|
761
|
-
try {
|
|
762
|
-
const { themeMode } = useThemeContext();
|
|
763
|
-
const styles = useMemo2(() => _styles ?? defaultStyles[themeMode], [
|
|
764
|
-
_styles,
|
|
765
|
-
themeMode
|
|
766
|
-
]);
|
|
767
|
-
const [canvas, setCanvas] = useState3(null);
|
|
768
|
-
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
769
|
-
const projection = useMemo2(() => getProjection(_projection), [
|
|
770
|
-
_projection
|
|
771
|
-
]);
|
|
772
|
-
const layers = useMemo2(() => {
|
|
773
|
-
return timer(() => createLayers(topology, features, styles));
|
|
774
|
-
}, [
|
|
775
|
-
topology,
|
|
776
|
-
features,
|
|
777
|
-
styles
|
|
778
|
-
]);
|
|
779
|
-
const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
|
|
780
|
-
const zoomRef = useDynamicRef(zoom);
|
|
781
|
-
useEffect4(() => {
|
|
782
|
-
if (center) {
|
|
783
|
-
setZoom(1);
|
|
784
|
-
setRotation(positionToRotation(geoToPosition(center)));
|
|
785
|
-
}
|
|
786
|
-
}, [
|
|
787
|
-
center
|
|
788
|
-
]);
|
|
789
|
-
const zooming = useRef(false);
|
|
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
|
-
})), [
|
|
820
|
-
canvas,
|
|
821
|
-
projection
|
|
822
|
-
]);
|
|
823
|
-
useEffect4(() => {
|
|
824
|
-
if (canvas && projection) {
|
|
825
|
-
timer(() => {
|
|
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,
|
|
735
|
+
center,
|
|
840
736
|
zoom,
|
|
841
737
|
translation,
|
|
842
738
|
rotation,
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
739
|
+
setCenter,
|
|
740
|
+
setZoom,
|
|
741
|
+
setTranslation,
|
|
742
|
+
setRotation
|
|
847
743
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
}
|
|
854
|
-
_effect.f();
|
|
855
|
-
}
|
|
744
|
+
}, /* @__PURE__ */ React2.createElement("div", {
|
|
745
|
+
...composableProps(props, {
|
|
746
|
+
classNames: "relative dx-container"
|
|
747
|
+
}),
|
|
748
|
+
ref: composedRef
|
|
749
|
+
}, children));
|
|
856
750
|
});
|
|
857
|
-
var
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
751
|
+
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: projectionProp, topology, features, styles: stylesProp }, forwardRef3) => {
|
|
752
|
+
const { themeMode } = useThemeContext();
|
|
753
|
+
const styles = useMemo2(() => stylesProp ?? defaultStyles[themeMode], [
|
|
754
|
+
stylesProp,
|
|
755
|
+
themeMode
|
|
756
|
+
]);
|
|
757
|
+
const [canvas, setCanvas] = useState3(null);
|
|
758
|
+
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
759
|
+
const projection = useMemo2(() => getProjection(projectionProp), [
|
|
760
|
+
projectionProp
|
|
761
|
+
]);
|
|
762
|
+
const layers = useMemo2(() => {
|
|
763
|
+
return timer(() => createLayers(topology, features, styles));
|
|
764
|
+
}, [
|
|
765
|
+
topology,
|
|
766
|
+
features,
|
|
767
|
+
styles
|
|
768
|
+
]);
|
|
769
|
+
const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
|
|
770
|
+
const zoomRef = useDynamicRef(zoom);
|
|
771
|
+
useEffect4(() => {
|
|
772
|
+
if (center) {
|
|
773
|
+
setZoom(1);
|
|
774
|
+
setRotation(positionToRotation(geoToPosition(center)));
|
|
775
|
+
}
|
|
776
|
+
}, [
|
|
777
|
+
center
|
|
778
|
+
]);
|
|
779
|
+
const zooming = useRef(false);
|
|
780
|
+
useImperativeHandle(forwardRef3, () => {
|
|
781
|
+
return {
|
|
782
|
+
canvas,
|
|
783
|
+
projection,
|
|
784
|
+
center,
|
|
785
|
+
get zoom() {
|
|
786
|
+
return zoomRef.current;
|
|
787
|
+
},
|
|
868
788
|
translation,
|
|
869
|
-
rotation
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
789
|
+
rotation,
|
|
790
|
+
setCenter,
|
|
791
|
+
setZoom: (state) => {
|
|
792
|
+
if (typeof state === "function") {
|
|
793
|
+
const is = interpolateNumber(zoomRef.current, state(zoomRef.current));
|
|
794
|
+
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
795
|
+
zooming.current = false;
|
|
796
|
+
});
|
|
797
|
+
} else {
|
|
798
|
+
setZoom(state);
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
setTranslation,
|
|
802
|
+
setRotation
|
|
803
|
+
};
|
|
804
|
+
}, [
|
|
805
|
+
canvas
|
|
806
|
+
]);
|
|
807
|
+
const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
|
|
808
|
+
alpha: false
|
|
809
|
+
})), [
|
|
810
|
+
canvas,
|
|
811
|
+
projection
|
|
812
|
+
]);
|
|
813
|
+
useEffect4(() => {
|
|
814
|
+
if (canvas && projection) {
|
|
815
|
+
timer(() => {
|
|
816
|
+
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
817
|
+
size.width / 2 + (translation?.x ?? 0),
|
|
818
|
+
size.height / 2 + (translation?.y ?? 0)
|
|
819
|
+
]).rotate(rotation ?? [
|
|
820
|
+
0,
|
|
821
|
+
0,
|
|
822
|
+
0
|
|
823
|
+
]);
|
|
824
|
+
renderLayers(generator, layers, zoom, styles);
|
|
825
|
+
});
|
|
826
|
+
}
|
|
827
|
+
}, [
|
|
828
|
+
generator,
|
|
829
|
+
size,
|
|
830
|
+
zoom,
|
|
831
|
+
translation,
|
|
832
|
+
rotation,
|
|
833
|
+
layers
|
|
834
|
+
]);
|
|
835
|
+
if (!size.width || !size.height) {
|
|
836
|
+
return null;
|
|
873
837
|
}
|
|
838
|
+
return /* @__PURE__ */ React2.createElement("canvas", {
|
|
839
|
+
ref: canvasRef,
|
|
840
|
+
width: size.width,
|
|
841
|
+
height: size.height
|
|
842
|
+
});
|
|
843
|
+
});
|
|
844
|
+
var GlobeDebug = ({ position = "topleft" }) => {
|
|
845
|
+
const { size, zoom, translation, rotation } = useGlobeContext();
|
|
846
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
847
|
+
className: mx("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded-sm", controlPositions[position])
|
|
848
|
+
}, /* @__PURE__ */ React2.createElement("pre", {
|
|
849
|
+
className: "font-mono text-xs text-green-700"
|
|
850
|
+
}, JSON.stringify({
|
|
851
|
+
size,
|
|
852
|
+
zoom,
|
|
853
|
+
translation,
|
|
854
|
+
rotation
|
|
855
|
+
}, null, 2)));
|
|
874
856
|
};
|
|
875
857
|
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
|
-
}
|
|
858
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
859
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
860
|
+
}, children);
|
|
884
861
|
};
|
|
885
862
|
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
|
-
}
|
|
863
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
864
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
865
|
+
}, children);
|
|
920
866
|
};
|
|
867
|
+
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React2.createElement(CustomControl, {
|
|
868
|
+
position,
|
|
869
|
+
...props
|
|
870
|
+
}, /* @__PURE__ */ React2.createElement(ZoomControls, {
|
|
871
|
+
onAction
|
|
872
|
+
}));
|
|
873
|
+
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React2.createElement(CustomControl, {
|
|
874
|
+
position,
|
|
875
|
+
...props
|
|
876
|
+
}, /* @__PURE__ */ React2.createElement(ActionControls, {
|
|
877
|
+
onAction
|
|
878
|
+
}));
|
|
921
879
|
var Globe = {
|
|
922
880
|
Root: GlobeRoot,
|
|
923
881
|
Canvas: GlobeCanvas,
|
|
@@ -928,16 +886,14 @@ var Globe = {
|
|
|
928
886
|
};
|
|
929
887
|
|
|
930
888
|
// src/components/Map/Map.tsx
|
|
931
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
932
889
|
import "leaflet/dist/leaflet.css";
|
|
933
890
|
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
934
891
|
import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
|
|
935
|
-
import
|
|
892
|
+
import React3, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useRef as useRef2 } from "react";
|
|
936
893
|
import { createRoot } from "react-dom/client";
|
|
937
|
-
import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
|
|
938
|
-
import { debounce } from "@dxos/async";
|
|
894
|
+
import { MapContainer, Marker, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
939
895
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
|
940
|
-
import { defaultTx, mx as mx2 } from "@dxos/
|
|
896
|
+
import { composable as composable2, composableProps as composableProps2, defaultTx, mx as mx2 } from "@dxos/ui-theme";
|
|
941
897
|
var defaults = {
|
|
942
898
|
center: {
|
|
943
899
|
lat: 51,
|
|
@@ -945,216 +901,183 @@ var defaults = {
|
|
|
945
901
|
},
|
|
946
902
|
zoom: 4
|
|
947
903
|
};
|
|
948
|
-
var [
|
|
949
|
-
var MapRoot =
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
}
|
|
962
|
-
}), []);
|
|
963
|
-
useEffect5(() => {
|
|
964
|
-
if (!map) {
|
|
965
|
-
return;
|
|
966
|
-
}
|
|
967
|
-
const handler = debounce(() => {
|
|
968
|
-
setAttention(true);
|
|
969
|
-
onChange?.({
|
|
970
|
-
center: map.getCenter(),
|
|
971
|
-
zoom: map.getZoom()
|
|
972
|
-
});
|
|
973
|
-
}, 100);
|
|
974
|
-
map.on("move", handler);
|
|
975
|
-
map.on("zoom", handler);
|
|
976
|
-
map.on("focus", () => setAttention(true));
|
|
977
|
-
map.on("blur", () => setAttention(false));
|
|
978
|
-
return () => {
|
|
979
|
-
map.off("move");
|
|
980
|
-
map.off("zoom");
|
|
981
|
-
map.off("focus");
|
|
982
|
-
map.off("blur");
|
|
983
|
-
};
|
|
984
|
-
}, [
|
|
985
|
-
map,
|
|
986
|
-
onChange
|
|
987
|
-
]);
|
|
988
|
-
useEffect5(() => {
|
|
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
|
-
}
|
|
904
|
+
var [MapContextProvider, useMapContext] = createContext2("Map");
|
|
905
|
+
var MapRoot = composable2(({ children, onChange, ...props }, forwardedRef) => {
|
|
906
|
+
const attention = false;
|
|
907
|
+
return /* @__PURE__ */ React3.createElement(MapContextProvider, {
|
|
908
|
+
attention,
|
|
909
|
+
onChange
|
|
910
|
+
}, /* @__PURE__ */ React3.createElement("div", {
|
|
911
|
+
...composableProps2(props, {
|
|
912
|
+
role: "none",
|
|
913
|
+
classNames: "dx-container grid dx-focus-ring-inset"
|
|
914
|
+
}),
|
|
915
|
+
ref: forwardedRef
|
|
916
|
+
}, children));
|
|
1018
917
|
});
|
|
1019
918
|
MapRoot.displayName = "Map.Root";
|
|
919
|
+
var MAP_CONTENT_NAME = "Map.Content";
|
|
920
|
+
var MapContent = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center, zoom, children, ...props }, forwardedRef) => {
|
|
921
|
+
const { attention } = useMapContext(MAP_CONTENT_NAME);
|
|
922
|
+
const mapRef = useRef2(null);
|
|
923
|
+
const map = mapRef.current;
|
|
924
|
+
useImperativeHandle2(forwardedRef, () => ({
|
|
925
|
+
setCenter: (center2, zoom2) => {
|
|
926
|
+
mapRef.current?.setView(center2, zoom2);
|
|
927
|
+
},
|
|
928
|
+
setZoom: (cb) => {
|
|
929
|
+
mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
|
|
930
|
+
}
|
|
931
|
+
}), []);
|
|
932
|
+
useEffect5(() => {
|
|
933
|
+
if (!map) {
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if (attention) {
|
|
937
|
+
map.scrollWheelZoom.enable();
|
|
938
|
+
} else {
|
|
939
|
+
map.scrollWheelZoom.disable();
|
|
940
|
+
}
|
|
941
|
+
}, [
|
|
942
|
+
map,
|
|
943
|
+
attention
|
|
944
|
+
]);
|
|
945
|
+
return /* @__PURE__ */ React3.createElement(MapContainer, {
|
|
946
|
+
...props,
|
|
947
|
+
className: mx2("group relative grid bg-base-surface!", classNames),
|
|
948
|
+
attributionControl: false,
|
|
949
|
+
zoomControl: false,
|
|
950
|
+
scrollWheelZoom,
|
|
951
|
+
doubleClickZoom,
|
|
952
|
+
touchZoom,
|
|
953
|
+
center: center ?? defaults.center,
|
|
954
|
+
zoom: zoom ?? defaults.zoom,
|
|
955
|
+
whenReady: () => {
|
|
956
|
+
},
|
|
957
|
+
ref: mapRef
|
|
958
|
+
}, children);
|
|
959
|
+
});
|
|
960
|
+
MapContent.displayName = "Map.Content";
|
|
961
|
+
var MAP_TILES_NAME = "Map.Tiles";
|
|
1020
962
|
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
|
-
|
|
963
|
+
const ref = useRef2(null);
|
|
964
|
+
const { onChange } = useMapContext(MAP_TILES_NAME);
|
|
965
|
+
useMapEvents({
|
|
966
|
+
zoomstart: (ev) => {
|
|
967
|
+
onChange?.({
|
|
968
|
+
center: ev.target.getCenter(),
|
|
969
|
+
zoom: ev.target.getZoom()
|
|
970
|
+
});
|
|
971
|
+
}
|
|
972
|
+
});
|
|
973
|
+
const { attention } = useMapContext(MAP_TILES_NAME);
|
|
974
|
+
useEffect5(() => {
|
|
975
|
+
if (ref.current) {
|
|
976
|
+
ref.current.getContainer().dataset.attention = attention ? "1" : "0";
|
|
977
|
+
}
|
|
978
|
+
}, [
|
|
979
|
+
attention
|
|
980
|
+
]);
|
|
981
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(TileLayer, {
|
|
982
|
+
ref,
|
|
983
|
+
"data-attention": attention,
|
|
984
|
+
detectRetina: true,
|
|
985
|
+
className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
|
|
986
|
+
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
987
|
+
keepBuffer: 4
|
|
988
|
+
}));
|
|
1043
989
|
};
|
|
1044
|
-
MapTiles.displayName =
|
|
990
|
+
MapTiles.displayName = MAP_TILES_NAME;
|
|
1045
991
|
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
|
-
}
|
|
992
|
+
const map = useMap();
|
|
993
|
+
useEffect5(() => {
|
|
994
|
+
if (markers.length > 0) {
|
|
995
|
+
const bounds = latLngBounds(markers.map((marker) => marker.location));
|
|
996
|
+
map.fitBounds(bounds);
|
|
997
|
+
} else {
|
|
998
|
+
map.setView(defaults.center, defaults.zoom);
|
|
999
|
+
}
|
|
1000
|
+
}, [
|
|
1001
|
+
markers
|
|
1002
|
+
]);
|
|
1003
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
|
|
1004
|
+
return /* @__PURE__ */ React3.createElement(Marker, {
|
|
1005
|
+
key: id,
|
|
1006
|
+
position: {
|
|
1007
|
+
lat,
|
|
1008
|
+
lng
|
|
1009
|
+
},
|
|
1010
|
+
icon: (
|
|
1011
|
+
// TODO(burdon): Create custom icon from bundled assets.
|
|
1012
|
+
// TODO(burdon): Selection state.
|
|
1013
|
+
new L.Icon({
|
|
1014
|
+
iconUrl: "https://dxos.network/marker-icon.png",
|
|
1015
|
+
iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
|
|
1016
|
+
shadowUrl: "https://dxos.network/marker-shadow.png",
|
|
1017
|
+
iconSize: [
|
|
1018
|
+
25,
|
|
1019
|
+
41
|
|
1020
|
+
],
|
|
1021
|
+
iconAnchor: [
|
|
1022
|
+
12,
|
|
1023
|
+
41
|
|
1024
|
+
],
|
|
1025
|
+
popupAnchor: [
|
|
1026
|
+
1,
|
|
1027
|
+
-34
|
|
1028
|
+
],
|
|
1029
|
+
shadowSize: [
|
|
1030
|
+
41,
|
|
1031
|
+
41
|
|
1032
|
+
]
|
|
1033
|
+
})
|
|
1034
|
+
)
|
|
1035
|
+
}, title && /* @__PURE__ */ React3.createElement(Popup, null, title));
|
|
1036
|
+
}));
|
|
1096
1037
|
};
|
|
1097
1038
|
MapMarkers.displayName = "Map.Markers";
|
|
1098
1039
|
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
|
-
}
|
|
1040
|
+
const map = useMap();
|
|
1041
|
+
useEffect5(() => {
|
|
1042
|
+
const control = new Control({
|
|
1043
|
+
position
|
|
1044
|
+
});
|
|
1045
|
+
control.onAdd = () => {
|
|
1046
|
+
const container = DomUtil.create("div", mx2("m-0!", controlPositions[position]));
|
|
1047
|
+
DomEvent.disableClickPropagation(container);
|
|
1048
|
+
DomEvent.disableScrollPropagation(container);
|
|
1049
|
+
const root = createRoot(container);
|
|
1050
|
+
root.render(/* @__PURE__ */ React3.createElement(ThemeProvider, {
|
|
1051
|
+
tx: defaultTx
|
|
1052
|
+
}, /* @__PURE__ */ React3.createElement(Tooltip.Provider, null, children)));
|
|
1053
|
+
return container;
|
|
1054
|
+
};
|
|
1055
|
+
control.addTo(map);
|
|
1056
|
+
return () => {
|
|
1057
|
+
control.remove();
|
|
1058
|
+
};
|
|
1059
|
+
}, [
|
|
1060
|
+
map,
|
|
1061
|
+
position,
|
|
1062
|
+
children
|
|
1063
|
+
]);
|
|
1064
|
+
return null;
|
|
1155
1065
|
};
|
|
1066
|
+
var MapZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl2, {
|
|
1067
|
+
position,
|
|
1068
|
+
...props
|
|
1069
|
+
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
1070
|
+
onAction
|
|
1071
|
+
}));
|
|
1072
|
+
var MapAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl2, {
|
|
1073
|
+
position,
|
|
1074
|
+
...props
|
|
1075
|
+
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
1076
|
+
onAction
|
|
1077
|
+
}));
|
|
1156
1078
|
var Map = {
|
|
1157
1079
|
Root: MapRoot,
|
|
1080
|
+
Content: MapContent,
|
|
1158
1081
|
Tiles: MapTiles,
|
|
1159
1082
|
Markers: MapMarkers,
|
|
1160
1083
|
Zoom: MapZoom,
|
|
@@ -1163,7 +1086,7 @@ var Map = {
|
|
|
1163
1086
|
export {
|
|
1164
1087
|
ActionControls,
|
|
1165
1088
|
Globe,
|
|
1166
|
-
|
|
1089
|
+
GlobeContext,
|
|
1167
1090
|
Map,
|
|
1168
1091
|
ZoomControls,
|
|
1169
1092
|
closestPoint,
|
|
@@ -1180,6 +1103,8 @@ export {
|
|
|
1180
1103
|
renderLayers,
|
|
1181
1104
|
restrictAxis,
|
|
1182
1105
|
timer,
|
|
1106
|
+
translationKey,
|
|
1107
|
+
translations,
|
|
1183
1108
|
useDrag,
|
|
1184
1109
|
useGlobeContext,
|
|
1185
1110
|
useGlobeZoomHandler,
|