@dxos/react-ui-geo 0.8.4-main.c4373fc → 0.8.4-main.c85a9c8dae

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.
@@ -4,42 +4,42 @@ import {
4
4
  } from "./chunk-JODBF4CC.mjs";
5
5
 
6
6
  // src/components/Globe/Globe.tsx
7
- import { useSignals as _useSignals3 } from "@preact-signals/safe-react/tracking";
8
7
  import { easeLinear, easeSinOut, geoMercator, geoOrthographic, geoPath as geoPath2, geoTransverseMercator, interpolateNumber, transition } from "d3";
9
8
  import React3, { forwardRef, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState3 } from "react";
10
9
  import { useResizeDetector } from "react-resize-detector";
11
10
  import { useDynamicRef, useThemeContext } from "@dxos/react-ui";
12
- import { mx } from "@dxos/react-ui-theme";
11
+ import { mx } from "@dxos/ui-theme";
13
12
 
14
13
  // src/hooks/context.tsx
15
- import { useSignals as _useSignals } from "@preact-signals/safe-react/tracking";
16
14
  import React, { createContext, useContext } from "react";
17
15
  import { raise } from "@dxos/debug";
18
16
  import { useControlledState } from "@dxos/react-ui";
17
+ var defaults = {
18
+ center: {
19
+ lat: 51,
20
+ lng: 0
21
+ },
22
+ zoom: 4
23
+ };
19
24
  var GlobeContext = /* @__PURE__ */ createContext(void 0);
20
- var GlobeContextProvider = ({ children, size, center: _center, zoom: _zoom, translation: _translation, rotation: _rotation }) => {
21
- var _effect = _useSignals();
22
- try {
23
- const [center, setCenter] = useControlledState(_center);
24
- const [zoom, setZoom] = useControlledState(_zoom);
25
- const [translation, setTranslation] = useControlledState(_translation);
26
- const [rotation, setRotation] = useControlledState(_rotation);
27
- return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
28
- value: {
29
- size,
30
- center,
31
- zoom,
32
- translation,
33
- rotation,
34
- setCenter,
35
- setZoom,
36
- setTranslation,
37
- setRotation
38
- }
39
- }, children);
40
- } finally {
41
- _effect.f();
42
- }
25
+ var GlobeContextProvider = ({ children, size, center: centerProp = defaults.center, zoom: zoomProp = defaults.zoom, translation: translationProp, rotation: rotationProp }) => {
26
+ const [center, setCenter] = useControlledState(centerProp);
27
+ const [zoom, setZoom] = useControlledState(zoomProp);
28
+ const [translation, setTranslation] = useControlledState(translationProp);
29
+ const [rotation, setRotation] = useControlledState(rotationProp);
30
+ return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
31
+ value: {
32
+ size,
33
+ center,
34
+ zoom,
35
+ translation,
36
+ rotation,
37
+ setCenter,
38
+ setZoom,
39
+ setTranslation,
40
+ setRotation
41
+ }
42
+ }, children);
43
43
  };
44
44
  var useGlobeContext = () => {
45
45
  return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
@@ -377,8 +377,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
377
377
  generator.pointRadius(value * scale);
378
378
  } else {
379
379
  context[key] = value;
380
- fill || (fill = key === "fillStyle");
381
- stroke || (stroke = key === "strokeStyle");
380
+ fill ||= key === "fillStyle";
381
+ stroke ||= key === "strokeStyle";
382
382
  }
383
383
  });
384
384
  }
@@ -428,6 +428,7 @@ var cancelDrag = (node) => node.on(".drag", null);
428
428
 
429
429
  // src/hooks/useGlobeZoomHandler.ts
430
430
  import { useCallback } from "react";
431
+ var ZOOM_FACTOR = 0.1;
431
432
  var useGlobeZoomHandler = (controller) => {
432
433
  return useCallback((event) => {
433
434
  if (!controller) {
@@ -435,11 +436,15 @@ var useGlobeZoomHandler = (controller) => {
435
436
  }
436
437
  switch (event) {
437
438
  case "zoom-in": {
438
- controller.setZoom((zoom) => zoom * 1.1);
439
+ controller.setZoom((zoom) => {
440
+ return zoom * (1 + ZOOM_FACTOR);
441
+ });
439
442
  break;
440
443
  }
441
444
  case "zoom-out": {
442
- controller.setZoom((zoom) => zoom * 0.9);
445
+ controller.setZoom((zoom) => {
446
+ return zoom * (1 - ZOOM_FACTOR);
447
+ });
443
448
  break;
444
449
  }
445
450
  }
@@ -620,9 +625,25 @@ var useTour = (controller, points, options = {}) => {
620
625
  };
621
626
 
622
627
  // src/components/Toolbar/Controls.tsx
623
- import { useSignals as _useSignals2 } from "@preact-signals/safe-react/tracking";
624
628
  import React2 from "react";
625
- import { IconButton, Toolbar } from "@dxos/react-ui";
629
+ import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
630
+
631
+ // src/translations.ts
632
+ var translationKey = "@dxos/react-ui-geo";
633
+ var translations = [
634
+ {
635
+ "en-US": {
636
+ [translationKey]: {
637
+ "zoom in icon button": "Zoom in",
638
+ "zoom out icon button": "Zoom out",
639
+ "start icon button": "Start",
640
+ "toggle icon button": "Toggle"
641
+ }
642
+ }
643
+ }
644
+ ];
645
+
646
+ // src/components/Toolbar/Controls.tsx
626
647
  var controlPositions = {
627
648
  topleft: "top-2 left-2",
628
649
  topright: "top-2 right-2",
@@ -630,58 +651,42 @@ var controlPositions = {
630
651
  bottomright: "bottom-2 right-2"
631
652
  };
632
653
  var ZoomControls = ({ classNames, onAction }) => {
633
- var _effect = _useSignals2();
634
- try {
635
- return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
636
- classNames: [
637
- "gap-2",
638
- classNames
639
- ]
640
- }, /* @__PURE__ */ React2.createElement(IconButton, {
641
- icon: "ph--plus--regular",
642
- label: "zoom in",
643
- iconOnly: true,
644
- size: 5,
645
- classNames: "px-0 aspect-square",
646
- onClick: () => onAction?.("zoom-in")
647
- }), /* @__PURE__ */ React2.createElement(IconButton, {
648
- icon: "ph--minus--regular",
649
- label: "zoom out",
650
- iconOnly: true,
651
- size: 5,
652
- classNames: "px-0 aspect-square",
653
- onClick: () => onAction?.("zoom-out")
654
- }));
655
- } finally {
656
- _effect.f();
657
- }
654
+ const { t } = useTranslation(translationKey);
655
+ return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
656
+ classNames: [
657
+ "gap-2",
658
+ classNames
659
+ ]
660
+ }, /* @__PURE__ */ React2.createElement(IconButton, {
661
+ icon: "ph--plus--regular",
662
+ iconOnly: true,
663
+ label: t("zoom in icon button"),
664
+ onClick: () => onAction?.("zoom-in")
665
+ }), /* @__PURE__ */ React2.createElement(IconButton, {
666
+ icon: "ph--minus--regular",
667
+ iconOnly: true,
668
+ label: t("zoom out icon button"),
669
+ onClick: () => onAction?.("zoom-out")
670
+ }));
658
671
  };
659
672
  var ActionControls = ({ classNames, onAction }) => {
660
- var _effect = _useSignals2();
661
- try {
662
- return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
663
- classNames: [
664
- "gap-2",
665
- classNames
666
- ]
667
- }, /* @__PURE__ */ React2.createElement(IconButton, {
668
- icon: "ph--play--regular",
669
- label: "start",
670
- iconOnly: true,
671
- size: 5,
672
- classNames: "px-0 aspect-square",
673
- onClick: () => onAction?.("start")
674
- }), /* @__PURE__ */ React2.createElement(IconButton, {
675
- icon: "ph--globe-hemisphere-west--regular",
676
- label: "toggle",
677
- iconOnly: true,
678
- size: 5,
679
- classNames: "px-0 aspect-square",
680
- onClick: () => onAction?.("toggle")
681
- }));
682
- } finally {
683
- _effect.f();
684
- }
673
+ const { t } = useTranslation(translationKey);
674
+ return /* @__PURE__ */ React2.createElement(Toolbar.Root, {
675
+ classNames: [
676
+ "gap-2",
677
+ classNames
678
+ ]
679
+ }, /* @__PURE__ */ React2.createElement(IconButton, {
680
+ icon: "ph--path--regular",
681
+ iconOnly: true,
682
+ label: t("start icon button"),
683
+ onClick: () => onAction?.("start")
684
+ }), /* @__PURE__ */ React2.createElement(IconButton, {
685
+ icon: "ph--globe-hemisphere-west--regular",
686
+ iconOnly: true,
687
+ label: t("toggle icon button"),
688
+ onClick: () => onAction?.("toggle")
689
+ }));
685
690
  };
686
691
 
687
692
  // src/components/Globe/Globe.tsx
@@ -740,185 +745,146 @@ var getProjection = (type = "orthographic") => {
740
745
  return type ?? geoOrthographic();
741
746
  };
742
747
  var GlobeRoot = ({ classNames, children, ...props }) => {
743
- var _effect = _useSignals3();
744
- try {
745
- const { ref, width, height } = useResizeDetector();
746
- return /* @__PURE__ */ React3.createElement("div", {
747
- ref,
748
- className: mx("relative flex grow overflow-hidden", classNames)
749
- }, /* @__PURE__ */ React3.createElement(GlobeContextProvider, {
750
- size: {
751
- width,
752
- height
753
- },
754
- ...props
755
- }, children));
756
- } finally {
757
- _effect.f();
758
- }
748
+ const { ref, width, height } = useResizeDetector();
749
+ return /* @__PURE__ */ React3.createElement("div", {
750
+ ref,
751
+ className: mx("relative flex grow overflow-hidden", classNames)
752
+ }, /* @__PURE__ */ React3.createElement(GlobeContextProvider, {
753
+ size: {
754
+ width,
755
+ height
756
+ },
757
+ ...props
758
+ }, children));
759
759
  };
760
- var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topology, features, styles: _styles }, forwardRef3) => {
761
- var _effect = _useSignals3();
762
- try {
763
- const { themeMode } = useThemeContext();
764
- const styles = useMemo2(() => _styles ?? defaultStyles[themeMode], [
765
- _styles,
766
- themeMode
767
- ]);
768
- const [canvas, setCanvas] = useState3(null);
769
- const canvasRef = (canvas2) => setCanvas(canvas2);
770
- const projection = useMemo2(() => getProjection(_projection), [
771
- _projection
772
- ]);
773
- const layers = useMemo2(() => {
774
- return timer(() => createLayers(topology, features, styles));
775
- }, [
776
- topology,
777
- features,
778
- styles
779
- ]);
780
- const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
781
- const zoomRef = useDynamicRef(zoom);
782
- useEffect4(() => {
783
- if (center) {
784
- setZoom(1);
785
- setRotation(positionToRotation(geoToPosition(center)));
786
- }
787
- }, [
788
- center
789
- ]);
790
- const zooming = useRef(false);
791
- useImperativeHandle(forwardRef3, () => {
792
- return {
793
- canvas,
794
- projection,
795
- center,
796
- get zoom() {
797
- return zoomRef.current;
798
- },
799
- translation,
800
- rotation,
801
- setCenter,
802
- setZoom: (s) => {
803
- if (typeof s === "function") {
804
- const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
805
- transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
806
- zooming.current = false;
807
- });
808
- } else {
809
- setZoom(s);
810
- }
811
- },
812
- setTranslation,
813
- setRotation
814
- };
815
- }, [
816
- canvas
817
- ]);
818
- const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
819
- alpha: false
820
- })), [
760
+ var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: projectionProp, topology, features, styles: stylesProp }, forwardRef3) => {
761
+ const { themeMode } = useThemeContext();
762
+ const styles = useMemo2(() => stylesProp ?? defaultStyles[themeMode], [
763
+ stylesProp,
764
+ themeMode
765
+ ]);
766
+ const [canvas, setCanvas] = useState3(null);
767
+ const canvasRef = (canvas2) => setCanvas(canvas2);
768
+ const projection = useMemo2(() => getProjection(projectionProp), [
769
+ projectionProp
770
+ ]);
771
+ const layers = useMemo2(() => {
772
+ return timer(() => createLayers(topology, features, styles));
773
+ }, [
774
+ topology,
775
+ features,
776
+ styles
777
+ ]);
778
+ const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
779
+ const zoomRef = useDynamicRef(zoom);
780
+ useEffect4(() => {
781
+ if (center) {
782
+ setZoom(1);
783
+ setRotation(positionToRotation(geoToPosition(center)));
784
+ }
785
+ }, [
786
+ center
787
+ ]);
788
+ const zooming = useRef(false);
789
+ useImperativeHandle(forwardRef3, () => {
790
+ return {
821
791
  canvas,
822
- projection
823
- ]);
824
- useEffect4(() => {
825
- if (canvas && projection) {
826
- timer(() => {
827
- projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
828
- size.width / 2 + (translation?.x ?? 0),
829
- size.height / 2 + (translation?.y ?? 0)
830
- ]).rotate(rotation ?? [
831
- 0,
832
- 0,
833
- 0
834
- ]);
835
- renderLayers(generator, layers, zoom, styles);
836
- });
837
- }
838
- }, [
839
- generator,
840
- size,
841
- zoom,
792
+ projection,
793
+ center,
794
+ get zoom() {
795
+ return zoomRef.current;
796
+ },
842
797
  translation,
843
798
  rotation,
844
- layers
845
- ]);
846
- if (!size.width || !size.height) {
847
- return null;
799
+ setCenter,
800
+ setZoom: (state) => {
801
+ if (typeof state === "function") {
802
+ const is = interpolateNumber(zoomRef.current, state(zoomRef.current));
803
+ transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
804
+ zooming.current = false;
805
+ });
806
+ } else {
807
+ setZoom(state);
808
+ }
809
+ },
810
+ setTranslation,
811
+ setRotation
812
+ };
813
+ }, [
814
+ canvas
815
+ ]);
816
+ const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
817
+ alpha: false
818
+ })), [
819
+ canvas,
820
+ projection
821
+ ]);
822
+ useEffect4(() => {
823
+ if (canvas && projection) {
824
+ timer(() => {
825
+ projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
826
+ size.width / 2 + (translation?.x ?? 0),
827
+ size.height / 2 + (translation?.y ?? 0)
828
+ ]).rotate(rotation ?? [
829
+ 0,
830
+ 0,
831
+ 0
832
+ ]);
833
+ renderLayers(generator, layers, zoom, styles);
834
+ });
848
835
  }
849
- return /* @__PURE__ */ React3.createElement("canvas", {
850
- ref: canvasRef,
851
- width: size.width,
852
- height: size.height
853
- });
854
- } finally {
855
- _effect.f();
836
+ }, [
837
+ generator,
838
+ size,
839
+ zoom,
840
+ translation,
841
+ rotation,
842
+ layers
843
+ ]);
844
+ if (!size.width || !size.height) {
845
+ return null;
856
846
  }
847
+ return /* @__PURE__ */ React3.createElement("canvas", {
848
+ ref: canvasRef,
849
+ width: size.width,
850
+ height: size.height
851
+ });
857
852
  });
858
853
  var GlobeDebug = ({ position = "topleft" }) => {
859
- var _effect = _useSignals3();
860
- try {
861
- const { size, zoom, translation, rotation } = useGlobeContext();
862
- return /* @__PURE__ */ React3.createElement("div", {
863
- className: mx("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
864
- }, /* @__PURE__ */ React3.createElement("pre", {
865
- className: "font-mono text-xs text-green-700"
866
- }, JSON.stringify({
867
- size,
868
- zoom,
869
- translation,
870
- rotation
871
- }, null, 2)));
872
- } finally {
873
- _effect.f();
874
- }
854
+ const { size, zoom, translation, rotation } = useGlobeContext();
855
+ return /* @__PURE__ */ React3.createElement("div", {
856
+ className: mx("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded-sm", controlPositions[position])
857
+ }, /* @__PURE__ */ React3.createElement("pre", {
858
+ className: "font-mono text-xs text-green-700"
859
+ }, JSON.stringify({
860
+ size,
861
+ zoom,
862
+ translation,
863
+ rotation
864
+ }, null, 2)));
875
865
  };
876
866
  var GlobePanel = ({ position, classNames, children }) => {
877
- var _effect = _useSignals3();
878
- try {
879
- return /* @__PURE__ */ React3.createElement("div", {
880
- className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
881
- }, children);
882
- } finally {
883
- _effect.f();
884
- }
867
+ return /* @__PURE__ */ React3.createElement("div", {
868
+ className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
869
+ }, children);
885
870
  };
886
871
  var CustomControl = ({ position, children }) => {
887
- var _effect = _useSignals3();
888
- try {
889
- return /* @__PURE__ */ React3.createElement("div", {
890
- className: mx("z-10 absolute overflow-hidden", controlPositions[position])
891
- }, children);
892
- } finally {
893
- _effect.f();
894
- }
895
- };
896
- var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
897
- var _effect = _useSignals3();
898
- try {
899
- return /* @__PURE__ */ React3.createElement(CustomControl, {
900
- position,
901
- ...props
902
- }, /* @__PURE__ */ React3.createElement(ZoomControls, {
903
- onAction
904
- }));
905
- } finally {
906
- _effect.f();
907
- }
908
- };
909
- var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
910
- var _effect = _useSignals3();
911
- try {
912
- return /* @__PURE__ */ React3.createElement(CustomControl, {
913
- position,
914
- ...props
915
- }, /* @__PURE__ */ React3.createElement(ActionControls, {
916
- onAction
917
- }));
918
- } finally {
919
- _effect.f();
920
- }
872
+ return /* @__PURE__ */ React3.createElement("div", {
873
+ className: mx("z-10 absolute overflow-hidden", controlPositions[position])
874
+ }, children);
921
875
  };
876
+ var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl, {
877
+ position,
878
+ ...props
879
+ }, /* @__PURE__ */ React3.createElement(ZoomControls, {
880
+ onAction
881
+ }));
882
+ var GlobeAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl, {
883
+ position,
884
+ ...props
885
+ }, /* @__PURE__ */ React3.createElement(ActionControls, {
886
+ onAction
887
+ }));
922
888
  var Globe = {
923
889
  Root: GlobeRoot,
924
890
  Canvas: GlobeCanvas,
@@ -929,17 +895,15 @@ var Globe = {
929
895
  };
930
896
 
931
897
  // src/components/Map/Map.tsx
932
- import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
933
898
  import "leaflet/dist/leaflet.css";
934
899
  import { createContext as createContext2 } from "@radix-ui/react-context";
935
900
  import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
936
901
  import React4, { forwardRef as forwardRef2, useEffect as useEffect5, useImperativeHandle as useImperativeHandle2, useRef as useRef2, useState as useState4 } from "react";
937
902
  import { createRoot } from "react-dom/client";
938
- import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
939
- import { debounce } from "@dxos/async";
903
+ import { MapContainer, Marker, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
940
904
  import { ThemeProvider, Tooltip } from "@dxos/react-ui";
941
- import { defaultTx, mx as mx2 } from "@dxos/react-ui-theme";
942
- var defaults = {
905
+ import { defaultTx, mx as mx2 } from "@dxos/ui-theme";
906
+ var defaults2 = {
943
907
  center: {
944
908
  lat: 51,
945
909
  lng: 0
@@ -947,213 +911,165 @@ var defaults = {
947
911
  zoom: 4
948
912
  };
949
913
  var [MapContextProvier, useMapContext] = createContext2("Map");
950
- var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center = defaults.center, zoom = defaults.zoom, onChange, ...props }, forwardedRef) => {
951
- var _effect = _useSignals4();
952
- try {
953
- const [attention, setAttention] = useState4(false);
954
- const mapRef = useRef2(null);
955
- const map = mapRef.current;
956
- useImperativeHandle2(forwardedRef, () => ({
957
- setCenter: (center2, zoom2) => {
958
- mapRef.current?.setView(center2, zoom2);
959
- },
960
- setZoom: (cb) => {
961
- mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
962
- }
963
- }), []);
964
- useEffect5(() => {
965
- if (!map) {
966
- return;
967
- }
968
- const handler = debounce(() => {
969
- setAttention(true);
970
- onChange?.({
971
- center: map.getCenter(),
972
- zoom: map.getZoom()
973
- });
974
- }, 100);
975
- map.on("move", handler);
976
- map.on("zoom", handler);
977
- map.on("focus", () => setAttention(true));
978
- map.on("blur", () => setAttention(false));
979
- return () => {
980
- map.off("move");
981
- map.off("zoom");
982
- map.off("focus");
983
- map.off("blur");
984
- };
985
- }, [
986
- map,
987
- onChange
988
- ]);
989
- useEffect5(() => {
990
- if (!map) {
991
- return;
992
- }
993
- if (attention) {
994
- map.scrollWheelZoom.enable();
995
- } else {
996
- map.scrollWheelZoom.disable();
997
- }
998
- }, [
999
- map,
1000
- attention
1001
- ]);
1002
- return /* @__PURE__ */ React4.createElement(MapContextProvier, {
1003
- attention
1004
- }, /* @__PURE__ */ React4.createElement(MapContainer, {
1005
- ...props,
1006
- ref: mapRef,
1007
- className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
1008
- attributionControl: false,
1009
- zoomControl: false,
1010
- scrollWheelZoom,
1011
- doubleClickZoom,
1012
- touchZoom,
1013
- center,
1014
- zoom
1015
- }));
1016
- } finally {
1017
- _effect.f();
1018
- }
914
+ var MapRoot = /* @__PURE__ */ forwardRef2(({ classNames, scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center, zoom, onChange, ...props }, forwardedRef) => {
915
+ const [attention, setAttention] = useState4(false);
916
+ const mapRef = useRef2(null);
917
+ const map = mapRef.current;
918
+ useImperativeHandle2(forwardedRef, () => ({
919
+ setCenter: (center2, zoom2) => {
920
+ mapRef.current?.setView(center2, zoom2);
921
+ },
922
+ setZoom: (cb) => {
923
+ mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
924
+ }
925
+ }), []);
926
+ useEffect5(() => {
927
+ if (!map) {
928
+ return;
929
+ }
930
+ if (attention) {
931
+ map.scrollWheelZoom.enable();
932
+ } else {
933
+ map.scrollWheelZoom.disable();
934
+ }
935
+ }, [
936
+ map,
937
+ attention
938
+ ]);
939
+ return /* @__PURE__ */ React4.createElement(MapContextProvier, {
940
+ attention,
941
+ onChange
942
+ }, /* @__PURE__ */ React4.createElement(MapContainer, {
943
+ ...props,
944
+ ref: mapRef,
945
+ className: mx2("group relative grid h-full w-full !bg-base-surface dx-focus-ring-inset", classNames),
946
+ attributionControl: false,
947
+ zoomControl: false,
948
+ scrollWheelZoom,
949
+ doubleClickZoom,
950
+ touchZoom,
951
+ center: center ?? defaults2.center,
952
+ zoom: zoom ?? defaults2.zoom
953
+ }));
1019
954
  });
1020
955
  MapRoot.displayName = "Map.Root";
956
+ var MAP_TILES_NAME = "Map.Tiles";
1021
957
  var MapTiles = (_props) => {
1022
- var _effect = _useSignals4();
1023
- try {
1024
- const ref = useRef2(null);
1025
- const { attention } = useMapContext(MapTiles.displayName);
1026
- useEffect5(() => {
1027
- if (ref.current) {
1028
- ref.current.getContainer().dataset.attention = attention ? "1" : "0";
1029
- }
1030
- }, [
1031
- attention
1032
- ]);
1033
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
1034
- ref,
1035
- "data-attention": attention,
1036
- detectRetina: true,
1037
- className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
1038
- url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
1039
- keepBuffer: 4
1040
- }));
1041
- } finally {
1042
- _effect.f();
1043
- }
958
+ const ref = useRef2(null);
959
+ const { onChange } = useMapContext(MAP_TILES_NAME);
960
+ useMapEvents({
961
+ zoomstart: (ev) => {
962
+ onChange?.({
963
+ center: ev.target.getCenter(),
964
+ zoom: ev.target.getZoom()
965
+ });
966
+ }
967
+ });
968
+ const { attention } = useMapContext(MAP_TILES_NAME);
969
+ useEffect5(() => {
970
+ if (ref.current) {
971
+ ref.current.getContainer().dataset.attention = attention ? "1" : "0";
972
+ }
973
+ }, [
974
+ attention
975
+ ]);
976
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
977
+ ref,
978
+ "data-attention": attention,
979
+ detectRetina: true,
980
+ className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
981
+ url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
982
+ keepBuffer: 4
983
+ }));
1044
984
  };
1045
- MapTiles.displayName = "Map.Tiles";
985
+ MapTiles.displayName = MAP_TILES_NAME;
1046
986
  var MapMarkers = ({ selected, markers }) => {
1047
- var _effect = _useSignals4();
1048
- try {
1049
- const map = useMap();
1050
- useEffect5(() => {
1051
- if (markers.length > 0) {
1052
- const bounds = latLngBounds(markers.map((marker) => marker.location));
1053
- map.fitBounds(bounds);
1054
- } else {
1055
- map.setView(defaults.center, defaults.zoom);
1056
- }
1057
- }, [
1058
- markers
1059
- ]);
1060
- return /* @__PURE__ */ React4.createElement(React4.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
1061
- return /* @__PURE__ */ React4.createElement(Marker, {
1062
- key: id,
1063
- position: {
1064
- lat,
1065
- lng
1066
- },
1067
- icon: (
1068
- // TODO(burdon): Create custom icon from bundled assets.
1069
- // TODO(burdon): Selection state.
1070
- new L.Icon({
1071
- iconUrl: "https://dxos.network/marker-icon.png",
1072
- iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
1073
- shadowUrl: "https://dxos.network/marker-shadow.png",
1074
- iconSize: [
1075
- 25,
1076
- 41
1077
- ],
1078
- iconAnchor: [
1079
- 12,
1080
- 41
1081
- ],
1082
- popupAnchor: [
1083
- 1,
1084
- -34
1085
- ],
1086
- shadowSize: [
1087
- 41,
1088
- 41
1089
- ]
1090
- })
1091
- )
1092
- }, title && /* @__PURE__ */ React4.createElement(Popup, null, title));
1093
- }));
1094
- } finally {
1095
- _effect.f();
1096
- }
987
+ const map = useMap();
988
+ useEffect5(() => {
989
+ if (markers.length > 0) {
990
+ const bounds = latLngBounds(markers.map((marker) => marker.location));
991
+ map.fitBounds(bounds);
992
+ } else {
993
+ map.setView(defaults2.center, defaults2.zoom);
994
+ }
995
+ }, [
996
+ markers
997
+ ]);
998
+ return /* @__PURE__ */ React4.createElement(React4.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
999
+ return /* @__PURE__ */ React4.createElement(Marker, {
1000
+ key: id,
1001
+ position: {
1002
+ lat,
1003
+ lng
1004
+ },
1005
+ icon: (
1006
+ // TODO(burdon): Create custom icon from bundled assets.
1007
+ // TODO(burdon): Selection state.
1008
+ new L.Icon({
1009
+ iconUrl: "https://dxos.network/marker-icon.png",
1010
+ iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
1011
+ shadowUrl: "https://dxos.network/marker-shadow.png",
1012
+ iconSize: [
1013
+ 25,
1014
+ 41
1015
+ ],
1016
+ iconAnchor: [
1017
+ 12,
1018
+ 41
1019
+ ],
1020
+ popupAnchor: [
1021
+ 1,
1022
+ -34
1023
+ ],
1024
+ shadowSize: [
1025
+ 41,
1026
+ 41
1027
+ ]
1028
+ })
1029
+ )
1030
+ }, title && /* @__PURE__ */ React4.createElement(Popup, null, title));
1031
+ }));
1097
1032
  };
1098
1033
  MapMarkers.displayName = "Map.Markers";
1099
1034
  var CustomControl2 = ({ position, children }) => {
1100
- var _effect = _useSignals4();
1101
- try {
1102
- const map = useMap();
1103
- useEffect5(() => {
1104
- const control = new Control({
1105
- position
1106
- });
1107
- control.onAdd = () => {
1108
- const container = DomUtil.create("div", mx2("!m-0", controlPositions[position]));
1109
- DomEvent.disableClickPropagation(container);
1110
- DomEvent.disableScrollPropagation(container);
1111
- const root = createRoot(container);
1112
- root.render(/* @__PURE__ */ React4.createElement(ThemeProvider, {
1113
- tx: defaultTx
1114
- }, /* @__PURE__ */ React4.createElement(Tooltip.Provider, null, children)));
1115
- return container;
1116
- };
1117
- control.addTo(map);
1118
- return () => {
1119
- control.remove();
1120
- };
1121
- }, [
1122
- map,
1123
- position,
1124
- children
1125
- ]);
1126
- return null;
1127
- } finally {
1128
- _effect.f();
1129
- }
1130
- };
1131
- var MapZoom = ({ onAction, position = "bottomleft", ...props }) => {
1132
- var _effect = _useSignals4();
1133
- try {
1134
- return /* @__PURE__ */ React4.createElement(CustomControl2, {
1135
- position,
1136
- ...props
1137
- }, /* @__PURE__ */ React4.createElement(ZoomControls, {
1138
- onAction
1139
- }));
1140
- } finally {
1141
- _effect.f();
1142
- }
1143
- };
1144
- var MapAction = ({ onAction, position = "bottomright", ...props }) => {
1145
- var _effect = _useSignals4();
1146
- try {
1147
- return /* @__PURE__ */ React4.createElement(CustomControl2, {
1148
- position,
1149
- ...props
1150
- }, /* @__PURE__ */ React4.createElement(ActionControls, {
1151
- onAction
1152
- }));
1153
- } finally {
1154
- _effect.f();
1155
- }
1035
+ const map = useMap();
1036
+ useEffect5(() => {
1037
+ const control = new Control({
1038
+ position
1039
+ });
1040
+ control.onAdd = () => {
1041
+ const container = DomUtil.create("div", mx2("m-0!", controlPositions[position]));
1042
+ DomEvent.disableClickPropagation(container);
1043
+ DomEvent.disableScrollPropagation(container);
1044
+ const root = createRoot(container);
1045
+ root.render(/* @__PURE__ */ React4.createElement(ThemeProvider, {
1046
+ tx: defaultTx
1047
+ }, /* @__PURE__ */ React4.createElement(Tooltip.Provider, null, children)));
1048
+ return container;
1049
+ };
1050
+ control.addTo(map);
1051
+ return () => {
1052
+ control.remove();
1053
+ };
1054
+ }, [
1055
+ map,
1056
+ position,
1057
+ children
1058
+ ]);
1059
+ return null;
1156
1060
  };
1061
+ var MapZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React4.createElement(CustomControl2, {
1062
+ position,
1063
+ ...props
1064
+ }, /* @__PURE__ */ React4.createElement(ZoomControls, {
1065
+ onAction
1066
+ }));
1067
+ var MapAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React4.createElement(CustomControl2, {
1068
+ position,
1069
+ ...props
1070
+ }, /* @__PURE__ */ React4.createElement(ActionControls, {
1071
+ onAction
1072
+ }));
1157
1073
  var Map = {
1158
1074
  Root: MapRoot,
1159
1075
  Tiles: MapTiles,
@@ -1181,6 +1097,8 @@ export {
1181
1097
  renderLayers,
1182
1098
  restrictAxis,
1183
1099
  timer,
1100
+ translationKey,
1101
+ translations,
1184
1102
  useDrag,
1185
1103
  useGlobeContext,
1186
1104
  useGlobeZoomHandler,