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

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 (100) hide show
  1. package/data/airports.ts +1 -1
  2. package/data/cities.ts +1 -1
  3. package/data/countries-110m.ts +1 -1
  4. package/data/countries-dots-3.ts +1 -1
  5. package/data/countries-dots-4.ts +1 -1
  6. package/dist/lib/browser/{countries-110m-WI4PCLDF.mjs → countries-110m-RE5RNRQG.mjs} +2 -2
  7. package/dist/lib/browser/countries-110m-RE5RNRQG.mjs.map +7 -0
  8. package/dist/lib/browser/data.mjs +4 -3
  9. package/dist/lib/browser/data.mjs.map +4 -4
  10. package/dist/lib/browser/index.mjs +396 -466
  11. package/dist/lib/browser/index.mjs.map +3 -3
  12. package/dist/lib/browser/meta.json +1 -1
  13. package/dist/lib/browser/translations.mjs +19 -0
  14. package/dist/lib/browser/translations.mjs.map +7 -0
  15. package/dist/lib/node-esm/{countries-110m-DQ4XRC4B.mjs → countries-110m-4EDBXSFJ.mjs} +2 -2
  16. package/dist/lib/node-esm/countries-110m-4EDBXSFJ.mjs.map +7 -0
  17. package/dist/lib/node-esm/data.mjs +5 -3
  18. package/dist/lib/node-esm/data.mjs.map +4 -4
  19. package/dist/lib/node-esm/index.mjs +396 -465
  20. package/dist/lib/node-esm/index.mjs.map +3 -3
  21. package/dist/lib/node-esm/meta.json +1 -1
  22. package/dist/lib/node-esm/translations.mjs +21 -0
  23. package/dist/lib/node-esm/translations.mjs.map +7 -0
  24. package/dist/types/data/airports.d.ts +4 -4
  25. package/dist/types/data/airports.d.ts.map +1 -1
  26. package/dist/types/data/cities.d.ts.map +1 -1
  27. package/dist/types/data/countries-110m.d.ts.map +1 -1
  28. package/dist/types/data/countries-dots-3.d.ts.map +1 -1
  29. package/dist/types/data/countries-dots-4.d.ts.map +1 -1
  30. package/dist/types/src/components/Globe/Globe.d.ts +6 -4
  31. package/dist/types/src/components/Globe/Globe.d.ts.map +1 -1
  32. package/dist/types/src/components/Globe/Globe.stories.d.ts +27 -9
  33. package/dist/types/src/components/Globe/Globe.stories.d.ts.map +1 -1
  34. package/dist/types/src/components/Map/Map.d.ts +42 -18
  35. package/dist/types/src/components/Map/Map.d.ts.map +1 -1
  36. package/dist/types/src/components/Map/Map.stories.d.ts +14 -8
  37. package/dist/types/src/components/Map/Map.stories.d.ts.map +1 -1
  38. package/dist/types/src/components/Toolbar/Controls.d.ts.map +1 -1
  39. package/dist/types/src/components/index.d.ts +0 -1
  40. package/dist/types/src/components/index.d.ts.map +1 -1
  41. package/dist/types/src/hooks/context.d.ts +6 -8
  42. package/dist/types/src/hooks/context.d.ts.map +1 -1
  43. package/dist/types/src/hooks/useDrag.d.ts.map +1 -1
  44. package/dist/types/src/hooks/useGlobeZoomHandler.d.ts +2 -2
  45. package/dist/types/src/hooks/useGlobeZoomHandler.d.ts.map +1 -1
  46. package/dist/types/src/hooks/useMapZoomHandler.d.ts +2 -2
  47. package/dist/types/src/hooks/useMapZoomHandler.d.ts.map +1 -1
  48. package/dist/types/src/hooks/useSpinner.d.ts +1 -1
  49. package/dist/types/src/hooks/useSpinner.d.ts.map +1 -1
  50. package/dist/types/src/hooks/useTour.d.ts +4 -3
  51. package/dist/types/src/hooks/useTour.d.ts.map +1 -1
  52. package/dist/types/src/index.d.ts +1 -2
  53. package/dist/types/src/index.d.ts.map +1 -1
  54. package/dist/types/src/translations.d.ts +12 -0
  55. package/dist/types/src/translations.d.ts.map +1 -0
  56. package/dist/types/src/types.d.ts +2 -1
  57. package/dist/types/src/types.d.ts.map +1 -1
  58. package/dist/types/src/util/debug.d.ts.map +1 -1
  59. package/dist/types/src/util/inertia.d.ts.map +1 -1
  60. package/dist/types/src/util/path.d.ts +5 -8
  61. package/dist/types/src/util/path.d.ts.map +1 -1
  62. package/dist/types/src/util/render.d.ts +4 -4
  63. package/dist/types/src/util/render.d.ts.map +1 -1
  64. package/dist/types/tsconfig.tsbuildinfo +1 -1
  65. package/package.json +43 -34
  66. package/src/components/Globe/Globe.stories.tsx +85 -38
  67. package/src/components/Globe/Globe.tsx +124 -81
  68. package/src/components/Map/Map.stories.tsx +27 -15
  69. package/src/components/Map/Map.tsx +220 -94
  70. package/src/components/Toolbar/Controls.tsx +14 -20
  71. package/src/components/index.ts +0 -2
  72. package/src/hooks/context.tsx +11 -34
  73. package/src/hooks/useGlobeZoomHandler.ts +9 -3
  74. package/src/hooks/useMapZoomHandler.ts +1 -1
  75. package/src/hooks/useSpinner.ts +1 -1
  76. package/src/hooks/useTour.ts +10 -8
  77. package/src/index.ts +1 -2
  78. package/src/translations.ts +20 -0
  79. package/src/types.ts +3 -1
  80. package/src/util/inertia.ts +1 -1
  81. package/src/util/path.ts +5 -6
  82. package/src/util/render.ts +4 -3
  83. package/dist/lib/browser/chunk-ENCWOTYX.mjs +0 -9
  84. package/dist/lib/browser/chunk-ENCWOTYX.mjs.map +0 -7
  85. package/dist/lib/browser/countries-110m-WI4PCLDF.mjs.map +0 -7
  86. package/dist/lib/node/chunk-LAICG6L2.cjs +0 -40
  87. package/dist/lib/node/chunk-LAICG6L2.cjs.map +0 -7
  88. package/dist/lib/node/countries-110m-KQ5WAB2O.cjs +0 -37877
  89. package/dist/lib/node/countries-110m-KQ5WAB2O.cjs.map +0 -7
  90. package/dist/lib/node/data.cjs +0 -28
  91. package/dist/lib/node/data.cjs.map +0 -7
  92. package/dist/lib/node/index.cjs +0 -1187
  93. package/dist/lib/node/index.cjs.map +0 -7
  94. package/dist/lib/node/meta.json +0 -1
  95. package/dist/lib/node-esm/chunk-PIIEDZEU.mjs +0 -11
  96. package/dist/lib/node-esm/chunk-PIIEDZEU.mjs.map +0 -7
  97. package/dist/lib/node-esm/countries-110m-DQ4XRC4B.mjs.map +0 -7
  98. package/dist/types/src/components/types.d.ts +0 -15
  99. package/dist/types/src/components/types.d.ts.map +0 -1
  100. package/src/components/types.ts +0 -19
@@ -4,14 +4,14 @@
4
4
 
5
5
  import {
6
6
  type GeoProjection,
7
+ easeLinear,
8
+ easeSinOut,
7
9
  geoMercator,
8
10
  geoOrthographic,
9
11
  geoPath,
10
12
  geoTransverseMercator,
11
13
  interpolateNumber,
12
14
  transition,
13
- easeLinear,
14
- easeSinOut,
15
15
  } from 'd3';
16
16
  import { type ControlPosition } from 'leaflet';
17
17
  import React, {
@@ -26,15 +26,17 @@ import React, {
26
26
  import { useResizeDetector } from 'react-resize-detector';
27
27
  import { type Topology } from 'topojson-specification';
28
28
 
29
- import { type ThemedClassName, type ThemeMode, useDynamicRef, useThemeContext } from '@dxos/react-ui';
30
- import { mx } from '@dxos/react-ui-theme';
31
-
32
29
  import {
33
- GlobeContextProvider,
34
- type GlobeContextProviderProps,
35
- type GlobeContextType,
36
- useGlobeContext,
37
- } from '../../hooks';
30
+ type ThemeMode,
31
+ type ThemedClassName,
32
+ useComposedRefs,
33
+ useControlledState,
34
+ useDynamicRef,
35
+ useThemeContext,
36
+ } from '@dxos/react-ui';
37
+ import { composable, composableProps, mx } from '@dxos/ui-theme';
38
+
39
+ import { GlobeContext, type GlobeContextType, type Point, type Vector, useGlobeContext } from '../../hooks';
38
40
  import {
39
41
  type Features,
40
42
  type StyleSet,
@@ -44,7 +46,7 @@ import {
44
46
  renderLayers,
45
47
  timer,
46
48
  } from '../../util';
47
- import { ZoomControls, ActionControls, type ControlProps, controlPositions } from '../Toolbar';
49
+ import { ActionControls, type ControlProps, ZoomControls, controlPositions } from '../Toolbar';
48
50
 
49
51
  /**
50
52
  * https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute
@@ -103,7 +105,7 @@ const defaultStyles: Record<ThemeMode, StyleSet> = {
103
105
  export type GlobeController = {
104
106
  canvas: HTMLCanvasElement;
105
107
  projection: GeoProjection;
106
- } & Pick<GlobeContextType, 'scale' | 'translation' | 'rotation' | 'setScale' | 'setTranslation' | 'setRotation'>;
108
+ } & Pick<GlobeContextType, 'zoom' | 'translation' | 'rotation' | 'setZoom' | 'setTranslation' | 'setRotation'>;
107
109
 
108
110
  export type ProjectionType = 'orthographic' | 'mercator' | 'transverse-mercator';
109
111
 
@@ -126,18 +128,43 @@ const getProjection = (type: GlobeCanvasProps['projection'] = 'orthographic'): G
126
128
  // Root
127
129
  //
128
130
 
129
- type GlobeRootProps = PropsWithChildren<ThemedClassName<GlobeContextProviderProps>>;
130
-
131
- const GlobeRoot = ({ classNames, children, ...props }: GlobeRootProps) => {
132
- const { ref, width, height } = useResizeDetector<HTMLDivElement>();
133
- return (
134
- <div ref={ref} className={mx('relative flex grow overflow-hidden', classNames)}>
135
- <GlobeContextProvider size={{ width, height }} {...props}>
136
- {children}
137
- </GlobeContextProvider>
138
- </div>
139
- );
140
- };
131
+ type GlobeRootProps = Partial<Pick<GlobeContextType, 'center' | 'zoom' | 'translation' | 'rotation'>>;
132
+
133
+ const GlobeRoot = composable<HTMLDivElement, GlobeRootProps>(
134
+ (
135
+ { children, center: centerProp, zoom: zoomProp, translation: translationProp, rotation: rotationProp, ...props },
136
+ forwardedRef,
137
+ ) => {
138
+ const localRef = useRef<HTMLDivElement>(null);
139
+ const composedRef = useComposedRefs<HTMLDivElement>(localRef, forwardedRef);
140
+ const { width, height } = useResizeDetector<HTMLDivElement>({ targetRef: localRef });
141
+
142
+ const [center, setCenter] = useControlledState(centerProp);
143
+ const [zoom, setZoom] = useControlledState(zoomProp ?? 4);
144
+ const [translation, setTranslation] = useControlledState<Point>(translationProp);
145
+ const [rotation, setRotation] = useControlledState<Vector>(rotationProp);
146
+
147
+ return (
148
+ <GlobeContext.Provider
149
+ value={{
150
+ size: { width, height },
151
+ center,
152
+ zoom,
153
+ translation,
154
+ rotation,
155
+ setCenter,
156
+ setZoom,
157
+ setTranslation,
158
+ setRotation,
159
+ }}
160
+ >
161
+ <div {...composableProps(props, { classNames: 'relative dx-container' })} ref={composedRef}>
162
+ {children}
163
+ </div>
164
+ </GlobeContext.Provider>
165
+ );
166
+ },
167
+ );
141
168
 
142
169
  //
143
170
  // Canvas
@@ -154,17 +181,18 @@ type GlobeCanvasProps = {
154
181
  * Basic globe renderer.
155
182
  * https://github.com/topojson/world-atlas
156
183
  */
184
+ // TODO(burdon): Move controller to root.
157
185
  const GlobeCanvas = forwardRef<GlobeController, GlobeCanvasProps>(
158
- ({ projection: _projection, topology, features, styles: _styles }, forwardRef) => {
186
+ ({ projection: projectionProp, topology, features, styles: stylesProp }, forwardRef) => {
159
187
  const { themeMode } = useThemeContext();
160
- const styles = useMemo(() => _styles ?? defaultStyles[themeMode], [_styles, themeMode]);
188
+ const styles = useMemo(() => stylesProp ?? defaultStyles[themeMode], [stylesProp, themeMode]);
161
189
 
162
190
  // Canvas.
163
191
  const [canvas, setCanvas] = useState<HTMLCanvasElement>(null);
164
192
  const canvasRef = (canvas: HTMLCanvasElement) => setCanvas(canvas);
165
193
 
166
194
  // Projection.
167
- const projection = useMemo(() => getProjection(_projection), [_projection]);
195
+ const projection = useMemo(() => getProjection(projectionProp), [projectionProp]);
168
196
 
169
197
  // Layers.
170
198
  // TODO(burdon): Generate on the fly based on what is visible.
@@ -173,55 +201,50 @@ const GlobeCanvas = forwardRef<GlobeController, GlobeCanvasProps>(
173
201
  }, [topology, features, styles]);
174
202
 
175
203
  // State.
176
- const { size, center, scale, translation, rotation, setCenter, setScale, setTranslation, setRotation } =
204
+ const { size, center, zoom, translation, rotation, setCenter, setZoom, setTranslation, setRotation } =
177
205
  useGlobeContext();
178
-
179
- const scaleRef = useDynamicRef(scale);
206
+ const zoomRef = useDynamicRef(zoom);
180
207
 
181
208
  // Update rotation.
182
209
  useEffect(() => {
183
210
  if (center) {
184
- setScale(1);
211
+ setZoom(1);
185
212
  setRotation(positionToRotation(geoToPosition(center)));
186
213
  }
187
214
  }, [center]);
188
215
 
189
216
  // External controller.
190
217
  const zooming = useRef(false);
191
- useImperativeHandle<GlobeController, GlobeController>(
192
- forwardRef,
193
- () => {
194
- return {
195
- canvas,
196
- projection,
197
- center,
198
- get scale() {
199
- return scaleRef.current;
200
- },
201
- translation,
202
- rotation,
203
- setCenter,
204
- setScale: (s) => {
205
- if (typeof s === 'function') {
206
- const is = interpolateNumber(scaleRef.current, s(scaleRef.current));
207
- // Stop easing if already zooming.
208
- transition()
209
- .ease(zooming.current ? easeLinear : easeSinOut)
210
- .duration(200)
211
- .tween('scale', () => (t) => setScale(is(t)))
212
- .on('end', () => {
213
- zooming.current = false;
214
- });
215
- } else {
216
- setScale(s);
217
- }
218
- },
219
- setTranslation,
220
- setRotation,
221
- };
222
- },
223
- [canvas],
224
- );
218
+ useImperativeHandle<GlobeController, GlobeController>(forwardRef, () => {
219
+ return {
220
+ canvas,
221
+ projection,
222
+ center,
223
+ get zoom() {
224
+ return zoomRef.current;
225
+ },
226
+ translation,
227
+ rotation,
228
+ setCenter,
229
+ setZoom: (state) => {
230
+ if (typeof state === 'function') {
231
+ const is = interpolateNumber(zoomRef.current, state(zoomRef.current));
232
+ // Stop easing if already zooming.
233
+ transition()
234
+ .ease(zooming.current ? easeLinear : easeSinOut)
235
+ .duration(200)
236
+ .tween('scale', () => (t) => setZoom(is(t)))
237
+ .on('end', () => {
238
+ zooming.current = false;
239
+ });
240
+ } else {
241
+ setZoom(state);
242
+ }
243
+ },
244
+ setTranslation,
245
+ setRotation,
246
+ };
247
+ }, [canvas]);
225
248
 
226
249
  // https://d3js.org/d3-geo/path#geoPath
227
250
  // https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/getContext
@@ -236,14 +259,14 @@ const GlobeCanvas = forwardRef<GlobeController, GlobeCanvasProps>(
236
259
  timer(() => {
237
260
  // https://d3js.org/d3-geo/projection
238
261
  projection
239
- .scale((Math.min(size.width, size.height) / 2) * scale)
262
+ .scale((Math.min(size.width, size.height) / 2) * zoom)
240
263
  .translate([size.width / 2 + (translation?.x ?? 0), size.height / 2 + (translation?.y ?? 0)])
241
264
  .rotate(rotation ?? [0, 0, 0]);
242
265
 
243
- renderLayers(generator, layers, scale, styles);
266
+ renderLayers(generator, layers, zoom, styles);
244
267
  });
245
268
  }
246
- }, [generator, size, scale, translation, rotation, layers]);
269
+ }, [generator, size, zoom, translation, rotation, layers]);
247
270
 
248
271
  if (!size.width || !size.height) {
249
272
  return null;
@@ -253,22 +276,30 @@ const GlobeCanvas = forwardRef<GlobeController, GlobeCanvasProps>(
253
276
  },
254
277
  );
255
278
 
279
+ //
280
+ // Debug
281
+ //
282
+
256
283
  const GlobeDebug = ({ position = 'topleft' }: { position?: ControlPosition }) => {
257
- const { size, scale, translation, rotation } = useGlobeContext();
284
+ const { size, zoom, translation, rotation } = useGlobeContext();
258
285
  return (
259
286
  <div
260
287
  className={mx(
261
- 'z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded',
288
+ 'z-10 absolute w-96 p-2 overflow-hidden border border-green-700 rounded-sm',
262
289
  controlPositions[position],
263
290
  )}
264
291
  >
265
292
  <pre className='font-mono text-xs text-green-700'>
266
- {JSON.stringify({ size, scale, translation, rotation }, null, 2)}
293
+ {JSON.stringify({ size, zoom, translation, rotation }, null, 2)}
267
294
  </pre>
268
295
  </div>
269
296
  );
270
297
  };
271
298
 
299
+ //
300
+ // Panel
301
+ //
302
+
272
303
  const GlobePanel = ({
273
304
  position,
274
305
  classNames,
@@ -277,25 +308,37 @@ const GlobePanel = ({
277
308
  return <div className={mx('z-10 absolute overflow-hidden', controlPositions[position], classNames)}>{children}</div>;
278
309
  };
279
310
 
311
+ //
312
+ // Controls
313
+ //
314
+
280
315
  const CustomControl = ({ position, children }: PropsWithChildren<{ position: ControlPosition }>) => {
281
316
  return <div className={mx('z-10 absolute overflow-hidden', controlPositions[position])}>{children}</div>;
282
317
  };
283
318
 
284
319
  type GlobeControlProps = { position?: ControlPosition } & Pick<ControlProps, 'onAction'>;
285
320
 
321
+ const GlobeZoom = ({ onAction, position = 'bottomleft', ...props }: GlobeControlProps) => (
322
+ <CustomControl position={position} {...props}>
323
+ <ZoomControls onAction={onAction} />
324
+ </CustomControl>
325
+ );
326
+
327
+ const GlobeAction = ({ onAction, position = 'bottomright', ...props }: GlobeControlProps) => (
328
+ <CustomControl position={position} {...props}>
329
+ <ActionControls onAction={onAction} />
330
+ </CustomControl>
331
+ );
332
+
333
+ //
334
+ // Globe
335
+ //
336
+
286
337
  export const Globe = {
287
338
  Root: GlobeRoot,
288
339
  Canvas: GlobeCanvas,
289
- Zoom: ({ onAction, position = 'bottomleft', ...props }: GlobeControlProps) => (
290
- <CustomControl position={position} {...props}>
291
- <ZoomControls onAction={onAction} />
292
- </CustomControl>
293
- ),
294
- Action: ({ onAction, position = 'bottomright', ...props }: GlobeControlProps) => (
295
- <CustomControl position={position} {...props}>
296
- <ActionControls onAction={onAction} />
297
- </CustomControl>
298
- ),
340
+ Zoom: GlobeZoom,
341
+ Action: GlobeAction,
299
342
  Debug: GlobeDebug,
300
343
  Panel: GlobePanel,
301
344
  };
@@ -2,45 +2,57 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import '@dxos-theme';
6
-
7
- import { type StoryObj, type Meta } from '@storybook/react';
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
8
6
  import React, { useState } from 'react';
9
7
 
10
- import { withLayout, withTheme } from '@dxos/storybook-utils';
8
+ import { withLayout, withTheme } from '@dxos/react-ui/testing';
11
9
 
12
- import { Map, type MapController } from './Map';
13
10
  import { useMapZoomHandler } from '../../hooks';
14
- import { type MapMarker } from '../../types';
11
+ import { type GeoMarker } from '../../types';
12
+ import { Map, type MapController } from './Map';
15
13
 
16
- const DefaultStory = ({ markers = [] }: { markers?: MapMarker[] }) => {
14
+ const DefaultStory = ({ markers = [] }: { markers?: GeoMarker[] }) => {
17
15
  const [controller, setController] = useState<MapController>();
18
16
  const handleZoomAction = useMapZoomHandler(controller);
19
17
 
20
18
  return (
21
19
  <Map.Root>
22
- <Map.Canvas ref={setController} markers={markers} />
23
- <Map.Zoom position='bottomleft' onAction={handleZoomAction} />
24
- <Map.Action position='bottomright' />
20
+ <Map.Content ref={setController}>
21
+ <Map.Tiles />
22
+ <Map.Markers markers={markers} />
23
+ <Map.Zoom position='bottomleft' onAction={handleZoomAction} />
24
+ <Map.Action position='bottomright' />
25
+ </Map.Content>
25
26
  </Map.Root>
26
27
  );
27
28
  };
28
29
 
29
- const meta: Meta<typeof DefaultStory> = {
30
+ const meta = {
30
31
  title: 'ui/react-ui-geo/Map',
32
+ component: Map.Root as any,
31
33
  render: DefaultStory,
32
- decorators: [withTheme, withLayout({ fullscreen: true })],
33
- };
34
+ decorators: [withTheme(), withLayout({ layout: 'fullscreen' })],
35
+ parameters: {
36
+ layout: 'fullscreen',
37
+ },
38
+ } satisfies Meta<typeof DefaultStory>;
34
39
 
35
40
  export default meta;
36
41
 
37
- type Story = StoryObj<typeof DefaultStory>;
42
+ type Story = StoryObj<typeof meta>;
38
43
 
39
44
  export const Default: Story = {};
40
45
 
41
46
  export const WithMarkers: Story = {
42
47
  args: {
43
48
  markers: [
49
+ { id: 'los angeles', title: 'Los Angeles', location: { lat: 34.0522, lng: -118.2437 } },
50
+ { id: 'new york', title: 'New York', location: { lat: 40.7128, lng: -74.006 } },
51
+ { id: 'warsaw', title: 'Warsaw', location: { lat: 52.2297, lng: 21.0122 } },
52
+ { id: 'london', title: 'London', location: { lat: 51.5074, lng: -0.1278 } },
53
+ { id: 'toronto', title: 'Toronto', location: { lat: 43.6532, lng: -79.3832 } },
54
+ { id: 'seattle', title: 'Seattle', location: { lat: 47.6062, lng: -122.3321 } },
55
+ { id: 'barcelona', title: 'Barcelona', location: { lat: 41.3851, lng: 2.1734 } },
44
56
  { id: 'tokyo', title: 'Tokyo', location: { lat: 35.6762, lng: 139.6503 } },
45
57
  { id: 'sydney', title: 'Sydney', location: { lat: -33.8688, lng: 151.2093 } },
46
58
  { id: 'auckland', title: 'Auckland', location: { lat: -36.8509, lng: 174.7645 } },
@@ -56,6 +68,6 @@ export const WithMarkers: Story = {
56
68
  { id: 'phnom-penh', title: 'Phnom Penh', location: { lat: 11.5564, lng: 104.9282 } },
57
69
  { id: 'vientiane', title: 'Vientiane', location: { lat: 17.9757, lng: 102.6331 } },
58
70
  { id: 'yangon', title: 'Yangon', location: { lat: 16.8661, lng: 96.1951 } },
59
- ] as MapMarker[],
71
+ ] as GeoMarker[],
60
72
  },
61
73
  };