@dxos/react-ui-geo 0.8.4-main.3f58842 → 0.8.4-main.548089c

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