@dxos/react-ui-geo 0.8.3 → 0.8.4-main.1da679c

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 (83) 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-WI4PCLDF.mjs → countries-110m-ZM3ZIEFS.mjs} +2 -2
  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 +189 -161
  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-PIIEDZEU.mjs → chunk-JODBF4CC.mjs} +3 -3
  14. package/dist/lib/node-esm/{countries-110m-DQ4XRC4B.mjs → countries-110m-3SFASWVD.mjs} +2 -2
  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 +189 -161
  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 +22 -8
  23. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Map/Map.d.ts +25 -12
  25. package/dist/types/src/components/Map/Map.d.ts.map +1 -1
  26. package/dist/types/src/components/Map/Map.stories.d.ts +11 -7
  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 +14 -11
  51. package/src/components/Globe/Globe.stories.tsx +80 -33
  52. package/src/components/Globe/Globe.tsx +74 -58
  53. package/src/components/Map/Map.stories.tsx +20 -10
  54. package/src/components/Map/Map.tsx +206 -91
  55. package/src/components/Toolbar/Controls.tsx +2 -6
  56. package/src/components/index.ts +0 -2
  57. package/src/hooks/context.tsx +10 -10
  58. package/src/hooks/useGlobeZoomHandler.ts +3 -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-ENCWOTYX.mjs +0 -9
  68. package/dist/lib/browser/countries-110m-WI4PCLDF.mjs.map +0 -7
  69. package/dist/lib/node/chunk-LAICG6L2.cjs +0 -40
  70. package/dist/lib/node/chunk-LAICG6L2.cjs.map +0 -7
  71. package/dist/lib/node/countries-110m-KQ5WAB2O.cjs +0 -37877
  72. package/dist/lib/node/countries-110m-KQ5WAB2O.cjs.map +0 -7
  73. package/dist/lib/node/data.cjs +0 -28
  74. package/dist/lib/node/data.cjs.map +0 -7
  75. package/dist/lib/node/index.cjs +0 -1187
  76. package/dist/lib/node/index.cjs.map +0 -7
  77. package/dist/lib/node/meta.json +0 -1
  78. package/dist/lib/node-esm/countries-110m-DQ4XRC4B.mjs.map +0 -7
  79. package/dist/types/src/components/types.d.ts +0 -15
  80. package/dist/types/src/components/types.d.ts.map +0 -1
  81. package/src/components/types.ts +0 -19
  82. /package/dist/lib/browser/{chunk-ENCWOTYX.mjs.map → chunk-GMWLKTLN.mjs.map} +0 -0
  83. /package/dist/lib/node-esm/{chunk-PIIEDZEU.mjs.map → chunk-JODBF4CC.mjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  loadTopology
3
- } from "./chunk-ENCWOTYX.mjs";
3
+ } from "./chunk-GMWLKTLN.mjs";
4
4
  export {
5
5
  loadTopology
6
6
  };
@@ -1,37 +1,37 @@
1
1
  import {
2
2
  loadTopology
3
- } from "./chunk-ENCWOTYX.mjs";
3
+ } from "./chunk-GMWLKTLN.mjs";
4
4
 
5
- // packages/ui/react-ui-geo/src/components/Globe/Globe.tsx
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";
11
11
  import { mx } from "@dxos/react-ui-theme";
12
12
 
13
- // packages/ui/react-ui-geo/src/hooks/context.tsx
13
+ // src/hooks/context.tsx
14
14
  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
18
  var GlobeContext = /* @__PURE__ */ createContext(void 0);
19
- var GlobeContextProvider = ({ children, size, center: _center, scale: _scale, translation: _translation, rotation: _rotation }) => {
19
+ var GlobeContextProvider = ({ children, size, center: _center, zoom: _zoom, translation: _translation, rotation: _rotation }) => {
20
20
  var _effect = _useSignals();
21
21
  try {
22
22
  const [center, setCenter] = useControlledState(_center);
23
- const [scale, setScale] = useControlledState(_scale);
23
+ const [zoom, setZoom] = useControlledState(_zoom);
24
24
  const [translation, setTranslation] = useControlledState(_translation);
25
25
  const [rotation, setRotation] = useControlledState(_rotation);
26
26
  return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
27
27
  value: {
28
28
  size,
29
29
  center,
30
- scale,
30
+ zoom,
31
31
  translation,
32
32
  rotation,
33
33
  setCenter,
34
- setScale,
34
+ setZoom,
35
35
  setTranslation,
36
36
  setRotation
37
37
  }
@@ -44,11 +44,11 @@ var useGlobeContext = () => {
44
44
  return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
45
45
  };
46
46
 
47
- // packages/ui/react-ui-geo/src/hooks/useDrag.ts
47
+ // src/hooks/useDrag.ts
48
48
  import { select as select2 } from "d3";
49
49
  import { useEffect } from "react";
50
50
 
51
- // packages/ui/react-ui-geo/src/util/debug.ts
51
+ // src/util/debug.ts
52
52
  var debug = false;
53
53
  var timer = (cb) => {
54
54
  const start = Date.now();
@@ -63,8 +63,8 @@ var timer = (cb) => {
63
63
  return data;
64
64
  };
65
65
 
66
- // packages/ui/react-ui-geo/src/util/inertia.ts
67
- import { select, drag, timer as timer2 } from "d3";
66
+ // src/util/inertia.ts
67
+ import { drag, select, timer as timer2 } from "d3";
68
68
  import versor from "versor";
69
69
  var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
70
70
  var geoInertiaDrag = (target, render, projection, options) => {
@@ -238,7 +238,7 @@ function inertiaHelper(opt) {
238
238
  return inertia;
239
239
  }
240
240
 
241
- // packages/ui/react-ui-geo/src/util/path.ts
241
+ // src/util/path.ts
242
242
  import { geoCircle as d3GeoCircle } from "d3";
243
243
  var positionToRotation = ([lng, lat], tilt = 0) => [
244
244
  -lng,
@@ -291,7 +291,7 @@ var getDistance = (point1, point2) => {
291
291
  return Math.sqrt(dx * dx + dy * dy);
292
292
  };
293
293
 
294
- // packages/ui/react-ui-geo/src/util/render.ts
294
+ // src/util/render.ts
295
295
  import { geoGraticule } from "d3";
296
296
  import { feature, mesh } from "topojson-client";
297
297
  var createLayers = (topology, features, styles) => {
@@ -376,8 +376,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
376
376
  generator.pointRadius(value * scale);
377
377
  } else {
378
378
  context[key] = value;
379
- fill ||= key === "fillStyle";
380
- stroke ||= key === "strokeStyle";
379
+ fill || (fill = key === "fillStyle");
380
+ stroke || (stroke = key === "strokeStyle");
381
381
  }
382
382
  });
383
383
  }
@@ -390,7 +390,7 @@ var renderLayers = (generator, layers = [], scale, styles) => {
390
390
  return context;
391
391
  };
392
392
 
393
- // packages/ui/react-ui-geo/src/hooks/useDrag.ts
393
+ // src/hooks/useDrag.ts
394
394
  var useDrag = (controller, options = {}) => {
395
395
  useEffect(() => {
396
396
  const canvas = controller?.canvas;
@@ -425,7 +425,7 @@ var useDrag = (controller, options = {}) => {
425
425
  };
426
426
  var cancelDrag = (node) => node.on(".drag", null);
427
427
 
428
- // packages/ui/react-ui-geo/src/hooks/useGlobeZoomHandler.ts
428
+ // src/hooks/useGlobeZoomHandler.ts
429
429
  import { useCallback } from "react";
430
430
  var useGlobeZoomHandler = (controller) => {
431
431
  return useCallback((event) => {
@@ -434,11 +434,11 @@ var useGlobeZoomHandler = (controller) => {
434
434
  }
435
435
  switch (event) {
436
436
  case "zoom-in": {
437
- controller.setScale((scale) => scale * 1.1);
437
+ controller.setZoom((zoom) => zoom * 1.1);
438
438
  break;
439
439
  }
440
440
  case "zoom-out": {
441
- controller.setScale((scale) => scale * 0.9);
441
+ controller.setZoom((zoom) => zoom * 0.9);
442
442
  break;
443
443
  }
444
444
  }
@@ -447,7 +447,7 @@ var useGlobeZoomHandler = (controller) => {
447
447
  ]);
448
448
  };
449
449
 
450
- // packages/ui/react-ui-geo/src/hooks/useMapZoomHandler.ts
450
+ // src/hooks/useMapZoomHandler.ts
451
451
  import { useCallback as useCallback2 } from "react";
452
452
  var useMapZoomHandler = (controller) => {
453
453
  return useCallback2((event) => {
@@ -469,7 +469,7 @@ var useMapZoomHandler = (controller) => {
469
469
  ]);
470
470
  };
471
471
 
472
- // packages/ui/react-ui-geo/src/hooks/useSpinner.ts
472
+ // src/hooks/useSpinner.ts
473
473
  import { timer as d3Timer } from "d3";
474
474
  import { useEffect as useEffect2, useState } from "react";
475
475
  var useSpinner = (controller, options = {}) => {
@@ -522,9 +522,9 @@ var useSpinner = (controller, options = {}) => {
522
522
  ];
523
523
  };
524
524
 
525
- // packages/ui/react-ui-geo/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";
525
+ // src/hooks/useTour.ts
526
+ import { selection as d3Selection, geoDistance, geoInterpolate, geoPath } from "d3";
527
+ import { useEffect as useEffect3, useMemo, useState as useState2 } from "react";
528
528
  import versor2 from "versor";
529
529
  var TRANSITION_NAME = "globe-tour";
530
530
  var defaultDuration = 1500;
@@ -571,7 +571,7 @@ var useTour = (controller, points, options = {}) => {
571
571
  {
572
572
  context.beginPath();
573
573
  context.strokeStyle = options?.styles?.arc?.strokeStyle ?? "yellow";
574
- context.lineWidth = (options?.styles?.arc?.lineWidth ?? 1.5) * (controller?.scale ?? 1);
574
+ context.lineWidth = (options?.styles?.arc?.lineWidth ?? 1.5) * (controller?.zoom ?? 1);
575
575
  context.setLineDash(options?.styles?.arc?.lineDash ?? []);
576
576
  path({
577
577
  type: "LineString",
@@ -583,7 +583,7 @@ var useTour = (controller, points, options = {}) => {
583
583
  context.stroke();
584
584
  context.beginPath();
585
585
  context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
586
- path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.scale ?? 1));
586
+ path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.zoom ?? 1));
587
587
  path({
588
588
  type: "Point",
589
589
  coordinates: ip(t22)
@@ -597,7 +597,7 @@ var useTour = (controller, points, options = {}) => {
597
597
  await transition2.end();
598
598
  last = next;
599
599
  }
600
- } catch (err) {
600
+ } catch {
601
601
  } finally {
602
602
  setRunning(false);
603
603
  }
@@ -618,7 +618,7 @@ var useTour = (controller, points, options = {}) => {
618
618
  ];
619
619
  };
620
620
 
621
- // packages/ui/react-ui-geo/src/components/Toolbar/Controls.tsx
621
+ // src/components/Toolbar/Controls.tsx
622
622
  import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
623
623
  import React2 from "react";
624
624
  import { IconButton, Toolbar } from "@dxos/react-ui";
@@ -633,11 +633,10 @@ var ZoomControls = ({ classNames, onAction }) => {
633
633
  try {
634
634
  return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
635
635
  classNames: [
636
- "gap-1",
636
+ "gap-2",
637
637
  classNames
638
638
  ]
639
639
  }, /* @__PURE__ */ React2.createElement(IconButton, {
640
- //
641
640
  icon: "ph--plus--regular",
642
641
  label: "zoom in",
643
642
  iconOnly: true,
@@ -645,7 +644,6 @@ var ZoomControls = ({ classNames, onAction }) => {
645
644
  classNames: "px-0 aspect-square",
646
645
  onClick: () => onAction?.("zoom-in")
647
646
  }), /* @__PURE__ */ React2.createElement(IconButton, {
648
- //
649
647
  icon: "ph--minus--regular",
650
648
  label: "zoom out",
651
649
  iconOnly: true,
@@ -662,11 +660,10 @@ var ActionControls = ({ classNames, onAction }) => {
662
660
  try {
663
661
  return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
664
662
  classNames: [
665
- "gap-1",
663
+ "gap-2",
666
664
  classNames
667
665
  ]
668
666
  }, /* @__PURE__ */ React2.createElement(IconButton, {
669
- //
670
667
  icon: "ph--play--regular",
671
668
  label: "start",
672
669
  iconOnly: true,
@@ -674,7 +671,6 @@ var ActionControls = ({ classNames, onAction }) => {
674
671
  classNames: "px-0 aspect-square",
675
672
  onClick: () => onAction?.("start")
676
673
  }), /* @__PURE__ */ React2.createElement(IconButton, {
677
- //
678
674
  icon: "ph--globe-hemisphere-west--regular",
679
675
  label: "toggle",
680
676
  iconOnly: true,
@@ -687,7 +683,7 @@ var ActionControls = ({ classNames, onAction }) => {
687
683
  }
688
684
  };
689
685
 
690
- // packages/ui/react-ui-geo/src/components/Globe/Globe.tsx
686
+ // src/components/Globe/Globe.tsx
691
687
  var defaultStyles = {
692
688
  light: {
693
689
  background: {
@@ -780,11 +776,11 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
780
776
  features,
781
777
  styles
782
778
  ]);
783
- const { size, center, scale, translation, rotation, setCenter, setScale, setTranslation, setRotation } = useGlobeContext();
784
- const scaleRef = useDynamicRef(scale);
779
+ const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
780
+ const zoomRef = useDynamicRef(zoom);
785
781
  useEffect4(() => {
786
782
  if (center) {
787
- setScale(1);
783
+ setZoom(1);
788
784
  setRotation(positionToRotation(geoToPosition(center)));
789
785
  }
790
786
  }, [
@@ -796,20 +792,20 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
796
792
  canvas,
797
793
  projection,
798
794
  center,
799
- get scale() {
800
- return scaleRef.current;
795
+ get zoom() {
796
+ return zoomRef.current;
801
797
  },
802
798
  translation,
803
799
  rotation,
804
800
  setCenter,
805
- setScale: (s) => {
801
+ setZoom: (s) => {
806
802
  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", () => {
803
+ const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
804
+ transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
809
805
  zooming.current = false;
810
806
  });
811
807
  } else {
812
- setScale(s);
808
+ setZoom(s);
813
809
  }
814
810
  },
815
811
  setTranslation,
@@ -827,7 +823,7 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
827
823
  useEffect4(() => {
828
824
  if (canvas && projection) {
829
825
  timer(() => {
830
- projection.scale(Math.min(size.width, size.height) / 2 * scale).translate([
826
+ projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
831
827
  size.width / 2 + (translation?.x ?? 0),
832
828
  size.height / 2 + (translation?.y ?? 0)
833
829
  ]).rotate(rotation ?? [
@@ -835,13 +831,13 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
835
831
  0,
836
832
  0
837
833
  ]);
838
- renderLayers(generator, layers, scale, styles);
834
+ renderLayers(generator, layers, zoom, styles);
839
835
  });
840
836
  }
841
837
  }, [
842
838
  generator,
843
839
  size,
844
- scale,
840
+ zoom,
845
841
  translation,
846
842
  rotation,
847
843
  layers
@@ -861,14 +857,14 @@ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topolog
861
857
  var GlobeDebug = ({ position = "topleft" }) => {
862
858
  var _effect = _useSignals3();
863
859
  try {
864
- const { size, scale, translation, rotation } = useGlobeContext();
860
+ const { size, zoom, translation, rotation } = useGlobeContext();
865
861
  return /* @__PURE__ */ React3.createElement("div", {
866
862
  className: mx("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
867
863
  }, /* @__PURE__ */ React3.createElement("pre", {
868
864
  className: "font-mono text-xs text-green-700"
869
865
  }, JSON.stringify({
870
866
  size,
871
- scale,
867
+ zoom,
872
868
  translation,
873
869
  rotation
874
870
  }, null, 2)));
@@ -896,112 +892,80 @@ var CustomControl = ({ position, children }) => {
896
892
  _effect.f();
897
893
  }
898
894
  };
895
+ var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
896
+ var _effect = _useSignals3();
897
+ try {
898
+ return /* @__PURE__ */ React3.createElement(CustomControl, {
899
+ position,
900
+ ...props
901
+ }, /* @__PURE__ */ React3.createElement(ZoomControls, {
902
+ onAction
903
+ }));
904
+ } finally {
905
+ _effect.f();
906
+ }
907
+ };
908
+ var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
909
+ var _effect = _useSignals3();
910
+ try {
911
+ return /* @__PURE__ */ React3.createElement(CustomControl, {
912
+ position,
913
+ ...props
914
+ }, /* @__PURE__ */ React3.createElement(ActionControls, {
915
+ onAction
916
+ }));
917
+ } finally {
918
+ _effect.f();
919
+ }
920
+ };
899
921
  var Globe = {
900
922
  Root: GlobeRoot,
901
923
  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
- },
924
+ Zoom: GlobeZoom,
925
+ Action: GlobeAction,
928
926
  Debug: GlobeDebug,
929
927
  Panel: GlobePanel
930
928
  };
931
929
 
932
- // packages/ui/react-ui-geo/src/components/Map/Map.tsx
930
+ // src/components/Map/Map.tsx
933
931
  import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
934
932
  import "leaflet/dist/leaflet.css";
933
+ import { createContext as createContext2 } from "@radix-ui/react-context";
935
934
  import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
936
- import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2 } from "react";
935
+ import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useRef as useRef2, useState as useState4 } from "react";
937
936
  import { createRoot } from "react-dom/client";
938
937
  import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
939
- import { useResizeDetector as useResizeDetector2 } from "react-resize-detector";
940
938
  import { debounce } from "@dxos/async";
941
939
  import { ThemeProvider, Tooltip } from "@dxos/react-ui";
942
940
  import { defaultTx, mx as mx2 } from "@dxos/react-ui-theme";
943
941
  var defaults = {
944
- // TODO(burdon): Guess location.
945
942
  center: {
946
943
  lat: 51,
947
944
  lng: 0
948
945
  },
949
946
  zoom: 4
950
947
  };
951
- var MapRoot = ({ classNames, center = defaults.center, zoom = defaults.zoom, ...props }) => {
952
- var _effect = _useSignals4();
953
- 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) => {
948
+ var [MapContextProvier, useMapContext] = createContext2("Map");
949
+ var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center = defaults.center, zoom = defaults.zoom, onChange, ...props }, forwardedRef) => {
969
950
  var _effect = _useSignals4();
970
951
  try {
971
- const { ref, width, height } = useResizeDetector2({
972
- refreshRate: 200
973
- });
974
- const map = useMap();
952
+ const [attention, setAttention] = useState4(false);
953
+ const mapRef = useRef2(null);
954
+ const map = mapRef.current;
975
955
  useImperativeHandle2(forwardedRef, () => ({
976
956
  setCenter: (center2, zoom2) => {
977
- map.setView(center2, zoom2);
957
+ mapRef.current?.setView(center2, zoom2);
978
958
  },
979
959
  setZoom: (cb) => {
980
- map.setZoom(cb(map.getZoom()));
960
+ mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
981
961
  }
982
- }), [
983
- map
984
- ]);
962
+ }), []);
985
963
  useEffect5(() => {
986
- if (width && height) {
987
- map.invalidateSize();
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);
964
+ if (!map) {
965
+ return;
998
966
  }
999
- }, [
1000
- center,
1001
- zoom
1002
- ]);
1003
- useEffect5(() => {
1004
967
  const handler = debounce(() => {
968
+ setAttention(true);
1005
969
  onChange?.({
1006
970
  center: map.getCenter(),
1007
971
  zoom: map.getZoom()
@@ -1009,14 +973,79 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
1009
973
  }, 100);
1010
974
  map.on("move", handler);
1011
975
  map.on("zoom", handler);
976
+ map.on("focus", () => setAttention(true));
977
+ map.on("blur", () => setAttention(false));
1012
978
  return () => {
1013
- map.off("move", handler);
1014
- map.off("zoom", handler);
979
+ map.off("move");
980
+ map.off("zoom");
981
+ map.off("focus");
982
+ map.off("blur");
1015
983
  };
1016
984
  }, [
1017
985
  map,
1018
986
  onChange
1019
987
  ]);
988
+ useEffect5(() => {
989
+ if (!map) {
990
+ return;
991
+ }
992
+ if (attention) {
993
+ map.scrollWheelZoom.enable();
994
+ } else {
995
+ map.scrollWheelZoom.disable();
996
+ }
997
+ }, [
998
+ map,
999
+ attention
1000
+ ]);
1001
+ return /* @__PURE__ */ React4.createElement(MapContextProvier, {
1002
+ attention
1003
+ }, /* @__PURE__ */ React4.createElement(MapContainer, {
1004
+ ...props,
1005
+ ref: mapRef,
1006
+ className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
1007
+ attributionControl: false,
1008
+ zoomControl: false,
1009
+ scrollWheelZoom,
1010
+ doubleClickZoom,
1011
+ touchZoom,
1012
+ center,
1013
+ zoom
1014
+ }));
1015
+ } finally {
1016
+ _effect.f();
1017
+ }
1018
+ });
1019
+ MapRoot.displayName = "Map.Root";
1020
+ var MapTiles = (_props) => {
1021
+ var _effect = _useSignals4();
1022
+ try {
1023
+ const ref = useRef2(null);
1024
+ const { attention } = useMapContext(MapTiles.displayName);
1025
+ useEffect5(() => {
1026
+ if (ref.current) {
1027
+ ref.current.getContainer().dataset.attention = attention ? "1" : "0";
1028
+ }
1029
+ }, [
1030
+ attention
1031
+ ]);
1032
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
1033
+ ref,
1034
+ "data-attention": attention,
1035
+ detectRetina: true,
1036
+ className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
1037
+ url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
1038
+ keepBuffer: 4
1039
+ }));
1040
+ } finally {
1041
+ _effect.f();
1042
+ }
1043
+ };
1044
+ MapTiles.displayName = "Map.Tiles";
1045
+ var MapMarkers = ({ selected, markers }) => {
1046
+ var _effect = _useSignals4();
1047
+ try {
1048
+ const map = useMap();
1020
1049
  useEffect5(() => {
1021
1050
  if (markers.length > 0) {
1022
1051
  const bounds = latLngBounds(markers.map((marker) => marker.location));
@@ -1027,13 +1056,7 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
1027
1056
  }, [
1028
1057
  markers
1029
1058
  ]);
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 } }) => {
1059
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
1037
1060
  return /* @__PURE__ */ React4.createElement(Marker, {
1038
1061
  key: id,
1039
1062
  position: {
@@ -1042,6 +1065,7 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
1042
1065
  },
1043
1066
  icon: (
1044
1067
  // TODO(burdon): Create custom icon from bundled assets.
1068
+ // TODO(burdon): Selection state.
1045
1069
  new L.Icon({
1046
1070
  iconUrl: "https://dxos.network/marker-icon.png",
1047
1071
  iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
@@ -1069,7 +1093,8 @@ var MapCanvas = /* @__PURE__ */ forwardRef2(({ markers, center, zoom, onChange }
1069
1093
  } finally {
1070
1094
  _effect.f();
1071
1095
  }
1072
- });
1096
+ };
1097
+ MapMarkers.displayName = "Map.Markers";
1073
1098
  var CustomControl2 = ({ position, children }) => {
1074
1099
  var _effect = _useSignals4();
1075
1100
  try {
@@ -1102,35 +1127,38 @@ var CustomControl2 = ({ position, children }) => {
1102
1127
  _effect.f();
1103
1128
  }
1104
1129
  };
1130
+ var MapZoom = ({ onAction, position = "bottomleft", ...props }) => {
1131
+ var _effect = _useSignals4();
1132
+ try {
1133
+ return /* @__PURE__ */ React4.createElement(CustomControl2, {
1134
+ position,
1135
+ ...props
1136
+ }, /* @__PURE__ */ React4.createElement(ZoomControls, {
1137
+ onAction
1138
+ }));
1139
+ } finally {
1140
+ _effect.f();
1141
+ }
1142
+ };
1143
+ var MapAction = ({ onAction, position = "bottomright", ...props }) => {
1144
+ var _effect = _useSignals4();
1145
+ try {
1146
+ return /* @__PURE__ */ React4.createElement(CustomControl2, {
1147
+ position,
1148
+ ...props
1149
+ }, /* @__PURE__ */ React4.createElement(ActionControls, {
1150
+ onAction
1151
+ }));
1152
+ } finally {
1153
+ _effect.f();
1154
+ }
1155
+ };
1105
1156
  var Map = {
1106
1157
  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
- }
1158
+ Tiles: MapTiles,
1159
+ Markers: MapMarkers,
1160
+ Zoom: MapZoom,
1161
+ Action: MapAction
1134
1162
  };
1135
1163
  export {
1136
1164
  ActionControls,