@dxos/react-ui-geo 0.8.1 → 0.8.2-main.2f9c567

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/react-ui-geo",
3
- "version": "0.8.1",
3
+ "version": "0.8.2-main.2f9c567",
4
4
  "description": "Geo components.",
5
5
  "homepage": "https://github.com/dxos",
6
6
  "bugs": "https://github.com/dxos/issues",
@@ -45,11 +45,11 @@
45
45
  "topojson-client": "^3.1.0",
46
46
  "topojson-simplify": "^3.0.3",
47
47
  "versor": "^0.2.0",
48
- "@dxos/async": "0.8.1",
49
- "@dxos/debug": "0.8.1",
50
- "@dxos/node-std": "0.8.1",
51
- "@dxos/log": "0.8.1",
52
- "@dxos/util": "0.8.1"
48
+ "@dxos/async": "0.8.2-main.2f9c567",
49
+ "@dxos/debug": "0.8.2-main.2f9c567",
50
+ "@dxos/log": "0.8.2-main.2f9c567",
51
+ "@dxos/util": "0.8.2-main.2f9c567",
52
+ "@dxos/node-std": "0.8.2-main.2f9c567"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@react-three/drei": "^9.99.0",
@@ -69,15 +69,15 @@
69
69
  "react": "~18.2.0",
70
70
  "react-dom": "~18.2.0",
71
71
  "three": "0.165.0",
72
- "@dxos/react-ui": "0.8.1",
73
- "@dxos/storybook-utils": "0.8.1",
74
- "@dxos/react-ui-theme": "0.8.1"
72
+ "@dxos/react-ui": "0.8.2-main.2f9c567",
73
+ "@dxos/react-ui-theme": "0.8.2-main.2f9c567",
74
+ "@dxos/storybook-utils": "0.8.2-main.2f9c567"
75
75
  },
76
76
  "peerDependencies": {
77
77
  "react": "~18.2.0",
78
78
  "react-dom": "~18.2.0",
79
- "@dxos/react-ui-theme": "0.8.1",
80
- "@dxos/react-ui": "0.8.1"
79
+ "@dxos/react-ui": "0.8.2-main.2f9c567",
80
+ "@dxos/react-ui-theme": "0.8.2-main.2f9c567"
81
81
  },
82
82
  "publishConfig": {
83
83
  "access": "public"
@@ -2,8 +2,17 @@
2
2
  // Copyright 2018 DXOS.org
3
3
  //
4
4
 
5
- import * as d3 from 'd3';
6
- import { type GeoProjection } from 'd3';
5
+ import {
6
+ type GeoProjection,
7
+ geoMercator,
8
+ geoOrthographic,
9
+ geoPath,
10
+ geoTransverseMercator,
11
+ interpolateNumber,
12
+ transition,
13
+ easeLinear,
14
+ easeSinOut,
15
+ } from 'd3';
7
16
  import { type ControlPosition } from 'leaflet';
8
17
  import React, {
9
18
  type PropsWithChildren,
@@ -99,18 +108,18 @@ export type GlobeController = {
99
108
  export type ProjectionType = 'orthographic' | 'mercator' | 'transverse-mercator';
100
109
 
101
110
  const projectionMap: Record<ProjectionType, () => GeoProjection> = {
102
- orthographic: d3.geoOrthographic,
103
- mercator: d3.geoMercator,
104
- 'transverse-mercator': d3.geoTransverseMercator,
111
+ orthographic: geoOrthographic,
112
+ mercator: geoMercator,
113
+ 'transverse-mercator': geoTransverseMercator,
105
114
  };
106
115
 
107
116
  const getProjection = (type: GlobeCanvasProps['projection'] = 'orthographic'): GeoProjection => {
108
117
  if (typeof type === 'string') {
109
- const constructor = projectionMap[type] ?? d3.geoOrthographic;
118
+ const constructor = projectionMap[type] ?? geoOrthographic;
110
119
  return constructor();
111
120
  }
112
121
 
113
- return type ?? d3.geoOrthographic();
122
+ return type ?? geoOrthographic();
114
123
  };
115
124
 
116
125
  //
@@ -194,10 +203,10 @@ const GlobeCanvas = forwardRef<GlobeController, GlobeCanvasProps>(
194
203
  setCenter,
195
204
  setScale: (s) => {
196
205
  if (typeof s === 'function') {
197
- const is = d3.interpolateNumber(scaleRef.current, s(scaleRef.current));
206
+ const is = interpolateNumber(scaleRef.current, s(scaleRef.current));
198
207
  // Stop easing if already zooming.
199
- d3.transition()
200
- .ease(zooming.current ? d3.easeLinear : d3.easeSinOut)
208
+ transition()
209
+ .ease(zooming.current ? easeLinear : easeSinOut)
201
210
  .duration(200)
202
211
  .tween('scale', () => (t) => setScale(is(t)))
203
212
  .on('end', () => {
@@ -217,7 +226,7 @@ const GlobeCanvas = forwardRef<GlobeController, GlobeCanvasProps>(
217
226
  // https://d3js.org/d3-geo/path#geoPath
218
227
  // https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
219
228
  const generator = useMemo(
220
- () => canvas && projection && d3.geoPath(projection, canvas.getContext('2d', { alpha: false })),
229
+ () => canvas && projection && geoPath(projection, canvas.getContext('2d', { alpha: false })),
221
230
  [canvas, projection],
222
231
  );
223
232
 
@@ -13,7 +13,7 @@ import { Map, type MapController } from './Map';
13
13
  import { useMapZoomHandler } from '../../hooks';
14
14
  import { type MapMarker } from '../../types';
15
15
 
16
- const Render = ({ markers }) => {
16
+ const DefaultStory = ({ markers = [] }: { markers?: MapMarker[] }) => {
17
17
  const [controller, setController] = useState<MapController>();
18
18
  const handleZoomAction = useMapZoomHandler(controller);
19
19
 
@@ -26,15 +26,15 @@ const Render = ({ markers }) => {
26
26
  );
27
27
  };
28
28
 
29
- const meta: Meta<typeof Render> = {
29
+ const meta: Meta<typeof DefaultStory> = {
30
30
  title: 'ui/react-ui-geo/Map',
31
- component: Render,
31
+ render: DefaultStory,
32
32
  decorators: [withTheme, withLayout({ fullscreen: true, tooltips: true })],
33
33
  };
34
34
 
35
35
  export default meta;
36
36
 
37
- type Story = StoryObj<typeof Render>;
37
+ type Story = StoryObj<typeof DefaultStory>;
38
38
 
39
39
  export const Default: Story = {};
40
40
 
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as d3 from 'd3';
5
+ import { select } from 'd3';
6
6
  import { useEffect } from 'react';
7
7
 
8
8
  import { type GlobeController } from '../components';
@@ -31,7 +31,7 @@ export const useDrag = (controller?: GlobeController | null, options: DragOption
31
31
  }
32
32
 
33
33
  geoInertiaDrag(
34
- d3.select(canvas),
34
+ select(canvas),
35
35
  () => {
36
36
  controller.setRotation(controller.projection.rotate());
37
37
  options.onUpdate?.({ type: 'move', controller });
@@ -47,7 +47,7 @@ export const useDrag = (controller?: GlobeController | null, options: DragOption
47
47
 
48
48
  // TODO(burdon): Cancel drag timer.
49
49
  return () => {
50
- cancelDrag(d3.select(canvas));
50
+ cancelDrag(select(canvas));
51
51
  };
52
52
  }, [controller, JSON.stringify(options)]);
53
53
  };
@@ -2,7 +2,7 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as d3 from 'd3';
5
+ import { timer as d3Timer } from 'd3';
6
6
  import { type Timer } from 'd3';
7
7
  import { useEffect, useState } from 'react';
8
8
 
@@ -27,7 +27,7 @@ export const useSpinner = (controller?: GlobeController | null, options: Spinner
27
27
 
28
28
  let t = 0;
29
29
  let lastRotation = controller.projection.rotate();
30
- timer = d3.timer((elapsed) => {
30
+ timer = d3Timer((elapsed) => {
31
31
  const dt = elapsed - t;
32
32
  t = elapsed;
33
33
 
@@ -2,12 +2,10 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import * as d3 from 'd3';
6
- import { type Dispatch, type SetStateAction, useEffect, useState } from 'react';
5
+ import { geoPath, geoInterpolate, geoDistance, selection as d3Selection } from 'd3';
6
+ import { type SetStateAction, type Dispatch, useEffect, useState, useMemo } from 'react';
7
7
  import versor from 'versor';
8
8
 
9
- import { log } from '@dxos/log';
10
-
11
9
  import type { GlobeController } from '../components';
12
10
  import { geoToPosition, type LatLng, positionToRotation, type StyleSet } from '../util';
13
11
 
@@ -34,7 +32,7 @@ export const useTour = (
34
32
  points?: LatLng[],
35
33
  options: TourOptions = {},
36
34
  ): [boolean, Dispatch<SetStateAction<boolean>>] => {
37
- const selection = d3.selection();
35
+ const selection = useMemo(() => d3Selection(), []);
38
36
  const [running, setRunning] = useState(options.running ?? false);
39
37
  useEffect(() => {
40
38
  if (!running) {
@@ -47,7 +45,7 @@ export const useTour = (
47
45
  t = setTimeout(async () => {
48
46
  const { canvas, projection, setRotation } = controller;
49
47
  const context = canvas.getContext('2d', { alpha: false });
50
- const path = d3.geoPath(projection, context).pointRadius(2);
48
+ const path = geoPath(projection, context).pointRadius(2);
51
49
 
52
50
  const tilt = options.tilt ?? 0;
53
51
  let last: LatLng;
@@ -65,8 +63,8 @@ export const useTour = (
65
63
  // Points.
66
64
  const p1 = last ? geoToPosition(last) : undefined;
67
65
  const p2 = geoToPosition(next);
68
- const ip = d3.geoInterpolate(p1 || p2, p2);
69
- const distance = d3.geoDistance(p1 || p2, p2);
66
+ const ip = geoInterpolate(p1 || p2, p2);
67
+ const distance = geoDistance(p1 || p2, p2);
70
68
 
71
69
  // Rotation.
72
70
  const r1 = p1 ? positionToRotation(p1, tilt) : controller.projection.rotate();
@@ -98,10 +96,8 @@ export const useTour = (
98
96
  context.restore();
99
97
 
100
98
  // TODO(burdon): This has to come after rendering above. Add to features to correct order?
101
- if (options.autoRotate) {
102
- projection.rotate(iv(t));
103
- setRotation(projection.rotate());
104
- }
99
+ projection.rotate(iv(t));
100
+ setRotation(projection.rotate());
105
101
  });
106
102
 
107
103
  // Throws if interrupted.
@@ -109,7 +105,7 @@ export const useTour = (
109
105
  last = next;
110
106
  }
111
107
  } catch (err) {
112
- log.catch(err);
108
+ // Ignore.
113
109
  } finally {
114
110
  setRunning(false);
115
111
  }
@@ -4,7 +4,7 @@
4
4
  // https://github.com/Fil/d3-inertia
5
5
  //
6
6
 
7
- import * as d3 from 'd3';
7
+ import { select, drag, timer } from 'd3';
8
8
  import versor from 'versor';
9
9
 
10
10
  export const restrictAxis =
@@ -26,7 +26,7 @@ export const geoInertiaDrag = (target, render, projection, options) => {
26
26
  if (target.node) {
27
27
  target = target.node();
28
28
  }
29
- target = d3.select(target);
29
+ target = select(target);
30
30
 
31
31
  // Complete params: (projection, render, startDrag, dragging, endDrag).
32
32
  const inertia = geoInertiaDragHelper({
@@ -45,7 +45,7 @@ export const geoInertiaDrag = (target, render, projection, options) => {
45
45
  hold: options.hold,
46
46
  });
47
47
 
48
- target.call(d3.drag().on('start', inertia.start).on('drag', inertia.move).on('end', inertia.end));
48
+ target.call(drag().on('start', inertia.start).on('drag', inertia.move).on('end', inertia.end));
49
49
  return inertia;
50
50
  };
51
51
 
@@ -119,7 +119,7 @@ function inertiaHelper(opt) {
119
119
  const inertia = {
120
120
  position: [0, 0],
121
121
  velocity: [0, 0], // Velocity in pixels/s.
122
- timer: d3.timer(() => {}),
122
+ timer: timer(() => {}),
123
123
  time: 0,
124
124
  t: 0,
125
125
 
@@ -135,7 +135,6 @@ function inertiaHelper(opt) {
135
135
 
136
136
  move: function (ev) {
137
137
  const position = [ev.x, ev.y];
138
-
139
138
  const time = performance.now();
140
139
  const deltaTime = time - inertia.time;
141
140
  const decay = 1 - Math.exp(-deltaTime / 1_000);
package/src/util/path.ts CHANGED
@@ -2,16 +2,13 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import * as d3 from 'd3';
6
- import { type GeoGeometryObjects } from 'd3';
5
+ import { type GeoGeometryObjects, geoCircle as d3GeoCircle } from 'd3';
7
6
  import { type Point, type Polygon, type Position } from 'geojson';
8
7
 
9
8
  import type { Vector } from '../hooks';
10
9
 
11
10
  export type LatLng = { lat: number; lng: number };
12
11
 
13
- // TODO(burdon): Clean-up.
14
-
15
12
  export const positionToRotation = ([lng, lat]: [number, number], tilt = 0): Vector => [-lng, tilt - lat, 0];
16
13
 
17
14
  export const geoToPosition = ({ lat, lng }: LatLng): [number, number] => [lng, lat];
@@ -20,7 +17,7 @@ export const geoPoint = (point: LatLng): Point => ({ type: 'Point', coordinates:
20
17
 
21
18
  // https://github.com/d3/d3-geo#geoCircle
22
19
  export const geoCircle = ({ lat, lng }: LatLng, radius: number): Polygon =>
23
- d3.geoCircle().radius(radius).center([lng, lat])();
20
+ d3GeoCircle().radius(radius).center([lng, lat])();
24
21
 
25
22
  export const geoLine = (p1: LatLng, p2: LatLng): GeoGeometryObjects => ({
26
23
  type: 'LineString',
@@ -2,9 +2,8 @@
2
2
  // Copyright 2020 DXOS.org
3
3
  //
4
4
 
5
- import * as d3 from 'd3';
6
- import { type GeoPath, type GeoPermissibleObjects } from 'd3';
7
- import * as topojson from 'topojson-client';
5
+ import { type GeoPath, type GeoPermissibleObjects, geoGraticule } from 'd3';
6
+ import { feature, mesh } from 'topojson-client';
8
7
  import { type Topology } from 'topojson-specification';
9
8
 
10
9
  import { type LatLng, geoLine, geoPoint } from './path';
@@ -53,7 +52,7 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
53
52
  if (styles.graticule) {
54
53
  layers.push({
55
54
  styles: styles.graticule,
56
- path: d3.geoGraticule().step([6, 6])(),
55
+ path: geoGraticule().step([6, 6])(),
57
56
  });
58
57
  }
59
58
 
@@ -65,14 +64,14 @@ export const createLayers = (topology: Topology, features: Features, styles: Sty
65
64
  if (topology.objects.land && styles.land) {
66
65
  layers.push({
67
66
  styles: styles.land,
68
- path: topojson.feature(topology, topology.objects.land),
67
+ path: feature(topology, topology.objects.land),
69
68
  });
70
69
  }
71
70
 
72
71
  if (topology.objects.countries && styles.border) {
73
72
  layers.push({
74
73
  styles: styles.border,
75
- path: topojson.mesh(topology, topology.objects.countries, (a: any, b: any) => a !== b),
74
+ path: mesh(topology, topology.objects.countries, (a: any, b: any) => a !== b),
76
75
  });
77
76
  }
78
77