@dxos/react-ui-geo 0.8.4-main.406dc2a → 0.8.4-main.40e3dcdf1b

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