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