gistda-sphere-react 1.0.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.
- package/README.md +827 -0
- package/dist/index.d.mts +1081 -0
- package/dist/index.d.ts +1081 -0
- package/dist/index.js +2057 -0
- package/dist/index.mjs +2013 -0
- package/package.json +70 -0
- package/src/__tests__/Layer.test.tsx +133 -0
- package/src/__tests__/Marker.test.tsx +183 -0
- package/src/__tests__/SphereContext.test.tsx +120 -0
- package/src/__tests__/SphereMap.test.tsx +240 -0
- package/src/__tests__/geometry.test.tsx +454 -0
- package/src/__tests__/hooks.test.tsx +173 -0
- package/src/__tests__/setup.ts +204 -0
- package/src/__tests__/useMapControls.test.tsx +168 -0
- package/src/__tests__/useOverlays.test.tsx +265 -0
- package/src/__tests__/useRoute.test.tsx +219 -0
- package/src/__tests__/useSearch.test.tsx +205 -0
- package/src/__tests__/useTags.test.tsx +179 -0
- package/src/components/Circle.tsx +189 -0
- package/src/components/Dot.tsx +150 -0
- package/src/components/Layer.tsx +177 -0
- package/src/components/Marker.tsx +204 -0
- package/src/components/Polygon.tsx +223 -0
- package/src/components/Polyline.tsx +211 -0
- package/src/components/Popup.tsx +130 -0
- package/src/components/Rectangle.tsx +194 -0
- package/src/components/SphereMap.tsx +315 -0
- package/src/components/index.ts +18 -0
- package/src/context/MapContext.tsx +41 -0
- package/src/context/SphereContext.tsx +348 -0
- package/src/context/index.ts +15 -0
- package/src/hooks/index.ts +42 -0
- package/src/hooks/useMapEvent.ts +66 -0
- package/src/hooks/useOverlays.ts +278 -0
- package/src/hooks/useRoute.ts +232 -0
- package/src/hooks/useSearch.ts +143 -0
- package/src/hooks/useSphere.ts +18 -0
- package/src/hooks/useTags.ts +129 -0
- package/src/index.ts +124 -0
- package/src/types/index.ts +1 -0
- package/src/types/sphere.ts +671 -0
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { useCallback, useMemo, useState } from "react";
|
|
2
|
+
import type { Icon, Location, PopupOptions, Range } from "../types";
|
|
3
|
+
|
|
4
|
+
interface BaseOverlay {
|
|
5
|
+
id: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface MarkerData extends BaseOverlay {
|
|
9
|
+
position: Location;
|
|
10
|
+
icon?: Icon;
|
|
11
|
+
title?: string;
|
|
12
|
+
detail?: string;
|
|
13
|
+
popup?: PopupOptions;
|
|
14
|
+
visibleRange?: Range;
|
|
15
|
+
clickable?: boolean;
|
|
16
|
+
draggable?: boolean;
|
|
17
|
+
zIndex?: number;
|
|
18
|
+
rotate?: number;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface PolygonData extends BaseOverlay {
|
|
22
|
+
positions: Location[];
|
|
23
|
+
title?: string;
|
|
24
|
+
detail?: string;
|
|
25
|
+
lineWidth?: number;
|
|
26
|
+
lineColor?: string;
|
|
27
|
+
fillColor?: string;
|
|
28
|
+
lineStyle?: "Solid" | "Dashed" | "Dot";
|
|
29
|
+
popup?: PopupOptions;
|
|
30
|
+
visibleRange?: Range;
|
|
31
|
+
clickable?: boolean;
|
|
32
|
+
draggable?: boolean;
|
|
33
|
+
editable?: boolean;
|
|
34
|
+
zIndex?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PolylineData extends BaseOverlay {
|
|
38
|
+
positions: Location[];
|
|
39
|
+
title?: string;
|
|
40
|
+
detail?: string;
|
|
41
|
+
lineWidth?: number;
|
|
42
|
+
lineColor?: string;
|
|
43
|
+
lineStyle?: "Solid" | "Dashed" | "Dot";
|
|
44
|
+
popup?: PopupOptions;
|
|
45
|
+
visibleRange?: Range;
|
|
46
|
+
clickable?: boolean;
|
|
47
|
+
draggable?: boolean;
|
|
48
|
+
editable?: boolean;
|
|
49
|
+
zIndex?: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface CircleData extends BaseOverlay {
|
|
53
|
+
center: Location;
|
|
54
|
+
radius: number;
|
|
55
|
+
title?: string;
|
|
56
|
+
detail?: string;
|
|
57
|
+
lineWidth?: number;
|
|
58
|
+
lineColor?: string;
|
|
59
|
+
fillColor?: string;
|
|
60
|
+
lineStyle?: "Solid" | "Dashed" | "Dot";
|
|
61
|
+
popup?: PopupOptions;
|
|
62
|
+
visibleRange?: Range;
|
|
63
|
+
clickable?: boolean;
|
|
64
|
+
draggable?: boolean;
|
|
65
|
+
zIndex?: number;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
type OverlayInput<T extends BaseOverlay> = Omit<T, "id"> & { id?: string };
|
|
69
|
+
|
|
70
|
+
interface UseOverlaysResult<T extends BaseOverlay> {
|
|
71
|
+
items: T[];
|
|
72
|
+
add: (data: OverlayInput<T>) => string;
|
|
73
|
+
update: (id: string, data: Partial<Omit<T, "id">>) => void;
|
|
74
|
+
remove: (id: string) => void;
|
|
75
|
+
clear: () => void;
|
|
76
|
+
get: (id: string) => T | undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function generateId(): string {
|
|
80
|
+
return `overlay-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function useOverlayState<T extends BaseOverlay>(): UseOverlaysResult<T> {
|
|
84
|
+
const [items, setItems] = useState<T[]>([]);
|
|
85
|
+
|
|
86
|
+
const add = useCallback((data: OverlayInput<T>): string => {
|
|
87
|
+
const id = data.id ?? generateId();
|
|
88
|
+
const newItem = { ...data, id } as T;
|
|
89
|
+
setItems((prev) => [...prev, newItem]);
|
|
90
|
+
return id;
|
|
91
|
+
}, []);
|
|
92
|
+
|
|
93
|
+
const update = useCallback(
|
|
94
|
+
(id: string, data: Partial<Omit<T, "id">>): void => {
|
|
95
|
+
setItems((prev) =>
|
|
96
|
+
prev.map((item) => (item.id === id ? { ...item, ...data } : item))
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
[]
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const remove = useCallback((id: string): void => {
|
|
103
|
+
setItems((prev) => prev.filter((item) => item.id !== id));
|
|
104
|
+
}, []);
|
|
105
|
+
|
|
106
|
+
const clear = useCallback((): void => {
|
|
107
|
+
setItems([]);
|
|
108
|
+
}, []);
|
|
109
|
+
|
|
110
|
+
const get = useCallback(
|
|
111
|
+
(id: string): T | undefined => {
|
|
112
|
+
return items.find((item) => item.id === id);
|
|
113
|
+
},
|
|
114
|
+
[items]
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
return useMemo(
|
|
118
|
+
() => ({ items, add, update, remove, clear, get }),
|
|
119
|
+
[items, add, update, remove, clear, get]
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Hook to manage markers with add/update/remove functionality.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```tsx
|
|
128
|
+
* function DrawingPanel() {
|
|
129
|
+
* const { items: markers, add, remove, clear } = useMarkers();
|
|
130
|
+
*
|
|
131
|
+
* const handleMapClick = (location: Location) => {
|
|
132
|
+
* add({ position: location, title: `Marker ${markers.length + 1}` });
|
|
133
|
+
* };
|
|
134
|
+
*
|
|
135
|
+
* return (
|
|
136
|
+
* <>
|
|
137
|
+
* {markers.map((m) => (
|
|
138
|
+
* <Marker
|
|
139
|
+
* key={m.id}
|
|
140
|
+
* position={m.position}
|
|
141
|
+
* title={m.title}
|
|
142
|
+
* onClick={() => remove(m.id)}
|
|
143
|
+
* />
|
|
144
|
+
* ))}
|
|
145
|
+
* </>
|
|
146
|
+
* );
|
|
147
|
+
* }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export function useMarkers(): UseOverlaysResult<MarkerData> {
|
|
151
|
+
return useOverlayState<MarkerData>();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Hook to manage polygons with add/update/remove functionality.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```tsx
|
|
159
|
+
* function DrawingPanel() {
|
|
160
|
+
* const { items: polygons, add, clear } = usePolygons();
|
|
161
|
+
*
|
|
162
|
+
* const handleFinishDrawing = (positions: Location[]) => {
|
|
163
|
+
* add({ positions, fillColor: 'rgba(255, 0, 0, 0.3)' });
|
|
164
|
+
* };
|
|
165
|
+
*
|
|
166
|
+
* return (
|
|
167
|
+
* <>
|
|
168
|
+
* {polygons.map((p) => (
|
|
169
|
+
* <Polygon key={p.id} positions={p.positions} fillColor={p.fillColor} />
|
|
170
|
+
* ))}
|
|
171
|
+
* </>
|
|
172
|
+
* );
|
|
173
|
+
* }
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export function usePolygons(): UseOverlaysResult<PolygonData> {
|
|
177
|
+
return useOverlayState<PolygonData>();
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Hook to manage polylines with add/update/remove functionality.
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* ```tsx
|
|
185
|
+
* function DrawingPanel() {
|
|
186
|
+
* const { items: polylines, add } = usePolylines();
|
|
187
|
+
*
|
|
188
|
+
* return (
|
|
189
|
+
* <>
|
|
190
|
+
* {polylines.map((p) => (
|
|
191
|
+
* <Polyline key={p.id} positions={p.positions} lineColor={p.lineColor} />
|
|
192
|
+
* ))}
|
|
193
|
+
* </>
|
|
194
|
+
* );
|
|
195
|
+
* }
|
|
196
|
+
* ```
|
|
197
|
+
*/
|
|
198
|
+
export function usePolylines(): UseOverlaysResult<PolylineData> {
|
|
199
|
+
return useOverlayState<PolylineData>();
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Hook to manage circles with add/update/remove functionality.
|
|
204
|
+
*
|
|
205
|
+
* @example
|
|
206
|
+
* ```tsx
|
|
207
|
+
* function DrawingPanel() {
|
|
208
|
+
* const { items: circles, add } = useCircles();
|
|
209
|
+
*
|
|
210
|
+
* const handleAddCircle = (center: Location, radius: number) => {
|
|
211
|
+
* add({ center, radius, fillColor: 'rgba(0, 0, 255, 0.3)' });
|
|
212
|
+
* };
|
|
213
|
+
*
|
|
214
|
+
* return (
|
|
215
|
+
* <>
|
|
216
|
+
* {circles.map((c) => (
|
|
217
|
+
* <Circle key={c.id} center={c.center} radius={c.radius} fillColor={c.fillColor} />
|
|
218
|
+
* ))}
|
|
219
|
+
* </>
|
|
220
|
+
* );
|
|
221
|
+
* }
|
|
222
|
+
* ```
|
|
223
|
+
*/
|
|
224
|
+
export function useCircles(): UseOverlaysResult<CircleData> {
|
|
225
|
+
return useOverlayState<CircleData>();
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Hook that combines all overlay types into a single manager.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```tsx
|
|
233
|
+
* function DrawingPanel() {
|
|
234
|
+
* const overlays = useOverlays();
|
|
235
|
+
*
|
|
236
|
+
* const handleClearAll = () => {
|
|
237
|
+
* overlays.markers.clear();
|
|
238
|
+
* overlays.polygons.clear();
|
|
239
|
+
* overlays.polylines.clear();
|
|
240
|
+
* overlays.circles.clear();
|
|
241
|
+
* };
|
|
242
|
+
*
|
|
243
|
+
* return (
|
|
244
|
+
* <>
|
|
245
|
+
* <button onClick={handleClearAll}>Clear All</button>
|
|
246
|
+
* {overlays.markers.items.map((m) => <Marker key={m.id} {...m} />)}
|
|
247
|
+
* {overlays.polygons.items.map((p) => <Polygon key={p.id} {...p} />)}
|
|
248
|
+
* </>
|
|
249
|
+
* );
|
|
250
|
+
* }
|
|
251
|
+
* ```
|
|
252
|
+
*/
|
|
253
|
+
export function useOverlays(): {
|
|
254
|
+
markers: UseOverlaysResult<MarkerData>;
|
|
255
|
+
polygons: UseOverlaysResult<PolygonData>;
|
|
256
|
+
polylines: UseOverlaysResult<PolylineData>;
|
|
257
|
+
circles: UseOverlaysResult<CircleData>;
|
|
258
|
+
clearAll: () => void;
|
|
259
|
+
} {
|
|
260
|
+
const markers = useMarkers();
|
|
261
|
+
const polygons = usePolygons();
|
|
262
|
+
const polylines = usePolylines();
|
|
263
|
+
const circles = useCircles();
|
|
264
|
+
|
|
265
|
+
const clearAll = useCallback(() => {
|
|
266
|
+
markers.clear();
|
|
267
|
+
polygons.clear();
|
|
268
|
+
polylines.clear();
|
|
269
|
+
circles.clear();
|
|
270
|
+
}, [markers, polygons, polylines, circles]);
|
|
271
|
+
|
|
272
|
+
return useMemo(
|
|
273
|
+
() => ({ markers, polygons, polylines, circles, clearAll }),
|
|
274
|
+
[markers, polygons, polylines, circles, clearAll]
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export type { BaseOverlay, OverlayInput, UseOverlaysResult };
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
import { useMap } from "../context/SphereContext";
|
|
3
|
+
import type {
|
|
4
|
+
GeometryOptions,
|
|
5
|
+
Location,
|
|
6
|
+
RouteLabelType,
|
|
7
|
+
RouteMode,
|
|
8
|
+
RouteType,
|
|
9
|
+
SphereMarker,
|
|
10
|
+
SpherePolyline,
|
|
11
|
+
} from "../types";
|
|
12
|
+
|
|
13
|
+
export interface RouteGuideStep {
|
|
14
|
+
instruction: string;
|
|
15
|
+
distance: number | string;
|
|
16
|
+
duration: number | string;
|
|
17
|
+
location: Location;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface UseRouteReturn {
|
|
21
|
+
isReady: boolean;
|
|
22
|
+
addDestination: (
|
|
23
|
+
destination: SphereMarker | Location,
|
|
24
|
+
mode?: RouteMode
|
|
25
|
+
) => void;
|
|
26
|
+
insertDestination: (
|
|
27
|
+
index: number,
|
|
28
|
+
destination: SphereMarker | Location,
|
|
29
|
+
mode?: RouteMode
|
|
30
|
+
) => void;
|
|
31
|
+
removeDestination: (destination: SphereMarker) => void;
|
|
32
|
+
removeDestinationAt: (index: number) => void;
|
|
33
|
+
clearDestinations: () => void;
|
|
34
|
+
clearPath: () => void;
|
|
35
|
+
clear: () => void;
|
|
36
|
+
reverse: () => void;
|
|
37
|
+
search: () => void;
|
|
38
|
+
getDistance: (format?: boolean) => number | string;
|
|
39
|
+
getInterval: (format?: boolean) => number | string;
|
|
40
|
+
getGuide: (format?: boolean) => RouteGuideStep[] | HTMLElement;
|
|
41
|
+
exportRouteLine: (options?: GeometryOptions) => SpherePolyline | null;
|
|
42
|
+
listDestinations: () => SphereMarker[];
|
|
43
|
+
size: () => number;
|
|
44
|
+
setMode: (mode: RouteMode) => void;
|
|
45
|
+
setModeAt: (index: number, mode: RouteMode) => void;
|
|
46
|
+
enableRouteType: (routeType: RouteType, state: boolean) => void;
|
|
47
|
+
setLabel: (label: RouteLabelType) => void;
|
|
48
|
+
setAuto: (state: boolean) => void;
|
|
49
|
+
setLanguage: (lang: string) => void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function useRoute(): UseRouteReturn {
|
|
53
|
+
const { map, isReady } = useMap();
|
|
54
|
+
|
|
55
|
+
const addDestination = useCallback(
|
|
56
|
+
(destination: SphereMarker | Location, mode?: RouteMode) => {
|
|
57
|
+
map?.Route?.add(destination, mode);
|
|
58
|
+
},
|
|
59
|
+
[map]
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
const insertDestination = useCallback(
|
|
63
|
+
(index: number, destination: SphereMarker | Location, mode?: RouteMode) => {
|
|
64
|
+
map?.Route?.insert(index, destination, mode);
|
|
65
|
+
},
|
|
66
|
+
[map]
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const removeDestination = useCallback(
|
|
70
|
+
(destination: SphereMarker) => {
|
|
71
|
+
map?.Route?.remove(destination);
|
|
72
|
+
},
|
|
73
|
+
[map]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const removeDestinationAt = useCallback(
|
|
77
|
+
(index: number) => {
|
|
78
|
+
map?.Route?.removeAt(index);
|
|
79
|
+
},
|
|
80
|
+
[map]
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const clearDestinations = useCallback(() => {
|
|
84
|
+
map?.Route?.clearDestination();
|
|
85
|
+
}, [map]);
|
|
86
|
+
|
|
87
|
+
const clearPath = useCallback(() => {
|
|
88
|
+
map?.Route?.clearPath();
|
|
89
|
+
}, [map]);
|
|
90
|
+
|
|
91
|
+
const clear = useCallback(() => {
|
|
92
|
+
map?.Route?.clear();
|
|
93
|
+
}, [map]);
|
|
94
|
+
|
|
95
|
+
const reverse = useCallback(() => {
|
|
96
|
+
map?.Route?.reverse();
|
|
97
|
+
}, [map]);
|
|
98
|
+
|
|
99
|
+
const search = useCallback(() => {
|
|
100
|
+
map?.Route?.search();
|
|
101
|
+
}, [map]);
|
|
102
|
+
|
|
103
|
+
const getDistance = useCallback(
|
|
104
|
+
(format = false): number | string => {
|
|
105
|
+
return map?.Route?.distance(format) ?? 0;
|
|
106
|
+
},
|
|
107
|
+
[map]
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const getInterval = useCallback(
|
|
111
|
+
(format = false): number | string => {
|
|
112
|
+
return map?.Route?.interval(format) ?? 0;
|
|
113
|
+
},
|
|
114
|
+
[map]
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const getGuide = useCallback(
|
|
118
|
+
(format = false): RouteGuideStep[] | HTMLElement => {
|
|
119
|
+
const result = map?.Route?.guide(format);
|
|
120
|
+
return (result as RouteGuideStep[] | HTMLElement) ?? [];
|
|
121
|
+
},
|
|
122
|
+
[map]
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const exportRouteLine = useCallback(
|
|
126
|
+
(options?: GeometryOptions): SpherePolyline | null => {
|
|
127
|
+
return map?.Route?.exportRouteLine(options) ?? null;
|
|
128
|
+
},
|
|
129
|
+
[map]
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
const listDestinations = useCallback((): SphereMarker[] => {
|
|
133
|
+
return map?.Route?.list() ?? [];
|
|
134
|
+
}, [map]);
|
|
135
|
+
|
|
136
|
+
const size = useCallback((): number => {
|
|
137
|
+
return map?.Route?.size() ?? 0;
|
|
138
|
+
}, [map]);
|
|
139
|
+
|
|
140
|
+
const setMode = useCallback(
|
|
141
|
+
(mode: RouteMode) => {
|
|
142
|
+
map?.Route?.mode(mode);
|
|
143
|
+
},
|
|
144
|
+
[map]
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
const setModeAt = useCallback(
|
|
148
|
+
(index: number, mode: RouteMode) => {
|
|
149
|
+
map?.Route?.modeOf(index, mode);
|
|
150
|
+
},
|
|
151
|
+
[map]
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
const enableRouteType = useCallback(
|
|
155
|
+
(routeType: RouteType, state: boolean) => {
|
|
156
|
+
map?.Route?.enableRoute(routeType, state);
|
|
157
|
+
},
|
|
158
|
+
[map]
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
const setLabel = useCallback(
|
|
162
|
+
(label: RouteLabelType) => {
|
|
163
|
+
map?.Route?.label(label);
|
|
164
|
+
},
|
|
165
|
+
[map]
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
const setAuto = useCallback(
|
|
169
|
+
(state: boolean) => {
|
|
170
|
+
map?.Route?.auto(state);
|
|
171
|
+
},
|
|
172
|
+
[map]
|
|
173
|
+
);
|
|
174
|
+
|
|
175
|
+
const setLanguage = useCallback(
|
|
176
|
+
(lang: string) => {
|
|
177
|
+
map?.Route?.language(lang);
|
|
178
|
+
},
|
|
179
|
+
[map]
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
return useMemo(
|
|
183
|
+
() => ({
|
|
184
|
+
isReady,
|
|
185
|
+
addDestination,
|
|
186
|
+
insertDestination,
|
|
187
|
+
removeDestination,
|
|
188
|
+
removeDestinationAt,
|
|
189
|
+
clearDestinations,
|
|
190
|
+
clearPath,
|
|
191
|
+
clear,
|
|
192
|
+
reverse,
|
|
193
|
+
search,
|
|
194
|
+
getDistance,
|
|
195
|
+
getInterval,
|
|
196
|
+
getGuide,
|
|
197
|
+
exportRouteLine,
|
|
198
|
+
listDestinations,
|
|
199
|
+
size,
|
|
200
|
+
setMode,
|
|
201
|
+
setModeAt,
|
|
202
|
+
enableRouteType,
|
|
203
|
+
setLabel,
|
|
204
|
+
setAuto,
|
|
205
|
+
setLanguage,
|
|
206
|
+
}),
|
|
207
|
+
[
|
|
208
|
+
isReady,
|
|
209
|
+
addDestination,
|
|
210
|
+
insertDestination,
|
|
211
|
+
removeDestination,
|
|
212
|
+
removeDestinationAt,
|
|
213
|
+
clearDestinations,
|
|
214
|
+
clearPath,
|
|
215
|
+
clear,
|
|
216
|
+
reverse,
|
|
217
|
+
search,
|
|
218
|
+
getDistance,
|
|
219
|
+
getInterval,
|
|
220
|
+
getGuide,
|
|
221
|
+
exportRouteLine,
|
|
222
|
+
listDestinations,
|
|
223
|
+
size,
|
|
224
|
+
setMode,
|
|
225
|
+
setModeAt,
|
|
226
|
+
enableRouteType,
|
|
227
|
+
setLabel,
|
|
228
|
+
setAuto,
|
|
229
|
+
setLanguage,
|
|
230
|
+
]
|
|
231
|
+
);
|
|
232
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { useCallback, useMemo } from "react";
|
|
2
|
+
import { useMap } from "../context/SphereContext";
|
|
3
|
+
import type {
|
|
4
|
+
AddressOptions,
|
|
5
|
+
Location,
|
|
6
|
+
NearPoiOptions,
|
|
7
|
+
SearchOptions,
|
|
8
|
+
SuggestOptions,
|
|
9
|
+
} from "../types";
|
|
10
|
+
|
|
11
|
+
export interface SearchResult {
|
|
12
|
+
data: object[];
|
|
13
|
+
total?: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AddressResult {
|
|
17
|
+
address?: string;
|
|
18
|
+
subdistrict?: string;
|
|
19
|
+
district?: string;
|
|
20
|
+
province?: string;
|
|
21
|
+
postcode?: string;
|
|
22
|
+
geocode?: string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface PoiResult {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
location: Location;
|
|
29
|
+
category?: string;
|
|
30
|
+
distance?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface UseSearchReturn {
|
|
34
|
+
isReady: boolean;
|
|
35
|
+
suggest: (keyword: string, options?: SuggestOptions) => Promise<SearchResult>;
|
|
36
|
+
search: (keyword: string, options?: SearchOptions) => Promise<SearchResult>;
|
|
37
|
+
address: (
|
|
38
|
+
location: Location,
|
|
39
|
+
options?: AddressOptions
|
|
40
|
+
) => Promise<AddressResult>;
|
|
41
|
+
nearPoi: (
|
|
42
|
+
location: Location,
|
|
43
|
+
options?: NearPoiOptions
|
|
44
|
+
) => Promise<PoiResult[]>;
|
|
45
|
+
clear: () => void;
|
|
46
|
+
enablePopup: (state: boolean) => void;
|
|
47
|
+
setLanguage: (lang: string) => void;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function useSearch(): UseSearchReturn {
|
|
51
|
+
const { map, isReady } = useMap();
|
|
52
|
+
|
|
53
|
+
const suggest = useCallback(
|
|
54
|
+
async (
|
|
55
|
+
keyword: string,
|
|
56
|
+
options?: SuggestOptions
|
|
57
|
+
): Promise<SearchResult> => {
|
|
58
|
+
if (!map?.Search) {
|
|
59
|
+
throw new Error("Search API not available");
|
|
60
|
+
}
|
|
61
|
+
return (await map.Search.suggest(keyword, options)) as SearchResult;
|
|
62
|
+
},
|
|
63
|
+
[map]
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const search = useCallback(
|
|
67
|
+
async (keyword: string, options?: SearchOptions): Promise<SearchResult> => {
|
|
68
|
+
if (!map?.Search) {
|
|
69
|
+
throw new Error("Search API not available");
|
|
70
|
+
}
|
|
71
|
+
return (await map.Search.search(keyword, options)) as SearchResult;
|
|
72
|
+
},
|
|
73
|
+
[map]
|
|
74
|
+
);
|
|
75
|
+
|
|
76
|
+
const address = useCallback(
|
|
77
|
+
async (
|
|
78
|
+
location: Location,
|
|
79
|
+
options?: AddressOptions
|
|
80
|
+
): Promise<AddressResult> => {
|
|
81
|
+
if (!map?.Search) {
|
|
82
|
+
throw new Error("Search API not available");
|
|
83
|
+
}
|
|
84
|
+
return (await map.Search.address(location, options)) as AddressResult;
|
|
85
|
+
},
|
|
86
|
+
[map]
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const nearPoi = useCallback(
|
|
90
|
+
async (
|
|
91
|
+
location: Location,
|
|
92
|
+
options?: NearPoiOptions
|
|
93
|
+
): Promise<PoiResult[]> => {
|
|
94
|
+
if (!map?.Search) {
|
|
95
|
+
throw new Error("Search API not available");
|
|
96
|
+
}
|
|
97
|
+
const result = await map.Search.nearPoi(location, options);
|
|
98
|
+
return (result as { data?: PoiResult[] }).data ?? (result as PoiResult[]);
|
|
99
|
+
},
|
|
100
|
+
[map]
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const clear = useCallback(() => {
|
|
104
|
+
map?.Search?.clear();
|
|
105
|
+
}, [map]);
|
|
106
|
+
|
|
107
|
+
const enablePopup = useCallback(
|
|
108
|
+
(state: boolean) => {
|
|
109
|
+
map?.Search?.enablePopup(state);
|
|
110
|
+
},
|
|
111
|
+
[map]
|
|
112
|
+
);
|
|
113
|
+
|
|
114
|
+
const setLanguage = useCallback(
|
|
115
|
+
(lang: string) => {
|
|
116
|
+
map?.Search?.language(lang);
|
|
117
|
+
},
|
|
118
|
+
[map]
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return useMemo(
|
|
122
|
+
() => ({
|
|
123
|
+
isReady,
|
|
124
|
+
suggest,
|
|
125
|
+
search,
|
|
126
|
+
address,
|
|
127
|
+
nearPoi,
|
|
128
|
+
clear,
|
|
129
|
+
enablePopup,
|
|
130
|
+
setLanguage,
|
|
131
|
+
}),
|
|
132
|
+
[
|
|
133
|
+
isReady,
|
|
134
|
+
suggest,
|
|
135
|
+
search,
|
|
136
|
+
address,
|
|
137
|
+
nearPoi,
|
|
138
|
+
clear,
|
|
139
|
+
enablePopup,
|
|
140
|
+
setLanguage,
|
|
141
|
+
]
|
|
142
|
+
);
|
|
143
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useSphereContext } from "../context/SphereContext";
|
|
2
|
+
import type { SphereNamespace } from "../types";
|
|
3
|
+
|
|
4
|
+
export function useSphere(): {
|
|
5
|
+
sphere: SphereNamespace | null;
|
|
6
|
+
isLoaded: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
apiKey: string;
|
|
9
|
+
} {
|
|
10
|
+
const { sphere, isLoaded, error, apiKey } = useSphereContext();
|
|
11
|
+
|
|
12
|
+
return {
|
|
13
|
+
sphere,
|
|
14
|
+
isLoaded,
|
|
15
|
+
error,
|
|
16
|
+
apiKey,
|
|
17
|
+
};
|
|
18
|
+
}
|