ferns-ui 0.37.7 → 0.37.9

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 (40) hide show
  1. package/dist/Common.d.ts +2 -0
  2. package/dist/Constants.d.ts +12681 -0
  3. package/dist/Constants.js +3256 -0
  4. package/dist/Constants.js.map +1 -1
  5. package/dist/Field.d.ts +5 -1
  6. package/dist/Field.js +11 -4
  7. package/dist/Field.js.map +1 -1
  8. package/dist/MobileAddressAutoComplete.d.ts +12 -0
  9. package/dist/MobileAddressAutoComplete.js +55 -0
  10. package/dist/MobileAddressAutoComplete.js.map +1 -0
  11. package/dist/TapToEdit.js +8 -5
  12. package/dist/TapToEdit.js.map +1 -1
  13. package/dist/UnifiedAddressAutoComplete.d.ts +12 -0
  14. package/dist/UnifiedAddressAutoComplete.js +22 -0
  15. package/dist/UnifiedAddressAutoComplete.js.map +1 -0
  16. package/dist/Unifier.d.ts +5 -0
  17. package/dist/Unifier.js.map +1 -1
  18. package/dist/Utilities.d.ts +19 -0
  19. package/dist/Utilities.js +79 -0
  20. package/dist/Utilities.js.map +1 -1
  21. package/dist/WebAddressAutocomplete.d.ts +10 -0
  22. package/dist/WebAddressAutocomplete.js +57 -0
  23. package/dist/WebAddressAutocomplete.js.map +1 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.js +3 -0
  26. package/dist/index.js.map +1 -1
  27. package/dist/useStoredState.d.ts +1 -1
  28. package/dist/useStoredState.js.map +1 -1
  29. package/package.json +2 -1
  30. package/src/Common.ts +2 -0
  31. package/src/Constants.ts +3258 -0
  32. package/src/Field.tsx +41 -6
  33. package/src/MobileAddressAutoComplete.tsx +129 -0
  34. package/src/TapToEdit.tsx +11 -2
  35. package/src/UnifiedAddressAutoComplete.tsx +71 -0
  36. package/src/Unifier.ts +6 -0
  37. package/src/Utilities.tsx +120 -0
  38. package/src/WebAddressAutocomplete.tsx +90 -0
  39. package/src/index.tsx +3 -0
  40. package/src/useStoredState.ts +3 -3
package/src/Field.tsx CHANGED
@@ -1,4 +1,5 @@
1
1
  import React from "react";
2
+ import {Styles} from "react-native-google-places-autocomplete";
2
3
 
3
4
  import {Box} from "./Box";
4
5
  import {CheckBox} from "./CheckBox";
@@ -11,6 +12,7 @@ import {Switch} from "./Switch";
11
12
  import {Text} from "./Text";
12
13
  import {TextArea} from "./TextArea";
13
14
  import {TextField} from "./TextField";
15
+ import {UnifiedAddressAutoCompleteField} from "./UnifiedAddressAutoComplete";
14
16
 
15
17
  export interface FieldProps extends FieldWithLabelsProps {
16
18
  name?: string;
@@ -41,6 +43,9 @@ export interface FieldProps extends FieldWithLabelsProps {
41
43
  placeholder?: string;
42
44
  disabled?: boolean;
43
45
  useCheckbox?: boolean;
46
+ includeCounty?: boolean;
47
+ googleMapsApiKey?: string;
48
+ googlePlacesMobileStyles?: Styles;
44
49
  }
45
50
 
46
51
  export const Field = ({
@@ -59,11 +64,18 @@ export const Field = ({
59
64
  errorMessageColor,
60
65
  helperText,
61
66
  helperTextColor,
67
+ includeCounty = false,
68
+ googleMapsApiKey,
69
+ googlePlacesMobileStyles,
62
70
  }: FieldProps) => {
63
71
  const handleAddressChange = (field: string, newValue: string) => {
64
72
  onChange({...value, [field]: newValue});
65
73
  };
66
74
 
75
+ const handleAutoCompleteChange = (newValue: AddressInterface) => {
76
+ onChange({...value, ...newValue});
77
+ };
78
+
67
79
  const handleSwitchChange = (switchValue: boolean) => {
68
80
  onChange(switchValue);
69
81
  };
@@ -169,16 +181,19 @@ export const Field = ({
169
181
  city = "",
170
182
  state = "",
171
183
  zipcode = "",
184
+ countyName = "",
185
+ countyCode = "",
172
186
  }: AddressInterface = addressValue;
173
187
  return (
174
188
  <>
175
- <TextField
189
+ <UnifiedAddressAutoCompleteField
176
190
  disabled={disabled}
177
- id="address1"
178
- label="Street Address"
179
- type="text"
180
- value={address1}
181
- onChange={(result) => handleAddressChange("address1", result.value)}
191
+ googleMapsApiKey={googleMapsApiKey}
192
+ googlePlacesMobileStyles={googlePlacesMobileStyles}
193
+ handleAddressChange={(result) => handleAddressChange("address1", result.value)}
194
+ handleAutoCompleteChange={(result) => handleAutoCompleteChange(result)}
195
+ includeCounty={includeCounty}
196
+ inputValue={address1}
182
197
  />
183
198
  <TextField
184
199
  disabled={disabled}
@@ -214,6 +229,26 @@ export const Field = ({
214
229
  value={zipcode}
215
230
  onChange={(result) => handleAddressChange("zipcode", result.value)}
216
231
  />
232
+ {includeCounty && (
233
+ <>
234
+ <TextField
235
+ disabled={disabled}
236
+ id="countyName"
237
+ label="County Name"
238
+ type="text"
239
+ value={countyName}
240
+ onChange={(result) => handleAddressChange("countyName", result.value)}
241
+ />
242
+ <TextField
243
+ disabled={disabled}
244
+ id="countyCode"
245
+ label="County Code"
246
+ type="number"
247
+ value={countyCode}
248
+ onChange={(result) => handleAddressChange("countyCode", result.value)}
249
+ />
250
+ </>
251
+ )}
217
252
  </>
218
253
  );
219
254
  } else if (type === "customSelect") {
@@ -0,0 +1,129 @@
1
+ import React, {useContext, useEffect, useRef, useState} from "react";
2
+ import {TextStyle, TouchableOpacity, View} from "react-native";
3
+ import {
4
+ GooglePlacesAutocomplete,
5
+ GooglePlacesAutocompleteRef,
6
+ Styles,
7
+ } from "react-native-google-places-autocomplete";
8
+
9
+ import {AddressInterface, OnChangeCallback} from "./Common";
10
+ import {GOOGLE_PLACES_API_RESTRICTIONS} from "./Constants";
11
+ import {TextField} from "./TextField";
12
+ import {ThemeContext} from "./Theme";
13
+ import {processAddressComponents} from "./Utilities";
14
+
15
+ export const MobileAddressAutocomplete = ({
16
+ disabled,
17
+ googleMapsApiKey,
18
+ includeCounty,
19
+ inputValue,
20
+ // More on react-native-google-places-autocomplete styles here: https://github.com/FaridSafi/react-native-google-places-autocomplete#styling
21
+ styles,
22
+ handleAddressChange,
23
+ handleAutoCompleteChange,
24
+ }: {
25
+ disabled?: boolean;
26
+ googleMapsApiKey?: string;
27
+ includeCounty?: boolean;
28
+ inputValue: string;
29
+ styles?: Styles;
30
+ handleAddressChange: OnChangeCallback;
31
+ handleAutoCompleteChange: (value: AddressInterface) => void;
32
+ }) => {
33
+ const {theme} = useContext(ThemeContext);
34
+ const ref = useRef<GooglePlacesAutocompleteRef | null>(null);
35
+ const [isFocused, setIsFocused] = useState(false);
36
+
37
+ useEffect(() => {
38
+ if (!googleMapsApiKey) return;
39
+ if (ref?.current) {
40
+ ref.current.setAddressText(inputValue);
41
+ }
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, []);
44
+
45
+ const textInputContainerStyles = {
46
+ backgroundColor: theme.white,
47
+ borderColor: isFocused ? theme.blue : theme.gray,
48
+ borderWidth: isFocused ? 5 : 1,
49
+ borderRadius: 16,
50
+ paddingHorizontal: isFocused ? 10 : 14,
51
+ paddingVertical: isFocused ? 0 : 4,
52
+ ...(styles?.textInputContainer as object),
53
+ };
54
+
55
+ const textInputStyles = {
56
+ backgroundColor: theme.white,
57
+ borderRadius: 16,
58
+ color: theme.darkGray,
59
+ fontFamily: theme.primaryFont,
60
+ fontSize: (styles?.textInput as TextStyle)?.fontSize ?? 14,
61
+ height: 40,
62
+ marginBottom: 0,
63
+ paddingHorizontal: 0,
64
+ paddingVertical: 4,
65
+ ...(styles?.textInput as object),
66
+ };
67
+
68
+ if (!googleMapsApiKey) {
69
+ return (
70
+ <TextField
71
+ disabled={disabled}
72
+ id="address1"
73
+ label="Street Address"
74
+ type="text"
75
+ value={inputValue}
76
+ onChange={(result) => handleAddressChange(result)}
77
+ />
78
+ );
79
+ }
80
+
81
+ return (
82
+ <TouchableOpacity activeOpacity={1} style={{flex: 1}} onPress={() => setIsFocused(false)}>
83
+ <View>
84
+ <GooglePlacesAutocomplete
85
+ ref={ref}
86
+ GooglePlacesDetailsQuery={{
87
+ fields: Object.values(GOOGLE_PLACES_API_RESTRICTIONS.fields).join(","),
88
+ }}
89
+ disableScroll
90
+ fetchDetails
91
+ placeholder="Street Address"
92
+ query={{
93
+ key: googleMapsApiKey,
94
+ language: "en",
95
+ components: `country:${GOOGLE_PLACES_API_RESTRICTIONS.components.country}`,
96
+ }}
97
+ styles={{
98
+ textInputContainer: {
99
+ ...textInputContainerStyles,
100
+ },
101
+ textInput: {
102
+ ...textInputStyles,
103
+ },
104
+ ...styles,
105
+ }}
106
+ textInputProps={{
107
+ onFocus: () => setIsFocused(true),
108
+ onBlur: () => setIsFocused(false),
109
+ onChange: (event) => {
110
+ handleAddressChange({value: event.nativeEvent.text});
111
+ },
112
+ }}
113
+ onPress={(data, details = null) => {
114
+ const addressComponents = details?.address_components;
115
+ const formattedAddressObject = processAddressComponents(addressComponents, {
116
+ includeCounty,
117
+ });
118
+ const {address1} = formattedAddressObject;
119
+ handleAutoCompleteChange(formattedAddressObject);
120
+ if (ref.current) {
121
+ ref.current.setAddressText(address1);
122
+ }
123
+ setIsFocused(false);
124
+ }}
125
+ />
126
+ </View>
127
+ </TouchableOpacity>
128
+ );
129
+ };
package/src/TapToEdit.tsx CHANGED
@@ -21,19 +21,28 @@ export function formatAddress(address: any, asString = false): string {
21
21
 
22
22
  const zip = address?.zipcode || "";
23
23
 
24
+ const countyName = address?.countyName ?? "";
25
+
26
+ const countyCode = address?.countyCode ?? "";
27
+
24
28
  const addressLineOne = address?.address1 ?? "";
25
29
  const addressLineTwo = address?.address2 ?? "";
26
30
  const addressLineThree = `${city}${state}${zip}`;
31
+ const addressLineFour = `${countyName}${address?.countyCode ? ` [${countyCode}]` : ""}`;
27
32
 
28
33
  if (!asString) {
29
34
  // Only add new lines if lines before and after are not empty to avoid awkward whitespace
30
35
  return `${addressLineOne}${
31
36
  addressLineOne && (addressLineTwo || addressLineThree) ? `\n` : ""
32
- }${addressLineTwo}${addressLineTwo && addressLineThree ? `\n` : ""}${addressLineThree}`;
37
+ }${addressLineTwo}${addressLineTwo && addressLineThree ? `\n` : ""}${addressLineThree}${
38
+ addressLineThree && addressLineFour ? `\n` : ""
39
+ }${addressLineFour}`;
33
40
  } else {
34
41
  return `${addressLineOne}${
35
42
  addressLineOne && (addressLineTwo || addressLineThree) ? `, ` : ""
36
- }${addressLineTwo}${addressLineTwo && addressLineThree ? `, ` : ""}${addressLineThree}`;
43
+ }${addressLineTwo}${addressLineTwo && addressLineThree ? `, ` : ""}${addressLineThree}${
44
+ addressLineThree && addressLineFour ? `, ` : ""
45
+ }${addressLineFour}`;
37
46
  }
38
47
  }
39
48
 
@@ -0,0 +1,71 @@
1
+ import React, {useMemo} from "react";
2
+ import {Styles} from "react-native-google-places-autocomplete";
3
+
4
+ import {AddressInterface, OnChangeCallback} from "./Common";
5
+ import {isMobileDevice} from "./MediaQuery";
6
+ import {MobileAddressAutocomplete} from "./MobileAddressAutoComplete";
7
+ import {TextField} from "./TextField";
8
+ import {isNative, isValidGoogleApiKey} from "./Utilities";
9
+ import {WebAddressAutocomplete} from "./WebAddressAutocomplete";
10
+
11
+ export const UnifiedAddressAutoCompleteField = ({
12
+ disabled,
13
+ googleMapsApiKey,
14
+ googlePlacesMobileStyles,
15
+ includeCounty,
16
+ inputValue,
17
+ handleAddressChange,
18
+ handleAutoCompleteChange,
19
+ }: {
20
+ disabled?: boolean;
21
+ googleMapsApiKey?: string;
22
+ googlePlacesMobileStyles?: Styles;
23
+ includeCounty?: boolean;
24
+ inputValue: string;
25
+ handleAddressChange: OnChangeCallback;
26
+ handleAutoCompleteChange: (value: AddressInterface) => void;
27
+ }) => {
28
+ const isWeb = typeof document !== "undefined";
29
+ const isValidatedGoogleApiKey = useMemo(
30
+ () => (googleMapsApiKey ? isValidGoogleApiKey(googleMapsApiKey) : false),
31
+ [googleMapsApiKey]
32
+ );
33
+
34
+ if (isWeb && isValidatedGoogleApiKey) {
35
+ return (
36
+ <WebAddressAutocomplete
37
+ disabled={disabled}
38
+ googleMapsApiKey={googleMapsApiKey}
39
+ handleAddressChange={handleAddressChange}
40
+ handleAutoCompleteChange={handleAutoCompleteChange}
41
+ includeCounty={includeCounty}
42
+ inputValue={inputValue}
43
+ />
44
+ );
45
+ } else if (isMobileDevice() && isNative() && isValidatedGoogleApiKey) {
46
+ return (
47
+ <MobileAddressAutocomplete
48
+ disabled={disabled}
49
+ googleMapsApiKey={googleMapsApiKey}
50
+ handleAddressChange={handleAddressChange}
51
+ handleAutoCompleteChange={handleAutoCompleteChange}
52
+ includeCounty={includeCounty}
53
+ inputValue={inputValue}
54
+ styles={googlePlacesMobileStyles}
55
+ />
56
+ );
57
+ } else {
58
+ return (
59
+ <TextField
60
+ disabled={disabled}
61
+ label="Street Address"
62
+ placeholder="Enter an address"
63
+ type="text"
64
+ value={inputValue}
65
+ onChange={({value}): void => {
66
+ handleAddressChange({value});
67
+ }}
68
+ />
69
+ );
70
+ }
71
+ };
package/src/Unifier.ts CHANGED
@@ -9,6 +9,12 @@ import {Dimensions, Keyboard, Linking, Platform, Vibration} from "react-native";
9
9
  import {PermissionKind, UnifiedTheme} from "./Common";
10
10
  import {requestPermissions} from "./Permissions";
11
11
 
12
+ declare global {
13
+ interface Window {
14
+ google: any;
15
+ }
16
+ }
17
+
12
18
  export type PlatformOS = "ios" | "android" | "web";
13
19
 
14
20
  type Luminance = "light" | "lighter" | "dark" | "darker";
package/src/Utilities.tsx CHANGED
@@ -3,6 +3,8 @@
3
3
  import get from "lodash/get";
4
4
  import {Platform} from "react-native";
5
5
 
6
+ import {COUNTY_AND_COUNTY_EQUIVALENT_ENTITIES} from "./Constants";
7
+
6
8
  export function mergeInlineStyles(inlineStyle?: any, newStyle?: any) {
7
9
  const inline = get(inlineStyle, "__style");
8
10
  return {
@@ -162,3 +164,121 @@ export const union =
162
164
  export const isNative = (): boolean => {
163
165
  return ["android", "ios"].includes(Platform.OS);
164
166
  };
167
+
168
+ // Find more information about the address component types here: https://developers.google.com/maps/documentation/javascript/place-autocomplete
169
+ export type AddressComponentType = {
170
+ long_name: string;
171
+ short_name: string;
172
+ types: string[];
173
+ };
174
+
175
+ export const findAddressComponent = (components: AddressComponentType[], type: string): string => {
176
+ return (
177
+ components.find((component: AddressComponentType) => component.types.includes(type))
178
+ ?.long_name ?? ""
179
+ );
180
+ };
181
+
182
+ interface ProcessAddressComponentOptions {
183
+ includeCounty?: boolean;
184
+ }
185
+
186
+ export const processAddressComponents = (
187
+ addressComponents: AddressComponentType[] | undefined,
188
+ options?: ProcessAddressComponentOptions
189
+ ) => {
190
+ let processedAddressComponents: {
191
+ address1: string;
192
+ city: string;
193
+ state: string;
194
+ zipcode: string;
195
+ countyName?: string;
196
+ countyCode?: string;
197
+ } = {
198
+ address1: "",
199
+ city: "",
200
+ state: "",
201
+ zipcode: "",
202
+ };
203
+
204
+ if (!addressComponents || addressComponents.length === 0) {
205
+ console.warn("Invalid address components");
206
+ if (options?.includeCounty) {
207
+ return {
208
+ ...processedAddressComponents,
209
+ countyName: "",
210
+ countyCode: "",
211
+ };
212
+ } else {
213
+ return processedAddressComponents;
214
+ }
215
+ }
216
+
217
+ const streetNumber = findAddressComponent(addressComponents, "street_number");
218
+ const streetName = findAddressComponent(addressComponents, "route");
219
+ const city = findAddressComponent(addressComponents, "locality");
220
+ const state = findAddressComponent(addressComponents, "administrative_area_level_1");
221
+ const zipcode = findAddressComponent(addressComponents, "postal_code");
222
+
223
+ processedAddressComponents = {
224
+ address1: `${streetNumber} ${streetName}`.trim(),
225
+ city,
226
+ state,
227
+ zipcode,
228
+ };
229
+
230
+ if (options?.includeCounty) {
231
+ const countyName = findAddressComponent(addressComponents, "administrative_area_level_2");
232
+ if (state && countyName) {
233
+ const countyCode = formattedCountyCode(state, countyName);
234
+ processedAddressComponents = {
235
+ ...processedAddressComponents,
236
+ countyName,
237
+ countyCode,
238
+ };
239
+ } else {
240
+ processedAddressComponents = {
241
+ ...processedAddressComponents,
242
+ countyName,
243
+ };
244
+ }
245
+ }
246
+ return processedAddressComponents;
247
+ };
248
+
249
+ // Google does not provide a way to validate API keys, so we have to do it ourselves
250
+ export const isValidGoogleApiKey = (apiKey: string): boolean => {
251
+ if (typeof apiKey !== "string" || apiKey.trim().length === 0) {
252
+ console.warn("Google API key validation failed: key is not a string or is empty");
253
+ return false;
254
+ }
255
+ // Typical Google API keys are around 39 characters
256
+ if (apiKey.length < 30 || apiKey.length > 50) {
257
+ console.warn("Google API key validation failed: key is invalid length");
258
+ return false;
259
+ }
260
+ // Check the presence of alphanumeric characters and dashes
261
+ const apiKeyRegex = /^[A-Za-z0-9-_]+$/;
262
+ if (!apiKeyRegex.test(apiKey)) {
263
+ console.warn("Google API key validation failed: key contains invalid characters");
264
+ return false;
265
+ }
266
+ return true;
267
+ };
268
+
269
+ export function formattedCountyCode(state: string, countyName: string): string {
270
+ // Remove whitespace and convert to lowercase for comparison
271
+ const stateKey = state.replace(/\s+/g, "").toLowerCase();
272
+ // Remove whitespace, periods, apostrophes, and dashes for comparison
273
+ const countyKey = countyName
274
+ .trim()
275
+ .toLowerCase()
276
+ .replace(/[\s.'-]/g, "");
277
+
278
+ const countyData = COUNTY_AND_COUNTY_EQUIVALENT_ENTITIES[stateKey]?.[countyKey];
279
+ if (!countyData) {
280
+ return "";
281
+ }
282
+
283
+ return `${countyData.stateFP}${countyData.countyFP}`;
284
+ }
@@ -0,0 +1,90 @@
1
+ import React, {ReactElement, useEffect, useRef, useState} from "react";
2
+
3
+ import {AddressInterface, OnChangeCallback} from "./Common";
4
+ import {GOOGLE_PLACES_API_RESTRICTIONS} from "./Constants";
5
+ import {TextField} from "./TextField";
6
+ import {processAddressComponents} from "./Utilities";
7
+
8
+ const loadGooglePlacesScript = (googleMapsApiKey: string, callbackName: any): Promise<void> => {
9
+ return new Promise<void>((resolve, reject): undefined => {
10
+ if (window.google && window.google.maps && window.google.maps.places) {
11
+ resolve();
12
+ return;
13
+ }
14
+ (window as any)[callbackName] = (): void => resolve();
15
+ const script: HTMLScriptElement = document.createElement("script");
16
+
17
+ script.src = `https://maps.googleapis.com/maps/api/js?key=${googleMapsApiKey}&libraries=places&callback=${callbackName}`;
18
+ script.async = true;
19
+ script.defer = true;
20
+ script.onerror = (): any => reject(new Error("Google Maps script failed to load"));
21
+ document.head.appendChild(script);
22
+ });
23
+ };
24
+
25
+ export const WebAddressAutocomplete = ({
26
+ disabled,
27
+ googleMapsApiKey,
28
+ includeCounty,
29
+ inputValue,
30
+ handleAddressChange,
31
+ handleAutoCompleteChange,
32
+ }: {
33
+ disabled?: boolean;
34
+ googleMapsApiKey?: string;
35
+ includeCounty?: boolean;
36
+ inputValue: string;
37
+ handleAddressChange: OnChangeCallback;
38
+ handleAutoCompleteChange: (value: AddressInterface) => void;
39
+ }): ReactElement => {
40
+ const [scriptLoaded, setScriptLoaded] = useState(true);
41
+ const autocompleteInputRef = useRef(null);
42
+
43
+ useEffect(() => {
44
+ const callbackName = "initAutocomplete";
45
+ if (!googleMapsApiKey) {
46
+ setScriptLoaded(false);
47
+ return;
48
+ }
49
+ loadGooglePlacesScript(googleMapsApiKey, callbackName)
50
+ .then(() => {
51
+ const autocomplete = new window.google.maps.places.Autocomplete(
52
+ autocompleteInputRef.current,
53
+ {
54
+ componentRestrictions: {country: GOOGLE_PLACES_API_RESTRICTIONS.components.country},
55
+ fields: Object.values(GOOGLE_PLACES_API_RESTRICTIONS.fields),
56
+ }
57
+ );
58
+ autocomplete.addListener("place_changed", () => {
59
+ const place = autocomplete.getPlace();
60
+ const addressComponents = place?.address_components;
61
+ const formattedAddressObject = processAddressComponents(addressComponents, {
62
+ includeCounty,
63
+ });
64
+ handleAutoCompleteChange(formattedAddressObject);
65
+ });
66
+ })
67
+ .catch((error) => {
68
+ console.warn(error);
69
+ setScriptLoaded(false);
70
+ });
71
+ // Cleanup
72
+ return () => {
73
+ (window as any)[callbackName] = null;
74
+ };
75
+ }, [googleMapsApiKey, includeCounty, handleAutoCompleteChange]);
76
+
77
+ return (
78
+ <TextField
79
+ disabled={disabled}
80
+ inputRef={scriptLoaded ? (ref: any): void => (autocompleteInputRef.current = ref) : undefined}
81
+ label="Street Address"
82
+ placeholder="Enter an address"
83
+ type="text"
84
+ value={inputValue}
85
+ onChange={({value}): void => {
86
+ handleAddressChange({value});
87
+ }}
88
+ />
89
+ );
90
+ };
package/src/index.tsx CHANGED
@@ -30,6 +30,7 @@ export * from "./InfoTooltipButton";
30
30
  export * from "./Link";
31
31
  export * from "./Mask";
32
32
  export * from "./Meta";
33
+ export * from "./MobileAddressAutoComplete";
33
34
  export * from "./Modal";
34
35
 
35
36
  export * from "./Page";
@@ -48,6 +49,7 @@ export * from "./Tooltip";
48
49
  export * from "./Toast";
49
50
  export * from "./UnifiedScreens";
50
51
  export * from "./Unifier";
52
+ export * from "./UnifiedAddressAutoComplete";
51
53
  export * from "./WithLabel";
52
54
  export * from "./DecimalRangeActionSheet";
53
55
  export * from "./HeightActionSheet";
@@ -63,6 +65,7 @@ export * from "./TableHeaderCell";
63
65
  export * from "./TableRow";
64
66
  export * from "./Theme";
65
67
  export * from "./useStoredState";
68
+ export * from "./WebAddressAutocomplete";
66
69
 
67
70
  // Lifted from react-native
68
71
  type ImageRequireSource = number;
@@ -5,8 +5,8 @@ import {Unifier} from "./Unifier";
5
5
  export const useStoredState = <T>(
6
6
  key: string,
7
7
  initialValue?: T
8
- ): [T | undefined | null, (value: T | undefined | null) => Promise<void>] => {
9
- const [state, setState] = useState<T | undefined | null>(initialValue);
8
+ ): [T | undefined, (value: T | undefined) => Promise<void>] => {
9
+ const [state, setState] = useState<T | undefined>(initialValue);
10
10
 
11
11
  // Function to fetch data from AsyncStorage
12
12
  const fetchData = useCallback(async (): Promise<T | undefined> => {
@@ -26,7 +26,7 @@ export const useStoredState = <T>(
26
26
  // eslint-disable-next-line react-hooks/exhaustive-deps
27
27
  }, []);
28
28
 
29
- const setAsyncStorageState = async (newValue: T | undefined | null): Promise<void> => {
29
+ const setAsyncStorageState = async (newValue: T | undefined): Promise<void> => {
30
30
  try {
31
31
  await Unifier.storage.setItem(key, newValue);
32
32
  setState(newValue);