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