@dxos/react-ui-geo 0.7.5-labs.071a3e2

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