gistda-sphere-react 1.0.0 → 1.0.1

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  type CSSProperties,
3
- forwardRef,
4
3
  type ReactNode,
4
+ type Ref,
5
5
  useEffect,
6
6
  useImperativeHandle,
7
7
  useRef,
@@ -19,8 +19,22 @@ import type {
19
19
  SphereMap as SphereMapInstance,
20
20
  } from "../types";
21
21
 
22
+ export interface SphereMapRef {
23
+ getMap(): SphereMapInstance | null;
24
+ setZoom(zoom: number, animate?: boolean): void;
25
+ setCenter(location: Location, animate?: boolean): void;
26
+ setBound(bound: Bound, options?: object): void;
27
+ goTo(target: FlyToOptions, animate?: boolean): void;
28
+ setRotate(angle: number, animate?: boolean): void;
29
+ setPitch(angle: number): void;
30
+ setFilter(filter: FilterType): void;
31
+ resize(): void;
32
+ repaint(): void;
33
+ }
34
+
22
35
  export interface SphereMapProps {
23
36
  children?: ReactNode;
37
+ ref?: Ref<SphereMapRef>;
24
38
  zoom?: number;
25
39
  zoomRange?: Range;
26
40
  center?: Location;
@@ -48,57 +62,57 @@ export interface SphereMapProps {
48
62
  onError?: (error: Error) => void;
49
63
  }
50
64
 
51
- export interface SphereMapRef {
52
- getMap(): SphereMapInstance | null;
53
- setZoom(zoom: number, animate?: boolean): void;
54
- setCenter(location: Location, animate?: boolean): void;
55
- setBound(bound: Bound, options?: object): void;
56
- goTo(target: FlyToOptions, animate?: boolean): void;
57
- setRotate(angle: number, animate?: boolean): void;
58
- setPitch(angle: number): void;
59
- setFilter(filter: FilterType): void;
60
- resize(): void;
61
- repaint(): void;
62
- }
63
-
64
- export const SphereMap = forwardRef<SphereMapRef, SphereMapProps>(
65
- function SphereMap(
66
- {
67
- children,
68
- zoom = 7,
69
- zoomRange,
70
- center,
71
- language = "th",
72
- input = true,
73
- lastView = false,
74
- ui,
75
- filter,
76
- rotate,
77
- pitch,
78
- className,
79
- style,
80
- id,
81
- onReady,
82
- onZoom,
83
- onLocation,
84
- onClick,
85
- onDoubleClick,
86
- onRotate,
87
- onPitch,
88
- onDrag,
89
- onDrop,
90
- onIdle,
91
- onMouseMove,
92
- onError,
93
- },
94
- ref
95
- ) {
96
- const containerRef = useRef<HTMLDivElement>(null);
97
- const mapRef = useRef<SphereMapInstance | null>(null);
98
- const [isReady, setIsReady] = useState(false);
99
- const { sphere, isLoaded, registerMap, unregisterMap } = useSphereContext();
100
-
101
- const callbacksRef = useRef({
65
+ export function SphereMap({
66
+ children,
67
+ ref,
68
+ zoom = 7,
69
+ zoomRange,
70
+ center,
71
+ language = "th",
72
+ input = true,
73
+ lastView = false,
74
+ ui,
75
+ filter,
76
+ rotate,
77
+ pitch,
78
+ className,
79
+ style,
80
+ id,
81
+ onReady,
82
+ onZoom,
83
+ onLocation,
84
+ onClick,
85
+ onDoubleClick,
86
+ onRotate,
87
+ onPitch,
88
+ onDrag,
89
+ onDrop,
90
+ onIdle,
91
+ onMouseMove,
92
+ onError,
93
+ }: SphereMapProps) {
94
+ const containerRef = useRef<HTMLDivElement>(null);
95
+ const mapRef = useRef<SphereMapInstance | null>(null);
96
+ const [isReady, setIsReady] = useState(false);
97
+ const { sphere, isLoaded, registerMap, unregisterMap } = useSphereContext();
98
+
99
+ const callbacksRef = useRef({
100
+ onReady,
101
+ onZoom,
102
+ onLocation,
103
+ onClick,
104
+ onDoubleClick,
105
+ onRotate,
106
+ onPitch,
107
+ onDrag,
108
+ onDrop,
109
+ onIdle,
110
+ onMouseMove,
111
+ onError,
112
+ });
113
+
114
+ useEffect(() => {
115
+ callbacksRef.current = {
102
116
  onReady,
103
117
  onZoom,
104
118
  onLocation,
@@ -111,205 +125,186 @@ export const SphereMap = forwardRef<SphereMapRef, SphereMapProps>(
111
125
  onIdle,
112
126
  onMouseMove,
113
127
  onError,
114
- });
115
-
116
- useEffect(() => {
117
- callbacksRef.current = {
118
- onReady,
119
- onZoom,
120
- onLocation,
121
- onClick,
122
- onDoubleClick,
123
- onRotate,
124
- onPitch,
125
- onDrag,
126
- onDrop,
127
- onIdle,
128
- onMouseMove,
129
- onError,
128
+ };
129
+ });
130
+
131
+ const initialPropsRef = useRef({
132
+ zoom,
133
+ zoomRange,
134
+ center,
135
+ language,
136
+ input,
137
+ lastView,
138
+ ui,
139
+ filter,
140
+ rotate,
141
+ pitch,
142
+ });
143
+
144
+ useEffect(() => {
145
+ if (!(isLoaded && sphere && containerRef.current)) {
146
+ return;
147
+ }
148
+
149
+ const initialProps = initialPropsRef.current;
150
+
151
+ try {
152
+ const options: MapOptions = {
153
+ placeholder: containerRef.current,
154
+ zoom: initialProps.zoom,
155
+ language: initialProps.language,
156
+ input: initialProps.input,
157
+ lastView: initialProps.lastView,
130
158
  };
131
- });
132
-
133
- const initialPropsRef = useRef({
134
- zoom,
135
- zoomRange,
136
- center,
137
- language,
138
- input,
139
- lastView,
140
- ui,
141
- filter,
142
- rotate,
143
- pitch,
144
- });
145
-
146
- useEffect(() => {
147
- if (!(isLoaded && sphere && containerRef.current)) {
148
- return;
159
+
160
+ if (initialProps.zoomRange) {
161
+ options.zoomRange = initialProps.zoomRange;
162
+ }
163
+
164
+ if (initialProps.center) {
165
+ options.location = initialProps.center;
149
166
  }
150
167
 
151
- const initialProps = initialPropsRef.current;
168
+ if (initialProps.ui) {
169
+ options.ui = initialProps.ui;
170
+ }
152
171
 
153
- try {
154
- const options: MapOptions = {
155
- placeholder: containerRef.current,
156
- zoom: initialProps.zoom,
157
- language: initialProps.language,
158
- input: initialProps.input,
159
- lastView: initialProps.lastView,
160
- };
172
+ const map = new sphere.Map(options);
173
+ mapRef.current = map;
161
174
 
162
- if (initialProps.zoomRange) {
163
- options.zoomRange = initialProps.zoomRange;
164
- }
175
+ map.Event.bind("ready", () => {
176
+ setIsReady(true);
177
+ registerMap(map);
165
178
 
166
- if (initialProps.center) {
167
- options.location = initialProps.center;
179
+ if (initialProps.filter && window.sphere) {
180
+ map.enableFilter(window.sphere.Filter[initialProps.filter]);
168
181
  }
169
182
 
170
- if (initialProps.ui) {
171
- options.ui = initialProps.ui;
183
+ if (typeof initialProps.rotate === "number") {
184
+ map.rotate(initialProps.rotate, false);
172
185
  }
173
186
 
174
- const map = new sphere.Map(options);
175
- mapRef.current = map;
176
-
177
- map.Event.bind("ready", () => {
178
- setIsReady(true);
179
- registerMap(map);
180
-
181
- if (initialProps.filter && window.sphere) {
182
- map.enableFilter(window.sphere.Filter[initialProps.filter]);
183
- }
184
-
185
- if (typeof initialProps.rotate === "number") {
186
- map.rotate(initialProps.rotate, false);
187
- }
188
-
189
- if (typeof initialProps.pitch === "number") {
190
- map.pitch(initialProps.pitch);
191
- }
192
-
193
- callbacksRef.current.onReady?.(map);
194
- });
195
-
196
- map.Event.bind("zoom", () => {
197
- const currentZoom = map.zoom() as number;
198
- callbacksRef.current.onZoom?.(currentZoom);
199
- });
200
-
201
- map.Event.bind("location", () => {
202
- const currentLocation = map.location() as Location;
203
- callbacksRef.current.onLocation?.(currentLocation);
204
- });
205
-
206
- map.Event.bind("click", (location: Location) => {
207
- callbacksRef.current.onClick?.(location);
208
- });
209
-
210
- map.Event.bind("doubleClick", (location: Location) => {
211
- callbacksRef.current.onDoubleClick?.(location);
212
- });
213
-
214
- map.Event.bind("rotate", () => {
215
- const angle = map.rotate() as number;
216
- callbacksRef.current.onRotate?.(angle);
217
- });
218
-
219
- map.Event.bind("pitch", () => {
220
- const angle = map.pitch() as number;
221
- callbacksRef.current.onPitch?.(angle);
222
- });
223
-
224
- map.Event.bind("drag", () => {
225
- callbacksRef.current.onDrag?.();
226
- });
227
-
228
- map.Event.bind("drop", () => {
229
- callbacksRef.current.onDrop?.();
230
- });
231
-
232
- map.Event.bind("idle", () => {
233
- callbacksRef.current.onIdle?.();
234
- });
235
-
236
- map.Event.bind("mousemove", (location: Location) => {
237
- callbacksRef.current.onMouseMove?.(location);
238
- });
239
-
240
- map.Event.bind("error", (error: Error) => {
241
- callbacksRef.current.onError?.(error);
242
- });
243
- } catch (error) {
244
- callbacksRef.current.onError?.(
245
- error instanceof Error ? error : new Error(String(error))
246
- );
247
- }
187
+ if (typeof initialProps.pitch === "number") {
188
+ map.pitch(initialProps.pitch);
189
+ }
248
190
 
249
- return () => {
250
- unregisterMap();
251
- mapRef.current = null;
252
- setIsReady(false);
253
- };
254
- // eslint-disable-next-line react-hooks/exhaustive-deps
255
- }, [isLoaded, sphere, registerMap, unregisterMap]);
256
-
257
- useImperativeHandle(
258
- ref,
259
- () => ({
260
- getMap: () => mapRef.current,
261
- setZoom: (newZoom: number, animate = true) => {
262
- mapRef.current?.zoom(newZoom, animate);
263
- },
264
- setCenter: (location: Location, animate = true) => {
265
- mapRef.current?.location(location, animate);
266
- },
267
- setBound: (bound: Bound, options?: object) => {
268
- mapRef.current?.bound(bound, options);
269
- },
270
- goTo: (target: FlyToOptions, animate = true) => {
271
- mapRef.current?.goTo(target, animate);
272
- },
273
- setRotate: (angle: number, animate = true) => {
274
- mapRef.current?.rotate(angle, animate);
275
- },
276
- setPitch: (angle: number) => {
277
- mapRef.current?.pitch(angle);
278
- },
279
- setFilter: (newFilter: FilterType) => {
280
- if (mapRef.current && window.sphere) {
281
- mapRef.current.enableFilter(window.sphere.Filter[newFilter]);
282
- }
283
- },
284
- resize: () => {
285
- mapRef.current?.resize();
286
- },
287
- repaint: () => {
288
- mapRef.current?.repaint();
289
- },
290
- }),
291
- []
292
- );
293
-
294
- const containerStyle: CSSProperties = {
295
- width: "100%",
296
- height: "100%",
297
- ...style,
191
+ callbacksRef.current.onReady?.(map);
192
+ });
193
+
194
+ map.Event.bind("zoom", () => {
195
+ const currentZoom = map.zoom() as number;
196
+ callbacksRef.current.onZoom?.(currentZoom);
197
+ });
198
+
199
+ map.Event.bind("location", () => {
200
+ const currentLocation = map.location() as Location;
201
+ callbacksRef.current.onLocation?.(currentLocation);
202
+ });
203
+
204
+ map.Event.bind("click", (location: Location) => {
205
+ callbacksRef.current.onClick?.(location);
206
+ });
207
+
208
+ map.Event.bind("doubleClick", (location: Location) => {
209
+ callbacksRef.current.onDoubleClick?.(location);
210
+ });
211
+
212
+ map.Event.bind("rotate", () => {
213
+ const angle = map.rotate() as number;
214
+ callbacksRef.current.onRotate?.(angle);
215
+ });
216
+
217
+ map.Event.bind("pitch", () => {
218
+ const angle = map.pitch() as number;
219
+ callbacksRef.current.onPitch?.(angle);
220
+ });
221
+
222
+ map.Event.bind("drag", () => {
223
+ callbacksRef.current.onDrag?.();
224
+ });
225
+
226
+ map.Event.bind("drop", () => {
227
+ callbacksRef.current.onDrop?.();
228
+ });
229
+
230
+ map.Event.bind("idle", () => {
231
+ callbacksRef.current.onIdle?.();
232
+ });
233
+
234
+ map.Event.bind("mousemove", (location: Location) => {
235
+ callbacksRef.current.onMouseMove?.(location);
236
+ });
237
+
238
+ map.Event.bind("error", (error: Error) => {
239
+ callbacksRef.current.onError?.(error);
240
+ });
241
+ } catch (error) {
242
+ callbacksRef.current.onError?.(
243
+ error instanceof Error ? error : new Error(String(error))
244
+ );
245
+ }
246
+
247
+ return () => {
248
+ unregisterMap();
249
+ mapRef.current = null;
250
+ setIsReady(false);
298
251
  };
299
-
300
- return (
301
- <div
302
- className={className}
303
- id={id}
304
- ref={containerRef}
305
- style={containerStyle}
306
- >
307
- <MapProvider isReady={isReady} map={mapRef.current}>
308
- {isReady && children}
309
- </MapProvider>
310
- </div>
311
- );
312
- }
313
- );
314
-
315
- export default SphereMap;
252
+ // eslint-disable-next-line react-hooks/exhaustive-deps
253
+ }, [isLoaded, sphere, registerMap, unregisterMap]);
254
+
255
+ useImperativeHandle(
256
+ ref,
257
+ () => ({
258
+ getMap: () => mapRef.current,
259
+ setZoom: (newZoom: number, animate = true) => {
260
+ mapRef.current?.zoom(newZoom, animate);
261
+ },
262
+ setCenter: (location: Location, animate = true) => {
263
+ mapRef.current?.location(location, animate);
264
+ },
265
+ setBound: (bound: Bound, options?: object) => {
266
+ mapRef.current?.bound(bound, options);
267
+ },
268
+ goTo: (target: FlyToOptions, animate = true) => {
269
+ mapRef.current?.goTo(target, animate);
270
+ },
271
+ setRotate: (angle: number, animate = true) => {
272
+ mapRef.current?.rotate(angle, animate);
273
+ },
274
+ setPitch: (angle: number) => {
275
+ mapRef.current?.pitch(angle);
276
+ },
277
+ setFilter: (newFilter: FilterType) => {
278
+ if (mapRef.current && window.sphere) {
279
+ mapRef.current.enableFilter(window.sphere.Filter[newFilter]);
280
+ }
281
+ },
282
+ resize: () => {
283
+ mapRef.current?.resize();
284
+ },
285
+ repaint: () => {
286
+ mapRef.current?.repaint();
287
+ },
288
+ }),
289
+ []
290
+ );
291
+
292
+ const containerStyle: CSSProperties = {
293
+ width: "100%",
294
+ height: "100%",
295
+ ...style,
296
+ };
297
+
298
+ return (
299
+ <div
300
+ className={className}
301
+ id={id}
302
+ ref={containerRef}
303
+ style={containerStyle}
304
+ >
305
+ <MapProvider isReady={isReady} map={mapRef.current}>
306
+ {isReady && children}
307
+ </MapProvider>
308
+ </div>
309
+ );
310
+ }
@@ -15,4 +15,4 @@ export { Popup } from "./Popup";
15
15
  export type { RectangleProps, RectangleRef } from "./Rectangle";
16
16
  export { Rectangle } from "./Rectangle";
17
17
  export type { SphereMapProps, SphereMapRef } from "./SphereMap";
18
- export { default as Map, SphereMap } from "./SphereMap";
18
+ export { SphereMap, SphereMap as Map } from "./SphereMap";