@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.
Files changed (121) hide show
  1. package/LICENSE +102 -5
  2. package/data/countries-10m.ts +12 -0
  3. package/data/countries-110m.ts +4 -10579
  4. package/data/countries-50m.ts +12 -0
  5. package/dist/lib/browser/chunk-SC2FBYFU.mjs +17 -0
  6. package/dist/lib/browser/chunk-SC2FBYFU.mjs.map +7 -0
  7. package/dist/lib/browser/countries-10m-CWWDOKH7.mjs +6 -0
  8. package/dist/lib/browser/countries-10m-CWWDOKH7.mjs.map +7 -0
  9. package/dist/lib/browser/countries-110m-72QBAA5E.mjs +6 -0
  10. package/dist/lib/browser/countries-110m-72QBAA5E.mjs.map +7 -0
  11. package/dist/lib/browser/countries-50m-H7SL7KVF.mjs +6 -0
  12. package/dist/lib/browser/countries-50m-H7SL7KVF.mjs.map +7 -0
  13. package/dist/lib/browser/data.mjs +1 -1
  14. package/dist/lib/browser/index.mjs +1054 -578
  15. package/dist/lib/browser/index.mjs.map +4 -4
  16. package/dist/lib/browser/meta.json +1 -1
  17. package/dist/lib/browser/translations.mjs +19 -0
  18. package/dist/lib/browser/translations.mjs.map +7 -0
  19. package/dist/lib/node-esm/chunk-VZENBYLJ.mjs +19 -0
  20. package/dist/lib/node-esm/chunk-VZENBYLJ.mjs.map +7 -0
  21. package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs +8 -0
  22. package/dist/lib/node-esm/countries-10m-DJZV66KG.mjs.map +7 -0
  23. package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs +8 -0
  24. package/dist/lib/node-esm/countries-110m-H3WY6K4Q.mjs.map +7 -0
  25. package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs +8 -0
  26. package/dist/lib/node-esm/countries-50m-ZY7Z3IWD.mjs.map +7 -0
  27. package/dist/lib/node-esm/data.mjs +1 -1
  28. package/dist/lib/node-esm/index.mjs +1054 -578
  29. package/dist/lib/node-esm/index.mjs.map +4 -4
  30. package/dist/lib/node-esm/meta.json +1 -1
  31. package/dist/lib/node-esm/translations.mjs +21 -0
  32. package/dist/lib/node-esm/translations.mjs.map +7 -0
  33. package/dist/types/data/airports.d.ts +4 -4
  34. package/dist/types/data/airports.d.ts.map +1 -1
  35. package/dist/types/data/cities.d.ts.map +1 -1
  36. package/dist/types/data/countries-10m.d.ts +8 -0
  37. package/dist/types/data/countries-10m.d.ts.map +1 -0
  38. package/dist/types/data/countries-110m.d.ts +2 -30
  39. package/dist/types/data/countries-110m.d.ts.map +1 -1
  40. package/dist/types/data/countries-50m.d.ts +8 -0
  41. package/dist/types/data/countries-50m.d.ts.map +1 -0
  42. package/dist/types/data/countries-dots-3.d.ts.map +1 -1
  43. package/dist/types/data/countries-dots-4.d.ts.map +1 -1
  44. package/dist/types/src/components/Globe/Globe.d.ts +19 -9
  45. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
  46. package/dist/types/src/components/Globe/Globe.stories.d.ts +37 -11
  47. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  48. package/dist/types/src/components/Map/Map.d.ts +55 -16
  49. package/dist/types/src/components/Map/Map.d.ts.map +1 -1
  50. package/dist/types/src/components/Map/Map.stories.d.ts +19 -9
  51. package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
  52. package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
  53. package/dist/types/src/data.d.ts +9 -1
  54. package/dist/types/src/data.d.ts.map +1 -1
  55. package/dist/types/src/hooks/context.d.ts +38 -3
  56. package/dist/types/src/hooks/context.d.ts.map +1 -1
  57. package/dist/types/src/hooks/index.d.ts +3 -0
  58. package/dist/types/src/hooks/index.d.ts.map +1 -1
  59. package/dist/types/src/hooks/useDrag.d.ts +22 -2
  60. package/dist/types/src/hooks/useDrag.d.ts.map +1 -1
  61. package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +3 -2
  62. package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
  63. package/dist/types/src/hooks/useMapZoomHandler.d.ts +1 -1
  64. package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
  65. package/dist/types/src/hooks/useSimplifiedTopology.d.ts +32 -0
  66. package/dist/types/src/hooks/useSimplifiedTopology.d.ts.map +1 -0
  67. package/dist/types/src/hooks/useSpinner.d.ts +1 -1
  68. package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
  69. package/dist/types/src/hooks/useTopology.d.ts +26 -0
  70. package/dist/types/src/hooks/useTopology.d.ts.map +1 -0
  71. package/dist/types/src/hooks/useTour.d.ts +3 -2
  72. package/dist/types/src/hooks/useTour.d.ts.map +1 -1
  73. package/dist/types/src/hooks/useWheel.d.ts +24 -0
  74. package/dist/types/src/hooks/useWheel.d.ts.map +1 -0
  75. package/dist/types/src/index.d.ts +0 -1
  76. package/dist/types/src/index.d.ts.map +1 -1
  77. package/dist/types/src/translations.d.ts +12 -0
  78. package/dist/types/src/translations.d.ts.map +1 -0
  79. package/dist/types/src/util/animation.d.ts +16 -0
  80. package/dist/types/src/util/animation.d.ts.map +1 -0
  81. package/dist/types/src/util/debug.d.ts.map +1 -1
  82. package/dist/types/src/util/index.d.ts +2 -0
  83. package/dist/types/src/util/index.d.ts.map +1 -1
  84. package/dist/types/src/util/inertia.d.ts.map +1 -1
  85. package/dist/types/src/util/path.d.ts.map +1 -1
  86. package/dist/types/src/util/render.d.ts +25 -1
  87. package/dist/types/src/util/render.d.ts.map +1 -1
  88. package/dist/types/src/util/styles.d.ts +4 -0
  89. package/dist/types/src/util/styles.d.ts.map +1 -0
  90. package/dist/types/tsconfig.tsbuildinfo +1 -1
  91. package/package.json +43 -37
  92. package/src/components/Globe/Globe.stories.tsx +201 -82
  93. package/src/components/Globe/Globe.tsx +263 -119
  94. package/src/components/Map/Map.stories.tsx +66 -17
  95. package/src/components/Map/Map.tsx +333 -120
  96. package/src/components/Toolbar/Controls.tsx +12 -14
  97. package/src/data.ts +19 -2
  98. package/src/hooks/context.tsx +49 -28
  99. package/src/hooks/index.ts +3 -0
  100. package/src/hooks/useDrag.ts +33 -5
  101. package/src/hooks/useGlobeZoomHandler.ts +10 -3
  102. package/src/hooks/useSimplifiedTopology.ts +81 -0
  103. package/src/hooks/useSpinner.ts +1 -2
  104. package/src/hooks/useTopology.ts +95 -0
  105. package/src/hooks/useTour.ts +71 -81
  106. package/src/hooks/useWheel.ts +83 -0
  107. package/src/index.ts +0 -1
  108. package/src/translations.ts +20 -0
  109. package/src/util/animation.ts +35 -0
  110. package/src/util/index.ts +2 -0
  111. package/src/util/inertia.ts +87 -4
  112. package/src/util/render.ts +105 -17
  113. package/src/util/styles.ts +62 -0
  114. package/dist/lib/browser/chunk-GMWLKTLN.mjs +0 -9
  115. package/dist/lib/browser/chunk-GMWLKTLN.mjs.map +0 -7
  116. package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs +0 -37859
  117. package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs.map +0 -7
  118. package/dist/lib/node-esm/chunk-JODBF4CC.mjs +0 -11
  119. package/dist/lib/node-esm/chunk-JODBF4CC.mjs.map +0 -7
  120. package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs +0 -37861
  121. package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs.map +0 -7
package/package.json CHANGED
@@ -1,87 +1,93 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-geo",
3
- "version": "0.8.4-main.fd6878d",
3
+ "version": "0.8.4-staging.60fe92afc8",
4
4
  "description": "Geo components.",
5
5
  "homepage": "https://github.com/dxos",
6
6
  "bugs": "https://github.com/dxos/issues",
7
- "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/dxos/dxos"
10
+ },
11
+ "license": "FSL-1.1-Apache-2.0",
8
12
  "author": "DXOS.org",
9
13
  "sideEffects": true,
10
14
  "type": "module",
15
+ "imports": {
16
+ "#translations": "./src/translations.ts"
17
+ },
11
18
  "exports": {
19
+ ".": {
20
+ "source": "./src/index.ts",
21
+ "types": "./dist/types/src/index.d.ts",
22
+ "browser": "./dist/lib/browser/index.mjs",
23
+ "node": "./dist/lib/node-esm/index.mjs"
24
+ },
12
25
  "./data": {
13
26
  "source": "./src/data.ts",
14
27
  "types": "./dist/types/src/data.d.ts",
15
28
  "browser": "./dist/lib/browser/data.mjs",
16
29
  "node": "./dist/lib/node-esm/data.mjs"
17
30
  },
18
- ".": {
19
- "source": "./src/index.ts",
20
- "types": "./dist/types/src/index.d.ts",
21
- "browser": "./dist/lib/browser/index.mjs",
22
- "node": "./dist/lib/node-esm/index.mjs"
31
+ "./translations": {
32
+ "source": "./src/translations.ts",
33
+ "types": "./dist/types/src/translations.d.ts",
34
+ "browser": "./dist/lib/browser/translations.mjs",
35
+ "node": "./dist/lib/node-esm/translations.mjs"
23
36
  }
24
37
  },
25
38
  "types": "dist/types/src/index.d.ts",
26
- "typesVersions": {
27
- "*": {
28
- "data": [
29
- "dist/types/src/data.d.ts"
30
- ]
31
- }
32
- },
33
39
  "files": [
34
40
  "data",
35
41
  "dist",
36
42
  "src"
37
43
  ],
38
44
  "dependencies": {
39
- "@preact-signals/safe-react": "^0.9.0",
40
- "@radix-ui/react-context": "^1.0.5",
45
+ "@radix-ui/react-compose-refs": "1.1.1",
46
+ "@radix-ui/react-context": "1.1.1",
41
47
  "d3": "^7.9.0",
42
48
  "d3-geo-projection": "^4.0.0",
43
49
  "d3-hexbin": "^0.2.2",
44
50
  "geojson": "^0.5.0",
45
51
  "leaflet": "^1.9.4",
46
52
  "lodash.defaultsdeep": "^4.6.1",
47
- "react-leaflet": "^4.2.1",
53
+ "react-leaflet": "^5.0.0",
48
54
  "react-resize-detector": "^11.0.1",
49
55
  "topojson-client": "^3.1.0",
50
56
  "topojson-simplify": "^3.0.3",
51
57
  "versor": "^0.2.0",
52
- "@dxos/async": "0.8.4-main.fd6878d",
53
- "@dxos/debug": "0.8.4-main.fd6878d",
54
- "@dxos/log": "0.8.4-main.fd6878d",
55
- "@dxos/node-std": "0.8.4-main.fd6878d",
56
- "@dxos/util": "0.8.4-main.fd6878d"
58
+ "@dxos/debug": "0.8.4-staging.60fe92afc8",
59
+ "@dxos/util": "0.8.4-staging.60fe92afc8",
60
+ "@dxos/node-std": "0.8.4-staging.60fe92afc8",
61
+ "@dxos/log": "0.8.4-staging.60fe92afc8",
62
+ "@dxos/async": "0.8.4-staging.60fe92afc8"
57
63
  },
58
64
  "devDependencies": {
59
- "@react-three/drei": "^9.99.0",
60
- "@react-three/fiber": "^8.15.0",
65
+ "@react-three/drei": "^10.7.7",
66
+ "@react-three/fiber": "^9.5.0",
61
67
  "@types/d3": "^7.4.3",
62
68
  "@types/geojson": "^7946.0.14",
63
69
  "@types/leaflet": "^1.9.16",
64
- "@types/react": "~18.2.0",
65
- "@types/react-dom": "~18.2.0",
70
+ "@types/react": "~19.2.7",
71
+ "@types/react-dom": "~19.2.3",
66
72
  "@types/three": "0.165.0",
67
73
  "@types/topojson-client": "^3.1.4",
68
74
  "@types/topojson-simplify": "^3.0.3",
69
75
  "@types/topojson-specification": "^1.0.5",
70
76
  "JSONStream": "^1.3.5",
71
77
  "geojson2h3": "^1.2.0",
72
- "leva": "^0.9.35",
73
- "react": "~18.2.0",
74
- "react-dom": "~18.2.0",
75
- "three": "0.165.0",
76
- "@dxos/react-ui": "0.8.4-main.fd6878d",
77
- "@dxos/react-ui-theme": "0.8.4-main.fd6878d",
78
- "@dxos/storybook-utils": "0.8.4-main.fd6878d"
78
+ "leva": "^0.10.1",
79
+ "react": "~19.2.3",
80
+ "react-dom": "~19.2.3",
81
+ "three": "^0.178.0",
82
+ "@dxos/react-ui": "0.8.4-staging.60fe92afc8",
83
+ "@dxos/storybook-utils": "0.8.4-staging.60fe92afc8",
84
+ "@dxos/ui-theme": "0.8.4-staging.60fe92afc8"
79
85
  },
80
86
  "peerDependencies": {
81
- "react": "~18.2.0",
82
- "react-dom": "~18.2.0",
83
- "@dxos/react-ui-theme": "0.8.4-main.fd6878d",
84
- "@dxos/react-ui": "0.8.4-main.fd6878d"
87
+ "react": "~19.2.3",
88
+ "react-dom": "~19.2.3",
89
+ "@dxos/react-ui": "0.8.4-staging.60fe92afc8",
90
+ "@dxos/ui-theme": "0.8.4-staging.60fe92afc8"
85
91
  },
86
92
  "publishConfig": {
87
93
  "access": "public"
@@ -2,59 +2,57 @@
2
2
  // Copyright 2018 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
- import { type Meta } from '@storybook/react-vite';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import { type FeatureCollection, type Geometry, type Position } from 'geojson';
9
7
  import { Leva } from 'leva';
10
- import React, { useMemo, useRef, useState } from 'react';
8
+ import React, { useMemo, useState } from 'react';
11
9
  import { type Topology } from 'topojson-specification';
12
10
 
13
11
  import { useAsyncState } from '@dxos/react-ui';
14
- import { withLayout, withTheme } from '@dxos/storybook-utils';
15
-
16
- import { type Vector, useDrag, useGlobeZoomHandler, useSpinner, useTour } from '../../hooks';
12
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
13
+
14
+ import { loadTopology } from '../../data';
15
+ import {
16
+ type GlobeController,
17
+ type Level,
18
+ type Vector,
19
+ useDrag,
20
+ useGlobeContext,
21
+ useGlobeZoomHandler,
22
+ useSpinner,
23
+ useTopology,
24
+ useTour,
25
+ useWheel,
26
+ } from '../../hooks';
17
27
  import { type LatLngLiteral } from '../../types';
18
28
  import { type StyleSet, closestPoint } from '../../util';
19
29
  import { type ControlProps } from '../Toolbar';
20
-
21
- import { Globe, type GlobeCanvasProps, type GlobeController, type GlobeRootProps } from './Globe';
22
-
23
- // TODO(burdon): Load from JSON at runtime?
24
- const useTopology = () => {
25
- return useAsyncState(async () => (await import('../../../data/countries-110m.ts')).default);
26
- };
30
+ import { Globe, type GlobeCanvasProps, type GlobeRootProps } from './Globe';
27
31
 
28
32
  const defaultStyles: StyleSet = {
29
33
  water: {
30
34
  fillStyle: '#0a0a0a',
31
35
  },
32
-
33
36
  land: {
34
37
  fillStyle: '#050505',
35
38
  strokeStyle: 'darkgreen',
36
39
  },
37
-
38
40
  graticule: {
39
41
  strokeStyle: '#111',
40
42
  },
41
-
42
43
  line: {
43
44
  lineWidth: 1,
44
45
  lineDash: [4, 16],
45
46
  strokeStyle: 'yellow',
46
47
  },
47
-
48
48
  point: {
49
49
  pointRadius: 2,
50
50
  fillStyle: 'red',
51
51
  },
52
-
53
52
  cursor: {
54
53
  fillStyle: 'orange',
55
54
  pointRadius: 2,
56
55
  },
57
-
58
56
  arc: {
59
57
  lineWidth: 2,
60
58
  strokeStyle: 'yellow',
@@ -66,17 +64,14 @@ const dotStyles: StyleSet = {
66
64
  fillStyle: '#444',
67
65
  pointRadius: 2,
68
66
  },
69
-
70
67
  point: {
71
68
  pointRadius: 2,
72
69
  fillStyle: 'red',
73
70
  },
74
-
75
71
  cursor: {
76
72
  fillStyle: 'orange',
77
73
  pointRadius: 2,
78
74
  },
79
-
80
75
  arc: {
81
76
  lineWidth: 2,
82
77
  strokeStyle: 'yellow',
@@ -130,16 +125,19 @@ const createTrip = (
130
125
  );
131
126
  };
132
127
 
133
- type StoryProps = Pick<GlobeRootProps, 'zoom' | 'translation' | 'rotation'> &
128
+ type DefaultStoryProps = Pick<GlobeRootProps, 'zoom' | 'translation' | 'rotation'> &
134
129
  Pick<GlobeCanvasProps, 'projection' | 'styles'> & {
135
130
  drag?: boolean;
136
131
  spin?: boolean;
137
132
  tour?: boolean;
138
- xAxis?: boolean;
133
+ wheel?: boolean;
134
+ lockTilt?: boolean;
135
+ mode?: 'linear' | 'versor';
136
+ level?: Level;
139
137
  };
140
138
 
141
- const Story = ({
142
- zoom: _zoom = 1,
139
+ const DefaultStory = ({
140
+ zoom: zoomProp = 1,
143
141
  translation,
144
142
  rotation = [0, 0, 0],
145
143
  projection,
@@ -147,9 +145,12 @@ const Story = ({
147
145
  drag = false,
148
146
  spin = false,
149
147
  tour = false,
150
- xAxis = false,
151
- }: StoryProps) => {
152
- const controller = useRef<GlobeController>(null);
148
+ wheel = false,
149
+ lockTilt = false,
150
+ mode,
151
+ level = '110m',
152
+ }: DefaultStoryProps) => {
153
+ const [controller, setController] = useState<GlobeController | null>(null);
153
154
  const [dots] = useAsyncState(async () => {
154
155
  const points = (await import('../../../data/countries-dots-3.ts')).default;
155
156
  return {
@@ -157,17 +158,19 @@ const Story = ({
157
158
  objects: { dots: points },
158
159
  } as any as Topology;
159
160
  });
160
- const [topology] = useTopology();
161
+ const [topology] = useAsyncState(() => loadTopology(level), [level]);
161
162
  const [airports] = useAsyncState(async () => (await import('../../../data/airports.ts')).default);
163
+
162
164
  const features = useMemo(() => {
163
165
  return airports ? createTrip(airports, routes, (dots?.objects.dots as any)?.geometries[0].coordinates) : undefined;
164
166
  }, [airports, routes, dots]);
165
167
 
166
168
  // Control hooks.
167
- const [startSpinner, stopSpinner] = useSpinner(controller.current, { disabled: !spin });
168
- const [_running, setRunning] = useTour(controller.current, features?.points, { disabled: !tour, styles });
169
- useDrag(controller.current, {
170
- xAxis,
169
+ const [startSpinner, stopSpinner] = useSpinner(controller, { disabled: !spin });
170
+ const [_running, setRunning] = useTour(controller, features?.points, { disabled: !tour, styles });
171
+ useDrag(controller, {
172
+ lockTilt,
173
+ mode,
171
174
  disabled: !drag,
172
175
  onUpdate: (event) => {
173
176
  switch (event.type) {
@@ -179,6 +182,13 @@ const Story = ({
179
182
  }
180
183
  },
181
184
  });
185
+ useWheel(controller, {
186
+ disabled: !wheel,
187
+ onUpdate: () => {
188
+ stopSpinner();
189
+ setRunning(false);
190
+ },
191
+ });
182
192
 
183
193
  // TODO(burdon): Factor out handlers.
184
194
  const handleAction: ControlProps['onAction'] = (event) => {
@@ -193,70 +203,122 @@ const Story = ({
193
203
  break;
194
204
  }
195
205
  case 'zoom-in': {
196
- controller.current.setZoom((scale) => scale * 1.1);
206
+ controller?.setZoom((scale) => scale * 1.1);
197
207
  break;
198
208
  }
199
209
  case 'zoom-out': {
200
- controller.current.setZoom((scale) => scale * 0.9);
210
+ controller?.setZoom((scale) => scale * 0.9);
201
211
  break;
202
212
  }
203
213
  }
204
214
  };
205
215
 
206
216
  return (
207
- <Globe.Root classNames='absolute inset-0' zoom={_zoom} translation={translation} rotation={rotation}>
208
- <Globe.Canvas
209
- ref={controller}
210
- topology={styles?.dots ? dots : topology}
211
- projection={projection}
212
- styles={styles}
213
- features={tour ? { points: features?.points ?? [] } : features}
214
- />
215
- <Globe.Zoom onAction={handleAction} />
216
- <Globe.Action onAction={handleAction} />
217
- <Globe.Debug />
218
- <Globe.Panel position='topright' classNames='w-20 h-20'>
219
- <Leva />
220
- </Globe.Panel>
217
+ <Globe.Root zoom={zoomProp} translation={translation} rotation={rotation} ref={setController}>
218
+ <Globe.Viewport>
219
+ <Globe.Canvas
220
+ topology={styles?.dots ? dots : topology}
221
+ projection={projection}
222
+ styles={styles}
223
+ features={tour ? { points: features?.points ?? [] } : features}
224
+ />
225
+ <Globe.Zoom onAction={handleAction} />
226
+ <Globe.Action onAction={handleAction} />
227
+ <Globe.Debug />
228
+ <Globe.Panel position='topright' classNames='w-20 h-20'>
229
+ <Leva />
230
+ </Globe.Panel>
231
+ </Globe.Viewport>
221
232
  </Globe.Root>
222
233
  );
223
234
  };
224
235
 
225
236
  const initialRotation: Vector = [0, -40, 0];
226
237
 
227
- const meta: Meta = {
238
+ const meta = {
228
239
  title: 'ui/react-ui-geo/Globe',
229
240
  component: Globe.Root,
230
- decorators: [withTheme, withLayout({ fullscreen: true, classNames: 'bg-[#000]' })],
231
- };
241
+ render: DefaultStory,
242
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
243
+ parameters: {
244
+ layout: 'fullscreen',
245
+ },
246
+ } satisfies Meta;
232
247
 
233
248
  export default meta;
234
249
 
235
- export const Earth1 = () => {
236
- const [topology] = useTopology();
250
+ const Earth = ({ level }: { level: Level }) => {
251
+ const [topology] = useAsyncState(() => loadTopology(level), [level]);
237
252
  const [controller, setController] = useState<GlobeController | null>();
238
253
  const handleAction = useGlobeZoomHandler(controller);
239
254
  useDrag(controller);
255
+ useWheel(controller);
256
+
257
+ return (
258
+ <Globe.Root zoom={1.2} rotation={[0, 0, 0]} ref={setController}>
259
+ <Globe.Viewport>
260
+ <Globe.Canvas topology={topology} styles={defaultStyles} />
261
+ <Globe.Zoom onAction={handleAction} />
262
+ </Globe.Viewport>
263
+ </Globe.Root>
264
+ );
265
+ };
266
+
267
+ export const Topology110 = () => {
268
+ return <Earth level='110m' />;
269
+ };
270
+
271
+ export const Topology50 = () => {
272
+ return <Earth level='50m' />;
273
+ };
274
+
275
+ export const Topology10 = () => {
276
+ return <Earth level='10m' />;
277
+ };
240
278
 
279
+ /**
280
+ * Discrete-resolution LOD: swaps resolution by zoom via `useTopology(zoom)`. Each resolution is a
281
+ * code-split chunk fetched on demand the first time its tier is entered (default tiers: 110m / 50m).
282
+ * Reads the live zoom from the globe context, so it must render inside `Globe.Root`.
283
+ */
284
+ const DynamicCanvas = ({ controller }: { controller: GlobeController | null | undefined }) => {
285
+ const { zoom } = useGlobeContext();
286
+ const topology = useTopology(zoom);
287
+ const handleAction = useGlobeZoomHandler(controller);
288
+ useDrag(controller);
289
+ useWheel(controller);
241
290
  return (
242
- <Globe.Root zoom={1.2} rotation={[Math.random() * 360, 0, 0]}>
243
- <Globe.Canvas ref={setController} topology={topology} styles={defaultStyles} />
291
+ <Globe.Viewport>
292
+ <Globe.Canvas topology={topology} styles={defaultStyles} />
244
293
  <Globe.Zoom onAction={handleAction} />
294
+ <Globe.Debug />
295
+ </Globe.Viewport>
296
+ );
297
+ };
298
+
299
+ export const Dynamic = () => {
300
+ const [controller, setController] = useState<GlobeController | null>();
301
+ return (
302
+ <Globe.Root zoom={1.2} rotation={[0, 0, 0]} ref={setController}>
303
+ <DynamicCanvas controller={controller} />
245
304
  </Globe.Root>
246
305
  );
247
306
  };
248
307
 
249
- export const Earth2 = () => {
250
- const [topology] = useTopology();
308
+ export const Earthrise = () => {
309
+ const topology = useTopology();
251
310
  const [controller, setController] = useState<GlobeController | null>();
252
311
  const handleAction = useGlobeZoomHandler(controller);
253
312
  useDrag(controller);
313
+ useWheel(controller);
254
314
 
255
315
  return (
256
316
  <div className='absolute bottom-0 left-0 right-0 '>
257
- <Globe.Root classNames='h-[400px]' zoom={2.8} translation={{ x: 0, y: 400 }}>
258
- <Globe.Canvas ref={setController} topology={topology} styles={defaultStyles} />
259
- <Globe.Zoom onAction={handleAction} />
317
+ <Globe.Root zoom={2.8} translation={{ x: 0, y: 400 }} ref={setController}>
318
+ <Globe.Viewport classNames='h-[400px]'>
319
+ <Globe.Canvas topology={topology} styles={defaultStyles} />
320
+ <Globe.Zoom onAction={handleAction} />
321
+ </Globe.Viewport>
260
322
  </Globe.Root>
261
323
  </div>
262
324
  );
@@ -266,55 +328,112 @@ const monochrome: StyleSet = {
266
328
  water: {
267
329
  fillStyle: '#191919',
268
330
  },
269
-
270
331
  land: {
271
332
  fillStyle: '#444',
272
333
  strokeStyle: '#222',
273
334
  },
274
-
275
335
  border: {
276
336
  strokeStyle: '#111',
277
337
  },
278
-
279
338
  graticule: {
280
339
  strokeStyle: '#111',
281
340
  },
282
341
  };
283
342
 
284
343
  export const Mercator = () => {
285
- const [topology] = useTopology();
344
+ const topology = useTopology();
286
345
  const [controller, setController] = useState<GlobeController | null>();
287
346
  const handleAction = useGlobeZoomHandler(controller);
288
347
  useDrag(controller);
348
+ useWheel(controller);
289
349
 
290
350
  return (
291
- <Globe.Root classNames='flex grow overflow-hidden' zoom={0.7} rotation={initialRotation}>
292
- <Globe.Canvas ref={setController} topology={topology} projection='mercator' styles={monochrome} />
293
- <Globe.Zoom onAction={handleAction} />
351
+ <Globe.Root zoom={0.7} rotation={initialRotation} ref={setController}>
352
+ <Globe.Viewport>
353
+ <Globe.Canvas topology={topology} projection='mercator' styles={monochrome} />
354
+ <Globe.Zoom onAction={handleAction} />
355
+ </Globe.Viewport>
294
356
  </Globe.Root>
295
357
  );
296
358
  };
297
359
 
298
- export const Globe1 = () => {
299
- return <Story drag projection='mercator' zoom={0.8} rotation={initialRotation} styles={defaultStyles} />;
360
+ type Story = StoryObj<typeof DefaultStory>;
361
+
362
+ export const Globe1: Story = {
363
+ args: {
364
+ drag: true,
365
+ wheel: true,
366
+ projection: 'mercator',
367
+ zoom: 0.8,
368
+ rotation: initialRotation,
369
+ styles: defaultStyles,
370
+ },
371
+ };
372
+
373
+ export const Globe2: Story = {
374
+ args: {
375
+ drag: true,
376
+ wheel: true,
377
+ projection: 'transverse-mercator',
378
+ zoom: 0.8,
379
+ rotation: initialRotation,
380
+ styles: defaultStyles,
381
+ },
300
382
  };
301
383
 
302
- export const Globe2 = () => {
303
- return <Story drag projection='transverse-mercator' zoom={0.8} rotation={initialRotation} styles={defaultStyles} />;
384
+ export const Globe3: Story = {
385
+ args: {
386
+ drag: true,
387
+ wheel: true,
388
+ spin: true,
389
+ zoom: 1.5,
390
+ rotation: initialRotation,
391
+ styles: defaultStyles,
392
+ },
304
393
  };
305
394
 
306
- export const Globe3 = () => {
307
- return <Story drag spin zoom={1.5} rotation={initialRotation} styles={defaultStyles} />;
395
+ export const Globe4: Story = {
396
+ args: {
397
+ drag: true,
398
+ wheel: true,
399
+ tour: true,
400
+ zoom: 2,
401
+ rotation: initialRotation,
402
+ styles: defaultStyles,
403
+ },
308
404
  };
309
405
 
310
- export const Globe4 = () => {
311
- return <Story drag tour zoom={2} rotation={initialRotation} styles={defaultStyles} />;
406
+ export const Globe5: Story = {
407
+ args: {
408
+ drag: true,
409
+ wheel: true,
410
+ tour: true,
411
+ zoom: 0.9,
412
+ rotation: initialRotation,
413
+ styles: dotStyles,
414
+ },
312
415
  };
313
416
 
314
- export const Globe5 = () => {
315
- return <Story drag tour zoom={0.9} rotation={initialRotation} styles={dotStyles} />;
417
+ export const Globe6: Story = {
418
+ args: {
419
+ drag: true,
420
+ wheel: true,
421
+ lockTilt: true,
422
+ tour: true,
423
+ zoom: 2,
424
+ translation: { x: 0, y: 600 },
425
+ rotation: [0, -20, 0],
426
+ styles: dotStyles,
427
+ },
316
428
  };
317
429
 
318
- export const Globe6 = () => {
319
- return <Story drag xAxis tour zoom={2} translation={{ x: 0, y: 600 }} rotation={[0, -20, 0]} styles={dotStyles} />;
430
+ export const VersorDrag: Story = {
431
+ args: {
432
+ drag: true,
433
+ wheel: true,
434
+ mode: 'versor',
435
+ zoom: 1.5,
436
+ rotation: initialRotation,
437
+ styles: defaultStyles,
438
+ },
320
439
  };