@dxos/react-ui-geo 0.8.3 → 0.8.4-main.1da679c

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.
Files changed (83) hide show
  1. package/data/airports.ts +1 -1
  2. package/data/cities.ts +1 -1
  3. package/data/countries-110m.ts +1 -1
  4. package/data/countries-dots-3.ts +1 -1
  5. package/data/countries-dots-4.ts +1 -1
  6. package/dist/lib/browser/chunk-GMWLKTLN.mjs +9 -0
  7. package/dist/lib/browser/{countries-110m-WI4PCLDF.mjs → countries-110m-ZM3ZIEFS.mjs} +2 -2
  8. package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs.map +7 -0
  9. package/dist/lib/browser/data.mjs +1 -1
  10. package/dist/lib/browser/index.mjs +189 -161
  11. package/dist/lib/browser/index.mjs.map +3 -3
  12. package/dist/lib/browser/meta.json +1 -1
  13. package/dist/lib/node-esm/{chunk-PIIEDZEU.mjs → chunk-JODBF4CC.mjs} +3 -3
  14. package/dist/lib/node-esm/{countries-110m-DQ4XRC4B.mjs → countries-110m-3SFASWVD.mjs} +2 -2
  15. package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs.map +7 -0
  16. package/dist/lib/node-esm/data.mjs +1 -1
  17. package/dist/lib/node-esm/index.mjs +189 -161
  18. package/dist/lib/node-esm/index.mjs.map +3 -3
  19. package/dist/lib/node-esm/meta.json +1 -1
  20. package/dist/types/src/components/Globe/Globe.d.ts +1 -1
  21. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
  22. package/dist/types/src/components/Globe/Globe.stories.d.ts +22 -8
  23. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  24. package/dist/types/src/components/Map/Map.d.ts +25 -12
  25. package/dist/types/src/components/Map/Map.d.ts.map +1 -1
  26. package/dist/types/src/components/Map/Map.stories.d.ts +11 -7
  27. package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
  29. package/dist/types/src/components/index.d.ts +0 -1
  30. package/dist/types/src/components/index.d.ts.map +1 -1
  31. package/dist/types/src/hooks/context.d.ts +7 -7
  32. package/dist/types/src/hooks/context.d.ts.map +1 -1
  33. package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +1 -1
  34. package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
  35. package/dist/types/src/hooks/useMapZoomHandler.d.ts +1 -1
  36. package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
  37. package/dist/types/src/hooks/useSpinner.d.ts +1 -1
  38. package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
  39. package/dist/types/src/hooks/useTour.d.ts +4 -3
  40. package/dist/types/src/hooks/useTour.d.ts.map +1 -1
  41. package/dist/types/src/index.d.ts +1 -1
  42. package/dist/types/src/index.d.ts.map +1 -1
  43. package/dist/types/src/types.d.ts +2 -1
  44. package/dist/types/src/types.d.ts.map +1 -1
  45. package/dist/types/src/util/path.d.ts +5 -8
  46. package/dist/types/src/util/path.d.ts.map +1 -1
  47. package/dist/types/src/util/render.d.ts +4 -4
  48. package/dist/types/src/util/render.d.ts.map +1 -1
  49. package/dist/types/tsconfig.tsbuildinfo +1 -1
  50. package/package.json +14 -11
  51. package/src/components/Globe/Globe.stories.tsx +80 -33
  52. package/src/components/Globe/Globe.tsx +74 -58
  53. package/src/components/Map/Map.stories.tsx +20 -10
  54. package/src/components/Map/Map.tsx +206 -91
  55. package/src/components/Toolbar/Controls.tsx +2 -6
  56. package/src/components/index.ts +0 -2
  57. package/src/hooks/context.tsx +10 -10
  58. package/src/hooks/useGlobeZoomHandler.ts +3 -3
  59. package/src/hooks/useMapZoomHandler.ts +1 -1
  60. package/src/hooks/useSpinner.ts +2 -1
  61. package/src/hooks/useTour.ts +9 -8
  62. package/src/index.ts +1 -1
  63. package/src/types.ts +3 -1
  64. package/src/util/inertia.ts +1 -1
  65. package/src/util/path.ts +5 -6
  66. package/src/util/render.ts +5 -3
  67. package/dist/lib/browser/chunk-ENCWOTYX.mjs +0 -9
  68. package/dist/lib/browser/countries-110m-WI4PCLDF.mjs.map +0 -7
  69. package/dist/lib/node/chunk-LAICG6L2.cjs +0 -40
  70. package/dist/lib/node/chunk-LAICG6L2.cjs.map +0 -7
  71. package/dist/lib/node/countries-110m-KQ5WAB2O.cjs +0 -37877
  72. package/dist/lib/node/countries-110m-KQ5WAB2O.cjs.map +0 -7
  73. package/dist/lib/node/data.cjs +0 -28
  74. package/dist/lib/node/data.cjs.map +0 -7
  75. package/dist/lib/node/index.cjs +0 -1187
  76. package/dist/lib/node/index.cjs.map +0 -7
  77. package/dist/lib/node/meta.json +0 -1
  78. package/dist/lib/node-esm/countries-110m-DQ4XRC4B.mjs.map +0 -7
  79. package/dist/types/src/components/types.d.ts +0 -15
  80. package/dist/types/src/components/types.d.ts.map +0 -1
  81. package/src/components/types.ts +0 -19
  82. /package/dist/lib/browser/{chunk-ENCWOTYX.mjs.map → chunk-GMWLKTLN.mjs.map} +0 -0
  83. /package/dist/lib/node-esm/{chunk-PIIEDZEU.mjs.map → chunk-JODBF4CC.mjs.map} +0 -0
@@ -1,1187 +0,0 @@
1
- var __create = Object.create;
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __getProtoOf = Object.getPrototypeOf;
6
- var __hasOwnProp = Object.prototype.hasOwnProperty;
7
- var __export = (target, all) => {
8
- for (var name in all)
9
- __defProp(target, name, { get: all[name], enumerable: true });
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
- var node_exports = {};
29
- __export(node_exports, {
30
- ActionControls: () => ActionControls,
31
- Globe: () => Globe,
32
- GlobeContextProvider: () => GlobeContextProvider,
33
- Map: () => Map,
34
- ZoomControls: () => ZoomControls,
35
- closestPoint: () => closestPoint,
36
- controlPositions: () => controlPositions,
37
- createLayers: () => createLayers,
38
- geoCircle: () => geoCircle,
39
- geoInertiaDrag: () => geoInertiaDrag,
40
- geoLine: () => geoLine,
41
- geoPoint: () => geoPoint,
42
- geoToPosition: () => geoToPosition,
43
- getDistance: () => getDistance,
44
- loadTopology: () => import_chunk_LAICG6L2.loadTopology,
45
- positionToRotation: () => positionToRotation,
46
- renderLayers: () => renderLayers,
47
- restrictAxis: () => restrictAxis,
48
- timer: () => timer,
49
- useDrag: () => useDrag,
50
- useGlobeContext: () => useGlobeContext,
51
- useGlobeZoomHandler: () => useGlobeZoomHandler,
52
- useMapZoomHandler: () => useMapZoomHandler,
53
- useSpinner: () => useSpinner,
54
- useTour: () => useTour
55
- });
56
- module.exports = __toCommonJS(node_exports);
57
- var import_chunk_LAICG6L2 = require("./chunk-LAICG6L2.cjs");
58
- var import_tracking = require("@preact-signals/safe-react/tracking");
59
- var import_d3 = require("d3");
60
- var import_react = __toESM(require("react"));
61
- var import_react_resize_detector = require("react-resize-detector");
62
- var import_react_ui = require("@dxos/react-ui");
63
- var import_react_ui_theme = require("@dxos/react-ui-theme");
64
- var import_tracking2 = require("@preact-signals/safe-react/tracking");
65
- var import_react2 = __toESM(require("react"));
66
- var import_debug = require("@dxos/debug");
67
- var import_react_ui2 = require("@dxos/react-ui");
68
- var import_d32 = require("d3");
69
- var import_react3 = require("react");
70
- var import_d33 = require("d3");
71
- var import_versor = __toESM(require("versor"));
72
- var import_d34 = require("d3");
73
- var import_d35 = require("d3");
74
- var import_topojson_client = require("topojson-client");
75
- var import_react4 = require("react");
76
- var import_react5 = require("react");
77
- var import_d36 = require("d3");
78
- var import_react6 = require("react");
79
- var import_d37 = require("d3");
80
- var import_react7 = require("react");
81
- var import_versor2 = __toESM(require("versor"));
82
- var import_tracking3 = require("@preact-signals/safe-react/tracking");
83
- var import_react8 = __toESM(require("react"));
84
- var import_react_ui3 = require("@dxos/react-ui");
85
- var import_tracking4 = require("@preact-signals/safe-react/tracking");
86
- var import_leaflet = require("leaflet/dist/leaflet.css");
87
- var import_leaflet2 = __toESM(require("leaflet"));
88
- var import_react9 = __toESM(require("react"));
89
- var import_client = require("react-dom/client");
90
- var import_react_leaflet = require("react-leaflet");
91
- var import_react_resize_detector2 = require("react-resize-detector");
92
- var import_async = require("@dxos/async");
93
- var import_react_ui4 = require("@dxos/react-ui");
94
- var import_react_ui_theme2 = require("@dxos/react-ui-theme");
95
- var GlobeContext = /* @__PURE__ */ (0, import_react2.createContext)(void 0);
96
- var GlobeContextProvider = ({ children, size, center: _center, scale: _scale, translation: _translation, rotation: _rotation }) => {
97
- var _effect = (0, import_tracking2.useSignals)();
98
- try {
99
- const [center, setCenter] = (0, import_react_ui2.useControlledState)(_center);
100
- const [scale, setScale] = (0, import_react_ui2.useControlledState)(_scale);
101
- const [translation, setTranslation] = (0, import_react_ui2.useControlledState)(_translation);
102
- const [rotation, setRotation] = (0, import_react_ui2.useControlledState)(_rotation);
103
- return /* @__PURE__ */ import_react2.default.createElement(GlobeContext.Provider, {
104
- value: {
105
- size,
106
- center,
107
- scale,
108
- translation,
109
- rotation,
110
- setCenter,
111
- setScale,
112
- setTranslation,
113
- setRotation
114
- }
115
- }, children);
116
- } finally {
117
- _effect.f();
118
- }
119
- };
120
- var useGlobeContext = () => {
121
- return (0, import_react2.useContext)(GlobeContext) ?? (0, import_debug.raise)(new Error("Missing GlobeContext"));
122
- };
123
- var debug = false;
124
- var timer = (cb) => {
125
- const start = Date.now();
126
- const data = cb();
127
- const t = Date.now() - start / 1e3;
128
- if (debug) {
129
- console.log({
130
- t,
131
- data
132
- });
133
- }
134
- return data;
135
- };
136
- var restrictAxis = (axis) => (original, current) => current.map((d, i) => axis[i] ? d : original[i]);
137
- var geoInertiaDrag = (target, render, projection, options) => {
138
- if (!options) {
139
- options = {};
140
- }
141
- if (target.node) {
142
- target = target.node();
143
- }
144
- target = (0, import_d33.select)(target);
145
- const inertia = geoInertiaDragHelper({
146
- projection,
147
- render: (rotation) => {
148
- projection.rotate(rotation);
149
- render && render();
150
- },
151
- axis: restrictAxis(options.xAxis ? [
152
- true,
153
- false,
154
- false
155
- ] : [
156
- true,
157
- true,
158
- true
159
- ]),
160
- start: options.start,
161
- move: options.move,
162
- end: options.end,
163
- stop: options.stop,
164
- finish: options.finish,
165
- time: options.time,
166
- hold: options.hold
167
- });
168
- target.call((0, import_d33.drag)().on("start", inertia.start).on("drag", inertia.move).on("end", inertia.end));
169
- return inertia;
170
- };
171
- var geoInertiaDragHelper = (opt) => {
172
- const projection = opt.projection;
173
- let v0;
174
- let r0;
175
- let q0;
176
- let v10;
177
- let v11;
178
- let q10;
179
- const inertia = inertiaHelper({
180
- axis: opt.axis,
181
- start: () => {
182
- v0 = import_versor.default.cartesian(projection.invert(inertia.position));
183
- r0 = projection.rotate();
184
- q0 = (0, import_versor.default)(r0);
185
- opt.start && opt.start();
186
- },
187
- move: () => {
188
- const inv = projection.rotate(r0).invert(inertia.position);
189
- if (isNaN(inv[0])) {
190
- return;
191
- }
192
- const v1 = import_versor.default.cartesian(inv);
193
- const q1 = import_versor.default.multiply(q0, import_versor.default.delta(v0, v1));
194
- const r1 = import_versor.default.rotation(q1);
195
- const r2 = opt.axis(r0, r1);
196
- opt.render(r2);
197
- opt.move && opt.move();
198
- },
199
- end: () => {
200
- v10 = import_versor.default.cartesian(projection.invert(inertia.position.map((d, i) => d - inertia.velocity[i] / 1e3)));
201
- q10 = (0, import_versor.default)(projection.rotate());
202
- v11 = import_versor.default.cartesian(projection.invert(inertia.position));
203
- opt.end && opt.end();
204
- },
205
- stop: opt.stop,
206
- finish: opt.finish,
207
- render: (t) => {
208
- const r1 = import_versor.default.rotation(import_versor.default.multiply(q10, import_versor.default.delta(v10, v11, t * 1e3)));
209
- const r2 = opt.axis(r0, r1);
210
- opt.render && opt.render(r2);
211
- },
212
- time: opt.time
213
- });
214
- return inertia;
215
- };
216
- function inertiaHelper(opt) {
217
- const A = opt.time || 5e3;
218
- const limit = 1.0001;
219
- const B = -Math.log(1 - 1 / limit);
220
- const inertia = {
221
- position: [
222
- 0,
223
- 0
224
- ],
225
- velocity: [
226
- 0,
227
- 0
228
- ],
229
- timer: (0, import_d33.timer)(() => {
230
- }),
231
- time: 0,
232
- t: 0,
233
- start: function(ev) {
234
- const position = [
235
- ev.x,
236
- ev.y
237
- ];
238
- inertia.position = position;
239
- inertia.velocity = [
240
- 0,
241
- 0
242
- ];
243
- inertia.timer.stop();
244
- this.classList.remove("inertia");
245
- this.classList.add("dragging");
246
- opt.start && opt.start.call(this, position);
247
- },
248
- move: function(ev) {
249
- const position = [
250
- ev.x,
251
- ev.y
252
- ];
253
- const time = performance.now();
254
- const deltaTime = time - inertia.time;
255
- const decay = 1 - Math.exp(-deltaTime / 1e3);
256
- inertia.velocity = inertia.velocity.map((d, i) => {
257
- const deltaPos = position[i] - inertia.position[i];
258
- const deltaTime2 = time - inertia.time;
259
- return 1e3 * (1 - decay) * deltaPos / deltaTime2 + d * decay;
260
- });
261
- inertia.velocity = opt.axis([
262
- 0,
263
- 0
264
- ], inertia.velocity);
265
- inertia.time = time;
266
- inertia.position = position;
267
- opt.move && opt.move.call(this, position);
268
- },
269
- end: function(ev) {
270
- this.classList.remove("dragging", "inertia");
271
- const v = inertia.velocity;
272
- if (v[0] * v[0] + v[1] * v[1] < 100) {
273
- inertia.timer.stop();
274
- return opt.stop && opt.stop();
275
- }
276
- const time = performance.now();
277
- const deltaTime = time - inertia.time;
278
- if (opt.hold === void 0) {
279
- opt.hold = 100;
280
- }
281
- if (deltaTime >= opt.hold) {
282
- inertia.timer.stop();
283
- return opt.stop && opt.stop();
284
- }
285
- this.classList.add("inertia");
286
- opt.end && opt.end();
287
- const self = this;
288
- inertia.timer.restart((e) => {
289
- inertia.t = limit * (1 - Math.exp(-B * e / A));
290
- opt.render && opt.render(inertia.t);
291
- if (inertia.t > 1) {
292
- inertia.timer.stop();
293
- self.classList.remove("inertia");
294
- inertia.velocity = [
295
- 0,
296
- 0
297
- ];
298
- inertia.t = 1;
299
- opt.finish && opt.finish();
300
- }
301
- });
302
- }
303
- };
304
- inertia.timer.stop();
305
- return inertia;
306
- }
307
- var positionToRotation = ([lng, lat], tilt = 0) => [
308
- -lng,
309
- tilt - lat,
310
- 0
311
- ];
312
- var geoToPosition = ({ lat, lng }) => [
313
- lng,
314
- lat
315
- ];
316
- var geoPoint = (point) => ({
317
- type: "Point",
318
- coordinates: geoToPosition(point)
319
- });
320
- var geoCircle = ({ lat, lng }, radius) => (0, import_d34.geoCircle)().radius(radius).center([
321
- lng,
322
- lat
323
- ])();
324
- var geoLine = (p1, p2) => ({
325
- type: "LineString",
326
- coordinates: [
327
- [
328
- p1.lng,
329
- p1.lat
330
- ],
331
- [
332
- p2.lng,
333
- p2.lat
334
- ]
335
- ]
336
- });
337
- var closestPoint = (points, target) => {
338
- if (points.length === 0) {
339
- return target;
340
- }
341
- let closestPoint2 = points[0];
342
- let minDistance = getDistance(points[0], target);
343
- for (const point of points) {
344
- const distance = getDistance(point, target);
345
- if (distance < minDistance) {
346
- minDistance = distance;
347
- closestPoint2 = point;
348
- }
349
- }
350
- return closestPoint2;
351
- };
352
- var getDistance = (point1, point2) => {
353
- const dx = point1[0] - point2[0];
354
- const dy = point1[1] - point2[1];
355
- return Math.sqrt(dx * dx + dy * dy);
356
- };
357
- var createLayers = (topology, features, styles) => {
358
- const layers = [];
359
- if (styles.water) {
360
- layers.push({
361
- styles: styles.water,
362
- path: {
363
- type: "Sphere"
364
- }
365
- });
366
- }
367
- if (styles.graticule) {
368
- layers.push({
369
- styles: styles.graticule,
370
- path: (0, import_d35.geoGraticule)().step([
371
- 6,
372
- 6
373
- ])()
374
- });
375
- }
376
- if (topology) {
377
- if (topology.objects.land && styles.land) {
378
- layers.push({
379
- styles: styles.land,
380
- path: (0, import_topojson_client.feature)(topology, topology.objects.land)
381
- });
382
- }
383
- if (topology.objects.countries && styles.border) {
384
- layers.push({
385
- styles: styles.border,
386
- path: (0, import_topojson_client.mesh)(topology, topology.objects.countries, (a, b) => a !== b)
387
- });
388
- }
389
- if (topology.objects.dots && styles.dots) {
390
- layers.push({
391
- styles: styles.dots,
392
- path: topology.objects.dots
393
- });
394
- }
395
- }
396
- if (features) {
397
- const { points, lines } = features;
398
- if (points && styles.point) {
399
- layers.push({
400
- styles: styles.point,
401
- path: {
402
- type: "GeometryCollection",
403
- geometries: points.map((point) => geoPoint(point))
404
- }
405
- });
406
- }
407
- if (lines && styles.line) {
408
- layers.push({
409
- styles: styles.line,
410
- path: {
411
- type: "GeometryCollection",
412
- geometries: lines.map(({ source, target }) => geoLine(source, target))
413
- }
414
- });
415
- }
416
- }
417
- return layers;
418
- };
419
- var renderLayers = (generator, layers = [], scale, styles) => {
420
- const context = generator.context();
421
- const { canvas: { width, height } } = context;
422
- context.reset();
423
- if (styles.background) {
424
- context.fillStyle = styles.background.fillStyle;
425
- context.fillRect(0, 0, width, height);
426
- } else {
427
- context.clearRect(0, 0, width, height);
428
- }
429
- layers.forEach(({ path, styles: styles2 }) => {
430
- context.save();
431
- let fill = false;
432
- let stroke = false;
433
- if (styles2) {
434
- Object.entries(styles2).forEach(([key, value]) => {
435
- if (key === "pointRadius") {
436
- generator.pointRadius(value * scale);
437
- } else {
438
- context[key] = value;
439
- fill ||= key === "fillStyle";
440
- stroke ||= key === "strokeStyle";
441
- }
442
- });
443
- }
444
- context.beginPath();
445
- generator(path);
446
- fill && context.fill();
447
- stroke && context.stroke();
448
- context.restore();
449
- });
450
- return context;
451
- };
452
- var useDrag = (controller, options = {}) => {
453
- (0, import_react3.useEffect)(() => {
454
- const canvas = controller?.canvas;
455
- if (!canvas || options.disabled) {
456
- return;
457
- }
458
- geoInertiaDrag((0, import_d32.select)(canvas), () => {
459
- controller.setRotation(controller.projection.rotate());
460
- options.onUpdate?.({
461
- type: "move",
462
- controller
463
- });
464
- }, controller.projection, {
465
- xAxis: options.xAxis,
466
- time: 3e3,
467
- start: () => options.onUpdate?.({
468
- type: "start",
469
- controller
470
- }),
471
- finish: () => options.onUpdate?.({
472
- type: "end",
473
- controller
474
- })
475
- });
476
- return () => {
477
- cancelDrag((0, import_d32.select)(canvas));
478
- };
479
- }, [
480
- controller,
481
- JSON.stringify(options)
482
- ]);
483
- };
484
- var cancelDrag = (node) => node.on(".drag", null);
485
- var useGlobeZoomHandler = (controller) => {
486
- return (0, import_react4.useCallback)((event) => {
487
- if (!controller) {
488
- return;
489
- }
490
- switch (event) {
491
- case "zoom-in": {
492
- controller.setScale((scale) => scale * 1.1);
493
- break;
494
- }
495
- case "zoom-out": {
496
- controller.setScale((scale) => scale * 0.9);
497
- break;
498
- }
499
- }
500
- }, [
501
- controller
502
- ]);
503
- };
504
- var useMapZoomHandler = (controller) => {
505
- return (0, import_react5.useCallback)((event) => {
506
- if (!controller) {
507
- return;
508
- }
509
- switch (event) {
510
- case "zoom-in": {
511
- controller.setZoom((scale) => scale + 1);
512
- break;
513
- }
514
- case "zoom-out": {
515
- controller.setZoom((scale) => scale - 1);
516
- break;
517
- }
518
- }
519
- }, [
520
- controller
521
- ]);
522
- };
523
- var useSpinner = (controller, options = {}) => {
524
- const [running, setRunning] = (0, import_react6.useState)(false);
525
- (0, import_react6.useEffect)(() => {
526
- let timer3;
527
- const start = () => {
528
- const delta = options.delta ?? [
529
- 1e-3,
530
- 0,
531
- 0
532
- ];
533
- let t = 0;
534
- let lastRotation = controller.projection.rotate();
535
- timer3 = (0, import_d36.timer)((elapsed) => {
536
- const dt = elapsed - t;
537
- t = elapsed;
538
- const rotation = [
539
- lastRotation[0] + delta[0] * dt,
540
- lastRotation[1] + delta[1] * dt,
541
- lastRotation[2] + delta[2] * dt
542
- ];
543
- lastRotation = rotation;
544
- controller.setRotation(rotation);
545
- });
546
- };
547
- const stop = () => {
548
- if (timer3) {
549
- timer3.stop();
550
- timer3 = void 0;
551
- }
552
- };
553
- if (controller && running) {
554
- start();
555
- } else {
556
- stop();
557
- }
558
- return () => stop();
559
- }, [
560
- controller,
561
- running
562
- ]);
563
- return [
564
- () => {
565
- if (!options.disabled) {
566
- setRunning(true);
567
- }
568
- },
569
- () => setRunning(false)
570
- ];
571
- };
572
- var TRANSITION_NAME = "globe-tour";
573
- var defaultDuration = 1500;
574
- var useTour = (controller, points, options = {}) => {
575
- const selection = (0, import_react7.useMemo)(() => (0, import_d37.selection)(), []);
576
- const [running, setRunning] = (0, import_react7.useState)(options.running ?? false);
577
- (0, import_react7.useEffect)(() => {
578
- if (!running) {
579
- selection.interrupt(TRANSITION_NAME);
580
- return;
581
- }
582
- let t;
583
- if (controller && running) {
584
- t = setTimeout(async () => {
585
- const { canvas, projection, setRotation } = controller;
586
- const context = canvas.getContext("2d", {
587
- alpha: false
588
- });
589
- const path = (0, import_d37.geoPath)(projection, context).pointRadius(2);
590
- const tilt = options.tilt ?? 0;
591
- let last;
592
- try {
593
- const p = [
594
- ...points
595
- ];
596
- if (options.loop) {
597
- p.push(p[0]);
598
- }
599
- for (const next of p) {
600
- if (!running) {
601
- break;
602
- }
603
- const p1 = last ? geoToPosition(last) : void 0;
604
- const p2 = geoToPosition(next);
605
- const ip = (0, import_d37.geoInterpolate)(p1 || p2, p2);
606
- const distance = (0, import_d37.geoDistance)(p1 || p2, p2);
607
- const r1 = p1 ? positionToRotation(p1, tilt) : controller.projection.rotate();
608
- const r2 = positionToRotation(p2, tilt);
609
- const iv = import_versor2.default.interpolate(r1, r2);
610
- const transition2 = selection.transition(TRANSITION_NAME).duration(Math.max(options.duration ?? defaultDuration, distance * 2e3)).tween("render", () => (t2) => {
611
- const t1 = Math.max(0, Math.min(1, t2 * 2 - 1));
612
- const t22 = Math.min(1, t2 * 2);
613
- context.save();
614
- {
615
- context.beginPath();
616
- context.strokeStyle = options?.styles?.arc?.strokeStyle ?? "yellow";
617
- context.lineWidth = (options?.styles?.arc?.lineWidth ?? 1.5) * (controller?.scale ?? 1);
618
- context.setLineDash(options?.styles?.arc?.lineDash ?? []);
619
- path({
620
- type: "LineString",
621
- coordinates: [
622
- ip(t1),
623
- ip(t22)
624
- ]
625
- });
626
- context.stroke();
627
- context.beginPath();
628
- context.fillStyle = options?.styles?.cursor?.fillStyle ?? "orange";
629
- path.pointRadius((options?.styles?.cursor?.pointRadius ?? 2) * (controller?.scale ?? 1));
630
- path({
631
- type: "Point",
632
- coordinates: ip(t22)
633
- });
634
- context.fill();
635
- }
636
- context.restore();
637
- projection.rotate(iv(t2));
638
- setRotation(projection.rotate());
639
- });
640
- await transition2.end();
641
- last = next;
642
- }
643
- } catch (err) {
644
- } finally {
645
- setRunning(false);
646
- }
647
- });
648
- return () => {
649
- clearTimeout(t);
650
- selection.interrupt(TRANSITION_NAME);
651
- };
652
- }
653
- }, [
654
- controller,
655
- running,
656
- JSON.stringify(options)
657
- ]);
658
- return [
659
- running,
660
- setRunning
661
- ];
662
- };
663
- var controlPositions = {
664
- topleft: "top-2 left-2",
665
- topright: "top-2 right-2",
666
- bottomleft: "bottom-2 left-2",
667
- bottomright: "bottom-2 right-2"
668
- };
669
- var ZoomControls = ({ classNames, onAction }) => {
670
- var _effect = (0, import_tracking3.useSignals)();
671
- try {
672
- return /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.Toolbar.Root, {
673
- classNames: [
674
- "gap-1",
675
- classNames
676
- ]
677
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
678
- //
679
- icon: "ph--plus--regular",
680
- label: "zoom in",
681
- iconOnly: true,
682
- size: 5,
683
- classNames: "px-0 aspect-square",
684
- onClick: () => onAction?.("zoom-in")
685
- }), /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
686
- //
687
- icon: "ph--minus--regular",
688
- label: "zoom out",
689
- iconOnly: true,
690
- size: 5,
691
- classNames: "px-0 aspect-square",
692
- onClick: () => onAction?.("zoom-out")
693
- }));
694
- } finally {
695
- _effect.f();
696
- }
697
- };
698
- var ActionControls = ({ classNames, onAction }) => {
699
- var _effect = (0, import_tracking3.useSignals)();
700
- try {
701
- return /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.Toolbar.Root, {
702
- classNames: [
703
- "gap-1",
704
- classNames
705
- ]
706
- }, /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
707
- //
708
- icon: "ph--play--regular",
709
- label: "start",
710
- iconOnly: true,
711
- size: 5,
712
- classNames: "px-0 aspect-square",
713
- onClick: () => onAction?.("start")
714
- }), /* @__PURE__ */ import_react8.default.createElement(import_react_ui3.IconButton, {
715
- //
716
- icon: "ph--globe-hemisphere-west--regular",
717
- label: "toggle",
718
- iconOnly: true,
719
- size: 5,
720
- classNames: "px-0 aspect-square",
721
- onClick: () => onAction?.("toggle")
722
- }));
723
- } finally {
724
- _effect.f();
725
- }
726
- };
727
- var defaultStyles = {
728
- light: {
729
- background: {
730
- fillStyle: "#EEE"
731
- },
732
- water: {
733
- fillStyle: "#555"
734
- },
735
- land: {
736
- fillStyle: "#999"
737
- },
738
- line: {
739
- strokeStyle: "darkred"
740
- },
741
- point: {
742
- fillStyle: "#111111",
743
- strokeStyle: "#111111",
744
- strokeWidth: 1,
745
- pointRadius: 0.5
746
- }
747
- },
748
- dark: {
749
- background: {
750
- fillStyle: "#111111"
751
- },
752
- water: {
753
- fillStyle: "#123E6A"
754
- },
755
- land: {
756
- fillStyle: "#032153"
757
- },
758
- line: {
759
- strokeStyle: "#111111"
760
- },
761
- point: {
762
- fillStyle: "#111111",
763
- strokeStyle: "#111111",
764
- strokeWidth: 1,
765
- pointRadius: 0.5
766
- }
767
- }
768
- };
769
- var projectionMap = {
770
- orthographic: import_d3.geoOrthographic,
771
- mercator: import_d3.geoMercator,
772
- "transverse-mercator": import_d3.geoTransverseMercator
773
- };
774
- var getProjection = (type = "orthographic") => {
775
- if (typeof type === "string") {
776
- const constructor = projectionMap[type] ?? import_d3.geoOrthographic;
777
- return constructor();
778
- }
779
- return type ?? (0, import_d3.geoOrthographic)();
780
- };
781
- var GlobeRoot = ({ classNames, children, ...props }) => {
782
- var _effect = (0, import_tracking.useSignals)();
783
- try {
784
- const { ref, width, height } = (0, import_react_resize_detector.useResizeDetector)();
785
- return /* @__PURE__ */ import_react.default.createElement("div", {
786
- ref,
787
- className: (0, import_react_ui_theme.mx)("relative flex grow overflow-hidden", classNames)
788
- }, /* @__PURE__ */ import_react.default.createElement(GlobeContextProvider, {
789
- size: {
790
- width,
791
- height
792
- },
793
- ...props
794
- }, children));
795
- } finally {
796
- _effect.f();
797
- }
798
- };
799
- var GlobeCanvas = /* @__PURE__ */ (0, import_react.forwardRef)(({ projection: _projection, topology, features, styles: _styles }, forwardRef3) => {
800
- var _effect = (0, import_tracking.useSignals)();
801
- try {
802
- const { themeMode } = (0, import_react_ui.useThemeContext)();
803
- const styles = (0, import_react.useMemo)(() => _styles ?? defaultStyles[themeMode], [
804
- _styles,
805
- themeMode
806
- ]);
807
- const [canvas, setCanvas] = (0, import_react.useState)(null);
808
- const canvasRef = (canvas2) => setCanvas(canvas2);
809
- const projection = (0, import_react.useMemo)(() => getProjection(_projection), [
810
- _projection
811
- ]);
812
- const layers = (0, import_react.useMemo)(() => {
813
- return timer(() => createLayers(topology, features, styles));
814
- }, [
815
- topology,
816
- features,
817
- styles
818
- ]);
819
- const { size, center, scale, translation, rotation, setCenter, setScale, setTranslation, setRotation } = useGlobeContext();
820
- const scaleRef = (0, import_react_ui.useDynamicRef)(scale);
821
- (0, import_react.useEffect)(() => {
822
- if (center) {
823
- setScale(1);
824
- setRotation(positionToRotation(geoToPosition(center)));
825
- }
826
- }, [
827
- center
828
- ]);
829
- const zooming = (0, import_react.useRef)(false);
830
- (0, import_react.useImperativeHandle)(forwardRef3, () => {
831
- return {
832
- canvas,
833
- projection,
834
- center,
835
- get scale() {
836
- return scaleRef.current;
837
- },
838
- translation,
839
- rotation,
840
- setCenter,
841
- setScale: (s) => {
842
- if (typeof s === "function") {
843
- const is = (0, import_d3.interpolateNumber)(scaleRef.current, s(scaleRef.current));
844
- (0, import_d3.transition)().ease(zooming.current ? import_d3.easeLinear : import_d3.easeSinOut).duration(200).tween("scale", () => (t) => setScale(is(t))).on("end", () => {
845
- zooming.current = false;
846
- });
847
- } else {
848
- setScale(s);
849
- }
850
- },
851
- setTranslation,
852
- setRotation
853
- };
854
- }, [
855
- canvas
856
- ]);
857
- const generator = (0, import_react.useMemo)(() => canvas && projection && (0, import_d3.geoPath)(projection, canvas.getContext("2d", {
858
- alpha: false
859
- })), [
860
- canvas,
861
- projection
862
- ]);
863
- (0, import_react.useEffect)(() => {
864
- if (canvas && projection) {
865
- timer(() => {
866
- projection.scale(Math.min(size.width, size.height) / 2 * scale).translate([
867
- size.width / 2 + (translation?.x ?? 0),
868
- size.height / 2 + (translation?.y ?? 0)
869
- ]).rotate(rotation ?? [
870
- 0,
871
- 0,
872
- 0
873
- ]);
874
- renderLayers(generator, layers, scale, styles);
875
- });
876
- }
877
- }, [
878
- generator,
879
- size,
880
- scale,
881
- translation,
882
- rotation,
883
- layers
884
- ]);
885
- if (!size.width || !size.height) {
886
- return null;
887
- }
888
- return /* @__PURE__ */ import_react.default.createElement("canvas", {
889
- ref: canvasRef,
890
- width: size.width,
891
- height: size.height
892
- });
893
- } finally {
894
- _effect.f();
895
- }
896
- });
897
- var GlobeDebug = ({ position = "topleft" }) => {
898
- var _effect = (0, import_tracking.useSignals)();
899
- try {
900
- const { size, scale, translation, rotation } = useGlobeContext();
901
- return /* @__PURE__ */ import_react.default.createElement("div", {
902
- className: (0, import_react_ui_theme.mx)("z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded", controlPositions[position])
903
- }, /* @__PURE__ */ import_react.default.createElement("pre", {
904
- className: "font-mono text-xs text-green-700"
905
- }, JSON.stringify({
906
- size,
907
- scale,
908
- translation,
909
- rotation
910
- }, null, 2)));
911
- } finally {
912
- _effect.f();
913
- }
914
- };
915
- var GlobePanel = ({ position, classNames, children }) => {
916
- var _effect = (0, import_tracking.useSignals)();
917
- try {
918
- return /* @__PURE__ */ import_react.default.createElement("div", {
919
- className: (0, import_react_ui_theme.mx)("z-10 absolute overflow-hidden", controlPositions[position], classNames)
920
- }, children);
921
- } finally {
922
- _effect.f();
923
- }
924
- };
925
- var CustomControl = ({ position, children }) => {
926
- var _effect = (0, import_tracking.useSignals)();
927
- try {
928
- return /* @__PURE__ */ import_react.default.createElement("div", {
929
- className: (0, import_react_ui_theme.mx)("z-10 absolute overflow-hidden", controlPositions[position])
930
- }, children);
931
- } finally {
932
- _effect.f();
933
- }
934
- };
935
- var Globe = {
936
- Root: GlobeRoot,
937
- Canvas: GlobeCanvas,
938
- Zoom: ({ onAction, position = "bottomleft", ...props }) => {
939
- var _effect = (0, import_tracking.useSignals)();
940
- try {
941
- return /* @__PURE__ */ import_react.default.createElement(CustomControl, {
942
- position,
943
- ...props
944
- }, /* @__PURE__ */ import_react.default.createElement(ZoomControls, {
945
- onAction
946
- }));
947
- } finally {
948
- _effect.f();
949
- }
950
- },
951
- Action: ({ onAction, position = "bottomright", ...props }) => {
952
- var _effect = (0, import_tracking.useSignals)();
953
- try {
954
- return /* @__PURE__ */ import_react.default.createElement(CustomControl, {
955
- position,
956
- ...props
957
- }, /* @__PURE__ */ import_react.default.createElement(ActionControls, {
958
- onAction
959
- }));
960
- } finally {
961
- _effect.f();
962
- }
963
- },
964
- Debug: GlobeDebug,
965
- Panel: GlobePanel
966
- };
967
- var defaults = {
968
- // TODO(burdon): Guess location.
969
- center: {
970
- lat: 51,
971
- lng: 0
972
- },
973
- zoom: 4
974
- };
975
- var MapRoot = ({ classNames, center = defaults.center, zoom = defaults.zoom, ...props }) => {
976
- var _effect = (0, import_tracking4.useSignals)();
977
- try {
978
- return /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.MapContainer, {
979
- className: (0, import_react_ui_theme2.mx)("relative grid grow bg-baseSurface", classNames),
980
- attributionControl: false,
981
- // TODO(burdon): Only if attention.
982
- scrollWheelZoom: true,
983
- zoomControl: false,
984
- center,
985
- zoom,
986
- ...props
987
- });
988
- } finally {
989
- _effect.f();
990
- }
991
- };
992
- var MapCanvas = /* @__PURE__ */ (0, import_react9.forwardRef)(({ markers, center, zoom, onChange }, forwardedRef) => {
993
- var _effect = (0, import_tracking4.useSignals)();
994
- try {
995
- const { ref, width, height } = (0, import_react_resize_detector2.useResizeDetector)({
996
- refreshRate: 200
997
- });
998
- const map = (0, import_react_leaflet.useMap)();
999
- (0, import_react9.useImperativeHandle)(forwardedRef, () => ({
1000
- setCenter: (center2, zoom2) => {
1001
- map.setView(center2, zoom2);
1002
- },
1003
- setZoom: (cb) => {
1004
- map.setZoom(cb(map.getZoom()));
1005
- }
1006
- }), [
1007
- map
1008
- ]);
1009
- (0, import_react9.useEffect)(() => {
1010
- if (width && height) {
1011
- map.invalidateSize();
1012
- }
1013
- }, [
1014
- width,
1015
- height
1016
- ]);
1017
- (0, import_react9.useEffect)(() => {
1018
- if (center) {
1019
- map.setView(center, zoom);
1020
- } else if (zoom !== void 0) {
1021
- map.setZoom(zoom);
1022
- }
1023
- }, [
1024
- center,
1025
- zoom
1026
- ]);
1027
- (0, import_react9.useEffect)(() => {
1028
- const handler = (0, import_async.debounce)(() => {
1029
- onChange?.({
1030
- center: map.getCenter(),
1031
- zoom: map.getZoom()
1032
- });
1033
- }, 100);
1034
- map.on("move", handler);
1035
- map.on("zoom", handler);
1036
- return () => {
1037
- map.off("move", handler);
1038
- map.off("zoom", handler);
1039
- };
1040
- }, [
1041
- map,
1042
- onChange
1043
- ]);
1044
- (0, import_react9.useEffect)(() => {
1045
- if (markers.length > 0) {
1046
- const bounds = (0, import_leaflet2.latLngBounds)(markers.map((marker) => marker.location));
1047
- map.fitBounds(bounds);
1048
- } else {
1049
- map.setView(defaults.center, defaults.zoom);
1050
- }
1051
- }, [
1052
- markers
1053
- ]);
1054
- return /* @__PURE__ */ import_react9.default.createElement("div", {
1055
- ref,
1056
- className: "flex w-full h-full overflow-hidden bg-baseSurface"
1057
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.TileLayer, {
1058
- className: "dark:filter dark:grayscale dark:invert",
1059
- url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
1060
- }), markers?.map(({ id, title, location: { lat, lng } }) => {
1061
- return /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.Marker, {
1062
- key: id,
1063
- position: {
1064
- lat,
1065
- lng
1066
- },
1067
- icon: (
1068
- // TODO(burdon): Create custom icon from bundled assets.
1069
- new import_leaflet2.default.Icon({
1070
- iconUrl: "https://dxos.network/marker-icon.png",
1071
- iconRetinaUrl: "https://dxos.network/marker-icon-2x.png",
1072
- shadowUrl: "https://dxos.network/marker-shadow.png",
1073
- iconSize: [
1074
- 25,
1075
- 41
1076
- ],
1077
- iconAnchor: [
1078
- 12,
1079
- 41
1080
- ],
1081
- popupAnchor: [
1082
- 1,
1083
- -34
1084
- ],
1085
- shadowSize: [
1086
- 41,
1087
- 41
1088
- ]
1089
- })
1090
- )
1091
- }, title && /* @__PURE__ */ import_react9.default.createElement(import_react_leaflet.Popup, null, title));
1092
- }));
1093
- } finally {
1094
- _effect.f();
1095
- }
1096
- });
1097
- var CustomControl2 = ({ position, children }) => {
1098
- var _effect = (0, import_tracking4.useSignals)();
1099
- try {
1100
- const map = (0, import_react_leaflet.useMap)();
1101
- (0, import_react9.useEffect)(() => {
1102
- const control = new import_leaflet2.Control({
1103
- position
1104
- });
1105
- control.onAdd = () => {
1106
- const container = import_leaflet2.DomUtil.create("div", (0, import_react_ui_theme2.mx)("!m-0", controlPositions[position]));
1107
- import_leaflet2.DomEvent.disableClickPropagation(container);
1108
- import_leaflet2.DomEvent.disableScrollPropagation(container);
1109
- const root = (0, import_client.createRoot)(container);
1110
- root.render(/* @__PURE__ */ import_react9.default.createElement(import_react_ui4.ThemeProvider, {
1111
- tx: import_react_ui_theme2.defaultTx
1112
- }, /* @__PURE__ */ import_react9.default.createElement(import_react_ui4.Tooltip.Provider, null, children)));
1113
- return container;
1114
- };
1115
- control.addTo(map);
1116
- return () => {
1117
- control.remove();
1118
- };
1119
- }, [
1120
- map,
1121
- position,
1122
- children
1123
- ]);
1124
- return null;
1125
- } finally {
1126
- _effect.f();
1127
- }
1128
- };
1129
- var Map = {
1130
- Root: MapRoot,
1131
- Canvas: MapCanvas,
1132
- Zoom: ({ onAction, position = "bottomleft", ...props }) => {
1133
- var _effect = (0, import_tracking4.useSignals)();
1134
- try {
1135
- return /* @__PURE__ */ import_react9.default.createElement(CustomControl2, {
1136
- position,
1137
- ...props
1138
- }, /* @__PURE__ */ import_react9.default.createElement(ZoomControls, {
1139
- onAction
1140
- }));
1141
- } finally {
1142
- _effect.f();
1143
- }
1144
- },
1145
- Action: ({ onAction, position = "bottomright", ...props }) => {
1146
- var _effect = (0, import_tracking4.useSignals)();
1147
- try {
1148
- return /* @__PURE__ */ import_react9.default.createElement(CustomControl2, {
1149
- position,
1150
- ...props
1151
- }, /* @__PURE__ */ import_react9.default.createElement(ActionControls, {
1152
- onAction
1153
- }));
1154
- } finally {
1155
- _effect.f();
1156
- }
1157
- }
1158
- };
1159
- // Annotate the CommonJS export names for ESM import in node:
1160
- 0 && (module.exports = {
1161
- ActionControls,
1162
- Globe,
1163
- GlobeContextProvider,
1164
- Map,
1165
- ZoomControls,
1166
- closestPoint,
1167
- controlPositions,
1168
- createLayers,
1169
- geoCircle,
1170
- geoInertiaDrag,
1171
- geoLine,
1172
- geoPoint,
1173
- geoToPosition,
1174
- getDistance,
1175
- loadTopology,
1176
- positionToRotation,
1177
- renderLayers,
1178
- restrictAxis,
1179
- timer,
1180
- useDrag,
1181
- useGlobeContext,
1182
- useGlobeZoomHandler,
1183
- useMapZoomHandler,
1184
- useSpinner,
1185
- useTour
1186
- });
1187
- //# sourceMappingURL=index.cjs.map