@dxos/react-ui-geo 0.8.4-main.a4bbb77 → 0.8.4-main.abd8ff62ef

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