@ttoss/google-maps 2.0.4 → 2.0.6

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,193 +0,0 @@
1
- /* eslint-disable react-hooks/exhaustive-deps */
2
- import { useCallback, useEffect, useRef, useState } from 'react';
3
- import { useGoogleMaps } from './../GoogleMapsProvider';
4
- import _debounce from './debounce';
5
- import useLatest from './useLatest';
6
-
7
- export interface HookArgs {
8
- requestOptions?: Omit<google.maps.places.AutocompletionRequest, 'input'>;
9
- debounce?: number;
10
- cache?: number | false;
11
- cacheKey?: string;
12
- callbackName?: string;
13
- defaultValue?: string;
14
- initOnMount?: boolean;
15
- }
16
-
17
- type Suggestion = google.maps.places.AutocompletePrediction;
18
-
19
- type Status = `${google.maps.places.PlacesServiceStatus}` | '';
20
-
21
- interface Suggestions {
22
- readonly loading: boolean;
23
- readonly status: Status;
24
- data: Suggestion[];
25
- }
26
-
27
- interface SetValue {
28
- (val: string, shouldFetchData?: boolean): void;
29
- }
30
-
31
- interface HookReturn {
32
- ready: boolean;
33
- value: string;
34
- suggestions: Suggestions;
35
- setValue: SetValue;
36
- clearSuggestions: () => void;
37
- clearCache: () => void;
38
- init: () => void;
39
- }
40
-
41
- export const loadApiErr = '💡 Google Maps Places API library must be loaded.';
42
-
43
- export const usePlacesAutocomplete = ({
44
- requestOptions,
45
- debounce = 200,
46
- cache = 24 * 60 * 60,
47
- cacheKey,
48
- callbackName,
49
- defaultValue = '',
50
- initOnMount = true,
51
- }: HookArgs = {}): HookReturn => {
52
- const [ready, setReady] = useState(false);
53
- const [value, setVal] = useState(defaultValue);
54
- const [suggestions, setSuggestions] = useState<Suggestions>({
55
- loading: false,
56
- status: '',
57
- data: [],
58
- });
59
- const asRef = useRef<any>(null);
60
- const requestOptionsRef = useLatest(requestOptions);
61
- const { googleMaps } = useGoogleMaps();
62
-
63
- const googleMapsRef = useLatest(googleMaps);
64
-
65
- const upaCacheKey = cacheKey ? `upa-${cacheKey}` : 'upa';
66
-
67
- const init = useCallback(() => {
68
- if (asRef.current) return;
69
-
70
- if (!googleMaps) {
71
- return;
72
- }
73
-
74
- const { current: gMaps } = googleMapsRef;
75
- const placesLib = gMaps?.places || googleMaps.places;
76
-
77
- if (!placesLib) {
78
- return;
79
- }
80
-
81
- asRef.current = new placesLib.AutocompleteService();
82
- setReady(true);
83
- }, [googleMaps]);
84
-
85
- const clearSuggestions = useCallback(() => {
86
- setSuggestions({ loading: false, status: '', data: [] });
87
- }, []);
88
-
89
- const clearCache = useCallback(() => {
90
- try {
91
- sessionStorage.removeItem(upaCacheKey);
92
- } catch (error) {
93
- // Skip exception
94
- }
95
- }, []);
96
-
97
- const fetchPredictions = useCallback(
98
- _debounce((val: string) => {
99
- if (!val) {
100
- clearSuggestions();
101
- return;
102
- }
103
-
104
- setSuggestions((prevState) => ({ ...prevState, loading: true }));
105
-
106
- let cachedData: Record<string, { data: Suggestion[]; maxAge: number }> =
107
- {};
108
-
109
- try {
110
- cachedData = JSON.parse(sessionStorage.getItem(upaCacheKey) || '{}');
111
- } catch (error) {
112
- // Skip exception
113
- }
114
-
115
- if (cache) {
116
- cachedData = Object.keys(cachedData).reduce(
117
- (acc: typeof cachedData, key) => {
118
- if (cachedData[key].maxAge - Date.now() >= 0)
119
- acc[key] = cachedData[key];
120
- return acc;
121
- },
122
- {}
123
- );
124
-
125
- if (cachedData[val]) {
126
- setSuggestions({
127
- loading: false,
128
- status: 'OK',
129
- data: cachedData[val].data,
130
- });
131
- return;
132
- }
133
- }
134
-
135
- asRef?.current?.getPlacePredictions(
136
- { ...requestOptionsRef.current, input: val },
137
- (data: Suggestion[] | null, status: Status) => {
138
- setSuggestions({ loading: false, status, data: data || [] });
139
-
140
- if (cache && status === 'OK') {
141
- cachedData[val] = {
142
- data: data as Suggestion[],
143
- maxAge: Date.now() + cache * 1000,
144
- };
145
-
146
- try {
147
- sessionStorage.setItem(upaCacheKey, JSON.stringify(cachedData));
148
- } catch (error) {
149
- // Skip exception
150
- }
151
- }
152
- }
153
- );
154
- }, debounce),
155
- [debounce, clearSuggestions]
156
- );
157
-
158
- const setValue: SetValue = useCallback(
159
- (val, shouldFetchData = true) => {
160
- setVal(val);
161
- if (asRef.current && shouldFetchData) fetchPredictions(val);
162
- },
163
- [fetchPredictions]
164
- );
165
-
166
- useEffect(() => {
167
- if (!initOnMount) {
168
- // eslint-disable-next-line react/display-name
169
- return () => null;
170
- }
171
-
172
- if (!googleMapsRef.current && !googleMaps && callbackName) {
173
- (window as any)[callbackName] = init;
174
- } else {
175
- init();
176
- }
177
-
178
- return () => {
179
- if ((window as any)[callbackName as string])
180
- delete (window as any)[callbackName as string];
181
- };
182
- }, [callbackName, init]);
183
-
184
- return {
185
- ready,
186
- value,
187
- suggestions,
188
- setValue,
189
- clearSuggestions,
190
- clearCache,
191
- init,
192
- };
193
- };
@@ -1,7 +0,0 @@
1
- import { RefObject, useRef } from 'react';
2
-
3
- export default <T>(val: T): RefObject<T> => {
4
- const ref = useRef(val);
5
- ref.current = val;
6
- return ref;
7
- };