@dxos/react-ui-geo 0.8.4-main.3a94e84 → 0.8.4-main.3c1ae3b

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