@dxos/react-ui-geo 0.8.4-staging.ac66bdf99f → 0.9.0

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 (120) 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 +774 -223
  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 +774 -223
  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 +18 -10
  45. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
  46. package/dist/types/src/components/Globe/Globe.stories.d.ts +16 -8
  47. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  48. package/dist/types/src/components/Map/Map.d.ts +49 -13
  49. package/dist/types/src/components/Map/Map.d.ts.map +1 -1
  50. package/dist/types/src/components/Map/Map.stories.d.ts +9 -5
  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 +37 -0
  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 -2
  76. package/dist/types/src/index.d.ts.map +1 -1
  77. package/dist/types/src/translations.d.ts +4 -4
  78. package/dist/types/src/translations.d.ts.map +1 -1
  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 +26 -24
  92. package/src/components/Globe/Globe.stories.tsx +135 -58
  93. package/src/components/Globe/Globe.tsx +237 -120
  94. package/src/components/Map/Map.stories.tsx +58 -12
  95. package/src/components/Map/Map.tsx +293 -91
  96. package/src/components/Toolbar/Controls.tsx +1 -1
  97. package/src/data.ts +19 -2
  98. package/src/hooks/context.tsx +44 -0
  99. package/src/hooks/index.ts +3 -0
  100. package/src/hooks/useDrag.ts +33 -5
  101. package/src/hooks/useGlobeZoomHandler.ts +2 -1
  102. package/src/hooks/useSimplifiedTopology.ts +81 -0
  103. package/src/hooks/useSpinner.ts +1 -1
  104. package/src/hooks/useTopology.ts +95 -0
  105. package/src/hooks/useTour.ts +70 -81
  106. package/src/hooks/useWheel.ts +83 -0
  107. package/src/index.ts +0 -2
  108. package/src/util/animation.ts +35 -0
  109. package/src/util/index.ts +2 -0
  110. package/src/util/inertia.ts +87 -4
  111. package/src/util/render.ts +105 -16
  112. package/src/util/styles.ts +62 -0
  113. package/dist/lib/browser/chunk-GMWLKTLN.mjs +0 -9
  114. package/dist/lib/browser/chunk-GMWLKTLN.mjs.map +0 -7
  115. package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs +0 -37859
  116. package/dist/lib/browser/countries-110m-ZM3ZIEFS.mjs.map +0 -7
  117. package/dist/lib/node-esm/chunk-JODBF4CC.mjs +0 -11
  118. package/dist/lib/node-esm/chunk-JODBF4CC.mjs.map +0 -7
  119. package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs +0 -37861
  120. package/dist/lib/node-esm/countries-110m-3SFASWVD.mjs.map +0 -7
@@ -28,14 +28,20 @@ export const geoInertiaDrag = (target, render, projection, options) => {
28
28
  }
29
29
  target = select(target);
30
30
 
31
- // Complete params: (projection, render, startDrag, dragging, endDrag).
32
- const inertia = geoInertiaDragHelper({
31
+ // `linear` (default) constrains rotation so that mouse Δx maps to lambda
32
+ // (polar spin) and Δy maps to phi (tilt); gamma is held at 0.
33
+ // `versor` lets the dragged point follow the cursor exactly, at the cost of
34
+ // inducing some roll. In linear mode `lockTilt` keeps phi pinned but still
35
+ // allows lambda from Δx.
36
+ const linear = (options.mode ?? 'linear') === 'linear';
37
+ const axis = restrictAxis(options.lockTilt ? [true, false, false] : [true, true, true]);
38
+ const sharedHandlers = {
33
39
  projection,
34
40
  render: (rotation) => {
35
41
  projection.rotate(rotation);
36
42
  render && render();
37
43
  },
38
- axis: restrictAxis(options.xAxis ? [true, false, false] : [true, true, true]),
44
+ axis,
39
45
  start: options.start,
40
46
  move: options.move,
41
47
  end: options.end,
@@ -43,7 +49,16 @@ export const geoInertiaDrag = (target, render, projection, options) => {
43
49
  finish: options.finish,
44
50
  time: options.time,
45
51
  hold: options.hold,
46
- });
52
+ };
53
+
54
+ // Complete params: (projection, render, startDrag, dragging, endDrag).
55
+ const inertia = linear
56
+ ? geoInertiaDragLinearHelper({
57
+ ...sharedHandlers,
58
+ sensitivity: options.sensitivity,
59
+ getZoom: options.getZoom,
60
+ })
61
+ : geoInertiaDragHelper(sharedHandlers);
47
62
 
48
63
  target.call(drag().on('start', inertia.start).on('drag', inertia.move).on('end', inertia.end));
49
64
  return inertia;
@@ -112,6 +127,74 @@ const geoInertiaDragHelper = (opt) => {
112
127
  return inertia;
113
128
  };
114
129
 
130
+ /**
131
+ * Linear pixel-to-Euler drag: Δx → lambda, Δy → phi, gamma fixed at 0.
132
+ * Inertia spin-down reuses the same shared decay curve as the versor path.
133
+ */
134
+ const DEFAULT_LINEAR_SENSITIVITY = 0.25;
135
+
136
+ const geoInertiaDragLinearHelper = (opt) => {
137
+ const projection = opt.projection;
138
+ const sensitivity = opt.sensitivity ?? DEFAULT_LINEAR_SENSITIVITY;
139
+ // Scale degrees-per-pixel by 1/zoom so the drag feels consistent at any zoom
140
+ // level (mirrors useWheel — a more zoomed-in globe needs smaller angular
141
+ // rotation per pixel of cursor travel). Clamped to a floor so very small
142
+ // zoom values don't blow up the gain.
143
+ const gain = () => sensitivity / Math.max(opt.getZoom?.() ?? 1, 0.1);
144
+
145
+ let r0; // Projection rotation as Euler angles at start of drag.
146
+ let p0; // Pointer pixel position at start of drag.
147
+ let kStart; // Gain captured at start of drag (held for the gesture + inertia).
148
+ let rEnd; // Projection rotation at end of drag.
149
+ let vEnd; // Pointer velocity (px/s) at end of drag.
150
+
151
+ const inertia = inertiaHelper({
152
+ axis: opt.axis,
153
+
154
+ start: () => {
155
+ r0 = projection.rotate();
156
+ p0 = [inertia.position[0], inertia.position[1]];
157
+ // Lock the gain at gesture start so a zoom change mid-gesture doesn't
158
+ // teleport the globe; inertia continues at the same gain.
159
+ kStart = gain();
160
+ opt.start && opt.start();
161
+ },
162
+
163
+ move: () => {
164
+ const dx = inertia.position[0] - p0[0];
165
+ const dy = inertia.position[1] - p0[1];
166
+ // Screen y grows downward; negate so dragging down rotates the globe to
167
+ // match the cursor (matches the feel of the versor-based path).
168
+ const r1 = [r0[0] + dx * kStart, r0[1] - dy * kStart, 0];
169
+ const r2 = opt.axis(r0, r1);
170
+ opt.render(r2);
171
+ opt.move && opt.move();
172
+ },
173
+
174
+ end: () => {
175
+ rEnd = projection.rotate();
176
+ vEnd = [inertia.velocity[0], inertia.velocity[1]];
177
+ opt.end && opt.end();
178
+ },
179
+
180
+ stop: opt.stop,
181
+
182
+ finish: opt.finish,
183
+
184
+ render: (t) => {
185
+ // t goes 0→1 along the decay curve; at t=1 we've added ~1s of velocity.
186
+ // dy sign flipped to match the move handler.
187
+ const r1 = [rEnd[0] + vEnd[0] * kStart * t, rEnd[1] - vEnd[1] * kStart * t, 0];
188
+ const r2 = opt.axis(rEnd, r1);
189
+ opt.render && opt.render(r2);
190
+ },
191
+
192
+ time: opt.time,
193
+ });
194
+
195
+ return inertia;
196
+ };
197
+
115
198
  function inertiaHelper(opt) {
116
199
  const A = opt.time || 5_000; // Reference time in ms.
117
200
  const limit = 1.0001;
@@ -2,7 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import { type GeoPath, type GeoPermissibleObjects, geoGraticule } from 'd3';
5
+ import { type GeoPath, type GeoPermissibleObjects, geoBounds, geoCentroid, geoDistance, geoGraticule } from 'd3';
6
+ import { type Feature, type Geometry } from 'geojson';
6
7
  import { feature, mesh } from 'topojson-client';
7
8
  import { type Topology } from 'topojson-specification';
8
9
 
@@ -30,9 +31,57 @@ export type Features = {
30
31
  lines?: { source: LatLngLiteral; target: LatLngLiteral }[];
31
32
  };
32
33
 
34
+ /**
35
+ * Per-feature bounding circle used for view-frustum culling on an
36
+ * orthographic globe. `centroid` is in lon/lat degrees and `radius` is the
37
+ * angular distance (degrees) from the centroid to the farthest sampled
38
+ * vertex of the feature.
39
+ */
40
+ export type FeatureBounds = {
41
+ geometry: Geometry;
42
+ centroid: [number, number];
43
+ radius: number;
44
+ };
45
+
33
46
  export type Layer = {
34
47
  styles: Styles;
35
48
  path: GeoPermissibleObjects;
49
+ /**
50
+ * If present, this layer is treated as a `GeometryCollection` whose
51
+ * member geometries are filtered per-frame by `viewCenter` against each
52
+ * member's `FeatureBounds`. `path` becomes the *unculled* fallback used
53
+ * when no `viewCenter` is supplied (e.g. non-orthographic projections).
54
+ */
55
+ cullable?: FeatureBounds[];
56
+ };
57
+
58
+ const RAD_TO_DEG = 180 / Math.PI;
59
+
60
+ /**
61
+ * Compute a spherical bounding circle for a GeoJSON feature. We sample the
62
+ * geoBounds corners (cheap, sufficient for typical country shapes); for
63
+ * features crossing the antimeridian d3.geoBounds returns west > east, which
64
+ * geoDistance handles correctly when called on the actual centroid.
65
+ */
66
+ const computeBounds = (geometry: Geometry): FeatureBounds => {
67
+ const feat: Feature = { type: 'Feature', geometry, properties: {} };
68
+ const centroid = geoCentroid(feat) as [number, number];
69
+ const [[w, s], [e, n]] = geoBounds(feat);
70
+ // Sample the four bbox corners; widest is the bounding radius.
71
+ const corners: Array<[number, number]> = [
72
+ [w, s],
73
+ [w, n],
74
+ [e, s],
75
+ [e, n],
76
+ ];
77
+ let radius = 0;
78
+ for (const corner of corners) {
79
+ const d = geoDistance(centroid, corner) * RAD_TO_DEG;
80
+ if (d > radius) {
81
+ radius = d;
82
+ }
83
+ }
84
+ return { geometry, centroid, radius };
36
85
  };
37
86
 
38
87
  /**
@@ -62,11 +111,25 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
62
111
  //
63
112
 
64
113
  if (topology) {
65
- if (topology.objects.land && styles.land) {
66
- layers.push({
67
- styles: styles.land,
68
- path: feature(topology, topology.objects.land),
69
- });
114
+ if (styles.land) {
115
+ // Prefer the `countries` GeometryCollection over the merged `land`
116
+ // multipolygon so each country can be culled independently. Visually
117
+ // identical (countries collectively tile the land surface).
118
+ if (topology.objects.countries) {
119
+ const fc = feature(topology, topology.objects.countries) as any;
120
+ const memberGeoms: Geometry[] = fc.features.map((f: Feature) => f.geometry);
121
+ const bounds = memberGeoms.map(computeBounds);
122
+ layers.push({
123
+ styles: styles.land,
124
+ path: { type: 'GeometryCollection', geometries: memberGeoms } as any,
125
+ cullable: bounds,
126
+ });
127
+ } else if (topology.objects.land) {
128
+ layers.push({
129
+ styles: styles.land,
130
+ path: feature(topology, topology.objects.land),
131
+ });
132
+ }
70
133
  }
71
134
 
72
135
  if (topology.objects.countries && styles.border) {
@@ -91,22 +154,24 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
91
154
  if (features) {
92
155
  const { points, lines } = features;
93
156
 
94
- if (points && styles.point) {
157
+ // Lines first so points (drawn after) sit on top — the route nodes should
158
+ // never be occluded by an arc that passes through them.
159
+ if (lines && styles.line) {
95
160
  layers.push({
96
- styles: styles.point,
161
+ styles: styles.line,
97
162
  path: {
98
163
  type: 'GeometryCollection',
99
- geometries: points.map((point) => geoPoint(point)),
164
+ geometries: lines.map(({ source, target }) => geoLine(source, target)),
100
165
  },
101
166
  });
102
167
  }
103
168
 
104
- if (lines && styles.line) {
169
+ if (points && styles.point) {
105
170
  layers.push({
106
- styles: styles.line,
171
+ styles: styles.point,
107
172
  path: {
108
173
  type: 'GeometryCollection',
109
- geometries: lines.map(({ source, target }) => geoLine(source, target)),
174
+ geometries: points.map((point) => geoPoint(point)),
110
175
  },
111
176
  });
112
177
  }
@@ -117,8 +182,19 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
117
182
 
118
183
  /**
119
184
  * Render layers created above.
185
+ *
186
+ * When `viewCenter` is supplied (orthographic globe), layers with a
187
+ * `cullable` index are filtered to just the features whose bounding circle
188
+ * intersects the visible hemisphere — keeping the d3-geo walk proportional
189
+ * to what's actually on-screen.
120
190
  */
121
- export const renderLayers = (generator: GeoPath, layers: Layer[] = [], scale: number, styles: StyleSet) => {
191
+ export const renderLayers = (
192
+ generator: GeoPath,
193
+ layers: Layer[] = [],
194
+ scale: number,
195
+ styles: StyleSet,
196
+ viewCenter?: [number, number],
197
+ ) => {
122
198
  const context: CanvasRenderingContext2D = generator.context();
123
199
  const {
124
200
  canvas: { width, height },
@@ -135,7 +211,8 @@ export const renderLayers = (generator: GeoPath, layers: Layer[] = [], scale: nu
135
211
 
136
212
  // Render features.
137
213
  // https://github.com/d3/d3-geo#_path
138
- layers.forEach(({ path, styles }) => {
214
+ layers.forEach((layer) => {
215
+ const { path, styles, cullable } = layer;
139
216
  context.save();
140
217
  let fill = false;
141
218
  let stroke = false;
@@ -151,9 +228,21 @@ export const renderLayers = (generator: GeoPath, layers: Layer[] = [], scale: nu
151
228
  });
152
229
  }
153
230
 
154
- context.beginPath();
231
+ let renderPath = path;
232
+ if (cullable && viewCenter) {
233
+ const geometries: Geometry[] = [];
234
+ for (let index = 0; index < cullable.length; index++) {
235
+ const bounds = cullable[index];
236
+ const angularDistance = geoDistance(viewCenter, bounds.centroid) * RAD_TO_DEG;
237
+ if (angularDistance < 90 + bounds.radius) {
238
+ geometries.push(bounds.geometry);
239
+ }
240
+ }
241
+ renderPath = { type: 'GeometryCollection', geometries } as any;
242
+ }
155
243
 
156
- generator(path);
244
+ context.beginPath();
245
+ generator(renderPath);
157
246
  fill && context.fill();
158
247
  stroke && context.stroke();
159
248
  context.restore();
@@ -0,0 +1,62 @@
1
+ //
2
+ // Copyright 2026 DXOS.org
3
+ //
4
+
5
+ import { type ThemeMode } from '@dxos/react-ui';
6
+
7
+ import { type StyleSet } from './render';
8
+
9
+ /**
10
+ * Default style set for the Globe, theme-aware. Originated in plugin-map's
11
+ * GlobeControl; lifted here so other plugins (plugin-trip, etc.) get the same
12
+ * baseline without copying the palette.
13
+ */
14
+ // Point colour; lines pick up the same colour at reduced alpha so the route
15
+ // reads as belonging to the same node set without competing with the nodes.
16
+ const POINT_COLOR = 'rgb(220, 38, 38)';
17
+ const LINE_COLOR = 'rgba(220, 38, 38, 0.5)';
18
+
19
+ export const globeStyles = (themeMode: ThemeMode): StyleSet =>
20
+ themeMode === 'dark'
21
+ ? {
22
+ water: {
23
+ fillStyle: '#191919',
24
+ },
25
+ land: {
26
+ fillStyle: '#444',
27
+ strokeStyle: '#222',
28
+ },
29
+ border: {
30
+ strokeStyle: '#111',
31
+ },
32
+ graticule: {
33
+ strokeStyle: '#111',
34
+ },
35
+ line: {
36
+ lineWidth: 1.5,
37
+ lineDash: [4, 16],
38
+ strokeStyle: LINE_COLOR,
39
+ },
40
+ point: {
41
+ radius: 0.2,
42
+ fillStyle: POINT_COLOR,
43
+ },
44
+ }
45
+ : {
46
+ water: {
47
+ fillStyle: '#C0DAE4',
48
+ },
49
+ land: {
50
+ fillStyle: '#C2D8B4',
51
+ strokeStyle: '#A6C291',
52
+ },
53
+ line: {
54
+ lineWidth: 1.5,
55
+ lineDash: [4, 16],
56
+ strokeStyle: LINE_COLOR,
57
+ },
58
+ point: {
59
+ radius: 0.2,
60
+ fillStyle: POINT_COLOR,
61
+ },
62
+ };
@@ -1,9 +0,0 @@
1
- // src/data.ts
2
- var loadTopology = async () => {
3
- return (await import("./countries-110m-ZM3ZIEFS.mjs")).default;
4
- };
5
-
6
- export {
7
- loadTopology
8
- };
9
- //# sourceMappingURL=chunk-GMWLKTLN.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/data.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport { type Topology } from 'topojson-specification';\n\nexport const loadTopology = async (): Promise<Topology> => {\n return (await import('../data/countries-110m.ts')).default;\n};\n"],
5
- "mappings": ";AAMO,IAAMA,eAAe,YAAA;AAC1B,UAAQ,MAAM,OAAO,+BAAA,GAA8BC;AACrD;",
6
- "names": ["loadTopology", "default"]
7
- }