@dxos/react-ui-geo 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8
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.
- package/LICENSE +102 -5
- package/data/countries-10m.ts +12 -0
- package/data/countries-110m.ts +4 -10579
- package/data/countries-50m.ts +12 -0
- package/dist/lib/browser/chunk-SC2FBYFU.mjs +17 -0
- package/dist/lib/browser/chunk-SC2FBYFU.mjs.map +7 -0
- package/dist/lib/browser/countries-10m-CWWDOKH7.mjs +6 -0
- package/dist/lib/browser/countries-10m-CWWDOKH7.mjs.map +7 -0
- package/dist/lib/browser/countries-110m-72QBAA5E.mjs +6 -0
- package/dist/lib/browser/countries-110m-72QBAA5E.mjs.map +7 -0
- package/dist/lib/browser/countries-50m-H7SL7KVF.mjs +6 -0
- package/dist/lib/browser/countries-50m-H7SL7KVF.mjs.map +7 -0
- package/dist/lib/browser/data.mjs +1 -1
- package/dist/lib/browser/index.mjs +1054 -578
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +19 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-VZENBYLJ.mjs +19 -0
- package/dist/lib/node-esm/chunk-VZENBYLJ.mjs.map +7 -0
- package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs +8 -0
- package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs.map +7 -0
- package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs +8 -0
- package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs.map +7 -0
- package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs +8 -0
- package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs.map +7 -0
- package/dist/lib/node-esm/data.mjs +1 -1
- package/dist/lib/node-esm/index.mjs +1054 -578
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +21 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/data/airports.d.ts +4 -4
- package/dist/types/data/airports.d.ts.map +1 -1
- package/dist/types/data/cities.d.ts.map +1 -1
- package/dist/types/data/countries-10m.d.ts +8 -0
- package/dist/types/data/countries-10m.d.ts.map +1 -0
- package/dist/types/data/countries-110m.d.ts +2 -30
- package/dist/types/data/countries-110m.d.ts.map +1 -1
- package/dist/types/data/countries-50m.d.ts +8 -0
- package/dist/types/data/countries-50m.d.ts.map +1 -0
- package/dist/types/data/countries-dots-3.d.ts.map +1 -1
- package/dist/types/data/countries-dots-4.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +19 -9
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +37 -11
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +55 -16
- package/dist/types/src/components/Map/Map.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.stories.d.ts +19 -9
- package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
- package/dist/types/src/data.d.ts +9 -1
- package/dist/types/src/data.d.ts.map +1 -1
- package/dist/types/src/hooks/context.d.ts +38 -3
- package/dist/types/src/hooks/context.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +3 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useDrag.d.ts +22 -2
- package/dist/types/src/hooks/useDrag.d.ts.map +1 -1
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +3 -2
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useSimplifiedTopology.d.ts +32 -0
- package/dist/types/src/hooks/useSimplifiedTopology.d.ts.map +1 -0
- package/dist/types/src/hooks/useSpinner.d.ts +1 -1
- package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
- package/dist/types/src/hooks/useTopology.d.ts +26 -0
- package/dist/types/src/hooks/useTopology.d.ts.map +1 -0
- package/dist/types/src/hooks/useTour.d.ts +3 -2
- package/dist/types/src/hooks/useTour.d.ts.map +1 -1
- package/dist/types/src/hooks/useWheel.d.ts +24 -0
- package/dist/types/src/hooks/useWheel.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +12 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/util/animation.d.ts +16 -0
- package/dist/types/src/util/animation.d.ts.map +1 -0
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/inertia.d.ts.map +1 -1
- package/dist/types/src/util/path.d.ts.map +1 -1
- package/dist/types/src/util/render.d.ts +25 -1
- package/dist/types/src/util/render.d.ts.map +1 -1
- package/dist/types/src/util/styles.d.ts +4 -0
- package/dist/types/src/util/styles.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -37
- package/src/components/Globe/Globe.stories.tsx +201 -82
- package/src/components/Globe/Globe.tsx +263 -119
- package/src/components/Map/Map.stories.tsx +66 -17
- package/src/components/Map/Map.tsx +333 -120
- package/src/components/Toolbar/Controls.tsx +12 -14
- package/src/data.ts +19 -2
- package/src/hooks/context.tsx +49 -28
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useDrag.ts +33 -5
- package/src/hooks/useGlobeZoomHandler.ts +10 -3
- package/src/hooks/useSimplifiedTopology.ts +81 -0
- package/src/hooks/useSpinner.ts +1 -2
- package/src/hooks/useTopology.ts +95 -0
- package/src/hooks/useTour.ts +71 -81
- package/src/hooks/useWheel.ts +83 -0
- package/src/index.ts +0 -1
- package/src/translations.ts +20 -0
- package/src/util/animation.ts +35 -0
- package/src/util/index.ts +2 -0
- package/src/util/inertia.ts +87 -4
- package/src/util/render.ts +105 -17
- package/src/util/styles.ts +62 -0
- package/dist/lib/browser/chunk-GMWLKTLN.mjs +0 -9
- package/dist/lib/browser/chunk-GMWLKTLN.mjs.map +0 -7
- package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs +0 -37859
- package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JODBF4CC.mjs +0 -11
- package/dist/lib/node-esm/chunk-JODBF4CC.mjs.map +0 -7
- package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs +0 -37861
- package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs.map +0 -7
|
@@ -1,45 +1,19 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadTopology
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SC2FBYFU.mjs";
|
|
4
4
|
|
|
5
5
|
// src/components/Globe/Globe.tsx
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import React3, { forwardRef, useEffect as useEffect4, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState3 } from "react";
|
|
6
|
+
import { selection as d3Selection, easeLinear, easeSinOut, geoMercator, geoOrthographic, geoPath as geoPath2, geoTransverseMercator, interpolateNumber, transition } from "d3";
|
|
7
|
+
import React2, { forwardRef, useCallback as useCallback3, useEffect as useEffect6, useId, useImperativeHandle, useMemo as useMemo2, useRef, useState as useState4 } from "react";
|
|
9
8
|
import { useResizeDetector } from "react-resize-detector";
|
|
10
|
-
import { useDynamicRef, useThemeContext } from "@dxos/react-ui";
|
|
11
|
-
import {
|
|
9
|
+
import { useComposedRefs, useControlledState, useDynamicRef, useThemeContext } from "@dxos/react-ui";
|
|
10
|
+
import { composable, composableProps } from "@dxos/react-ui";
|
|
11
|
+
import { mx } from "@dxos/ui-theme";
|
|
12
12
|
|
|
13
13
|
// src/hooks/context.tsx
|
|
14
|
-
import {
|
|
15
|
-
import React, { createContext, useContext } from "react";
|
|
14
|
+
import { createContext, useContext } from "react";
|
|
16
15
|
import { raise } from "@dxos/debug";
|
|
17
|
-
import { useControlledState } from "@dxos/react-ui";
|
|
18
16
|
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
|
-
}
|
|
42
|
-
};
|
|
43
17
|
var useGlobeContext = () => {
|
|
44
18
|
return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
|
|
45
19
|
};
|
|
@@ -48,6 +22,18 @@ var useGlobeContext = () => {
|
|
|
48
22
|
import { select as select2 } from "d3";
|
|
49
23
|
import { useEffect } from "react";
|
|
50
24
|
|
|
25
|
+
// src/util/animation.ts
|
|
26
|
+
import { geoDistance } from "d3";
|
|
27
|
+
import versor from "versor";
|
|
28
|
+
var flyDuration = (p1, p2, base, scale) => Math.max(base, geoDistance(p1, p2) * scale);
|
|
29
|
+
var createRotationTween = (projection, setRotation, r1, r2) => {
|
|
30
|
+
const iv = versor.interpolate(r1, r2);
|
|
31
|
+
return (t) => {
|
|
32
|
+
projection.rotate(iv(t));
|
|
33
|
+
setRotation(projection.rotate());
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
|
|
51
37
|
// src/util/debug.ts
|
|
52
38
|
var debug = false;
|
|
53
39
|
var timer = (cb) => {
|
|
@@ -65,7 +51,7 @@ var timer = (cb) => {
|
|
|
65
51
|
|
|
66
52
|
// src/util/inertia.ts
|
|
67
53
|
import { drag, select, timer as timer2 } from "d3";
|
|
68
|
-
import
|
|
54
|
+
import versor2 from "versor";
|
|
69
55
|
var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
|
|
70
56
|
var geoInertiaDrag = (target, render, projection, options) => {
|
|
71
57
|
if (!options) {
|
|
@@ -75,21 +61,23 @@ var geoInertiaDrag = (target, render, projection, options) => {
|
|
|
75
61
|
target = target.node();
|
|
76
62
|
}
|
|
77
63
|
target = select(target);
|
|
78
|
-
const
|
|
64
|
+
const linear = (options.mode ?? "linear") === "linear";
|
|
65
|
+
const axis = restrictAxis(options.lockTilt ? [
|
|
66
|
+
true,
|
|
67
|
+
false,
|
|
68
|
+
false
|
|
69
|
+
] : [
|
|
70
|
+
true,
|
|
71
|
+
true,
|
|
72
|
+
true
|
|
73
|
+
]);
|
|
74
|
+
const sharedHandlers = {
|
|
79
75
|
projection,
|
|
80
76
|
render: (rotation) => {
|
|
81
77
|
projection.rotate(rotation);
|
|
82
78
|
render && render();
|
|
83
79
|
},
|
|
84
|
-
axis
|
|
85
|
-
true,
|
|
86
|
-
false,
|
|
87
|
-
false
|
|
88
|
-
] : [
|
|
89
|
-
true,
|
|
90
|
-
true,
|
|
91
|
-
true
|
|
92
|
-
]),
|
|
80
|
+
axis,
|
|
93
81
|
start: options.start,
|
|
94
82
|
move: options.move,
|
|
95
83
|
end: options.end,
|
|
@@ -97,7 +85,12 @@ var geoInertiaDrag = (target, render, projection, options) => {
|
|
|
97
85
|
finish: options.finish,
|
|
98
86
|
time: options.time,
|
|
99
87
|
hold: options.hold
|
|
100
|
-
}
|
|
88
|
+
};
|
|
89
|
+
const inertia = linear ? geoInertiaDragLinearHelper({
|
|
90
|
+
...sharedHandlers,
|
|
91
|
+
sensitivity: options.sensitivity,
|
|
92
|
+
getZoom: options.getZoom
|
|
93
|
+
}) : geoInertiaDragHelper(sharedHandlers);
|
|
101
94
|
target.call(drag().on("start", inertia.start).on("drag", inertia.move).on("end", inertia.end));
|
|
102
95
|
return inertia;
|
|
103
96
|
};
|
|
@@ -112,9 +105,9 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
112
105
|
const inertia = inertiaHelper({
|
|
113
106
|
axis: opt.axis,
|
|
114
107
|
start: () => {
|
|
115
|
-
v0 =
|
|
108
|
+
v0 = versor2.cartesian(projection.invert(inertia.position));
|
|
116
109
|
r0 = projection.rotate();
|
|
117
|
-
q0 =
|
|
110
|
+
q0 = versor2(r0);
|
|
118
111
|
opt.start && opt.start();
|
|
119
112
|
},
|
|
120
113
|
move: () => {
|
|
@@ -122,23 +115,23 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
122
115
|
if (isNaN(inv[0])) {
|
|
123
116
|
return;
|
|
124
117
|
}
|
|
125
|
-
const v1 =
|
|
126
|
-
const q1 =
|
|
127
|
-
const r1 =
|
|
118
|
+
const v1 = versor2.cartesian(inv);
|
|
119
|
+
const q1 = versor2.multiply(q0, versor2.delta(v0, v1));
|
|
120
|
+
const r1 = versor2.rotation(q1);
|
|
128
121
|
const r2 = opt.axis(r0, r1);
|
|
129
122
|
opt.render(r2);
|
|
130
123
|
opt.move && opt.move();
|
|
131
124
|
},
|
|
132
125
|
end: () => {
|
|
133
|
-
v10 =
|
|
134
|
-
q10 =
|
|
135
|
-
v11 =
|
|
126
|
+
v10 = versor2.cartesian(projection.invert(inertia.position.map((d, i) => d - inertia.velocity[i] / 1e3)));
|
|
127
|
+
q10 = versor2(projection.rotate());
|
|
128
|
+
v11 = versor2.cartesian(projection.invert(inertia.position));
|
|
136
129
|
opt.end && opt.end();
|
|
137
130
|
},
|
|
138
131
|
stop: opt.stop,
|
|
139
132
|
finish: opt.finish,
|
|
140
133
|
render: (t) => {
|
|
141
|
-
const r1 =
|
|
134
|
+
const r1 = versor2.rotation(versor2.multiply(q10, versor2.delta(v10, v11, t * 1e3)));
|
|
142
135
|
const r2 = opt.axis(r0, r1);
|
|
143
136
|
opt.render && opt.render(r2);
|
|
144
137
|
},
|
|
@@ -146,6 +139,62 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
146
139
|
});
|
|
147
140
|
return inertia;
|
|
148
141
|
};
|
|
142
|
+
var DEFAULT_LINEAR_SENSITIVITY = 0.25;
|
|
143
|
+
var geoInertiaDragLinearHelper = (opt) => {
|
|
144
|
+
const projection = opt.projection;
|
|
145
|
+
const sensitivity = opt.sensitivity ?? DEFAULT_LINEAR_SENSITIVITY;
|
|
146
|
+
const gain = () => sensitivity / Math.max(opt.getZoom?.() ?? 1, 0.1);
|
|
147
|
+
let r0;
|
|
148
|
+
let p0;
|
|
149
|
+
let kStart;
|
|
150
|
+
let rEnd;
|
|
151
|
+
let vEnd;
|
|
152
|
+
const inertia = inertiaHelper({
|
|
153
|
+
axis: opt.axis,
|
|
154
|
+
start: () => {
|
|
155
|
+
r0 = projection.rotate();
|
|
156
|
+
p0 = [
|
|
157
|
+
inertia.position[0],
|
|
158
|
+
inertia.position[1]
|
|
159
|
+
];
|
|
160
|
+
kStart = gain();
|
|
161
|
+
opt.start && opt.start();
|
|
162
|
+
},
|
|
163
|
+
move: () => {
|
|
164
|
+
const dx = inertia.position[0] - p0[0];
|
|
165
|
+
const dy = inertia.position[1] - p0[1];
|
|
166
|
+
const r1 = [
|
|
167
|
+
r0[0] + dx * kStart,
|
|
168
|
+
r0[1] - dy * kStart,
|
|
169
|
+
0
|
|
170
|
+
];
|
|
171
|
+
const r2 = opt.axis(r0, r1);
|
|
172
|
+
opt.render(r2);
|
|
173
|
+
opt.move && opt.move();
|
|
174
|
+
},
|
|
175
|
+
end: () => {
|
|
176
|
+
rEnd = projection.rotate();
|
|
177
|
+
vEnd = [
|
|
178
|
+
inertia.velocity[0],
|
|
179
|
+
inertia.velocity[1]
|
|
180
|
+
];
|
|
181
|
+
opt.end && opt.end();
|
|
182
|
+
},
|
|
183
|
+
stop: opt.stop,
|
|
184
|
+
finish: opt.finish,
|
|
185
|
+
render: (t) => {
|
|
186
|
+
const r1 = [
|
|
187
|
+
rEnd[0] + vEnd[0] * kStart * t,
|
|
188
|
+
rEnd[1] - vEnd[1] * kStart * t,
|
|
189
|
+
0
|
|
190
|
+
];
|
|
191
|
+
const r2 = opt.axis(rEnd, r1);
|
|
192
|
+
opt.render && opt.render(r2);
|
|
193
|
+
},
|
|
194
|
+
time: opt.time
|
|
195
|
+
});
|
|
196
|
+
return inertia;
|
|
197
|
+
};
|
|
149
198
|
function inertiaHelper(opt) {
|
|
150
199
|
const A = opt.time || 5e3;
|
|
151
200
|
const limit = 1.0001;
|
|
@@ -249,9 +298,9 @@ var geoToPosition = ({ lat, lng }) => [
|
|
|
249
298
|
lng,
|
|
250
299
|
lat
|
|
251
300
|
];
|
|
252
|
-
var geoPoint = (
|
|
301
|
+
var geoPoint = (point2) => ({
|
|
253
302
|
type: "Point",
|
|
254
|
-
coordinates: geoToPosition(
|
|
303
|
+
coordinates: geoToPosition(point2)
|
|
255
304
|
});
|
|
256
305
|
var geoCircle = ({ lat, lng }, radius) => d3GeoCircle().radius(radius).center([
|
|
257
306
|
lng,
|
|
@@ -276,11 +325,11 @@ var closestPoint = (points, target) => {
|
|
|
276
325
|
}
|
|
277
326
|
let closestPoint2 = points[0];
|
|
278
327
|
let minDistance = getDistance(points[0], target);
|
|
279
|
-
for (const
|
|
280
|
-
const distance = getDistance(
|
|
328
|
+
for (const point2 of points) {
|
|
329
|
+
const distance = getDistance(point2, target);
|
|
281
330
|
if (distance < minDistance) {
|
|
282
331
|
minDistance = distance;
|
|
283
|
-
closestPoint2 =
|
|
332
|
+
closestPoint2 = point2;
|
|
284
333
|
}
|
|
285
334
|
}
|
|
286
335
|
return closestPoint2;
|
|
@@ -292,8 +341,48 @@ var getDistance = (point1, point2) => {
|
|
|
292
341
|
};
|
|
293
342
|
|
|
294
343
|
// src/util/render.ts
|
|
295
|
-
import { geoGraticule } from "d3";
|
|
344
|
+
import { geoBounds, geoCentroid, geoDistance as geoDistance2, geoGraticule } from "d3";
|
|
296
345
|
import { feature, mesh } from "topojson-client";
|
|
346
|
+
var RAD_TO_DEG = 180 / Math.PI;
|
|
347
|
+
var computeBounds = (geometry) => {
|
|
348
|
+
const feat = {
|
|
349
|
+
type: "Feature",
|
|
350
|
+
geometry,
|
|
351
|
+
properties: {}
|
|
352
|
+
};
|
|
353
|
+
const centroid = geoCentroid(feat);
|
|
354
|
+
const [[w, s], [e, n]] = geoBounds(feat);
|
|
355
|
+
const corners = [
|
|
356
|
+
[
|
|
357
|
+
w,
|
|
358
|
+
s
|
|
359
|
+
],
|
|
360
|
+
[
|
|
361
|
+
w,
|
|
362
|
+
n
|
|
363
|
+
],
|
|
364
|
+
[
|
|
365
|
+
e,
|
|
366
|
+
s
|
|
367
|
+
],
|
|
368
|
+
[
|
|
369
|
+
e,
|
|
370
|
+
n
|
|
371
|
+
]
|
|
372
|
+
];
|
|
373
|
+
let radius = 0;
|
|
374
|
+
for (const corner of corners) {
|
|
375
|
+
const d = geoDistance2(centroid, corner) * RAD_TO_DEG;
|
|
376
|
+
if (d > radius) {
|
|
377
|
+
radius = d;
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
return {
|
|
381
|
+
geometry,
|
|
382
|
+
centroid,
|
|
383
|
+
radius
|
|
384
|
+
};
|
|
385
|
+
};
|
|
297
386
|
var createLayers = (topology, features, styles) => {
|
|
298
387
|
const layers = [];
|
|
299
388
|
if (styles.water) {
|
|
@@ -314,11 +403,25 @@ var createLayers = (topology, features, styles) => {
|
|
|
314
403
|
});
|
|
315
404
|
}
|
|
316
405
|
if (topology) {
|
|
317
|
-
if (
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
406
|
+
if (styles.land) {
|
|
407
|
+
if (topology.objects.countries) {
|
|
408
|
+
const fc = feature(topology, topology.objects.countries);
|
|
409
|
+
const memberGeoms = fc.features.map((f) => f.geometry);
|
|
410
|
+
const bounds = memberGeoms.map(computeBounds);
|
|
411
|
+
layers.push({
|
|
412
|
+
styles: styles.land,
|
|
413
|
+
path: {
|
|
414
|
+
type: "GeometryCollection",
|
|
415
|
+
geometries: memberGeoms
|
|
416
|
+
},
|
|
417
|
+
cullable: bounds
|
|
418
|
+
});
|
|
419
|
+
} else if (topology.objects.land) {
|
|
420
|
+
layers.push({
|
|
421
|
+
styles: styles.land,
|
|
422
|
+
path: feature(topology, topology.objects.land)
|
|
423
|
+
});
|
|
424
|
+
}
|
|
322
425
|
}
|
|
323
426
|
if (topology.objects.countries && styles.border) {
|
|
324
427
|
layers.push({
|
|
@@ -335,28 +438,28 @@ var createLayers = (topology, features, styles) => {
|
|
|
335
438
|
}
|
|
336
439
|
if (features) {
|
|
337
440
|
const { points, lines } = features;
|
|
338
|
-
if (
|
|
441
|
+
if (lines && styles.line) {
|
|
339
442
|
layers.push({
|
|
340
|
-
styles: styles.
|
|
443
|
+
styles: styles.line,
|
|
341
444
|
path: {
|
|
342
445
|
type: "GeometryCollection",
|
|
343
|
-
geometries:
|
|
446
|
+
geometries: lines.map(({ source, target }) => geoLine(source, target))
|
|
344
447
|
}
|
|
345
448
|
});
|
|
346
449
|
}
|
|
347
|
-
if (
|
|
450
|
+
if (points && styles.point) {
|
|
348
451
|
layers.push({
|
|
349
|
-
styles: styles.
|
|
452
|
+
styles: styles.point,
|
|
350
453
|
path: {
|
|
351
454
|
type: "GeometryCollection",
|
|
352
|
-
geometries:
|
|
455
|
+
geometries: points.map((point2) => geoPoint(point2))
|
|
353
456
|
}
|
|
354
457
|
});
|
|
355
458
|
}
|
|
356
459
|
}
|
|
357
460
|
return layers;
|
|
358
461
|
};
|
|
359
|
-
var renderLayers = (generator, layers = [], scale, styles) => {
|
|
462
|
+
var renderLayers = (generator, layers = [], scale, styles, viewCenter) => {
|
|
360
463
|
const context = generator.context();
|
|
361
464
|
const { canvas: { width, height } } = context;
|
|
362
465
|
context.reset();
|
|
@@ -366,7 +469,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
366
469
|
} else {
|
|
367
470
|
context.clearRect(0, 0, width, height);
|
|
368
471
|
}
|
|
369
|
-
layers.forEach((
|
|
472
|
+
layers.forEach((layer) => {
|
|
473
|
+
const { path, styles: styles2, cullable } = layer;
|
|
370
474
|
context.save();
|
|
371
475
|
let fill = false;
|
|
372
476
|
let stroke = false;
|
|
@@ -381,8 +485,23 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
381
485
|
}
|
|
382
486
|
});
|
|
383
487
|
}
|
|
488
|
+
let renderPath = path;
|
|
489
|
+
if (cullable && viewCenter) {
|
|
490
|
+
const geometries = [];
|
|
491
|
+
for (let index = 0; index < cullable.length; index++) {
|
|
492
|
+
const bounds = cullable[index];
|
|
493
|
+
const angularDistance = geoDistance2(viewCenter, bounds.centroid) * RAD_TO_DEG;
|
|
494
|
+
if (angularDistance < 90 + bounds.radius) {
|
|
495
|
+
geometries.push(bounds.geometry);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
renderPath = {
|
|
499
|
+
type: "GeometryCollection",
|
|
500
|
+
geometries
|
|
501
|
+
};
|
|
502
|
+
}
|
|
384
503
|
context.beginPath();
|
|
385
|
-
generator(
|
|
504
|
+
generator(renderPath);
|
|
386
505
|
fill && context.fill();
|
|
387
506
|
stroke && context.stroke();
|
|
388
507
|
context.restore();
|
|
@@ -390,6 +509,57 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
390
509
|
return context;
|
|
391
510
|
};
|
|
392
511
|
|
|
512
|
+
// src/util/styles.ts
|
|
513
|
+
var POINT_COLOR = "rgb(220, 38, 38)";
|
|
514
|
+
var LINE_COLOR = "rgba(220, 38, 38, 0.5)";
|
|
515
|
+
var globeStyles = (themeMode) => themeMode === "dark" ? {
|
|
516
|
+
water: {
|
|
517
|
+
fillStyle: "#191919"
|
|
518
|
+
},
|
|
519
|
+
land: {
|
|
520
|
+
fillStyle: "#444",
|
|
521
|
+
strokeStyle: "#222"
|
|
522
|
+
},
|
|
523
|
+
border: {
|
|
524
|
+
strokeStyle: "#111"
|
|
525
|
+
},
|
|
526
|
+
graticule: {
|
|
527
|
+
strokeStyle: "#111"
|
|
528
|
+
},
|
|
529
|
+
line: {
|
|
530
|
+
lineWidth: 1.5,
|
|
531
|
+
lineDash: [
|
|
532
|
+
4,
|
|
533
|
+
16
|
|
534
|
+
],
|
|
535
|
+
strokeStyle: LINE_COLOR
|
|
536
|
+
},
|
|
537
|
+
point: {
|
|
538
|
+
radius: 0.2,
|
|
539
|
+
fillStyle: POINT_COLOR
|
|
540
|
+
}
|
|
541
|
+
} : {
|
|
542
|
+
water: {
|
|
543
|
+
fillStyle: "#C0DAE4"
|
|
544
|
+
},
|
|
545
|
+
land: {
|
|
546
|
+
fillStyle: "#C2D8B4",
|
|
547
|
+
strokeStyle: "#A6C291"
|
|
548
|
+
},
|
|
549
|
+
line: {
|
|
550
|
+
lineWidth: 1.5,
|
|
551
|
+
lineDash: [
|
|
552
|
+
4,
|
|
553
|
+
16
|
|
554
|
+
],
|
|
555
|
+
strokeStyle: LINE_COLOR
|
|
556
|
+
},
|
|
557
|
+
point: {
|
|
558
|
+
radius: 0.2,
|
|
559
|
+
fillStyle: POINT_COLOR
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
|
|
393
563
|
// src/hooks/useDrag.ts
|
|
394
564
|
var useDrag = (controller, options = {}) => {
|
|
395
565
|
useEffect(() => {
|
|
@@ -397,14 +567,19 @@ var useDrag = (controller, options = {}) => {
|
|
|
397
567
|
if (!canvas || options.disabled) {
|
|
398
568
|
return;
|
|
399
569
|
}
|
|
400
|
-
geoInertiaDrag(select2(canvas), () => {
|
|
570
|
+
const inertia = geoInertiaDrag(select2(canvas), () => {
|
|
401
571
|
controller.setRotation(controller.projection.rotate());
|
|
402
572
|
options.onUpdate?.({
|
|
403
573
|
type: "move",
|
|
404
574
|
controller
|
|
405
575
|
});
|
|
406
576
|
}, controller.projection, {
|
|
407
|
-
|
|
577
|
+
lockTilt: options.lockTilt,
|
|
578
|
+
mode: options.mode,
|
|
579
|
+
sensitivity: options.sensitivity,
|
|
580
|
+
// Zoom-driven gain: matches useWheel — degrees-per-pixel shrinks as the
|
|
581
|
+
// globe gets larger on screen so the drag feel is consistent across zoom.
|
|
582
|
+
getZoom: () => controller.zoom,
|
|
408
583
|
time: 3e3,
|
|
409
584
|
start: () => options.onUpdate?.({
|
|
410
585
|
type: "start",
|
|
@@ -417,6 +592,7 @@ var useDrag = (controller, options = {}) => {
|
|
|
417
592
|
});
|
|
418
593
|
return () => {
|
|
419
594
|
cancelDrag(select2(canvas));
|
|
595
|
+
inertia?.timer?.stop();
|
|
420
596
|
};
|
|
421
597
|
}, [
|
|
422
598
|
controller,
|
|
@@ -427,6 +603,7 @@ var cancelDrag = (node) => node.on(".drag", null);
|
|
|
427
603
|
|
|
428
604
|
// src/hooks/useGlobeZoomHandler.ts
|
|
429
605
|
import { useCallback } from "react";
|
|
606
|
+
var ZOOM_FACTOR = 0.1;
|
|
430
607
|
var useGlobeZoomHandler = (controller) => {
|
|
431
608
|
return useCallback((event) => {
|
|
432
609
|
if (!controller) {
|
|
@@ -434,11 +611,15 @@ var useGlobeZoomHandler = (controller) => {
|
|
|
434
611
|
}
|
|
435
612
|
switch (event) {
|
|
436
613
|
case "zoom-in": {
|
|
437
|
-
controller.setZoom((zoom) =>
|
|
614
|
+
controller.setZoom((zoom) => {
|
|
615
|
+
return zoom * (1 + ZOOM_FACTOR);
|
|
616
|
+
});
|
|
438
617
|
break;
|
|
439
618
|
}
|
|
440
619
|
case "zoom-out": {
|
|
441
|
-
controller.setZoom((zoom) =>
|
|
620
|
+
controller.setZoom((zoom) => {
|
|
621
|
+
return zoom * (1 - ZOOM_FACTOR);
|
|
622
|
+
});
|
|
442
623
|
break;
|
|
443
624
|
}
|
|
444
625
|
}
|
|
@@ -469,6 +650,61 @@ var useMapZoomHandler = (controller) => {
|
|
|
469
650
|
]);
|
|
470
651
|
};
|
|
471
652
|
|
|
653
|
+
// src/hooks/useSimplifiedTopology.ts
|
|
654
|
+
import { useMemo } from "react";
|
|
655
|
+
import { presimplify, quantile, simplify } from "topojson-simplify";
|
|
656
|
+
var DEFAULT_TIERS = [
|
|
657
|
+
{
|
|
658
|
+
minZoom: 0,
|
|
659
|
+
percentile: 0.95
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
minZoom: 2,
|
|
663
|
+
percentile: 0.85
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
minZoom: 4,
|
|
667
|
+
percentile: 0.6
|
|
668
|
+
},
|
|
669
|
+
{
|
|
670
|
+
minZoom: 7,
|
|
671
|
+
percentile: 0.3
|
|
672
|
+
},
|
|
673
|
+
{
|
|
674
|
+
minZoom: 12,
|
|
675
|
+
percentile: 0
|
|
676
|
+
}
|
|
677
|
+
];
|
|
678
|
+
var pickTier = (zoom, tiers) => {
|
|
679
|
+
let match = tiers[0];
|
|
680
|
+
for (const tier of tiers) {
|
|
681
|
+
if (zoom >= tier.minZoom) {
|
|
682
|
+
match = tier;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
return match;
|
|
686
|
+
};
|
|
687
|
+
var useSimplifiedTopology = (topology, zoom, options = {}) => {
|
|
688
|
+
const { tiers = DEFAULT_TIERS } = options;
|
|
689
|
+
const presimplified = useMemo(() => topology ? presimplify(topology) : void 0, [
|
|
690
|
+
topology
|
|
691
|
+
]);
|
|
692
|
+
const tier = pickTier(zoom, tiers);
|
|
693
|
+
return useMemo(() => {
|
|
694
|
+
if (!presimplified) {
|
|
695
|
+
return void 0;
|
|
696
|
+
}
|
|
697
|
+
if (tier.percentile <= 0) {
|
|
698
|
+
return presimplified;
|
|
699
|
+
}
|
|
700
|
+
const minWeight = quantile(presimplified, tier.percentile);
|
|
701
|
+
return simplify(presimplified, minWeight);
|
|
702
|
+
}, [
|
|
703
|
+
presimplified,
|
|
704
|
+
tier
|
|
705
|
+
]);
|
|
706
|
+
};
|
|
707
|
+
|
|
472
708
|
// src/hooks/useSpinner.ts
|
|
473
709
|
import { timer as d3Timer } from "d3";
|
|
474
710
|
import { useEffect as useEffect2, useState } from "react";
|
|
@@ -522,91 +758,139 @@ var useSpinner = (controller, options = {}) => {
|
|
|
522
758
|
];
|
|
523
759
|
};
|
|
524
760
|
|
|
761
|
+
// src/hooks/useTopology.ts
|
|
762
|
+
import { useEffect as useEffect3, useState as useState2 } from "react";
|
|
763
|
+
import { log } from "@dxos/log";
|
|
764
|
+
var __dxlog_file = "/__w/dxos/dxos/packages/ui/react-ui-geo/src/hooks/useTopology.ts";
|
|
765
|
+
var DEFAULT_TIERS2 = [
|
|
766
|
+
{
|
|
767
|
+
minZoom: 0,
|
|
768
|
+
level: "110m"
|
|
769
|
+
}
|
|
770
|
+
];
|
|
771
|
+
var pickTier2 = (zoom, tiers) => {
|
|
772
|
+
let match = tiers[0];
|
|
773
|
+
for (const tier of tiers) {
|
|
774
|
+
if (zoom >= tier.minZoom) {
|
|
775
|
+
match = tier;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
return match;
|
|
779
|
+
};
|
|
780
|
+
var topologyCache = /* @__PURE__ */ new Map();
|
|
781
|
+
var useTopology = (zoom, options = {}) => {
|
|
782
|
+
const { tiers = DEFAULT_TIERS2 } = options;
|
|
783
|
+
const level = zoom === void 0 ? "110m" : pickTier2(zoom, tiers).level;
|
|
784
|
+
const [topology, setTopology] = useState2(() => topologyCache.get(level));
|
|
785
|
+
useEffect3(() => {
|
|
786
|
+
const cached = topologyCache.get(level);
|
|
787
|
+
if (cached) {
|
|
788
|
+
setTopology(cached);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
let disposed = false;
|
|
792
|
+
void loadTopology(level).then((loaded) => {
|
|
793
|
+
topologyCache.set(level, loaded);
|
|
794
|
+
if (!disposed) {
|
|
795
|
+
setTopology(loaded);
|
|
796
|
+
}
|
|
797
|
+
}).catch((err) => {
|
|
798
|
+
if (!disposed) {
|
|
799
|
+
log.warn("failed to load topology", {
|
|
800
|
+
level,
|
|
801
|
+
err
|
|
802
|
+
}, { "~LogMeta": "~LogMeta", F: __dxlog_file, L: 52, S: void 0 });
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
return () => {
|
|
806
|
+
disposed = true;
|
|
807
|
+
};
|
|
808
|
+
}, [
|
|
809
|
+
level
|
|
810
|
+
]);
|
|
811
|
+
return topology;
|
|
812
|
+
};
|
|
813
|
+
|
|
525
814
|
// src/hooks/useTour.ts
|
|
526
|
-
import {
|
|
527
|
-
import { useEffect as
|
|
528
|
-
import versor2 from "versor";
|
|
529
|
-
var TRANSITION_NAME = "globe-tour";
|
|
815
|
+
import { geoInterpolate, geoPath } from "d3";
|
|
816
|
+
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
530
817
|
var defaultDuration = 1500;
|
|
531
818
|
var useTour = (controller, points, options = {}) => {
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
if (!running) {
|
|
536
|
-
selection.interrupt(TRANSITION_NAME);
|
|
819
|
+
const [running, setRunning] = useState3(options.running ?? false);
|
|
820
|
+
useEffect4(() => {
|
|
821
|
+
if (!controller || !running) {
|
|
537
822
|
return;
|
|
538
823
|
}
|
|
539
|
-
let
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
const
|
|
824
|
+
let cancelled = false;
|
|
825
|
+
const t = setTimeout(async () => {
|
|
826
|
+
const { canvas, projection } = controller;
|
|
827
|
+
const context = canvas.getContext("2d", {
|
|
828
|
+
alpha: false
|
|
829
|
+
});
|
|
830
|
+
const path = geoPath(projection, context).pointRadius(2);
|
|
831
|
+
try {
|
|
832
|
+
const tourPoints = [
|
|
833
|
+
...points
|
|
834
|
+
];
|
|
835
|
+
if (options.loop) {
|
|
836
|
+
tourPoints.push(tourPoints[0]);
|
|
837
|
+
}
|
|
548
838
|
let last;
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
];
|
|
553
|
-
if (options.loop) {
|
|
554
|
-
p.push(p[0]);
|
|
839
|
+
for (const next of tourPoints) {
|
|
840
|
+
if (cancelled) {
|
|
841
|
+
break;
|
|
555
842
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
const
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
|
|
586
|
-
path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.zoom ?? 1));
|
|
587
|
-
path({
|
|
588
|
-
type: "Point",
|
|
589
|
-
coordinates: ip(t22)
|
|
590
|
-
});
|
|
591
|
-
context.fill();
|
|
592
|
-
}
|
|
843
|
+
const p1 = last ? geoToPosition(last) : void 0;
|
|
844
|
+
const p2 = geoToPosition(next);
|
|
845
|
+
const ip = geoInterpolate(p1 ?? p2, p2);
|
|
846
|
+
const onTick = (t2) => {
|
|
847
|
+
const t1 = Math.max(0, Math.min(1, t2 * 2 - 1));
|
|
848
|
+
const t22 = Math.min(1, t2 * 2);
|
|
849
|
+
context.save();
|
|
850
|
+
try {
|
|
851
|
+
context.beginPath();
|
|
852
|
+
context.strokeStyle = options.styles?.arc?.strokeStyle ?? "yellow";
|
|
853
|
+
context.lineWidth = (options.styles?.arc?.lineWidth ?? 1.5) * (controller.zoom ?? 1);
|
|
854
|
+
context.setLineDash(options.styles?.arc?.lineDash ?? []);
|
|
855
|
+
path({
|
|
856
|
+
type: "LineString",
|
|
857
|
+
coordinates: [
|
|
858
|
+
ip(t1),
|
|
859
|
+
ip(t22)
|
|
860
|
+
]
|
|
861
|
+
});
|
|
862
|
+
context.stroke();
|
|
863
|
+
context.beginPath();
|
|
864
|
+
context.fillStyle = options.styles?.cursor?.fillStyle ?? "orange";
|
|
865
|
+
path.pointRadius((options.styles?.cursor?.pointRadius ?? 2) * (controller.zoom ?? 1));
|
|
866
|
+
path({
|
|
867
|
+
type: "Point",
|
|
868
|
+
coordinates: ip(t22)
|
|
869
|
+
});
|
|
870
|
+
context.fill();
|
|
871
|
+
} finally {
|
|
593
872
|
context.restore();
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
873
|
+
}
|
|
874
|
+
};
|
|
875
|
+
await controller.flyTo(next, {
|
|
876
|
+
duration: options.duration ?? defaultDuration,
|
|
877
|
+
tilt: options.tilt ?? 0,
|
|
878
|
+
onTick
|
|
879
|
+
});
|
|
880
|
+
last = next;
|
|
881
|
+
}
|
|
882
|
+
} catch {
|
|
883
|
+
} finally {
|
|
884
|
+
if (!cancelled) {
|
|
602
885
|
setRunning(false);
|
|
603
886
|
}
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
return () => {
|
|
890
|
+
cancelled = true;
|
|
891
|
+
clearTimeout(t);
|
|
892
|
+
controller.cancelFlyTo();
|
|
893
|
+
};
|
|
610
894
|
}, [
|
|
611
895
|
controller,
|
|
612
896
|
running,
|
|
@@ -618,10 +902,55 @@ var useTour = (controller, points, options = {}) => {
|
|
|
618
902
|
];
|
|
619
903
|
};
|
|
620
904
|
|
|
905
|
+
// src/hooks/useWheel.ts
|
|
906
|
+
import { useEffect as useEffect5 } from "react";
|
|
907
|
+
var DEFAULT_SENSITIVITY = 0.25;
|
|
908
|
+
var DEFAULT_ZOOM_SENSITIVITY = 0.01;
|
|
909
|
+
var useWheel = (controller, options = {}) => {
|
|
910
|
+
useEffect5(() => {
|
|
911
|
+
const canvas = controller?.canvas;
|
|
912
|
+
if (!canvas || options.disabled) {
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
const sensitivity = options.sensitivity ?? DEFAULT_SENSITIVITY;
|
|
916
|
+
const zoomSensitivity = options.zoomSensitivity ?? DEFAULT_ZOOM_SENSITIVITY;
|
|
917
|
+
const handleWheel = (event) => {
|
|
918
|
+
event.preventDefault();
|
|
919
|
+
if (event.ctrlKey) {
|
|
920
|
+
const factor = Math.exp(-event.deltaY * zoomSensitivity);
|
|
921
|
+
controller.setZoom(controller.zoom * factor);
|
|
922
|
+
} else {
|
|
923
|
+
const [lambda, phi, gamma] = controller.projection.rotate();
|
|
924
|
+
const k = sensitivity / Math.max(controller.zoom, 0.1);
|
|
925
|
+
const next = [
|
|
926
|
+
lambda - event.deltaX * k,
|
|
927
|
+
phi + event.deltaY * k,
|
|
928
|
+
gamma
|
|
929
|
+
];
|
|
930
|
+
controller.projection.rotate(next);
|
|
931
|
+
controller.setRotation(controller.projection.rotate());
|
|
932
|
+
}
|
|
933
|
+
options.onUpdate?.(controller);
|
|
934
|
+
};
|
|
935
|
+
canvas.addEventListener("wheel", handleWheel, {
|
|
936
|
+
passive: false
|
|
937
|
+
});
|
|
938
|
+
return () => {
|
|
939
|
+
canvas.removeEventListener("wheel", handleWheel);
|
|
940
|
+
};
|
|
941
|
+
}, [
|
|
942
|
+
controller,
|
|
943
|
+
options.disabled,
|
|
944
|
+
options.sensitivity,
|
|
945
|
+
options.zoomSensitivity,
|
|
946
|
+
options.onUpdate
|
|
947
|
+
]);
|
|
948
|
+
};
|
|
949
|
+
|
|
621
950
|
// src/components/Toolbar/Controls.tsx
|
|
622
|
-
import
|
|
623
|
-
import
|
|
624
|
-
import {
|
|
951
|
+
import React from "react";
|
|
952
|
+
import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
|
|
953
|
+
import { translationKey } from "#translations";
|
|
625
954
|
var controlPositions = {
|
|
626
955
|
topleft: "top-2 left-2",
|
|
627
956
|
topright: "top-2 right-2",
|
|
@@ -629,58 +958,42 @@ var controlPositions = {
|
|
|
629
958
|
bottomright: "bottom-2 right-2"
|
|
630
959
|
};
|
|
631
960
|
var ZoomControls = ({ classNames, onAction }) => {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
iconOnly: true,
|
|
650
|
-
size: 5,
|
|
651
|
-
classNames: "px-0 aspect-square",
|
|
652
|
-
onClick: () => onAction?.("zoom-out")
|
|
653
|
-
}));
|
|
654
|
-
} finally {
|
|
655
|
-
_effect.f();
|
|
656
|
-
}
|
|
961
|
+
const { t } = useTranslation(translationKey);
|
|
962
|
+
return /* @__PURE__ */ React.createElement(Toolbar.Root, {
|
|
963
|
+
classNames: [
|
|
964
|
+
"gap-2",
|
|
965
|
+
classNames
|
|
966
|
+
]
|
|
967
|
+
}, /* @__PURE__ */ React.createElement(IconButton, {
|
|
968
|
+
icon: "ph--plus--regular",
|
|
969
|
+
iconOnly: true,
|
|
970
|
+
label: t("zoom-in-icon.button"),
|
|
971
|
+
onClick: () => onAction?.("zoom-in")
|
|
972
|
+
}), /* @__PURE__ */ React.createElement(IconButton, {
|
|
973
|
+
icon: "ph--minus--regular",
|
|
974
|
+
iconOnly: true,
|
|
975
|
+
label: t("zoom-out-icon.button"),
|
|
976
|
+
onClick: () => onAction?.("zoom-out")
|
|
977
|
+
}));
|
|
657
978
|
};
|
|
658
979
|
var ActionControls = ({ classNames, onAction }) => {
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
iconOnly: true,
|
|
677
|
-
size: 5,
|
|
678
|
-
classNames: "px-0 aspect-square",
|
|
679
|
-
onClick: () => onAction?.("toggle")
|
|
680
|
-
}));
|
|
681
|
-
} finally {
|
|
682
|
-
_effect.f();
|
|
683
|
-
}
|
|
980
|
+
const { t } = useTranslation(translationKey);
|
|
981
|
+
return /* @__PURE__ */ React.createElement(Toolbar.Root, {
|
|
982
|
+
classNames: [
|
|
983
|
+
"gap-2",
|
|
984
|
+
classNames
|
|
985
|
+
]
|
|
986
|
+
}, /* @__PURE__ */ React.createElement(IconButton, {
|
|
987
|
+
icon: "ph--path--regular",
|
|
988
|
+
iconOnly: true,
|
|
989
|
+
label: t("start-icon.button"),
|
|
990
|
+
onClick: () => onAction?.("start")
|
|
991
|
+
}), /* @__PURE__ */ React.createElement(IconButton, {
|
|
992
|
+
icon: "ph--globe-hemisphere-west--regular",
|
|
993
|
+
iconOnly: true,
|
|
994
|
+
label: t("toggle-icon.button"),
|
|
995
|
+
onClick: () => onAction?.("toggle")
|
|
996
|
+
}));
|
|
684
997
|
};
|
|
685
998
|
|
|
686
999
|
// src/components/Globe/Globe.tsx
|
|
@@ -738,188 +1051,245 @@ var getProjection = (type = "orthographic") => {
|
|
|
738
1051
|
}
|
|
739
1052
|
return type ?? geoOrthographic();
|
|
740
1053
|
};
|
|
741
|
-
var
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
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
|
-
})), [
|
|
820
|
-
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,
|
|
1054
|
+
var DEFAULT_ZOOM = 1.5;
|
|
1055
|
+
var GlobeRoot = /* @__PURE__ */ forwardRef(({ children, center: centerProp, zoom: zoomProp = DEFAULT_ZOOM, translation: translationProp, rotation: rotationProp }, forwardedRef) => {
|
|
1056
|
+
const [size, setSize] = useState4({
|
|
1057
|
+
width: 0,
|
|
1058
|
+
height: 0
|
|
1059
|
+
});
|
|
1060
|
+
const [center, setCenter] = useControlledState(centerProp);
|
|
1061
|
+
const [zoom, setZoom] = useControlledState(zoomProp);
|
|
1062
|
+
const [translation, setTranslation] = useControlledState(translationProp);
|
|
1063
|
+
const [rotation, setRotation] = useControlledState(rotationProp);
|
|
1064
|
+
const [controller, setController] = useState4(null);
|
|
1065
|
+
const registerController = useCallback3((next) => setController(next), []);
|
|
1066
|
+
useImperativeHandle(forwardedRef, () => controller, [
|
|
1067
|
+
controller
|
|
1068
|
+
]);
|
|
1069
|
+
return /* @__PURE__ */ React2.createElement(GlobeContext.Provider, {
|
|
1070
|
+
value: {
|
|
839
1071
|
size,
|
|
1072
|
+
center,
|
|
840
1073
|
zoom,
|
|
841
1074
|
translation,
|
|
842
1075
|
rotation,
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1076
|
+
setSize,
|
|
1077
|
+
setCenter,
|
|
1078
|
+
setZoom,
|
|
1079
|
+
setTranslation,
|
|
1080
|
+
setRotation,
|
|
1081
|
+
registerController
|
|
847
1082
|
}
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
1083
|
+
}, children);
|
|
1084
|
+
});
|
|
1085
|
+
GlobeRoot.displayName = "Globe.Root";
|
|
1086
|
+
var GlobeViewport = composable(({ children, ...props }, forwardedRef) => {
|
|
1087
|
+
const { setSize } = useGlobeContext();
|
|
1088
|
+
const localRef = useRef(null);
|
|
1089
|
+
const composedRef = useComposedRefs(localRef, forwardedRef);
|
|
1090
|
+
const { width, height } = useResizeDetector({
|
|
1091
|
+
targetRef: localRef
|
|
1092
|
+
});
|
|
1093
|
+
useEffect6(() => {
|
|
1094
|
+
setSize({
|
|
1095
|
+
width: width ?? 0,
|
|
1096
|
+
height: height ?? 0
|
|
852
1097
|
});
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
|
|
1098
|
+
}, [
|
|
1099
|
+
width,
|
|
1100
|
+
height,
|
|
1101
|
+
setSize
|
|
1102
|
+
]);
|
|
1103
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1104
|
+
...composableProps(props, {
|
|
1105
|
+
classNames: "relative dx-container"
|
|
1106
|
+
}),
|
|
1107
|
+
ref: composedRef
|
|
1108
|
+
}, children);
|
|
856
1109
|
});
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1110
|
+
GlobeViewport.displayName = "Globe.Viewport";
|
|
1111
|
+
var GlobeCanvas = ({ projection: projectionProp, topology, features, styles: stylesProp }) => {
|
|
1112
|
+
const { themeMode } = useThemeContext();
|
|
1113
|
+
const styles = useMemo2(() => stylesProp ?? defaultStyles[themeMode], [
|
|
1114
|
+
stylesProp,
|
|
1115
|
+
themeMode
|
|
1116
|
+
]);
|
|
1117
|
+
const { size, center, zoom, translation, rotation, setZoom, setTranslation, setRotation, registerController } = useGlobeContext();
|
|
1118
|
+
const zoomRef = useDynamicRef(zoom);
|
|
1119
|
+
const [canvas, setCanvas] = useState4(null);
|
|
1120
|
+
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
1121
|
+
const projection = useMemo2(() => getProjection(projectionProp), [
|
|
1122
|
+
projectionProp
|
|
1123
|
+
]);
|
|
1124
|
+
const layers = useMemo2(() => {
|
|
1125
|
+
return timer(() => createLayers(topology, features, styles));
|
|
1126
|
+
}, [
|
|
1127
|
+
topology,
|
|
1128
|
+
features,
|
|
1129
|
+
styles
|
|
1130
|
+
]);
|
|
1131
|
+
useEffect6(() => {
|
|
1132
|
+
if (center) {
|
|
1133
|
+
setRotation(positionToRotation(geoToPosition(center)));
|
|
1134
|
+
}
|
|
1135
|
+
}, [
|
|
1136
|
+
center
|
|
1137
|
+
]);
|
|
1138
|
+
const flyToSelection = useMemo2(() => d3Selection(), []);
|
|
1139
|
+
const flyToTransitionName = `globe-fly-to-${useId()}`;
|
|
1140
|
+
useEffect6(() => () => {
|
|
1141
|
+
flyToSelection.interrupt(flyToTransitionName);
|
|
1142
|
+
}, [
|
|
1143
|
+
flyToSelection,
|
|
1144
|
+
flyToTransitionName
|
|
1145
|
+
]);
|
|
1146
|
+
const zooming = useRef(false);
|
|
1147
|
+
const controller = useMemo2(() => {
|
|
1148
|
+
return {
|
|
1149
|
+
canvas,
|
|
1150
|
+
projection,
|
|
1151
|
+
get zoom() {
|
|
1152
|
+
return zoomRef.current;
|
|
1153
|
+
},
|
|
868
1154
|
translation,
|
|
869
|
-
rotation
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
1155
|
+
rotation,
|
|
1156
|
+
setZoom: (state) => {
|
|
1157
|
+
if (typeof state === "function") {
|
|
1158
|
+
const is = interpolateNumber(zoomRef.current, state(zoomRef.current));
|
|
1159
|
+
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
1160
|
+
zooming.current = false;
|
|
1161
|
+
});
|
|
1162
|
+
} else {
|
|
1163
|
+
setZoom(state);
|
|
1164
|
+
}
|
|
1165
|
+
},
|
|
1166
|
+
setTranslation,
|
|
1167
|
+
setRotation,
|
|
1168
|
+
flyTo: (target, options = {}) => {
|
|
1169
|
+
const { duration = 1200, tilt = 0, onTick } = options;
|
|
1170
|
+
const p2 = geoToPosition(target);
|
|
1171
|
+
const r1 = projection.rotate();
|
|
1172
|
+
const r2 = positionToRotation(p2, tilt);
|
|
1173
|
+
const p1 = [
|
|
1174
|
+
-r1[0],
|
|
1175
|
+
-r1[1]
|
|
1176
|
+
];
|
|
1177
|
+
const rotationTween = createRotationTween(projection, setRotation, r1, r2);
|
|
1178
|
+
const iz = target.zoom !== void 0 ? interpolateNumber(zoomRef.current, target.zoom) : void 0;
|
|
1179
|
+
flyToSelection.interrupt(flyToTransitionName);
|
|
1180
|
+
const tx = flyToSelection.transition(flyToTransitionName).duration(flyDuration(p1, p2, duration, 1500));
|
|
1181
|
+
if (onTick) {
|
|
1182
|
+
tx.tween("flyToOnTick", () => onTick);
|
|
1183
|
+
}
|
|
1184
|
+
tx.tween("flyToRotation", () => rotationTween);
|
|
1185
|
+
if (iz) {
|
|
1186
|
+
tx.tween("flyToZoom", () => (t) => setZoom(iz(t)));
|
|
1187
|
+
}
|
|
1188
|
+
return tx.end();
|
|
1189
|
+
},
|
|
1190
|
+
cancelFlyTo: () => {
|
|
1191
|
+
flyToSelection.interrupt(flyToTransitionName);
|
|
1192
|
+
}
|
|
1193
|
+
};
|
|
1194
|
+
}, [
|
|
1195
|
+
canvas,
|
|
1196
|
+
projection,
|
|
1197
|
+
flyToSelection,
|
|
1198
|
+
flyToTransitionName
|
|
1199
|
+
]);
|
|
1200
|
+
useEffect6(() => {
|
|
1201
|
+
registerController(controller);
|
|
1202
|
+
return () => registerController(null);
|
|
1203
|
+
}, [
|
|
1204
|
+
registerController,
|
|
1205
|
+
controller
|
|
1206
|
+
]);
|
|
1207
|
+
const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d")), [
|
|
1208
|
+
canvas,
|
|
1209
|
+
projection
|
|
1210
|
+
]);
|
|
1211
|
+
useEffect6(() => {
|
|
1212
|
+
if (canvas && projection) {
|
|
1213
|
+
timer(() => {
|
|
1214
|
+
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
1215
|
+
size.width / 2 + (translation?.x ?? 0),
|
|
1216
|
+
size.height / 2 + (translation?.y ?? 0)
|
|
1217
|
+
]).rotate(rotation ?? [
|
|
1218
|
+
0,
|
|
1219
|
+
0,
|
|
1220
|
+
0
|
|
1221
|
+
]);
|
|
1222
|
+
const isOrthographic = !projectionProp || projectionProp === "orthographic";
|
|
1223
|
+
const [lambda, phi] = rotation ?? [
|
|
1224
|
+
0,
|
|
1225
|
+
0,
|
|
1226
|
+
0
|
|
1227
|
+
];
|
|
1228
|
+
const viewCenter = isOrthographic ? [
|
|
1229
|
+
-lambda,
|
|
1230
|
+
-phi
|
|
1231
|
+
] : void 0;
|
|
1232
|
+
renderLayers(generator, layers, zoom, styles, viewCenter);
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
}, [
|
|
1236
|
+
generator,
|
|
1237
|
+
size,
|
|
1238
|
+
zoom,
|
|
1239
|
+
translation,
|
|
1240
|
+
rotation,
|
|
1241
|
+
layers,
|
|
1242
|
+
projectionProp
|
|
1243
|
+
]);
|
|
1244
|
+
if (!size.width || !size.height) {
|
|
1245
|
+
return null;
|
|
873
1246
|
}
|
|
1247
|
+
return /* @__PURE__ */ React2.createElement("canvas", {
|
|
1248
|
+
ref: canvasRef,
|
|
1249
|
+
className: "bg-base-surface",
|
|
1250
|
+
width: size.width,
|
|
1251
|
+
height: size.height
|
|
1252
|
+
});
|
|
1253
|
+
};
|
|
1254
|
+
GlobeCanvas.displayName = "Globe.Canvas";
|
|
1255
|
+
var GlobeDebug = ({ position = "topleft" }) => {
|
|
1256
|
+
const { size, zoom, translation, rotation } = useGlobeContext();
|
|
1257
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1258
|
+
className: mx("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded-sm", controlPositions[position])
|
|
1259
|
+
}, /* @__PURE__ */ React2.createElement("pre", {
|
|
1260
|
+
className: "font-mono text-xs text-green-700"
|
|
1261
|
+
}, JSON.stringify({
|
|
1262
|
+
size,
|
|
1263
|
+
zoom,
|
|
1264
|
+
translation,
|
|
1265
|
+
rotation
|
|
1266
|
+
}, null, 2)));
|
|
874
1267
|
};
|
|
875
1268
|
var GlobePanel = ({ position, classNames, children }) => {
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
880
|
-
}, children);
|
|
881
|
-
} finally {
|
|
882
|
-
_effect.f();
|
|
883
|
-
}
|
|
1269
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1270
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
1271
|
+
}, children);
|
|
884
1272
|
};
|
|
885
1273
|
var CustomControl = ({ position, children }) => {
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
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
|
-
}
|
|
1274
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1275
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
1276
|
+
}, children);
|
|
920
1277
|
};
|
|
1278
|
+
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React2.createElement(CustomControl, {
|
|
1279
|
+
position,
|
|
1280
|
+
...props
|
|
1281
|
+
}, /* @__PURE__ */ React2.createElement(ZoomControls, {
|
|
1282
|
+
onAction
|
|
1283
|
+
}));
|
|
1284
|
+
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React2.createElement(CustomControl, {
|
|
1285
|
+
position,
|
|
1286
|
+
...props
|
|
1287
|
+
}, /* @__PURE__ */ React2.createElement(ActionControls, {
|
|
1288
|
+
onAction
|
|
1289
|
+
}));
|
|
921
1290
|
var Globe = {
|
|
922
1291
|
Root: GlobeRoot,
|
|
1292
|
+
Viewport: GlobeViewport,
|
|
923
1293
|
Canvas: GlobeCanvas,
|
|
924
1294
|
Zoom: GlobeZoom,
|
|
925
1295
|
Action: GlobeAction,
|
|
@@ -928,16 +1298,15 @@ var Globe = {
|
|
|
928
1298
|
};
|
|
929
1299
|
|
|
930
1300
|
// src/components/Map/Map.tsx
|
|
931
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
932
1301
|
import "leaflet/dist/leaflet.css";
|
|
933
1302
|
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
934
|
-
import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
|
|
935
|
-
import
|
|
1303
|
+
import L, { Control, DomEvent, DomUtil, point, latLngBounds } from "leaflet";
|
|
1304
|
+
import React3, { forwardRef as forwardRef2, useCallback as useCallback4, useEffect as useEffect7, useImperativeHandle as useImperativeHandle2, useRef as useRef2, useState as useState5 } from "react";
|
|
936
1305
|
import { createRoot } from "react-dom/client";
|
|
937
|
-
import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
|
|
938
|
-
import { debounce } from "@dxos/async";
|
|
1306
|
+
import { MapContainer, Marker, Polyline, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
939
1307
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
|
940
|
-
import {
|
|
1308
|
+
import { composable as composable2, composableProps as composableProps2, defaultTx } from "@dxos/react-ui";
|
|
1309
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
941
1310
|
var defaults = {
|
|
942
1311
|
center: {
|
|
943
1312
|
lat: 51,
|
|
@@ -945,237 +1314,341 @@ var defaults = {
|
|
|
945
1314
|
},
|
|
946
1315
|
zoom: 4
|
|
947
1316
|
};
|
|
948
|
-
var [
|
|
949
|
-
var MapRoot = /* @__PURE__ */ forwardRef2(({
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1317
|
+
var [MapContextProvider, useMapContext] = createContext2("Map");
|
|
1318
|
+
var MapRoot = /* @__PURE__ */ forwardRef2(({ children, onChange }, forwardedRef) => {
|
|
1319
|
+
const mapRef = useRef2(null);
|
|
1320
|
+
const registerMap = useCallback4((map) => {
|
|
1321
|
+
mapRef.current = map;
|
|
1322
|
+
}, []);
|
|
1323
|
+
useImperativeHandle2(forwardedRef, () => ({
|
|
1324
|
+
getCenter: () => {
|
|
1325
|
+
const center = mapRef.current?.getCenter();
|
|
1326
|
+
return center ? {
|
|
1327
|
+
lat: center.lat,
|
|
1328
|
+
lng: center.lng
|
|
1329
|
+
} : void 0;
|
|
1330
|
+
},
|
|
1331
|
+
getZoom: () => mapRef.current?.getZoom(),
|
|
1332
|
+
setCenter: (center, zoom) => {
|
|
1333
|
+
mapRef.current?.setView(center, zoom);
|
|
1334
|
+
},
|
|
1335
|
+
setZoom: (cb) => {
|
|
1336
|
+
mapRef.current?.setZoom(cb(mapRef.current?.getZoom() ?? 0));
|
|
1337
|
+
}
|
|
1338
|
+
}), []);
|
|
1339
|
+
const attention = false;
|
|
1340
|
+
return /* @__PURE__ */ React3.createElement(MapContextProvider, {
|
|
1341
|
+
attention,
|
|
1342
|
+
onChange,
|
|
1343
|
+
registerMap
|
|
1344
|
+
}, children);
|
|
1345
|
+
});
|
|
1346
|
+
MapRoot.displayName = "Map.Root";
|
|
1347
|
+
var MAP_VIEWPORT_NAME = "Map.Viewport";
|
|
1348
|
+
var MapResize = () => {
|
|
1349
|
+
const map = useMap();
|
|
1350
|
+
useEffect7(() => {
|
|
1351
|
+
const container = map.getContainer();
|
|
1352
|
+
let frame = 0;
|
|
1353
|
+
const observer = new ResizeObserver(() => {
|
|
1354
|
+
cancelAnimationFrame(frame);
|
|
1355
|
+
frame = requestAnimationFrame(() => map.invalidateSize());
|
|
1356
|
+
});
|
|
1357
|
+
observer.observe(container);
|
|
1358
|
+
return () => {
|
|
1359
|
+
cancelAnimationFrame(frame);
|
|
1360
|
+
observer.disconnect();
|
|
1361
|
+
};
|
|
1362
|
+
}, [
|
|
1363
|
+
map
|
|
1364
|
+
]);
|
|
1365
|
+
return null;
|
|
1366
|
+
};
|
|
1367
|
+
var PINCH_ZOOM_SENSITIVITY = 0.03;
|
|
1368
|
+
var MapPinchZoom = () => {
|
|
1369
|
+
const map = useMap();
|
|
1370
|
+
useEffect7(() => {
|
|
1371
|
+
const container = map.getContainer();
|
|
1372
|
+
let frame = 0;
|
|
1373
|
+
let point2;
|
|
1374
|
+
let target;
|
|
1375
|
+
const onWheel = (event) => {
|
|
1376
|
+
if (!event.ctrlKey) {
|
|
965
1377
|
return;
|
|
966
1378
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
1379
|
+
event.preventDefault();
|
|
1380
|
+
const rect = container.getBoundingClientRect();
|
|
1381
|
+
point2 = L.point(event.clientX - rect.left, event.clientY - rect.top);
|
|
1382
|
+
target = (target ?? map.getZoom()) - event.deltaY * PINCH_ZOOM_SENSITIVITY;
|
|
1383
|
+
if (!frame) {
|
|
1384
|
+
frame = requestAnimationFrame(() => {
|
|
1385
|
+
frame = 0;
|
|
1386
|
+
if (target !== void 0 && point2) {
|
|
1387
|
+
map.setZoomAround(point2, target, {
|
|
1388
|
+
animate: false
|
|
1389
|
+
});
|
|
1390
|
+
target = void 0;
|
|
1391
|
+
}
|
|
972
1392
|
});
|
|
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
1393
|
}
|
|
997
|
-
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
return
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
}
|
|
1394
|
+
};
|
|
1395
|
+
container.addEventListener("wheel", onWheel, {
|
|
1396
|
+
passive: false
|
|
1397
|
+
});
|
|
1398
|
+
return () => {
|
|
1399
|
+
container.removeEventListener("wheel", onWheel);
|
|
1400
|
+
cancelAnimationFrame(frame);
|
|
1401
|
+
};
|
|
1402
|
+
}, [
|
|
1403
|
+
map
|
|
1404
|
+
]);
|
|
1405
|
+
return null;
|
|
1406
|
+
};
|
|
1407
|
+
var MapViewport = composable2((props, _forwardedRef) => {
|
|
1408
|
+
const { scrollWheelZoom = true, doubleClickZoom = true, touchZoom = true, center, zoom, whenReady, children, ...rest } = props;
|
|
1409
|
+
const { attention, registerMap } = useMapContext(MAP_VIEWPORT_NAME);
|
|
1410
|
+
const [map, setMap] = useState5(null);
|
|
1411
|
+
const setMapRef = useCallback4((next) => {
|
|
1412
|
+
setMap(next);
|
|
1413
|
+
registerMap(next);
|
|
1414
|
+
}, [
|
|
1415
|
+
registerMap
|
|
1416
|
+
]);
|
|
1417
|
+
useEffect7(() => {
|
|
1418
|
+
if (!map) {
|
|
1419
|
+
return;
|
|
1420
|
+
}
|
|
1421
|
+
if (attention) {
|
|
1422
|
+
map.scrollWheelZoom.enable();
|
|
1423
|
+
} else {
|
|
1424
|
+
map.scrollWheelZoom.disable();
|
|
1425
|
+
}
|
|
1426
|
+
}, [
|
|
1427
|
+
map,
|
|
1428
|
+
attention
|
|
1429
|
+
]);
|
|
1430
|
+
return /* @__PURE__ */ React3.createElement(MapContainer, {
|
|
1431
|
+
...composableProps2(rest, {
|
|
1432
|
+
// Frame classes (formerly on Map.Root): focusable grid container.
|
|
1433
|
+
classNames: "dx-container group relative grid dx-focus-ring-inset bg-base-surface!"
|
|
1434
|
+
}),
|
|
1435
|
+
attributionControl: false,
|
|
1436
|
+
zoomControl: false,
|
|
1437
|
+
scrollWheelZoom,
|
|
1438
|
+
doubleClickZoom,
|
|
1439
|
+
touchZoom,
|
|
1440
|
+
// Allow fractional zoom so trackpad pinch (small ctrl+wheel deltas) isn't rounded away.
|
|
1441
|
+
zoomSnap: 0,
|
|
1442
|
+
center: center ?? defaults.center,
|
|
1443
|
+
zoom: zoom ?? defaults.zoom,
|
|
1444
|
+
whenReady,
|
|
1445
|
+
ref: setMapRef
|
|
1446
|
+
}, /* @__PURE__ */ React3.createElement(MapResize, null), /* @__PURE__ */ React3.createElement(MapPinchZoom, null), children);
|
|
1018
1447
|
});
|
|
1019
|
-
|
|
1020
|
-
var
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1448
|
+
MapViewport.displayName = "Map.Viewport";
|
|
1449
|
+
var MAP_TILES_NAME = "Map.Tiles";
|
|
1450
|
+
var DEFAULT_TILE_URL = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
|
|
1451
|
+
var MapTiles = ({ url = DEFAULT_TILE_URL }) => {
|
|
1452
|
+
const ref = useRef2(null);
|
|
1453
|
+
const { onChange } = useMapContext(MAP_TILES_NAME);
|
|
1454
|
+
useMapEvents({
|
|
1455
|
+
moveend: (ev) => {
|
|
1456
|
+
onChange?.({
|
|
1457
|
+
center: ev.target.getCenter(),
|
|
1458
|
+
zoom: ev.target.getZoom()
|
|
1459
|
+
});
|
|
1460
|
+
}
|
|
1461
|
+
});
|
|
1462
|
+
const { attention } = useMapContext(MAP_TILES_NAME);
|
|
1463
|
+
useEffect7(() => {
|
|
1464
|
+
if (ref.current) {
|
|
1465
|
+
ref.current.getContainer().dataset.attention = attention ? "1" : "0";
|
|
1466
|
+
}
|
|
1467
|
+
}, [
|
|
1468
|
+
attention
|
|
1469
|
+
]);
|
|
1470
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, /* @__PURE__ */ React3.createElement(TileLayer, {
|
|
1471
|
+
ref,
|
|
1472
|
+
"data-attention": attention,
|
|
1473
|
+
detectRetina: true,
|
|
1474
|
+
className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
|
|
1475
|
+
url,
|
|
1476
|
+
keepBuffer: 4
|
|
1477
|
+
}));
|
|
1043
1478
|
};
|
|
1044
|
-
MapTiles.displayName =
|
|
1045
|
-
var MapMarkers = ({ selected, markers }) => {
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1479
|
+
MapTiles.displayName = MAP_TILES_NAME;
|
|
1480
|
+
var MapMarkers = ({ selected, markers, lines, onSelect }) => {
|
|
1481
|
+
const map = useMap();
|
|
1482
|
+
useEffect7(() => {
|
|
1483
|
+
const points = [
|
|
1484
|
+
...markers?.map((marker) => marker.location) ?? [],
|
|
1485
|
+
...lines?.flatMap((line) => [
|
|
1486
|
+
line.source,
|
|
1487
|
+
line.target
|
|
1488
|
+
]) ?? []
|
|
1489
|
+
];
|
|
1490
|
+
if (points.length > 0) {
|
|
1491
|
+
const bounds = latLngBounds(points);
|
|
1492
|
+
const size = map.getSize();
|
|
1493
|
+
const padding = Math.max(48, Math.min(size.x, size.y) / 6);
|
|
1494
|
+
map.fitBounds(bounds, {
|
|
1495
|
+
padding: point(padding, padding),
|
|
1496
|
+
animate: false
|
|
1497
|
+
});
|
|
1498
|
+
}
|
|
1499
|
+
}, [
|
|
1500
|
+
markers,
|
|
1501
|
+
lines,
|
|
1502
|
+
map
|
|
1503
|
+
]);
|
|
1504
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, markers?.map(({ id, title, location: { lat, lng } }) => {
|
|
1505
|
+
return /* @__PURE__ */ React3.createElement(Marker, {
|
|
1506
|
+
key: id,
|
|
1507
|
+
position: {
|
|
1508
|
+
lat,
|
|
1509
|
+
lng
|
|
1510
|
+
},
|
|
1511
|
+
eventHandlers: onSelect ? {
|
|
1512
|
+
click: () => onSelect(id)
|
|
1513
|
+
} : void 0,
|
|
1514
|
+
icon: (
|
|
1515
|
+
// TODO(burdon): Create custom icon from bundled assets.
|
|
1516
|
+
// TODO(burdon): Selection state.
|
|
1517
|
+
new L.Icon({
|
|
1518
|
+
iconUrl: "https://dxos.network/marker-icon.png",
|
|
1519
|
+
iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
|
|
1520
|
+
shadowUrl: "https://dxos.network/marker-shadow.png",
|
|
1521
|
+
iconSize: [
|
|
1522
|
+
25,
|
|
1523
|
+
41
|
|
1524
|
+
],
|
|
1525
|
+
iconAnchor: [
|
|
1526
|
+
12,
|
|
1527
|
+
41
|
|
1528
|
+
],
|
|
1529
|
+
popupAnchor: [
|
|
1530
|
+
1,
|
|
1531
|
+
-34
|
|
1532
|
+
],
|
|
1533
|
+
shadowSize: [
|
|
1534
|
+
41,
|
|
1535
|
+
41
|
|
1536
|
+
]
|
|
1537
|
+
})
|
|
1538
|
+
)
|
|
1539
|
+
}, title && /* @__PURE__ */ React3.createElement(Popup, null, title));
|
|
1540
|
+
}));
|
|
1096
1541
|
};
|
|
1097
1542
|
MapMarkers.displayName = "Map.Markers";
|
|
1098
|
-
var
|
|
1099
|
-
|
|
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
|
-
]);
|
|
1543
|
+
var MapLines = ({ lines }) => {
|
|
1544
|
+
if (!lines || lines.length === 0) {
|
|
1125
1545
|
return null;
|
|
1126
|
-
} finally {
|
|
1127
|
-
_effect.f();
|
|
1128
1546
|
}
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1547
|
+
const polylines = [];
|
|
1548
|
+
for (const { source, target, color } of lines) {
|
|
1549
|
+
const last = polylines[polylines.length - 1];
|
|
1550
|
+
const lastPos = last?.positions[last.positions.length - 1];
|
|
1551
|
+
if (last && last.color === color && lastPos?.lat === source.lat && lastPos?.lng === source.lng) {
|
|
1552
|
+
last.positions.push(target);
|
|
1553
|
+
} else {
|
|
1554
|
+
polylines.push({
|
|
1555
|
+
positions: [
|
|
1556
|
+
source,
|
|
1557
|
+
target
|
|
1558
|
+
],
|
|
1559
|
+
color
|
|
1560
|
+
});
|
|
1561
|
+
}
|
|
1141
1562
|
}
|
|
1563
|
+
return /* @__PURE__ */ React3.createElement(React3.Fragment, null, polylines.map(({ positions, color }, index) => /* @__PURE__ */ React3.createElement(Polyline, {
|
|
1564
|
+
key: index,
|
|
1565
|
+
positions,
|
|
1566
|
+
pathOptions: {
|
|
1567
|
+
color,
|
|
1568
|
+
weight: 4,
|
|
1569
|
+
opacity: 0.8
|
|
1570
|
+
}
|
|
1571
|
+
})));
|
|
1142
1572
|
};
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1573
|
+
MapLines.displayName = "Map.Lines";
|
|
1574
|
+
var CustomControl2 = ({ position, children }) => {
|
|
1575
|
+
const map = useMap();
|
|
1576
|
+
const rootRef = useRef2(void 0);
|
|
1577
|
+
useEffect7(() => {
|
|
1578
|
+
const control = new Control({
|
|
1579
|
+
position
|
|
1580
|
+
});
|
|
1581
|
+
control.onAdd = () => {
|
|
1582
|
+
const container = DomUtil.create("div", mx2("m-0!", controlPositions[position]));
|
|
1583
|
+
DomEvent.disableClickPropagation(container);
|
|
1584
|
+
DomEvent.disableScrollPropagation(container);
|
|
1585
|
+
const root = createRoot(container);
|
|
1586
|
+
rootRef.current = root;
|
|
1587
|
+
root.render(/* @__PURE__ */ React3.createElement(ThemeProvider, {
|
|
1588
|
+
tx: defaultTx
|
|
1589
|
+
}, /* @__PURE__ */ React3.createElement(Tooltip.Provider, null, children)));
|
|
1590
|
+
return container;
|
|
1591
|
+
};
|
|
1592
|
+
control.addTo(map);
|
|
1593
|
+
return () => {
|
|
1594
|
+
control.remove();
|
|
1595
|
+
const root = rootRef.current;
|
|
1596
|
+
rootRef.current = void 0;
|
|
1597
|
+
queueMicrotask(() => root?.unmount());
|
|
1598
|
+
};
|
|
1599
|
+
}, [
|
|
1600
|
+
map,
|
|
1601
|
+
position
|
|
1602
|
+
]);
|
|
1603
|
+
useEffect7(() => {
|
|
1604
|
+
rootRef.current?.render(/* @__PURE__ */ React3.createElement(ThemeProvider, {
|
|
1605
|
+
tx: defaultTx
|
|
1606
|
+
}, /* @__PURE__ */ React3.createElement(Tooltip.Provider, null, children)));
|
|
1607
|
+
}, [
|
|
1608
|
+
children
|
|
1609
|
+
]);
|
|
1610
|
+
return null;
|
|
1155
1611
|
};
|
|
1156
|
-
var
|
|
1612
|
+
var MapZoom = ({ onAction, position = "bottomleft", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl2, {
|
|
1613
|
+
position,
|
|
1614
|
+
...props
|
|
1615
|
+
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
1616
|
+
onAction
|
|
1617
|
+
}));
|
|
1618
|
+
var MapAction = ({ onAction, position = "bottomright", ...props }) => /* @__PURE__ */ React3.createElement(CustomControl2, {
|
|
1619
|
+
position,
|
|
1620
|
+
...props
|
|
1621
|
+
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
1622
|
+
onAction
|
|
1623
|
+
}));
|
|
1624
|
+
var Map2 = {
|
|
1157
1625
|
Root: MapRoot,
|
|
1626
|
+
Viewport: MapViewport,
|
|
1158
1627
|
Tiles: MapTiles,
|
|
1159
1628
|
Markers: MapMarkers,
|
|
1629
|
+
Lines: MapLines,
|
|
1160
1630
|
Zoom: MapZoom,
|
|
1161
1631
|
Action: MapAction
|
|
1162
1632
|
};
|
|
1163
1633
|
export {
|
|
1164
1634
|
ActionControls,
|
|
1635
|
+
DEFAULT_TILE_URL,
|
|
1165
1636
|
Globe,
|
|
1166
|
-
|
|
1167
|
-
Map,
|
|
1637
|
+
GlobeContext,
|
|
1638
|
+
Map2 as Map,
|
|
1168
1639
|
ZoomControls,
|
|
1169
1640
|
closestPoint,
|
|
1170
1641
|
controlPositions,
|
|
1171
1642
|
createLayers,
|
|
1643
|
+
createRotationTween,
|
|
1644
|
+
flyDuration,
|
|
1172
1645
|
geoCircle,
|
|
1173
1646
|
geoInertiaDrag,
|
|
1174
1647
|
geoLine,
|
|
1175
1648
|
geoPoint,
|
|
1176
1649
|
geoToPosition,
|
|
1177
1650
|
getDistance,
|
|
1178
|
-
|
|
1651
|
+
globeStyles,
|
|
1179
1652
|
positionToRotation,
|
|
1180
1653
|
renderLayers,
|
|
1181
1654
|
restrictAxis,
|
|
@@ -1184,7 +1657,10 @@ export {
|
|
|
1184
1657
|
useGlobeContext,
|
|
1185
1658
|
useGlobeZoomHandler,
|
|
1186
1659
|
useMapZoomHandler,
|
|
1660
|
+
useSimplifiedTopology,
|
|
1187
1661
|
useSpinner,
|
|
1188
|
-
|
|
1662
|
+
useTopology,
|
|
1663
|
+
useTour,
|
|
1664
|
+
useWheel
|
|
1189
1665
|
};
|
|
1190
1666
|
//# sourceMappingURL=index.mjs.map
|