@dxos/react-ui-geo 0.8.4-main.fd6878d → 0.8.4-staging.60fe92afc8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/data/countries-10m.ts +12 -0
- package/data/countries-110m.ts +4 -10579
- package/data/countries-50m.ts +12 -0
- package/dist/lib/browser/chunk-SC2FBYFU.mjs +17 -0
- package/dist/lib/browser/chunk-SC2FBYFU.mjs.map +7 -0
- package/dist/lib/browser/countries-10m-CWWDOKH7.mjs +6 -0
- package/dist/lib/browser/countries-10m-CWWDOKH7.mjs.map +7 -0
- package/dist/lib/browser/countries-110m-72QBAA5E.mjs +6 -0
- package/dist/lib/browser/countries-110m-72QBAA5E.mjs.map +7 -0
- package/dist/lib/browser/countries-50m-H7SL7KVF.mjs +6 -0
- package/dist/lib/browser/countries-50m-H7SL7KVF.mjs.map +7 -0
- package/dist/lib/browser/data.mjs +1 -1
- package/dist/lib/browser/index.mjs +1054 -578
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/translations.mjs +19 -0
- package/dist/lib/browser/translations.mjs.map +7 -0
- package/dist/lib/node-esm/chunk-VZENBYLJ.mjs +19 -0
- package/dist/lib/node-esm/chunk-VZENBYLJ.mjs.map +7 -0
- package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs +8 -0
- package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs.map +7 -0
- package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs +8 -0
- package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs.map +7 -0
- package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs +8 -0
- package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs.map +7 -0
- package/dist/lib/node-esm/data.mjs +1 -1
- package/dist/lib/node-esm/index.mjs +1054 -578
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/translations.mjs +21 -0
- package/dist/lib/node-esm/translations.mjs.map +7 -0
- package/dist/types/data/airports.d.ts +4 -4
- package/dist/types/data/airports.d.ts.map +1 -1
- package/dist/types/data/cities.d.ts.map +1 -1
- package/dist/types/data/countries-10m.d.ts +8 -0
- package/dist/types/data/countries-10m.d.ts.map +1 -0
- package/dist/types/data/countries-110m.d.ts +2 -30
- package/dist/types/data/countries-110m.d.ts.map +1 -1
- package/dist/types/data/countries-50m.d.ts +8 -0
- package/dist/types/data/countries-50m.d.ts.map +1 -0
- package/dist/types/data/countries-dots-3.d.ts.map +1 -1
- package/dist/types/data/countries-dots-4.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.d.ts +19 -9
- package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
- package/dist/types/src/components/Globe/Globe.stories.d.ts +37 -11
- package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.d.ts +55 -16
- package/dist/types/src/components/Map/Map.d.ts.map +1 -1
- package/dist/types/src/components/Map/Map.stories.d.ts +19 -9
- package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
- package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
- package/dist/types/src/data.d.ts +9 -1
- package/dist/types/src/data.d.ts.map +1 -1
- package/dist/types/src/hooks/context.d.ts +38 -3
- package/dist/types/src/hooks/context.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +3 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useDrag.d.ts +22 -2
- package/dist/types/src/hooks/useDrag.d.ts.map +1 -1
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +3 -2
- package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts +1 -1
- package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useSimplifiedTopology.d.ts +32 -0
- package/dist/types/src/hooks/useSimplifiedTopology.d.ts.map +1 -0
- package/dist/types/src/hooks/useSpinner.d.ts +1 -1
- package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
- package/dist/types/src/hooks/useTopology.d.ts +26 -0
- package/dist/types/src/hooks/useTopology.d.ts.map +1 -0
- package/dist/types/src/hooks/useTour.d.ts +3 -2
- package/dist/types/src/hooks/useTour.d.ts.map +1 -1
- package/dist/types/src/hooks/useWheel.d.ts +24 -0
- package/dist/types/src/hooks/useWheel.d.ts.map +1 -0
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +12 -0
- package/dist/types/src/translations.d.ts.map +1 -0
- package/dist/types/src/util/animation.d.ts +16 -0
- package/dist/types/src/util/animation.d.ts.map +1 -0
- package/dist/types/src/util/debug.d.ts.map +1 -1
- package/dist/types/src/util/index.d.ts +2 -0
- package/dist/types/src/util/index.d.ts.map +1 -1
- package/dist/types/src/util/inertia.d.ts.map +1 -1
- package/dist/types/src/util/path.d.ts.map +1 -1
- package/dist/types/src/util/render.d.ts +25 -1
- package/dist/types/src/util/render.d.ts.map +1 -1
- package/dist/types/src/util/styles.d.ts +4 -0
- package/dist/types/src/util/styles.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +43 -37
- package/src/components/Globe/Globe.stories.tsx +201 -82
- package/src/components/Globe/Globe.tsx +263 -119
- package/src/components/Map/Map.stories.tsx +66 -17
- package/src/components/Map/Map.tsx +333 -120
- package/src/components/Toolbar/Controls.tsx +12 -14
- package/src/data.ts +19 -2
- package/src/hooks/context.tsx +49 -28
- package/src/hooks/index.ts +3 -0
- package/src/hooks/useDrag.ts +33 -5
- package/src/hooks/useGlobeZoomHandler.ts +10 -3
- package/src/hooks/useSimplifiedTopology.ts +81 -0
- package/src/hooks/useSpinner.ts +1 -2
- package/src/hooks/useTopology.ts +95 -0
- package/src/hooks/useTour.ts +71 -81
- package/src/hooks/useWheel.ts +83 -0
- package/src/index.ts +0 -1
- package/src/translations.ts +20 -0
- package/src/util/animation.ts +35 -0
- package/src/util/index.ts +2 -0
- package/src/util/inertia.ts +87 -4
- package/src/util/render.ts +105 -17
- package/src/util/styles.ts +62 -0
- package/dist/lib/browser/chunk-GMWLKTLN.mjs +0 -9
- package/dist/lib/browser/chunk-GMWLKTLN.mjs.map +0 -7
- package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs +0 -37859
- package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-JODBF4CC.mjs +0 -11
- package/dist/lib/node-esm/chunk-JODBF4CC.mjs.map +0 -7
- package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs +0 -37861
- package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs.map +0 -7
|
@@ -1,46 +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
17
|
var GlobeContext = /* @__PURE__ */ createContext(void 0);
|
|
20
|
-
var GlobeContextProvider = ({ children, size, center: _center, zoom: _zoom, translation: _translation, rotation: _rotation }) => {
|
|
21
|
-
var _effect = _useSignals();
|
|
22
|
-
try {
|
|
23
|
-
const [center, setCenter] = useControlledState(_center);
|
|
24
|
-
const [zoom, setZoom] = useControlledState(_zoom);
|
|
25
|
-
const [translation, setTranslation] = useControlledState(_translation);
|
|
26
|
-
const [rotation, setRotation] = useControlledState(_rotation);
|
|
27
|
-
return /* @__PURE__ */ React.createElement(GlobeContext.Provider, {
|
|
28
|
-
value: {
|
|
29
|
-
size,
|
|
30
|
-
center,
|
|
31
|
-
zoom,
|
|
32
|
-
translation,
|
|
33
|
-
rotation,
|
|
34
|
-
setCenter,
|
|
35
|
-
setZoom,
|
|
36
|
-
setTranslation,
|
|
37
|
-
setRotation
|
|
38
|
-
}
|
|
39
|
-
}, children);
|
|
40
|
-
} finally {
|
|
41
|
-
_effect.f();
|
|
42
|
-
}
|
|
43
|
-
};
|
|
44
18
|
var useGlobeContext = () => {
|
|
45
19
|
return useContext(GlobeContext) ?? raise(new Error("Missing GlobeContext"));
|
|
46
20
|
};
|
|
@@ -49,6 +23,18 @@ var useGlobeContext = () => {
|
|
|
49
23
|
import { select as select2 } from "d3";
|
|
50
24
|
import { useEffect } from "react";
|
|
51
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
|
+
|
|
52
38
|
// src/util/debug.ts
|
|
53
39
|
var debug = false;
|
|
54
40
|
var timer = (cb) => {
|
|
@@ -66,7 +52,7 @@ var timer = (cb) => {
|
|
|
66
52
|
|
|
67
53
|
// src/util/inertia.ts
|
|
68
54
|
import { drag, select, timer as timer2 } from "d3";
|
|
69
|
-
import
|
|
55
|
+
import versor2 from "versor";
|
|
70
56
|
var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
|
|
71
57
|
var geoInertiaDrag = (target, render, projection, options) => {
|
|
72
58
|
if (!options) {
|
|
@@ -76,21 +62,23 @@ var geoInertiaDrag = (target, render, projection, options) => {
|
|
|
76
62
|
target = target.node();
|
|
77
63
|
}
|
|
78
64
|
target = select(target);
|
|
79
|
-
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 = {
|
|
80
76
|
projection,
|
|
81
77
|
render: (rotation) => {
|
|
82
78
|
projection.rotate(rotation);
|
|
83
79
|
render && render();
|
|
84
80
|
},
|
|
85
|
-
axis
|
|
86
|
-
true,
|
|
87
|
-
false,
|
|
88
|
-
false
|
|
89
|
-
] : [
|
|
90
|
-
true,
|
|
91
|
-
true,
|
|
92
|
-
true
|
|
93
|
-
]),
|
|
81
|
+
axis,
|
|
94
82
|
start: options.start,
|
|
95
83
|
move: options.move,
|
|
96
84
|
end: options.end,
|
|
@@ -98,7 +86,12 @@ var geoInertiaDrag = (target, render, projection, options) => {
|
|
|
98
86
|
finish: options.finish,
|
|
99
87
|
time: options.time,
|
|
100
88
|
hold: options.hold
|
|
101
|
-
}
|
|
89
|
+
};
|
|
90
|
+
const inertia = linear ? geoInertiaDragLinearHelper({
|
|
91
|
+
...sharedHandlers,
|
|
92
|
+
sensitivity: options.sensitivity,
|
|
93
|
+
getZoom: options.getZoom
|
|
94
|
+
}) : geoInertiaDragHelper(sharedHandlers);
|
|
102
95
|
target.call(drag().on("start", inertia.start).on("drag", inertia.move).on("end", inertia.end));
|
|
103
96
|
return inertia;
|
|
104
97
|
};
|
|
@@ -113,9 +106,9 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
113
106
|
const inertia = inertiaHelper({
|
|
114
107
|
axis: opt.axis,
|
|
115
108
|
start: () => {
|
|
116
|
-
v0 =
|
|
109
|
+
v0 = versor2.cartesian(projection.invert(inertia.position));
|
|
117
110
|
r0 = projection.rotate();
|
|
118
|
-
q0 =
|
|
111
|
+
q0 = versor2(r0);
|
|
119
112
|
opt.start && opt.start();
|
|
120
113
|
},
|
|
121
114
|
move: () => {
|
|
@@ -123,23 +116,23 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
123
116
|
if (isNaN(inv[0])) {
|
|
124
117
|
return;
|
|
125
118
|
}
|
|
126
|
-
const v1 =
|
|
127
|
-
const q1 =
|
|
128
|
-
const r1 =
|
|
119
|
+
const v1 = versor2.cartesian(inv);
|
|
120
|
+
const q1 = versor2.multiply(q0, versor2.delta(v0, v1));
|
|
121
|
+
const r1 = versor2.rotation(q1);
|
|
129
122
|
const r2 = opt.axis(r0, r1);
|
|
130
123
|
opt.render(r2);
|
|
131
124
|
opt.move && opt.move();
|
|
132
125
|
},
|
|
133
126
|
end: () => {
|
|
134
|
-
v10 =
|
|
135
|
-
q10 =
|
|
136
|
-
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));
|
|
137
130
|
opt.end && opt.end();
|
|
138
131
|
},
|
|
139
132
|
stop: opt.stop,
|
|
140
133
|
finish: opt.finish,
|
|
141
134
|
render: (t) => {
|
|
142
|
-
const r1 =
|
|
135
|
+
const r1 = versor2.rotation(versor2.multiply(q10, versor2.delta(v10, v11, t * 1e3)));
|
|
143
136
|
const r2 = opt.axis(r0, r1);
|
|
144
137
|
opt.render && opt.render(r2);
|
|
145
138
|
},
|
|
@@ -147,6 +140,62 @@ var geoInertiaDragHelper = (opt) => {
|
|
|
147
140
|
});
|
|
148
141
|
return inertia;
|
|
149
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
|
+
};
|
|
150
199
|
function inertiaHelper(opt) {
|
|
151
200
|
const A = opt.time || 5e3;
|
|
152
201
|
const limit = 1.0001;
|
|
@@ -250,9 +299,9 @@ var geoToPosition = ({ lat, lng }) => [
|
|
|
250
299
|
lng,
|
|
251
300
|
lat
|
|
252
301
|
];
|
|
253
|
-
var geoPoint = (
|
|
302
|
+
var geoPoint = (point2) => ({
|
|
254
303
|
type: "Point",
|
|
255
|
-
coordinates: geoToPosition(
|
|
304
|
+
coordinates: geoToPosition(point2)
|
|
256
305
|
});
|
|
257
306
|
var geoCircle = ({ lat, lng }, radius) => d3GeoCircle().radius(radius).center([
|
|
258
307
|
lng,
|
|
@@ -277,11 +326,11 @@ var closestPoint = (points, target) => {
|
|
|
277
326
|
}
|
|
278
327
|
let closestPoint2 = points[0];
|
|
279
328
|
let minDistance = getDistance(points[0], target);
|
|
280
|
-
for (const
|
|
281
|
-
const distance = getDistance(
|
|
329
|
+
for (const point2 of points) {
|
|
330
|
+
const distance = getDistance(point2, target);
|
|
282
331
|
if (distance < minDistance) {
|
|
283
332
|
minDistance = distance;
|
|
284
|
-
closestPoint2 =
|
|
333
|
+
closestPoint2 = point2;
|
|
285
334
|
}
|
|
286
335
|
}
|
|
287
336
|
return closestPoint2;
|
|
@@ -293,8 +342,48 @@ var getDistance = (point1, point2) => {
|
|
|
293
342
|
};
|
|
294
343
|
|
|
295
344
|
// src/util/render.ts
|
|
296
|
-
import { geoGraticule } from "d3";
|
|
345
|
+
import { geoBounds, geoCentroid, geoDistance as geoDistance2, geoGraticule } from "d3";
|
|
297
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
|
+
};
|
|
298
387
|
var createLayers = (topology, features, styles) => {
|
|
299
388
|
const layers = [];
|
|
300
389
|
if (styles.water) {
|
|
@@ -315,11 +404,25 @@ var createLayers = (topology, features, styles) => {
|
|
|
315
404
|
});
|
|
316
405
|
}
|
|
317
406
|
if (topology) {
|
|
318
|
-
if (
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
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
|
+
}
|
|
323
426
|
}
|
|
324
427
|
if (topology.objects.countries && styles.border) {
|
|
325
428
|
layers.push({
|
|
@@ -336,28 +439,28 @@ var createLayers = (topology, features, styles) => {
|
|
|
336
439
|
}
|
|
337
440
|
if (features) {
|
|
338
441
|
const { points, lines } = features;
|
|
339
|
-
if (
|
|
442
|
+
if (lines && styles.line) {
|
|
340
443
|
layers.push({
|
|
341
|
-
styles: styles.
|
|
444
|
+
styles: styles.line,
|
|
342
445
|
path: {
|
|
343
446
|
type: "GeometryCollection",
|
|
344
|
-
geometries:
|
|
447
|
+
geometries: lines.map(({ source, target }) => geoLine(source, target))
|
|
345
448
|
}
|
|
346
449
|
});
|
|
347
450
|
}
|
|
348
|
-
if (
|
|
451
|
+
if (points && styles.point) {
|
|
349
452
|
layers.push({
|
|
350
|
-
styles: styles.
|
|
453
|
+
styles: styles.point,
|
|
351
454
|
path: {
|
|
352
455
|
type: "GeometryCollection",
|
|
353
|
-
geometries:
|
|
456
|
+
geometries: points.map((point2) => geoPoint(point2))
|
|
354
457
|
}
|
|
355
458
|
});
|
|
356
459
|
}
|
|
357
460
|
}
|
|
358
461
|
return layers;
|
|
359
462
|
};
|
|
360
|
-
var renderLayers = (generator, layers = [], scale, styles) => {
|
|
463
|
+
var renderLayers = (generator, layers = [], scale, styles, viewCenter) => {
|
|
361
464
|
const context = generator.context();
|
|
362
465
|
const { canvas: { width, height } } = context;
|
|
363
466
|
context.reset();
|
|
@@ -367,7 +470,8 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
367
470
|
} else {
|
|
368
471
|
context.clearRect(0, 0, width, height);
|
|
369
472
|
}
|
|
370
|
-
layers.forEach((
|
|
473
|
+
layers.forEach((layer) => {
|
|
474
|
+
const { path, styles: styles2, cullable } = layer;
|
|
371
475
|
context.save();
|
|
372
476
|
let fill = false;
|
|
373
477
|
let stroke = false;
|
|
@@ -382,8 +486,23 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
382
486
|
}
|
|
383
487
|
});
|
|
384
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
|
+
}
|
|
385
504
|
context.beginPath();
|
|
386
|
-
generator(
|
|
505
|
+
generator(renderPath);
|
|
387
506
|
fill && context.fill();
|
|
388
507
|
stroke && context.stroke();
|
|
389
508
|
context.restore();
|
|
@@ -391,6 +510,57 @@ var renderLayers = (generator, layers = [], scale, styles) => {
|
|
|
391
510
|
return context;
|
|
392
511
|
};
|
|
393
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
|
+
|
|
394
564
|
// src/hooks/useDrag.ts
|
|
395
565
|
var useDrag = (controller, options = {}) => {
|
|
396
566
|
useEffect(() => {
|
|
@@ -398,14 +568,19 @@ var useDrag = (controller, options = {}) => {
|
|
|
398
568
|
if (!canvas || options.disabled) {
|
|
399
569
|
return;
|
|
400
570
|
}
|
|
401
|
-
geoInertiaDrag(select2(canvas), () => {
|
|
571
|
+
const inertia = geoInertiaDrag(select2(canvas), () => {
|
|
402
572
|
controller.setRotation(controller.projection.rotate());
|
|
403
573
|
options.onUpdate?.({
|
|
404
574
|
type: "move",
|
|
405
575
|
controller
|
|
406
576
|
});
|
|
407
577
|
}, controller.projection, {
|
|
408
|
-
|
|
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,
|
|
409
584
|
time: 3e3,
|
|
410
585
|
start: () => options.onUpdate?.({
|
|
411
586
|
type: "start",
|
|
@@ -418,6 +593,7 @@ var useDrag = (controller, options = {}) => {
|
|
|
418
593
|
});
|
|
419
594
|
return () => {
|
|
420
595
|
cancelDrag(select2(canvas));
|
|
596
|
+
inertia?.timer?.stop();
|
|
421
597
|
};
|
|
422
598
|
}, [
|
|
423
599
|
controller,
|
|
@@ -428,6 +604,7 @@ var cancelDrag = (node) => node.on(".drag", null);
|
|
|
428
604
|
|
|
429
605
|
// src/hooks/useGlobeZoomHandler.ts
|
|
430
606
|
import { useCallback } from "react";
|
|
607
|
+
var ZOOM_FACTOR = 0.1;
|
|
431
608
|
var useGlobeZoomHandler = (controller) => {
|
|
432
609
|
return useCallback((event) => {
|
|
433
610
|
if (!controller) {
|
|
@@ -435,11 +612,15 @@ var useGlobeZoomHandler = (controller) => {
|
|
|
435
612
|
}
|
|
436
613
|
switch (event) {
|
|
437
614
|
case "zoom-in": {
|
|
438
|
-
controller.setZoom((zoom) =>
|
|
615
|
+
controller.setZoom((zoom) => {
|
|
616
|
+
return zoom * (1 + ZOOM_FACTOR);
|
|
617
|
+
});
|
|
439
618
|
break;
|
|
440
619
|
}
|
|
441
620
|
case "zoom-out": {
|
|
442
|
-
controller.setZoom((zoom) =>
|
|
621
|
+
controller.setZoom((zoom) => {
|
|
622
|
+
return zoom * (1 - ZOOM_FACTOR);
|
|
623
|
+
});
|
|
443
624
|
break;
|
|
444
625
|
}
|
|
445
626
|
}
|
|
@@ -470,6 +651,61 @@ var useMapZoomHandler = (controller) => {
|
|
|
470
651
|
]);
|
|
471
652
|
};
|
|
472
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
|
+
|
|
473
709
|
// src/hooks/useSpinner.ts
|
|
474
710
|
import { timer as d3Timer } from "d3";
|
|
475
711
|
import { useEffect as useEffect2, useState } from "react";
|
|
@@ -523,91 +759,139 @@ var useSpinner = (controller, options = {}) => {
|
|
|
523
759
|
];
|
|
524
760
|
};
|
|
525
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
|
+
|
|
526
815
|
// src/hooks/useTour.ts
|
|
527
|
-
import {
|
|
528
|
-
import { useEffect as
|
|
529
|
-
import versor2 from "versor";
|
|
530
|
-
var TRANSITION_NAME = "globe-tour";
|
|
816
|
+
import { geoInterpolate, geoPath } from "d3";
|
|
817
|
+
import { useEffect as useEffect4, useState as useState3 } from "react";
|
|
531
818
|
var defaultDuration = 1500;
|
|
532
819
|
var useTour = (controller, points, options = {}) => {
|
|
533
|
-
const
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
if (!running) {
|
|
537
|
-
selection.interrupt(TRANSITION_NAME);
|
|
820
|
+
const [running, setRunning] = useState3(options.running ?? false);
|
|
821
|
+
useEffect4(() => {
|
|
822
|
+
if (!controller || !running) {
|
|
538
823
|
return;
|
|
539
824
|
}
|
|
540
|
-
let
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
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
|
+
}
|
|
549
839
|
let last;
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
];
|
|
554
|
-
if (options.loop) {
|
|
555
|
-
p.push(p[0]);
|
|
840
|
+
for (const next of tourPoints) {
|
|
841
|
+
if (cancelled) {
|
|
842
|
+
break;
|
|
556
843
|
}
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
const
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
|
|
587
|
-
path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.zoom ?? 1));
|
|
588
|
-
path({
|
|
589
|
-
type: "Point",
|
|
590
|
-
coordinates: ip(t22)
|
|
591
|
-
});
|
|
592
|
-
context.fill();
|
|
593
|
-
}
|
|
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 {
|
|
594
873
|
context.restore();
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
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) {
|
|
603
886
|
setRunning(false);
|
|
604
887
|
}
|
|
605
|
-
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
888
|
+
}
|
|
889
|
+
});
|
|
890
|
+
return () => {
|
|
891
|
+
cancelled = true;
|
|
892
|
+
clearTimeout(t);
|
|
893
|
+
controller.cancelFlyTo();
|
|
894
|
+
};
|
|
611
895
|
}, [
|
|
612
896
|
controller,
|
|
613
897
|
running,
|
|
@@ -619,10 +903,55 @@ var useTour = (controller, points, options = {}) => {
|
|
|
619
903
|
];
|
|
620
904
|
};
|
|
621
905
|
|
|
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;
|
|
915
|
+
}
|
|
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
|
+
};
|
|
950
|
+
|
|
622
951
|
// src/components/Toolbar/Controls.tsx
|
|
623
|
-
import
|
|
624
|
-
import
|
|
625
|
-
import {
|
|
952
|
+
import React from "react";
|
|
953
|
+
import { IconButton, Toolbar, useTranslation } from "@dxos/react-ui";
|
|
954
|
+
import { translationKey } from "#translations";
|
|
626
955
|
var controlPositions = {
|
|
627
956
|
topleft: "top-2 left-2",
|
|
628
957
|
topright: "top-2 right-2",
|
|
@@ -630,58 +959,42 @@ var controlPositions = {
|
|
|
630
959
|
bottomright: "bottom-2 right-2"
|
|
631
960
|
};
|
|
632
961
|
var ZoomControls = ({ classNames, onAction }) => {
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
iconOnly: true,
|
|
651
|
-
size: 5,
|
|
652
|
-
classNames: "px-0 aspect-square",
|
|
653
|
-
onClick: () => onAction?.("zoom-out")
|
|
654
|
-
}));
|
|
655
|
-
} finally {
|
|
656
|
-
_effect.f();
|
|
657
|
-
}
|
|
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
|
+
}));
|
|
658
979
|
};
|
|
659
980
|
var ActionControls = ({ classNames, onAction }) => {
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
iconOnly: true,
|
|
678
|
-
size: 5,
|
|
679
|
-
classNames: "px-0 aspect-square",
|
|
680
|
-
onClick: () => onAction?.("toggle")
|
|
681
|
-
}));
|
|
682
|
-
} finally {
|
|
683
|
-
_effect.f();
|
|
684
|
-
}
|
|
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
|
+
}));
|
|
685
998
|
};
|
|
686
999
|
|
|
687
1000
|
// src/components/Globe/Globe.tsx
|
|
@@ -739,188 +1052,245 @@ var getProjection = (type = "orthographic") => {
|
|
|
739
1052
|
}
|
|
740
1053
|
return type ?? geoOrthographic();
|
|
741
1054
|
};
|
|
742
|
-
var
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
};
|
|
760
|
-
var GlobeCanvas = /* @__PURE__ */ forwardRef(({ projection: _projection, topology, features, styles: _styles }, forwardRef3) => {
|
|
761
|
-
var _effect = _useSignals3();
|
|
762
|
-
try {
|
|
763
|
-
const { themeMode } = useThemeContext();
|
|
764
|
-
const styles = useMemo2(() => _styles ?? defaultStyles[themeMode], [
|
|
765
|
-
_styles,
|
|
766
|
-
themeMode
|
|
767
|
-
]);
|
|
768
|
-
const [canvas, setCanvas] = useState3(null);
|
|
769
|
-
const canvasRef = (canvas2) => setCanvas(canvas2);
|
|
770
|
-
const projection = useMemo2(() => getProjection(_projection), [
|
|
771
|
-
_projection
|
|
772
|
-
]);
|
|
773
|
-
const layers = useMemo2(() => {
|
|
774
|
-
return timer(() => createLayers(topology, features, styles));
|
|
775
|
-
}, [
|
|
776
|
-
topology,
|
|
777
|
-
features,
|
|
778
|
-
styles
|
|
779
|
-
]);
|
|
780
|
-
const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } = useGlobeContext();
|
|
781
|
-
const zoomRef = useDynamicRef(zoom);
|
|
782
|
-
useEffect4(() => {
|
|
783
|
-
if (center) {
|
|
784
|
-
setZoom(1);
|
|
785
|
-
setRotation(positionToRotation(geoToPosition(center)));
|
|
786
|
-
}
|
|
787
|
-
}, [
|
|
788
|
-
center
|
|
789
|
-
]);
|
|
790
|
-
const zooming = useRef(false);
|
|
791
|
-
useImperativeHandle(forwardRef3, () => {
|
|
792
|
-
return {
|
|
793
|
-
canvas,
|
|
794
|
-
projection,
|
|
795
|
-
center,
|
|
796
|
-
get zoom() {
|
|
797
|
-
return zoomRef.current;
|
|
798
|
-
},
|
|
799
|
-
translation,
|
|
800
|
-
rotation,
|
|
801
|
-
setCenter,
|
|
802
|
-
setZoom: (s) => {
|
|
803
|
-
if (typeof s === "function") {
|
|
804
|
-
const is = interpolateNumber(zoomRef.current, s(zoomRef.current));
|
|
805
|
-
transition().ease(zooming.current ? easeLinear : easeSinOut).duration(200).tween("scale", () => (t) => setZoom(is(t))).on("end", () => {
|
|
806
|
-
zooming.current = false;
|
|
807
|
-
});
|
|
808
|
-
} else {
|
|
809
|
-
setZoom(s);
|
|
810
|
-
}
|
|
811
|
-
},
|
|
812
|
-
setTranslation,
|
|
813
|
-
setRotation
|
|
814
|
-
};
|
|
815
|
-
}, [
|
|
816
|
-
canvas
|
|
817
|
-
]);
|
|
818
|
-
const generator = useMemo2(() => canvas && projection && geoPath2(projection, canvas.getContext("2d", {
|
|
819
|
-
alpha: false
|
|
820
|
-
})), [
|
|
821
|
-
canvas,
|
|
822
|
-
projection
|
|
823
|
-
]);
|
|
824
|
-
useEffect4(() => {
|
|
825
|
-
if (canvas && projection) {
|
|
826
|
-
timer(() => {
|
|
827
|
-
projection.scale(Math.min(size.width, size.height) / 2 * zoom).translate([
|
|
828
|
-
size.width / 2 + (translation?.x ?? 0),
|
|
829
|
-
size.height / 2 + (translation?.y ?? 0)
|
|
830
|
-
]).rotate(rotation ?? [
|
|
831
|
-
0,
|
|
832
|
-
0,
|
|
833
|
-
0
|
|
834
|
-
]);
|
|
835
|
-
renderLayers(generator, layers, zoom, styles);
|
|
836
|
-
});
|
|
837
|
-
}
|
|
838
|
-
}, [
|
|
839
|
-
generator,
|
|
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: {
|
|
840
1072
|
size,
|
|
1073
|
+
center,
|
|
841
1074
|
zoom,
|
|
842
1075
|
translation,
|
|
843
1076
|
rotation,
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
1077
|
+
setSize,
|
|
1078
|
+
setCenter,
|
|
1079
|
+
setZoom,
|
|
1080
|
+
setTranslation,
|
|
1081
|
+
setRotation,
|
|
1082
|
+
registerController
|
|
848
1083
|
}
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
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
|
|
853
1098
|
});
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
|
|
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);
|
|
857
1110
|
});
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
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
|
+
},
|
|
869
1155
|
translation,
|
|
870
|
-
rotation
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
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;
|
|
874
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)));
|
|
875
1268
|
};
|
|
876
1269
|
var GlobePanel = ({ position, classNames, children }) => {
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
881
|
-
}, children);
|
|
882
|
-
} finally {
|
|
883
|
-
_effect.f();
|
|
884
|
-
}
|
|
1270
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1271
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position], classNames)
|
|
1272
|
+
}, children);
|
|
885
1273
|
};
|
|
886
1274
|
var CustomControl = ({ position, children }) => {
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
891
|
-
}, children);
|
|
892
|
-
} finally {
|
|
893
|
-
_effect.f();
|
|
894
|
-
}
|
|
895
|
-
};
|
|
896
|
-
var GlobeZoom = ({ onAction, position = "bottomleft", ...props }) => {
|
|
897
|
-
var _effect = _useSignals3();
|
|
898
|
-
try {
|
|
899
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
900
|
-
position,
|
|
901
|
-
...props
|
|
902
|
-
}, /* @__PURE__ */ React3.createElement(ZoomControls, {
|
|
903
|
-
onAction
|
|
904
|
-
}));
|
|
905
|
-
} finally {
|
|
906
|
-
_effect.f();
|
|
907
|
-
}
|
|
908
|
-
};
|
|
909
|
-
var GlobeAction = ({ onAction, position = "bottomright", ...props }) => {
|
|
910
|
-
var _effect = _useSignals3();
|
|
911
|
-
try {
|
|
912
|
-
return /* @__PURE__ */ React3.createElement(CustomControl, {
|
|
913
|
-
position,
|
|
914
|
-
...props
|
|
915
|
-
}, /* @__PURE__ */ React3.createElement(ActionControls, {
|
|
916
|
-
onAction
|
|
917
|
-
}));
|
|
918
|
-
} finally {
|
|
919
|
-
_effect.f();
|
|
920
|
-
}
|
|
1275
|
+
return /* @__PURE__ */ React2.createElement("div", {
|
|
1276
|
+
className: mx("z-10 absolute overflow-hidden", controlPositions[position])
|
|
1277
|
+
}, children);
|
|
921
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
|
+
}));
|
|
922
1291
|
var Globe = {
|
|
923
1292
|
Root: GlobeRoot,
|
|
1293
|
+
Viewport: GlobeViewport,
|
|
924
1294
|
Canvas: GlobeCanvas,
|
|
925
1295
|
Zoom: GlobeZoom,
|
|
926
1296
|
Action: GlobeAction,
|
|
@@ -929,16 +1299,15 @@ var Globe = {
|
|
|
929
1299
|
};
|
|
930
1300
|
|
|
931
1301
|
// src/components/Map/Map.tsx
|
|
932
|
-
import { useSignals as _useSignals4 } from "@preact-signals/safe-react/tracking";
|
|
933
1302
|
import "leaflet/dist/leaflet.css";
|
|
934
1303
|
import { createContext as createContext2 } from "@radix-ui/react-context";
|
|
935
|
-
import L, { Control, DomEvent, DomUtil, latLngBounds } from "leaflet";
|
|
936
|
-
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";
|
|
937
1306
|
import { createRoot } from "react-dom/client";
|
|
938
|
-
import { MapContainer, Marker, Popup, TileLayer, useMap } from "react-leaflet";
|
|
939
|
-
import { debounce } from "@dxos/async";
|
|
1307
|
+
import { MapContainer, Marker, Polyline, Popup, TileLayer, useMap, useMapEvents } from "react-leaflet";
|
|
940
1308
|
import { ThemeProvider, Tooltip } from "@dxos/react-ui";
|
|
941
|
-
import {
|
|
1309
|
+
import { composable as composable2, composableProps as composableProps2, defaultTx } from "@dxos/react-ui";
|
|
1310
|
+
import { mx as mx2 } from "@dxos/ui-theme";
|
|
942
1311
|
var defaults = {
|
|
943
1312
|
center: {
|
|
944
1313
|
lat: 51,
|
|
@@ -946,237 +1315,341 @@ var defaults = {
|
|
|
946
1315
|
},
|
|
947
1316
|
zoom: 4
|
|
948
1317
|
};
|
|
949
|
-
var [
|
|
950
|
-
var MapRoot = /* @__PURE__ */ forwardRef2(({
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
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);
|
|
1346
|
+
});
|
|
1347
|
+
MapRoot.displayName = "Map.Root";
|
|
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) {
|
|
966
1378
|
return;
|
|
967
1379
|
}
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
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
|
+
}
|
|
973
1393
|
});
|
|
974
|
-
}, 100);
|
|
975
|
-
map.on("move", handler);
|
|
976
|
-
map.on("zoom", handler);
|
|
977
|
-
map.on("focus", () => setAttention(true));
|
|
978
|
-
map.on("blur", () => setAttention(false));
|
|
979
|
-
return () => {
|
|
980
|
-
map.off("move");
|
|
981
|
-
map.off("zoom");
|
|
982
|
-
map.off("focus");
|
|
983
|
-
map.off("blur");
|
|
984
|
-
};
|
|
985
|
-
}, [
|
|
986
|
-
map,
|
|
987
|
-
onChange
|
|
988
|
-
]);
|
|
989
|
-
useEffect5(() => {
|
|
990
|
-
if (!map) {
|
|
991
|
-
return;
|
|
992
|
-
}
|
|
993
|
-
if (attention) {
|
|
994
|
-
map.scrollWheelZoom.enable();
|
|
995
|
-
} else {
|
|
996
|
-
map.scrollWheelZoom.disable();
|
|
997
1394
|
}
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
return
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
}
|
|
1395
|
+
};
|
|
1396
|
+
container.addEventListener("wheel", onWheel, {
|
|
1397
|
+
passive: false
|
|
1398
|
+
});
|
|
1399
|
+
return () => {
|
|
1400
|
+
container.removeEventListener("wheel", onWheel);
|
|
1401
|
+
cancelAnimationFrame(frame);
|
|
1402
|
+
};
|
|
1403
|
+
}, [
|
|
1404
|
+
map
|
|
1405
|
+
]);
|
|
1406
|
+
return null;
|
|
1407
|
+
};
|
|
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);
|
|
1019
1448
|
});
|
|
1020
|
-
|
|
1021
|
-
var
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
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
|
+
}));
|
|
1044
1479
|
};
|
|
1045
|
-
MapTiles.displayName =
|
|
1046
|
-
var MapMarkers = ({ selected, markers }) => {
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
const
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
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
|
|
1498
|
+
});
|
|
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
|
+
}));
|
|
1097
1542
|
};
|
|
1098
1543
|
MapMarkers.displayName = "Map.Markers";
|
|
1099
|
-
var
|
|
1100
|
-
|
|
1101
|
-
try {
|
|
1102
|
-
const map = useMap();
|
|
1103
|
-
useEffect5(() => {
|
|
1104
|
-
const control = new Control({
|
|
1105
|
-
position
|
|
1106
|
-
});
|
|
1107
|
-
control.onAdd = () => {
|
|
1108
|
-
const container = DomUtil.create("div", mx2("!m-0", controlPositions[position]));
|
|
1109
|
-
DomEvent.disableClickPropagation(container);
|
|
1110
|
-
DomEvent.disableScrollPropagation(container);
|
|
1111
|
-
const root = createRoot(container);
|
|
1112
|
-
root.render(/* @__PURE__ */ React4.createElement(ThemeProvider, {
|
|
1113
|
-
tx: defaultTx
|
|
1114
|
-
}, /* @__PURE__ */ React4.createElement(Tooltip.Provider, null, children)));
|
|
1115
|
-
return container;
|
|
1116
|
-
};
|
|
1117
|
-
control.addTo(map);
|
|
1118
|
-
return () => {
|
|
1119
|
-
control.remove();
|
|
1120
|
-
};
|
|
1121
|
-
}, [
|
|
1122
|
-
map,
|
|
1123
|
-
position,
|
|
1124
|
-
children
|
|
1125
|
-
]);
|
|
1544
|
+
var MapLines = ({ lines }) => {
|
|
1545
|
+
if (!lines || lines.length === 0) {
|
|
1126
1546
|
return null;
|
|
1127
|
-
} finally {
|
|
1128
|
-
_effect.f();
|
|
1129
1547
|
}
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
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
|
+
}
|
|
1142
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
|
+
})));
|
|
1143
1573
|
};
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
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;
|
|
1156
1612
|
};
|
|
1157
|
-
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 = {
|
|
1158
1626
|
Root: MapRoot,
|
|
1627
|
+
Viewport: MapViewport,
|
|
1159
1628
|
Tiles: MapTiles,
|
|
1160
1629
|
Markers: MapMarkers,
|
|
1630
|
+
Lines: MapLines,
|
|
1161
1631
|
Zoom: MapZoom,
|
|
1162
1632
|
Action: MapAction
|
|
1163
1633
|
};
|
|
1164
1634
|
export {
|
|
1165
1635
|
ActionControls,
|
|
1636
|
+
DEFAULT_TILE_URL,
|
|
1166
1637
|
Globe,
|
|
1167
|
-
|
|
1168
|
-
Map,
|
|
1638
|
+
GlobeContext,
|
|
1639
|
+
Map2 as Map,
|
|
1169
1640
|
ZoomControls,
|
|
1170
1641
|
closestPoint,
|
|
1171
1642
|
controlPositions,
|
|
1172
1643
|
createLayers,
|
|
1644
|
+
createRotationTween,
|
|
1645
|
+
flyDuration,
|
|
1173
1646
|
geoCircle,
|
|
1174
1647
|
geoInertiaDrag,
|
|
1175
1648
|
geoLine,
|
|
1176
1649
|
geoPoint,
|
|
1177
1650
|
geoToPosition,
|
|
1178
1651
|
getDistance,
|
|
1179
|
-
|
|
1652
|
+
globeStyles,
|
|
1180
1653
|
positionToRotation,
|
|
1181
1654
|
renderLayers,
|
|
1182
1655
|
restrictAxis,
|
|
@@ -1185,7 +1658,10 @@ export {
|
|
|
1185
1658
|
useGlobeContext,
|
|
1186
1659
|
useGlobeZoomHandler,
|
|
1187
1660
|
useMapZoomHandler,
|
|
1661
|
+
useSimplifiedTopology,
|
|
1188
1662
|
useSpinner,
|
|
1189
|
-
|
|
1663
|
+
useTopology,
|
|
1664
|
+
useTour,
|
|
1665
|
+
useWheel
|
|
1190
1666
|
};
|
|
1191
1667
|
//# sourceMappingURL=index.mjs.map
|