@dxos/react-ui-geo 0.8.4-main.84f28bd → 0.8.4-main.ae835ea

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 (74) 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 +187 -163
  11. package/dist/lib/browser/index.mjs.map +3 -3
  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 +187 -163
  18. package/dist/lib/node-esm/index.mjs.map +3 -3
  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 +1 -1
  42. package/dist/types/src/index.d.ts.map +1 -1
  43. package/dist/types/src/types.d.ts +2 -1
  44. package/dist/types/src/types.d.ts.map +1 -1
  45. package/dist/types/src/util/path.d.ts +5 -8
  46. package/dist/types/src/util/path.d.ts.map +1 -1
  47. package/dist/types/src/util/render.d.ts +4 -4
  48. package/dist/types/src/util/render.d.ts.map +1 -1
  49. package/dist/types/tsconfig.tsbuildinfo +1 -1
  50. package/package.json +22 -19
  51. package/src/components/Globe/Globe.stories.tsx +81 -33
  52. package/src/components/Globe/Globe.tsx +78 -61
  53. package/src/components/Map/Map.stories.tsx +25 -14
  54. package/src/components/Map/Map.tsx +180 -95
  55. package/src/components/Toolbar/Controls.tsx +2 -6
  56. package/src/components/index.ts +0 -2
  57. package/src/hooks/context.tsx +22 -16
  58. package/src/hooks/useGlobeZoomHandler.ts +9 -3
  59. package/src/hooks/useMapZoomHandler.ts +1 -1
  60. package/src/hooks/useSpinner.ts +2 -1
  61. package/src/hooks/useTour.ts +9 -8
  62. package/src/index.ts +1 -1
  63. package/src/types.ts +3 -1
  64. package/src/util/inertia.ts +1 -1
  65. package/src/util/path.ts +5 -6
  66. package/src/util/render.ts +5 -3
  67. package/dist/lib/browser/chunk-CYCBMCOP.mjs +0 -9
  68. package/dist/lib/browser/countries-110m-37VAAFCK.mjs.map +0 -7
  69. package/dist/lib/node-esm/countries-110m-36TTKK5B.mjs.map +0 -7
  70. package/dist/types/src/components/types.d.ts +0 -15
  71. package/dist/types/src/components/types.d.ts.map +0 -1
  72. package/src/components/types.ts +0 -19
  73. /package/dist/lib/browser/{chunk-CYCBMCOP.mjs.map → chunk-GMWLKTLN.mjs.map} +0 -0
  74. /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
  }
@@ -634,11 +646,10 @@ var ZoomControls = ({ classNames, onAction }) => {
634
646
  try {
635
647
  return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
636
648
  classNames: [
637
- "gap-1",
649
+ "gap-2",
638
650
  classNames
639
651
  ]
640
652
  }, /* @__PURE__ */ React2.createElement(IconButton, {
641
- //
642
653
  icon: "ph--plus--regular",
643
654
  label: "zoom in",
644
655
  iconOnly: true,
@@ -646,7 +657,6 @@ var ZoomControls = ({ classNames, onAction }) => {
646
657
  classNames: "px-0 aspect-square",
647
658
  onClick: () => onAction?.("zoom-in")
648
659
  }), /* @__PURE__ */ React2.createElement(IconButton, {
649
- //
650
660
  icon: "ph--minus--regular",
651
661
  label: "zoom out",
652
662
  iconOnly: true,
@@ -663,11 +673,10 @@ var ActionControls = ({ classNames, onAction }) => {
663
673
  try {
664
674
  return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
665
675
  classNames: [
666
- "gap-1",
676
+ "gap-2",
667
677
  classNames
668
678
  ]
669
679
  }, /* @__PURE__ */ React2.createElement(IconButton, {
670
- //
671
680
  icon: "ph--play--regular",
672
681
  label: "start",
673
682
  iconOnly: true,
@@ -675,7 +684,6 @@ var ActionControls = ({ classNames, onAction }) => {
675
684
  classNames: "px-0 aspect-square",
676
685
  onClick: () => onAction?.("start")
677
686
  }), /* @__PURE__ */ React2.createElement(IconButton, {
678
- //
679
687
  icon: "ph--globe-hemisphere-west--regular",
680
688
  label: "toggle",
681
689
  iconOnly: true,
@@ -761,18 +769,18 @@ var GlobeRoot = ({ classNames, children, ...props }) => {
761
769
  _effect.f();
762
770
  }
763
771
  };
764
- var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topology, features, styles: _styles }, forwardRef3) => {
772
+ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: projectionParam, topology, features, styles: stylesParam }, forwardRef3) => {
765
773
  var _effect = _useSignals3();
766
774
  try {
767
775
  const { themeMode } = useThemeContext();
768
- const styles = useMemo2(() => _styles ?? defaultStyles[themeMode], [
769
- _styles,
776
+ const styles = useMemo2(() => stylesParam ?? defaultStyles[themeMode], [
777
+ stylesParam,
770
778
  themeMode
771
779
  ]);
772
780
  const [canvas, setCanvas] = useState3(null);
773
781
  const canvasRef = (canvas2) => setCanvas(canvas2);
774
- const projection = useMemo2(() => getProjection(_projection), [
775
- _projection
782
+ const projection = useMemo2(() => getProjection(projectionParam), [
783
+ projectionParam
776
784
  ]);
777
785
  const layers = useMemo2(() => {
778
786
  return timer(() => createLayers(topology, features, styles));
@@ -781,11 +789,11 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
781
789
  features,
782
790
  styles
783
791
  ]);
784
- const { size, center, scale, translation, rotation, setCenter, setScale, setTranslation, setRotation } = useGlobeContext();
785
- const scaleRef = useDynamicRef(scale);
792
+ const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
793
+ const zoomRef = useDynamicRef(zoom);
786
794
  useEffect4(() => {
787
795
  if (center) {
788
- setScale(1);
796
+ setZoom(1);
789
797
  setRotation(positionToRotation(geoToPosition(center)));
790
798
  }
791
799
  }, [
@@ -797,20 +805,20 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
797
805
  canvas,
798
806
  projection,
799
807
  center,
800
- get scale() {
801
- return scaleRef.current;
808
+ get zoom() {
809
+ return zoomRef.current;
802
810
  },
803
811
  translation,
804
812
  rotation,
805
813
  setCenter,
806
- setScale: (s) => {
814
+ setZoom: (s) => {
807
815
  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", () => {
816
+ const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
817
+ transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
810
818
  zooming.current = false;
811
819
  });
812
820
  } else {
813
- setScale(s);
821
+ setZoom(s);
814
822
  }
815
823
  },
816
824
  setTranslation,
@@ -828,7 +836,7 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
828
836
  useEffect4(() => {
829
837
  if (canvas && projection) {
830
838
  timer(() => {
831
- projection.scale(Math.min(size.width, size.height) / 2 * scale).translate([
839
+ projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
832
840
  size.width / 2 + (translation?.x ?? 0),
833
841
  size.height / 2 + (translation?.y ?? 0)
834
842
  ]).rotate(rotation ?? [
@@ -836,13 +844,13 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
836
844
  0,
837
845
  0
838
846
  ]);
839
- renderLayers(generator, layers, scale, styles);
847
+ renderLayers(generator, layers, zoom, styles);
840
848
  });
841
849
  }
842
850
  }, [
843
851
  generator,
844
852
  size,
845
- scale,
853
+ zoom,
846
854
  translation,
847
855
  rotation,
848
856
  layers
@@ -862,14 +870,14 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
862
870
  var GlobeDebug = ({ position = "topleft" }) => {
863
871
  var _effect = _useSignals3();
864
872
  try {
865
- const { size, scale, translation, rotation } = useGlobeContext();
873
+ const { size, zoom, translation, rotation } = useGlobeContext();
866
874
  return /* @__PURE__ */ React3.createElement("div", {
867
875
  className: mx("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
868
876
  }, /* @__PURE__ */ React3.createElement("pre", {
869
877
  className: "font-mono text-xs text-green-700"
870
878
  }, JSON.stringify({
871
879
  size,
872
- scale,
880
+ zoom,
873
881
  translation,
874
882
  rotation
875
883
  }, null, 2)));
@@ -897,35 +905,37 @@ var CustomControl = ({ position, children }) => {
897
905
  _effect.f();
898
906
  }
899
907
  };
908
+ var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
909
+ var _effect = _useSignals3();
910
+ try {
911
+ return /* @__PURE__ */ React3.createElement(CustomControl, {
912
+ position,
913
+ ...props
914
+ }, /* @__PURE__ */ React3.createElement(ZoomControls, {
915
+ onAction
916
+ }));
917
+ } finally {
918
+ _effect.f();
919
+ }
920
+ };
921
+ var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
922
+ var _effect = _useSignals3();
923
+ try {
924
+ return /* @__PURE__ */ React3.createElement(CustomControl, {
925
+ position,
926
+ ...props
927
+ }, /* @__PURE__ */ React3.createElement(ActionControls, {
928
+ onAction
929
+ }));
930
+ } finally {
931
+ _effect.f();
932
+ }
933
+ };
900
934
  var Globe = {
901
935
  Root: GlobeRoot,
902
936
  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
- },
937
+ Zoom: GlobeZoom,
938
+ Action: GlobeAction,
929
939
  Debug: GlobeDebug,
930
940
  Panel: GlobePanel
931
941
  };
@@ -933,108 +943,117 @@ var Globe = {
933
943
  // src/components/Map/Map.tsx
934
944
  import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
935
945
  import "leaflet/dist/leaflet.css";
946
+ import { createContext as createContext2 } from "@radix-ui/react-context";
936
947
  import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
937
- import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2 } from "react";
948
+ import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useRef as useRef2, useState as useState4 } from "react";
938
949
  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";
950
+ import { MapContainer, Marker, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
942
951
  import { ThemeProvider, Tooltip } from "@dxos/react-ui";
943
952
  import { defaultTx, mx as mx2 } from "@dxos/react-ui-theme";
944
- var defaults = {
945
- // TODO(burdon): Guess location.
953
+ var defaults2 = {
946
954
  center: {
947
955
  lat: 51,
948
956
  lng: 0
949
957
  },
950
958
  zoom: 4
951
959
  };
952
- var MapRoot = ({ classNames, center = defaults.center, zoom = defaults.zoom, ...props }) => {
960
+ var [MapContextProvier, useMapContext] = createContext2("Map");
961
+ var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center, zoom, onChange, ...props }, forwardedRef) => {
953
962
  var _effect = _useSignals4();
954
963
  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();
964
+ const [attention, setAttention] = useState4(false);
965
+ const mapRef = useRef2(null);
966
+ const map = mapRef.current;
976
967
  useImperativeHandle2(forwardedRef, () => ({
977
968
  setCenter: (center2, zoom2) => {
978
- map.setView(center2, zoom2);
969
+ mapRef.current?.setView(center2, zoom2);
979
970
  },
980
971
  setZoom: (cb) => {
981
- map.setZoom(cb(map.getZoom()));
972
+ mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
982
973
  }
983
- }), [
984
- map
985
- ]);
974
+ }), []);
986
975
  useEffect5(() => {
987
- if (width && height) {
988
- map.invalidateSize();
976
+ if (!map) {
977
+ return;
989
978
  }
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);
979
+ if (attention) {
980
+ map.scrollWheelZoom.enable();
981
+ } else {
982
+ map.scrollWheelZoom.disable();
999
983
  }
1000
984
  }, [
1001
- center,
1002
- zoom
985
+ map,
986
+ attention
1003
987
  ]);
1004
- useEffect5(() => {
1005
- const handler = debounce(() => {
988
+ return /* @__PURE__ */ React4.createElement(MapContextProvier, {
989
+ attention,
990
+ onChange
991
+ }, /* @__PURE__ */ React4.createElement(MapContainer, {
992
+ ...props,
993
+ ref: mapRef,
994
+ className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
995
+ attributionControl: false,
996
+ zoomControl: false,
997
+ scrollWheelZoom,
998
+ doubleClickZoom,
999
+ touchZoom,
1000
+ center: center ?? defaults2.center,
1001
+ zoom: zoom ?? defaults2.zoom
1002
+ }));
1003
+ } finally {
1004
+ _effect.f();
1005
+ }
1006
+ });
1007
+ MapRoot.displayName = "Map.Root";
1008
+ var MapTiles = (_props) => {
1009
+ var _effect = _useSignals4();
1010
+ try {
1011
+ const ref = useRef2(null);
1012
+ const { onChange } = useMapContext(MapTiles.displayName);
1013
+ useMapEvents({
1014
+ zoomstart: (ev) => {
1006
1015
  onChange?.({
1007
- center: map.getCenter(),
1008
- zoom: map.getZoom()
1016
+ center: ev.target.getCenter(),
1017
+ zoom: ev.target.getZoom()
1009
1018
  });
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
- };
1019
+ }
1020
+ });
1021
+ const { attention } = useMapContext(MapTiles.displayName);
1022
+ useEffect5(() => {
1023
+ if (ref.current) {
1024
+ ref.current.getContainer().dataset.attention = attention ? "1" : "0";
1025
+ }
1017
1026
  }, [
1018
- map,
1019
- onChange
1027
+ attention
1020
1028
  ]);
1029
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
1030
+ ref,
1031
+ "data-attention": attention,
1032
+ detectRetina: true,
1033
+ className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
1034
+ url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
1035
+ keepBuffer: 4
1036
+ }));
1037
+ } finally {
1038
+ _effect.f();
1039
+ }
1040
+ };
1041
+ MapTiles.displayName = "Map.Tiles";
1042
+ var MapMarkers = ({ selected, markers }) => {
1043
+ var _effect = _useSignals4();
1044
+ try {
1045
+ const map = useMap();
1021
1046
  useEffect5(() => {
1022
1047
  if (markers.length > 0) {
1023
1048
  const bounds = latLngBounds(markers.map((marker) => marker.location));
1024
1049
  map.fitBounds(bounds);
1025
1050
  } else {
1026
- map.setView(defaults.center, defaults.zoom);
1051
+ map.setView(defaults2.center, defaults2.zoom);
1027
1052
  }
1028
1053
  }, [
1029
1054
  markers
1030
1055
  ]);
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 } }) => {
1056
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
1038
1057
  return /* @__PURE__ */ React4.createElement(Marker, {
1039
1058
  key: id,
1040
1059
  position: {
@@ -1043,6 +1062,7 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
1043
1062
  },
1044
1063
  icon: (
1045
1064
  // TODO(burdon): Create custom icon from bundled assets.
1065
+ // TODO(burdon): Selection state.
1046
1066
  new L.Icon({
1047
1067
  iconUrl: "https://dxos.network/marker-icon.png",
1048
1068
  iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
@@ -1070,7 +1090,8 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
1070
1090
  } finally {
1071
1091
  _effect.f();
1072
1092
  }
1073
- });
1093
+ };
1094
+ MapMarkers.displayName = "Map.Markers";
1074
1095
  var CustomControl2 = ({ position, children }) => {
1075
1096
  var _effect = _useSignals4();
1076
1097
  try {
@@ -1103,35 +1124,38 @@ var CustomControl2 = ({ position, children }) => {
1103
1124
  _effect.f();
1104
1125
  }
1105
1126
  };
1127
+ var MapZoom = ({ onAction, position = "bottomleft", ...props }) => {
1128
+ var _effect = _useSignals4();
1129
+ try {
1130
+ return /* @__PURE__ */ React4.createElement(CustomControl2, {
1131
+ position,
1132
+ ...props
1133
+ }, /* @__PURE__ */ React4.createElement(ZoomControls, {
1134
+ onAction
1135
+ }));
1136
+ } finally {
1137
+ _effect.f();
1138
+ }
1139
+ };
1140
+ var MapAction = ({ onAction, position = "bottomright", ...props }) => {
1141
+ var _effect = _useSignals4();
1142
+ try {
1143
+ return /* @__PURE__ */ React4.createElement(CustomControl2, {
1144
+ position,
1145
+ ...props
1146
+ }, /* @__PURE__ */ React4.createElement(ActionControls, {
1147
+ onAction
1148
+ }));
1149
+ } finally {
1150
+ _effect.f();
1151
+ }
1152
+ };
1106
1153
  var Map = {
1107
1154
  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
- }
1155
+ Tiles: MapTiles,
1156
+ Markers: MapMarkers,
1157
+ Zoom: MapZoom,
1158
+ Action: MapAction
1135
1159
  };
1136
1160
  export {
1137
1161
  ActionControls,