@dxos/react-ui-geo 0.8.4-main.f9ba587 → 0.8.4-main.fffef41

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