@dxos/react-ui-geo 0.8.4-main.fffef41 → 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 +1046 -579
- 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 +1046 -579
- 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 +17 -7
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +51 -9
- package/dist/types/src/components/Map/Map.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.stories.d.ts +9 -5
- 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 -2
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +6 -6
- package/dist/types/src/translations.d.ts.map +1 -1
- 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 +41 -35
- package/src/components/Globe/Globe.stories.tsx +141 -65
- package/src/components/Globe/Globe.tsx +262 -119
- package/src/components/Map/Map.stories.tsx +59 -12
- package/src/components/Map/Map.tsx +325 -82
- package/src/components/Toolbar/Controls.tsx +5 -5
- package/src/data.ts +19 -2
- package/src/hooks/context.tsx +46 -31
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useDrag.ts +33 -5
- package/src/hooks/useGlobeZoomHandler.ts +2 -1
- 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 +70 -81
- package/src/hooks/useWheel.ts +83 -0
- package/src/index.ts +0 -2
- package/src/translations.ts +5 -5
- 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,52 +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
|
-
var defaults = {
|
|
19
|
-
center: {
|
|
20
|
-
lat: 51,
|
|
21
|
-
lng: 0
|
|
22
|
-
},
|
|
23
|
-
zoom: 4
|
|
24
|
-
};
|
|
25
16
|
var GlobeContext = /* @__PURE__ */ createContext(void 0);
|
|
26
|
-
var GlobeContextProvider = ({ children, size, center: centerParam = defaults.center, zoom: zoomParam = defaults.zoom, translation: translationParam, rotation: rotationParam }) => {
|
|
27
|
-
var _effect = _useSignals();
|
|
28
|
-
try {
|
|
29
|
-
const [center, setCenter] = useControlledState(centerParam);
|
|
30
|
-
const [zoom, setZoom] = useControlledState(zoomParam);
|
|
31
|
-
const [translation, setTranslation] = useControlledState(translationParam);
|
|
32
|
-
const [rotation, setRotation] = useControlledState(rotationParam);
|
|
33
|
-
return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
|
|
34
|
-
value: {
|
|
35
|
-
size,
|
|
36
|
-
center,
|
|
37
|
-
zoom,
|
|
38
|
-
translation,
|
|
39
|
-
rotation,
|
|
40
|
-
setCenter,
|
|
41
|
-
setZoom,
|
|
42
|
-
setTranslation,
|
|
43
|
-
setRotation
|
|
44
|
-
}
|
|
45
|
-
}, children);
|
|
46
|
-
} finally {
|
|
47
|
-
_effect.f();
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
17
|
var useGlobeContext = () => {
|
|
51
18
|
return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
|
|
52
19
|
};
|
|
@@ -55,6 +22,18 @@ var useGlobeContext = () => {
|
|
|
55
22
|
import { select as select2 } from "d3";
|
|
56
23
|
import { useEffect } from "react";
|
|
57
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
|
+
|
|
58
37
|
// src/util/debug.ts
|
|
59
38
|
var debug = false;
|
|
60
39
|
var timer = (cb) => {
|
|
@@ -72,7 +51,7 @@ var timer = (cb) => {
|
|
|
72
51
|
|
|
73
52
|
// src/util/inertia.ts
|
|
74
53
|
import { drag, select, timer as timer2 } from "d3";
|
|
75
|
-
import
|
|
54
|
+
import versor2 from "versor";
|
|
76
55
|
var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
|
|
77
56
|
var geoInertiaDrag = (target, render, projection, options) => {
|
|
78
57
|
if (!options) {
|
|
@@ -82,21 +61,23 @@ var geoInertiaDrag = (target, render, projection, options) => {
|
|
|
82
61
|
target = target.node();
|
|
83
62
|
}
|
|
84
63
|
target = select(target);
|
|
85
|
-
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 = {
|
|
86
75
|
projection,
|
|
87
76
|
render: (rotation) => {
|
|
88
77
|
projection.rotate(rotation);
|
|
89
78
|
render && render();
|
|
90
79
|
},
|
|
91
|
-
axis
|
|
92
|
-
true,
|
|
93
|
-
false,
|
|
94
|
-
false
|
|
95
|
-
] : [
|
|
96
|
-
true,
|
|
97
|
-
true,
|
|
98
|
-
true
|
|
99
|
-
]),
|
|
80
|
+
axis,
|
|
100
81
|
start: options.start,
|
|
101
82
|
move: options.move,
|
|
102
83
|
end: options.end,
|
|
@@ -104,7 +85,12 @@ var geoInertiaDrag = (target, render, projection, options) => {
|
|
|
104
85
|
finish: options.finish,
|
|
105
86
|
time: options.time,
|
|
106
87
|
hold: options.hold
|
|
107
|
-
}
|
|
88
|
+
};
|
|
89
|
+
const inertia = linear ? geoInertiaDragLinearHelper({
|
|
90
|
+
...sharedHandlers,
|
|
91
|
+
sensitivity: options.sensitivity,
|
|
92
|
+
getZoom: options.getZoom
|
|
93
|
+
}) : geoInertiaDragHelper(sharedHandlers);
|
|
108
94
|
target.call(drag().on("start", inertia.start).on("drag", inertia.move).on("end", inertia.end));
|
|
109
95
|
return inertia;
|
|
110
96
|
};
|
|
@@ -119,9 +105,9 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
119
105
|
const inertia = inertiaHelper({
|
|
120
106
|
axis: opt.axis,
|
|
121
107
|
start: () => {
|
|
122
|
-
v0 =
|
|
108
|
+
v0 = versor2.cartesian(projection.invert(inertia.position));
|
|
123
109
|
r0 = projection.rotate();
|
|
124
|
-
q0 =
|
|
110
|
+
q0 = versor2(r0);
|
|
125
111
|
opt.start && opt.start();
|
|
126
112
|
},
|
|
127
113
|
move: () => {
|
|
@@ -129,23 +115,23 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
129
115
|
if (isNaN(inv[0])) {
|
|
130
116
|
return;
|
|
131
117
|
}
|
|
132
|
-
const v1 =
|
|
133
|
-
const q1 =
|
|
134
|
-
const r1 =
|
|
118
|
+
const v1 = versor2.cartesian(inv);
|
|
119
|
+
const q1 = versor2.multiply(q0, versor2.delta(v0, v1));
|
|
120
|
+
const r1 = versor2.rotation(q1);
|
|
135
121
|
const r2 = opt.axis(r0, r1);
|
|
136
122
|
opt.render(r2);
|
|
137
123
|
opt.move && opt.move();
|
|
138
124
|
},
|
|
139
125
|
end: () => {
|
|
140
|
-
v10 =
|
|
141
|
-
q10 =
|
|
142
|
-
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));
|
|
143
129
|
opt.end && opt.end();
|
|
144
130
|
},
|
|
145
131
|
stop: opt.stop,
|
|
146
132
|
finish: opt.finish,
|
|
147
133
|
render: (t) => {
|
|
148
|
-
const r1 =
|
|
134
|
+
const r1 = versor2.rotation(versor2.multiply(q10, versor2.delta(v10, v11, t * 1e3)));
|
|
149
135
|
const r2 = opt.axis(r0, r1);
|
|
150
136
|
opt.render && opt.render(r2);
|
|
151
137
|
},
|
|
@@ -153,6 +139,62 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
153
139
|
});
|
|
154
140
|
return inertia;
|
|
155
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
|
+
};
|
|
156
198
|
function inertiaHelper(opt) {
|
|
157
199
|
const A = opt.time || 5e3;
|
|
158
200
|
const limit = 1.0001;
|
|
@@ -256,9 +298,9 @@ var geoToPosition = ({ lat, lng }) => [
|
|
|
256
298
|
lng,
|
|
257
299
|
lat
|
|
258
300
|
];
|
|
259
|
-
var geoPoint = (
|
|
301
|
+
var geoPoint = (point2) => ({
|
|
260
302
|
type: "Point",
|
|
261
|
-
coordinates: geoToPosition(
|
|
303
|
+
coordinates: geoToPosition(point2)
|
|
262
304
|
});
|
|
263
305
|
var geoCircle = ({ lat, lng }, radius) => d3GeoCircle().radius(radius).center([
|
|
264
306
|
lng,
|
|
@@ -283,11 +325,11 @@ var closestPoint = (points, target) => {
|
|
|
283
325
|
}
|
|
284
326
|
let closestPoint2 = points[0];
|
|
285
327
|
let minDistance = getDistance(points[0], target);
|
|
286
|
-
for (const
|
|
287
|
-
const distance = getDistance(
|
|
328
|
+
for (const point2 of points) {
|
|
329
|
+
const distance = getDistance(point2, target);
|
|
288
330
|
if (distance < minDistance) {
|
|
289
331
|
minDistance = distance;
|
|
290
|
-
closestPoint2 =
|
|
332
|
+
closestPoint2 = point2;
|
|
291
333
|
}
|
|
292
334
|
}
|
|
293
335
|
return closestPoint2;
|
|
@@ -299,8 +341,48 @@ var getDistance = (point1, point2) => {
|
|
|
299
341
|
};
|
|
300
342
|
|
|
301
343
|
// src/util/render.ts
|
|
302
|
-
import { geoGraticule } from "d3";
|
|
344
|
+
import { geoBounds, geoCentroid, geoDistance as geoDistance2, geoGraticule } from "d3";
|
|
303
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
|
+
};
|
|
304
386
|
var createLayers = (topology, features, styles) => {
|
|
305
387
|
const layers = [];
|
|
306
388
|
if (styles.water) {
|
|
@@ -321,11 +403,25 @@ var createLayers = (topology, features, styles) => {
|
|
|
321
403
|
});
|
|
322
404
|
}
|
|
323
405
|
if (topology) {
|
|
324
|
-
if (
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
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
|
+
}
|
|
329
425
|
}
|
|
330
426
|
if (topology.objects.countries && styles.border) {
|
|
331
427
|
layers.push({
|
|
@@ -342,28 +438,28 @@ var createLayers = (topology, features, styles) => {
|
|
|
342
438
|
}
|
|
343
439
|
if (features) {
|
|
344
440
|
const { points, lines } = features;
|
|
345
|
-
if (
|
|
441
|
+
if (lines && styles.line) {
|
|
346
442
|
layers.push({
|
|
347
|
-
styles: styles.
|
|
443
|
+
styles: styles.line,
|
|
348
444
|
path: {
|
|
349
445
|
type: "GeometryCollection",
|
|
350
|
-
geometries:
|
|
446
|
+
geometries: lines.map(({ source, target }) => geoLine(source, target))
|
|
351
447
|
}
|
|
352
448
|
});
|
|
353
449
|
}
|
|
354
|
-
if (
|
|
450
|
+
if (points && styles.point) {
|
|
355
451
|
layers.push({
|
|
356
|
-
styles: styles.
|
|
452
|
+
styles: styles.point,
|
|
357
453
|
path: {
|
|
358
454
|
type: "GeometryCollection",
|
|
359
|
-
geometries:
|
|
455
|
+
geometries: points.map((point2) => geoPoint(point2))
|
|
360
456
|
}
|
|
361
457
|
});
|
|
362
458
|
}
|
|
363
459
|
}
|
|
364
460
|
return layers;
|
|
365
461
|
};
|
|
366
|
-
var renderLayers = (generator, layers = [], scale, styles) => {
|
|
462
|
+
var renderLayers = (generator, layers = [], scale, styles, viewCenter) => {
|
|
367
463
|
const context = generator.context();
|
|
368
464
|
const { canvas: { width, height } } = context;
|
|
369
465
|
context.reset();
|
|
@@ -373,7 +469,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
373
469
|
} else {
|
|
374
470
|
context.clearRect(0, 0, width, height);
|
|
375
471
|
}
|
|
376
|
-
layers.forEach((
|
|
472
|
+
layers.forEach((layer) => {
|
|
473
|
+
const { path, styles: styles2, cullable } = layer;
|
|
377
474
|
context.save();
|
|
378
475
|
let fill = false;
|
|
379
476
|
let stroke = false;
|
|
@@ -388,8 +485,23 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
388
485
|
}
|
|
389
486
|
});
|
|
390
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
|
+
}
|
|
391
503
|
context.beginPath();
|
|
392
|
-
generator(
|
|
504
|
+
generator(renderPath);
|
|
393
505
|
fill && context.fill();
|
|
394
506
|
stroke && context.stroke();
|
|
395
507
|
context.restore();
|
|
@@ -397,6 +509,57 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
397
509
|
return context;
|
|
398
510
|
};
|
|
399
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
|
+
|
|
400
563
|
// src/hooks/useDrag.ts
|
|
401
564
|
var useDrag = (controller, options = {}) => {
|
|
402
565
|
useEffect(() => {
|
|
@@ -404,14 +567,19 @@ var useDrag = (controller, options = {}) => {
|
|
|
404
567
|
if (!canvas || options.disabled) {
|
|
405
568
|
return;
|
|
406
569
|
}
|
|
407
|
-
geoInertiaDrag(select2(canvas), () => {
|
|
570
|
+
const inertia = geoInertiaDrag(select2(canvas), () => {
|
|
408
571
|
controller.setRotation(controller.projection.rotate());
|
|
409
572
|
options.onUpdate?.({
|
|
410
573
|
type: "move",
|
|
411
574
|
controller
|
|
412
575
|
});
|
|
413
576
|
}, controller.projection, {
|
|
414
|
-
|
|
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,
|
|
415
583
|
time: 3e3,
|
|
416
584
|
start: () => options.onUpdate?.({
|
|
417
585
|
type: "start",
|
|
@@ -424,6 +592,7 @@ var useDrag = (controller, options = {}) => {
|
|
|
424
592
|
});
|
|
425
593
|
return () => {
|
|
426
594
|
cancelDrag(select2(canvas));
|
|
595
|
+
inertia?.timer?.stop();
|
|
427
596
|
};
|
|
428
597
|
}, [
|
|
429
598
|
controller,
|
|
@@ -481,6 +650,61 @@ var useMapZoomHandler = (controller) => {
|
|
|
481
650
|
]);
|
|
482
651
|
};
|
|
483
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
|
+
|
|
484
708
|
// src/hooks/useSpinner.ts
|
|
485
709
|
import { timer as d3Timer } from "d3";
|
|
486
710
|
import { useEffect as useEffect2, useState } from "react";
|
|
@@ -534,91 +758,139 @@ var useSpinner = (controller, options = {}) => {
|
|
|
534
758
|
];
|
|
535
759
|
};
|
|
536
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
|
+
|
|
537
814
|
// src/hooks/useTour.ts
|
|
538
|
-
import {
|
|
539
|
-
import { useEffect as
|
|
540
|
-
import versor2 from "versor";
|
|
541
|
-
var TRANSITION_NAME = "globe-tour";
|
|
815
|
+
import { geoInterpolate, geoPath } from "d3";
|
|
816
|
+
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
542
817
|
var defaultDuration = 1500;
|
|
543
818
|
var useTour = (controller, points, options = {}) => {
|
|
544
|
-
const
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
if (!running) {
|
|
548
|
-
selection.interrupt(TRANSITION_NAME);
|
|
819
|
+
const [running, setRunning] = useState3(options.running ?? false);
|
|
820
|
+
useEffect4(() => {
|
|
821
|
+
if (!controller || !running) {
|
|
549
822
|
return;
|
|
550
823
|
}
|
|
551
|
-
let
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
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
|
+
}
|
|
560
838
|
let last;
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
];
|
|
565
|
-
if (options.loop) {
|
|
566
|
-
p.push(p[0]);
|
|
839
|
+
for (const next of tourPoints) {
|
|
840
|
+
if (cancelled) {
|
|
841
|
+
break;
|
|
567
842
|
}
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
const
|
|
573
|
-
const
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
|
|
598
|
-
path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.zoom ?? 1));
|
|
599
|
-
path({
|
|
600
|
-
type: "Point",
|
|
601
|
-
coordinates: ip(t22)
|
|
602
|
-
});
|
|
603
|
-
context.fill();
|
|
604
|
-
}
|
|
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 {
|
|
605
872
|
context.restore();
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
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) {
|
|
614
885
|
setRunning(false);
|
|
615
886
|
}
|
|
616
|
-
}
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
887
|
+
}
|
|
888
|
+
});
|
|
889
|
+
return () => {
|
|
890
|
+
cancelled = true;
|
|
891
|
+
clearTimeout(t);
|
|
892
|
+
controller.cancelFlyTo();
|
|
893
|
+
};
|
|
622
894
|
}, [
|
|
623
895
|
controller,
|
|
624
896
|
running,
|
|
@@ -630,27 +902,55 @@ var useTour = (controller, points, options = {}) => {
|
|
|
630
902
|
];
|
|
631
903
|
};
|
|
632
904
|
|
|
633
|
-
// src/
|
|
634
|
-
import {
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
"en-US": {
|
|
643
|
-
[translationKey]: {
|
|
644
|
-
"zoom in icon button": "Zoom in",
|
|
645
|
-
"zoom out icon button": "Zoom out",
|
|
646
|
-
"start icon button": "Start",
|
|
647
|
-
"toggle icon button": "Toggle"
|
|
648
|
-
}
|
|
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;
|
|
649
914
|
}
|
|
650
|
-
|
|
651
|
-
|
|
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
|
+
};
|
|
652
949
|
|
|
653
950
|
// src/components/Toolbar/Controls.tsx
|
|
951
|
+
import React from "react";
|
|
952
|
+
import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
|
|
953
|
+
import { translationKey } from "#translations";
|
|
654
954
|
var controlPositions = {
|
|
655
955
|
topleft: "top-2 left-2",
|
|
656
956
|
topright: "top-2 right-2",
|
|
@@ -658,52 +958,42 @@ var controlPositions = {
|
|
|
658
958
|
bottomright: "bottom-2 right-2"
|
|
659
959
|
};
|
|
660
960
|
var ZoomControls = ({ classNames, onAction }) => {
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
classNames
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
onClick: () => onAction?.("zoom-out")
|
|
679
|
-
}));
|
|
680
|
-
} finally {
|
|
681
|
-
_effect.f();
|
|
682
|
-
}
|
|
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
|
+
}));
|
|
683
978
|
};
|
|
684
979
|
var ActionControls = ({ classNames, onAction }) => {
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
classNames
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
onClick: () => onAction?.("toggle")
|
|
703
|
-
}));
|
|
704
|
-
} finally {
|
|
705
|
-
_effect.f();
|
|
706
|
-
}
|
|
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
|
+
}));
|
|
707
997
|
};
|
|
708
998
|
|
|
709
999
|
// src/components/Globe/Globe.tsx
|
|
@@ -761,188 +1051,245 @@ var getProjection = (type = "orthographic") => {
|
|
|
761
1051
|
}
|
|
762
1052
|
return type ?? geoOrthographic();
|
|
763
1053
|
};
|
|
764
|
-
var
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
};
|
|
782
|
-
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: projectionParam, topology, features, styles: stylesParam }, forwardRef3) => {
|
|
783
|
-
var _effect = _useSignals3();
|
|
784
|
-
try {
|
|
785
|
-
const { themeMode } = useThemeContext();
|
|
786
|
-
const styles = useMemo2(() => stylesParam ?? defaultStyles[themeMode], [
|
|
787
|
-
stylesParam,
|
|
788
|
-
themeMode
|
|
789
|
-
]);
|
|
790
|
-
const [canvas, setCanvas] = useState3(null);
|
|
791
|
-
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
792
|
-
const projection = useMemo2(() => getProjection(projectionParam), [
|
|
793
|
-
projectionParam
|
|
794
|
-
]);
|
|
795
|
-
const layers = useMemo2(() => {
|
|
796
|
-
return timer(() => createLayers(topology, features, styles));
|
|
797
|
-
}, [
|
|
798
|
-
topology,
|
|
799
|
-
features,
|
|
800
|
-
styles
|
|
801
|
-
]);
|
|
802
|
-
const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
|
|
803
|
-
const zoomRef = useDynamicRef(zoom);
|
|
804
|
-
useEffect4(() => {
|
|
805
|
-
if (center) {
|
|
806
|
-
setZoom(1);
|
|
807
|
-
setRotation(positionToRotation(geoToPosition(center)));
|
|
808
|
-
}
|
|
809
|
-
}, [
|
|
810
|
-
center
|
|
811
|
-
]);
|
|
812
|
-
const zooming = useRef(false);
|
|
813
|
-
useImperativeHandle(forwardRef3, () => {
|
|
814
|
-
return {
|
|
815
|
-
canvas,
|
|
816
|
-
projection,
|
|
817
|
-
center,
|
|
818
|
-
get zoom() {
|
|
819
|
-
return zoomRef.current;
|
|
820
|
-
},
|
|
821
|
-
translation,
|
|
822
|
-
rotation,
|
|
823
|
-
setCenter,
|
|
824
|
-
setZoom: (s) => {
|
|
825
|
-
if (typeof s === "function") {
|
|
826
|
-
const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
|
|
827
|
-
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
828
|
-
zooming.current = false;
|
|
829
|
-
});
|
|
830
|
-
} else {
|
|
831
|
-
setZoom(s);
|
|
832
|
-
}
|
|
833
|
-
},
|
|
834
|
-
setTranslation,
|
|
835
|
-
setRotation
|
|
836
|
-
};
|
|
837
|
-
}, [
|
|
838
|
-
canvas
|
|
839
|
-
]);
|
|
840
|
-
const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
|
|
841
|
-
alpha: false
|
|
842
|
-
})), [
|
|
843
|
-
canvas,
|
|
844
|
-
projection
|
|
845
|
-
]);
|
|
846
|
-
useEffect4(() => {
|
|
847
|
-
if (canvas && projection) {
|
|
848
|
-
timer(() => {
|
|
849
|
-
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
850
|
-
size.width / 2 + (translation?.x ?? 0),
|
|
851
|
-
size.height / 2 + (translation?.y ?? 0)
|
|
852
|
-
]).rotate(rotation ?? [
|
|
853
|
-
0,
|
|
854
|
-
0,
|
|
855
|
-
0
|
|
856
|
-
]);
|
|
857
|
-
renderLayers(generator, layers, zoom, styles);
|
|
858
|
-
});
|
|
859
|
-
}
|
|
860
|
-
}, [
|
|
861
|
-
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: {
|
|
862
1071
|
size,
|
|
1072
|
+
center,
|
|
863
1073
|
zoom,
|
|
864
1074
|
translation,
|
|
865
1075
|
rotation,
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1076
|
+
setSize,
|
|
1077
|
+
setCenter,
|
|
1078
|
+
setZoom,
|
|
1079
|
+
setTranslation,
|
|
1080
|
+
setRotation,
|
|
1081
|
+
registerController
|
|
870
1082
|
}
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
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
|
|
875
1097
|
});
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
|
|
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);
|
|
879
1109
|
});
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
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
|
+
},
|
|
891
1154
|
translation,
|
|
892
|
-
rotation
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
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;
|
|
896
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)));
|
|
897
1267
|
};
|
|
898
1268
|
var GlobePanel = ({ position, classNames, children }) => {
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
903
|
-
}, children);
|
|
904
|
-
} finally {
|
|
905
|
-
_effect.f();
|
|
906
|
-
}
|
|
1269
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1270
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
1271
|
+
}, children);
|
|
907
1272
|
};
|
|
908
1273
|
var CustomControl = ({ position, children }) => {
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
913
|
-
}, children);
|
|
914
|
-
} finally {
|
|
915
|
-
_effect.f();
|
|
916
|
-
}
|
|
917
|
-
};
|
|
918
|
-
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
|
|
919
|
-
var _effect = _useSignals3();
|
|
920
|
-
try {
|
|
921
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
922
|
-
position,
|
|
923
|
-
...props
|
|
924
|
-
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
925
|
-
onAction
|
|
926
|
-
}));
|
|
927
|
-
} finally {
|
|
928
|
-
_effect.f();
|
|
929
|
-
}
|
|
930
|
-
};
|
|
931
|
-
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
|
|
932
|
-
var _effect = _useSignals3();
|
|
933
|
-
try {
|
|
934
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
935
|
-
position,
|
|
936
|
-
...props
|
|
937
|
-
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
938
|
-
onAction
|
|
939
|
-
}));
|
|
940
|
-
} finally {
|
|
941
|
-
_effect.f();
|
|
942
|
-
}
|
|
1274
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1275
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
1276
|
+
}, children);
|
|
943
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
|
+
}));
|
|
944
1290
|
var Globe = {
|
|
945
1291
|
Root: GlobeRoot,
|
|
1292
|
+
Viewport: GlobeViewport,
|
|
946
1293
|
Canvas: GlobeCanvas,
|
|
947
1294
|
Zoom: GlobeZoom,
|
|
948
1295
|
Action: GlobeAction,
|
|
@@ -951,249 +1298,369 @@ var Globe = {
|
|
|
951
1298
|
};
|
|
952
1299
|
|
|
953
1300
|
// src/components/Map/Map.tsx
|
|
954
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
955
1301
|
import "leaflet/dist/leaflet.css";
|
|
956
1302
|
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
957
|
-
import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
|
|
958
|
-
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";
|
|
959
1305
|
import { createRoot } from "react-dom/client";
|
|
960
|
-
import { MapContainer, Marker, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
1306
|
+
import { MapContainer, Marker, Polyline, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
961
1307
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
|
962
|
-
import {
|
|
963
|
-
|
|
1308
|
+
import { composable as composable2, composableProps as composableProps2, defaultTx } from "@dxos/react-ui";
|
|
1309
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
1310
|
+
var defaults = {
|
|
964
1311
|
center: {
|
|
965
1312
|
lat: 51,
|
|
966
1313
|
lng: 0
|
|
967
1314
|
},
|
|
968
1315
|
zoom: 4
|
|
969
1316
|
};
|
|
970
|
-
var [
|
|
971
|
-
var MapRoot = /* @__PURE__ */ forwardRef2(({
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
return /* @__PURE__ */ React4.createElement(MapContextProvier, {
|
|
999
|
-
attention,
|
|
1000
|
-
onChange
|
|
1001
|
-
}, /* @__PURE__ */ React4.createElement(MapContainer, {
|
|
1002
|
-
...props,
|
|
1003
|
-
ref: mapRef,
|
|
1004
|
-
className: mx2("group relative grid bs-full is-full !bg-baseSurface dx-focus-ring-inset", classNames),
|
|
1005
|
-
attributionControl: false,
|
|
1006
|
-
zoomControl: false,
|
|
1007
|
-
scrollWheelZoom,
|
|
1008
|
-
doubleClickZoom,
|
|
1009
|
-
touchZoom,
|
|
1010
|
-
center: center ?? defaults2.center,
|
|
1011
|
-
zoom: zoom ?? defaults2.zoom
|
|
1012
|
-
}));
|
|
1013
|
-
} finally {
|
|
1014
|
-
_effect.f();
|
|
1015
|
-
}
|
|
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);
|
|
1016
1345
|
});
|
|
1017
1346
|
MapRoot.displayName = "Map.Root";
|
|
1018
|
-
var
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
const
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
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) {
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
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
|
+
}
|
|
1028
1392
|
});
|
|
1029
1393
|
}
|
|
1394
|
+
};
|
|
1395
|
+
container.addEventListener("wheel", onWheel, {
|
|
1396
|
+
passive: false
|
|
1030
1397
|
});
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
return /* @__PURE__ */ React4.createElement(React4.Fragment, null, /* @__PURE__ */ React4.createElement(TileLayer, {
|
|
1040
|
-
ref,
|
|
1041
|
-
"data-attention": attention,
|
|
1042
|
-
detectRetina: true,
|
|
1043
|
-
className: 'dark:grayscale dark:invert data-[attention="0"]:!opacity-80',
|
|
1044
|
-
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png",
|
|
1045
|
-
keepBuffer: 4
|
|
1046
|
-
}));
|
|
1047
|
-
} finally {
|
|
1048
|
-
_effect.f();
|
|
1049
|
-
}
|
|
1398
|
+
return () => {
|
|
1399
|
+
container.removeEventListener("wheel", onWheel);
|
|
1400
|
+
cancelAnimationFrame(frame);
|
|
1401
|
+
};
|
|
1402
|
+
}, [
|
|
1403
|
+
map
|
|
1404
|
+
]);
|
|
1405
|
+
return null;
|
|
1050
1406
|
};
|
|
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
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
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);
|
|
1447
|
+
});
|
|
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
|
+
}));
|
|
1103
1478
|
};
|
|
1104
|
-
|
|
1105
|
-
var
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
const
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
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
|
|
1112
1497
|
});
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
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
|
+
}));
|
|
1541
|
+
};
|
|
1542
|
+
MapMarkers.displayName = "Map.Markers";
|
|
1543
|
+
var MapLines = ({ lines }) => {
|
|
1544
|
+
if (!lines || lines.length === 0) {
|
|
1132
1545
|
return null;
|
|
1133
|
-
} finally {
|
|
1134
|
-
_effect.f();
|
|
1135
1546
|
}
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
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
|
+
}
|
|
1148
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
|
+
})));
|
|
1149
1572
|
};
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
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;
|
|
1162
1611
|
};
|
|
1163
|
-
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 = {
|
|
1164
1625
|
Root: MapRoot,
|
|
1626
|
+
Viewport: MapViewport,
|
|
1165
1627
|
Tiles: MapTiles,
|
|
1166
1628
|
Markers: MapMarkers,
|
|
1629
|
+
Lines: MapLines,
|
|
1167
1630
|
Zoom: MapZoom,
|
|
1168
1631
|
Action: MapAction
|
|
1169
1632
|
};
|
|
1170
1633
|
export {
|
|
1171
1634
|
ActionControls,
|
|
1635
|
+
DEFAULT_TILE_URL,
|
|
1172
1636
|
Globe,
|
|
1173
|
-
|
|
1174
|
-
Map,
|
|
1637
|
+
GlobeContext,
|
|
1638
|
+
Map2 as Map,
|
|
1175
1639
|
ZoomControls,
|
|
1176
1640
|
closestPoint,
|
|
1177
1641
|
controlPositions,
|
|
1178
1642
|
createLayers,
|
|
1643
|
+
createRotationTween,
|
|
1644
|
+
flyDuration,
|
|
1179
1645
|
geoCircle,
|
|
1180
1646
|
geoInertiaDrag,
|
|
1181
1647
|
geoLine,
|
|
1182
1648
|
geoPoint,
|
|
1183
1649
|
geoToPosition,
|
|
1184
1650
|
getDistance,
|
|
1185
|
-
|
|
1651
|
+
globeStyles,
|
|
1186
1652
|
positionToRotation,
|
|
1187
1653
|
renderLayers,
|
|
1188
1654
|
restrictAxis,
|
|
1189
1655
|
timer,
|
|
1190
|
-
translationKey,
|
|
1191
|
-
translations,
|
|
1192
1656
|
useDrag,
|
|
1193
1657
|
useGlobeContext,
|
|
1194
1658
|
useGlobeZoomHandler,
|
|
1195
1659
|
useMapZoomHandler,
|
|
1660
|
+
useSimplifiedTopology,
|
|
1196
1661
|
useSpinner,
|
|
1197
|
-
|
|
1662
|
+
useTopology,
|
|
1663
|
+
useTour,
|
|
1664
|
+
useWheel
|
|
1198
1665
|
};
|
|
1199
1666
|
//# sourceMappingURL=index.mjs.map
|