@terreno/ui 0.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.
- package/LICENSE +203 -0
- package/README.md +160 -0
- package/dist/Accordion.d.ts +3 -0
- package/dist/Accordion.js +30 -0
- package/dist/Accordion.js.map +1 -0
- package/dist/ActionSheet.d.ts +169 -0
- package/dist/ActionSheet.js +637 -0
- package/dist/ActionSheet.js.map +1 -0
- package/dist/AddressField.d.ts +3 -0
- package/dist/AddressField.js +18 -0
- package/dist/AddressField.js.map +1 -0
- package/dist/Avatar.d.ts +3 -0
- package/dist/Avatar.js +189 -0
- package/dist/Avatar.js.map +1 -0
- package/dist/Badge.d.ts +3 -0
- package/dist/Badge.js +100 -0
- package/dist/Badge.js.map +1 -0
- package/dist/Banner.d.ts +4 -0
- package/dist/Banner.js +103 -0
- package/dist/Banner.js.map +1 -0
- package/dist/Body.d.ts +3 -0
- package/dist/Body.js +17 -0
- package/dist/Body.js.map +1 -0
- package/dist/BooleanField.d.ts +3 -0
- package/dist/BooleanField.js +89 -0
- package/dist/BooleanField.js.map +1 -0
- package/dist/Box.d.ts +3 -0
- package/dist/Box.js +289 -0
- package/dist/Box.js.map +1 -0
- package/dist/Button.d.ts +3 -0
- package/dist/Button.js +105 -0
- package/dist/Button.js.map +1 -0
- package/dist/Card.d.ts +2 -0
- package/dist/Card.js +18 -0
- package/dist/Card.js.map +1 -0
- package/dist/CheckBox.d.ts +3 -0
- package/dist/CheckBox.js +28 -0
- package/dist/CheckBox.js.map +1 -0
- package/dist/Common.d.ts +2325 -0
- package/dist/Common.js +47 -0
- package/dist/Common.js.map +1 -0
- package/dist/CommonIconTypes.d.ts +3 -0
- package/dist/CommonIconTypes.js +2 -0
- package/dist/CommonIconTypes.js.map +1 -0
- package/dist/Constants.d.ts +12685 -0
- package/dist/Constants.js +3310 -0
- package/dist/Constants.js.map +1 -0
- package/dist/CustomSelectField.d.ts +3 -0
- package/dist/CustomSelectField.js +59 -0
- package/dist/CustomSelectField.js.map +1 -0
- package/dist/DataTable.d.ts +3 -0
- package/dist/DataTable.js +190 -0
- package/dist/DataTable.js.map +1 -0
- package/dist/DateTimeActionSheet.d.ts +2 -0
- package/dist/DateTimeActionSheet.js +270 -0
- package/dist/DateTimeActionSheet.js.map +1 -0
- package/dist/DateTimeField.d.ts +3 -0
- package/dist/DateTimeField.js +514 -0
- package/dist/DateTimeField.js.map +1 -0
- package/dist/DateUtilities.d.ts +57 -0
- package/dist/DateUtilities.js +308 -0
- package/dist/DateUtilities.js.map +1 -0
- package/dist/DecimalRangeActionSheet.d.ts +6 -0
- package/dist/DecimalRangeActionSheet.js +45 -0
- package/dist/DecimalRangeActionSheet.js.map +1 -0
- package/dist/DismissButton.d.ts +3 -0
- package/dist/DismissButton.js +12 -0
- package/dist/DismissButton.js.map +1 -0
- package/dist/EmailField.d.ts +3 -0
- package/dist/EmailField.js +48 -0
- package/dist/EmailField.js.map +1 -0
- package/dist/EmojiSelector.d.ts +113 -0
- package/dist/EmojiSelector.js +322 -0
- package/dist/EmojiSelector.js.map +1 -0
- package/dist/ErrorBoundary.d.ts +19 -0
- package/dist/ErrorBoundary.js +30 -0
- package/dist/ErrorBoundary.js.map +1 -0
- package/dist/ErrorPage.d.ts +6 -0
- package/dist/ErrorPage.js +15 -0
- package/dist/ErrorPage.js.map +1 -0
- package/dist/Field.d.ts +3 -0
- package/dist/Field.js +80 -0
- package/dist/Field.js.map +1 -0
- package/dist/FlatList.d.ts +2 -0
- package/dist/FlatList.js +3 -0
- package/dist/FlatList.js.map +1 -0
- package/dist/Heading.d.ts +3 -0
- package/dist/Heading.js +43 -0
- package/dist/Heading.js.map +1 -0
- package/dist/HeightActionSheet.d.ts +11 -0
- package/dist/HeightActionSheet.js +46 -0
- package/dist/HeightActionSheet.js.map +1 -0
- package/dist/Hyperlink.d.ts +30 -0
- package/dist/Hyperlink.js +144 -0
- package/dist/Hyperlink.js.map +1 -0
- package/dist/Icon.d.ts +3 -0
- package/dist/Icon.js +15 -0
- package/dist/Icon.js.map +1 -0
- package/dist/IconButton.d.ts +3 -0
- package/dist/IconButton.js +111 -0
- package/dist/IconButton.js.map +1 -0
- package/dist/Image.d.ts +8 -0
- package/dist/Image.js +37 -0
- package/dist/Image.js.map +1 -0
- package/dist/ImageBackground.d.ts +10 -0
- package/dist/ImageBackground.js +9 -0
- package/dist/ImageBackground.js.map +1 -0
- package/dist/InfoModalIcon.d.ts +3 -0
- package/dist/InfoModalIcon.js +10 -0
- package/dist/InfoModalIcon.js.map +1 -0
- package/dist/InfoTooltipButton.d.ts +3 -0
- package/dist/InfoTooltipButton.js +6 -0
- package/dist/InfoTooltipButton.js.map +1 -0
- package/dist/Link.d.ts +3 -0
- package/dist/Link.js +10 -0
- package/dist/Link.js.map +1 -0
- package/dist/MarkdownView.d.ts +5 -0
- package/dist/MarkdownView.js +44 -0
- package/dist/MarkdownView.js.map +1 -0
- package/dist/MediaQuery.d.ts +4 -0
- package/dist/MediaQuery.js +52 -0
- package/dist/MediaQuery.js.map +1 -0
- package/dist/MobileAddressAutoComplete.d.ts +2 -0
- package/dist/MobileAddressAutoComplete.js +54 -0
- package/dist/MobileAddressAutoComplete.js.map +1 -0
- package/dist/Modal.d.ts +3 -0
- package/dist/Modal.js +127 -0
- package/dist/Modal.js.map +1 -0
- package/dist/ModalSheet.d.ts +6 -0
- package/dist/ModalSheet.js +42 -0
- package/dist/ModalSheet.js.map +1 -0
- package/dist/MultiselectField.d.ts +3 -0
- package/dist/MultiselectField.js +45 -0
- package/dist/MultiselectField.js.map +1 -0
- package/dist/NumberField.d.ts +3 -0
- package/dist/NumberField.js +60 -0
- package/dist/NumberField.js.map +1 -0
- package/dist/NumberPickerActionSheet.d.ts +7 -0
- package/dist/NumberPickerActionSheet.js +22 -0
- package/dist/NumberPickerActionSheet.js.map +1 -0
- package/dist/OpenAPIContext.d.ts +4 -0
- package/dist/OpenAPIContext.js +53 -0
- package/dist/OpenAPIContext.js.map +1 -0
- package/dist/Page.d.ts +7 -0
- package/dist/Page.js +24 -0
- package/dist/Page.js.map +1 -0
- package/dist/Pagination.d.ts +3 -0
- package/dist/Pagination.js +106 -0
- package/dist/Pagination.js.map +1 -0
- package/dist/PasswordField.d.ts +2 -0
- package/dist/PasswordField.js +6 -0
- package/dist/PasswordField.js.map +1 -0
- package/dist/Permissions.d.ts +2 -0
- package/dist/Permissions.js +35 -0
- package/dist/Permissions.js.map +1 -0
- package/dist/PhoneNumberField.d.ts +3 -0
- package/dist/PhoneNumberField.js +83 -0
- package/dist/PhoneNumberField.js.map +1 -0
- package/dist/PickerSelect.d.ts +46 -0
- package/dist/PickerSelect.js +306 -0
- package/dist/PickerSelect.js.map +1 -0
- package/dist/Radio.d.ts +3 -0
- package/dist/Radio.js +21 -0
- package/dist/Radio.js.map +1 -0
- package/dist/RadioField.d.ts +3 -0
- package/dist/RadioField.js +16 -0
- package/dist/RadioField.js.map +1 -0
- package/dist/ScrollView.d.ts +2 -0
- package/dist/ScrollView.js +3 -0
- package/dist/ScrollView.js.map +1 -0
- package/dist/SectionDivider.d.ts +2 -0
- package/dist/SectionDivider.js +12 -0
- package/dist/SectionDivider.js.map +1 -0
- package/dist/SegmentedControl.d.ts +3 -0
- package/dist/SegmentedControl.js +65 -0
- package/dist/SegmentedControl.js.map +1 -0
- package/dist/SelectBadge.d.ts +3 -0
- package/dist/SelectBadge.js +166 -0
- package/dist/SelectBadge.js.map +1 -0
- package/dist/SelectField.d.ts +3 -0
- package/dist/SelectField.js +16 -0
- package/dist/SelectField.js.map +1 -0
- package/dist/SideDrawer.d.ts +3 -0
- package/dist/SideDrawer.js +32 -0
- package/dist/SideDrawer.js.map +1 -0
- package/dist/Signature.d.ts +8 -0
- package/dist/Signature.js +21 -0
- package/dist/Signature.js.map +1 -0
- package/dist/Signature.native.d.ts +8 -0
- package/dist/Signature.native.js +26 -0
- package/dist/Signature.native.js.map +1 -0
- package/dist/SignatureField.d.ts +3 -0
- package/dist/SignatureField.js +42 -0
- package/dist/SignatureField.js.map +1 -0
- package/dist/Slider.d.ts +3 -0
- package/dist/Slider.js +78 -0
- package/dist/Slider.js.map +1 -0
- package/dist/Spinner.d.ts +3 -0
- package/dist/Spinner.js +33 -0
- package/dist/Spinner.js.map +1 -0
- package/dist/SplitPage.d.ts +2 -0
- package/dist/SplitPage.js +139 -0
- package/dist/SplitPage.js.map +1 -0
- package/dist/SplitPage.native.d.ts +2 -0
- package/dist/SplitPage.native.js +75 -0
- package/dist/SplitPage.native.js.map +1 -0
- package/dist/TapToEdit.d.ts +4 -0
- package/dist/TapToEdit.js +170 -0
- package/dist/TapToEdit.js.map +1 -0
- package/dist/TerrenoProvider.d.ts +6 -0
- package/dist/TerrenoProvider.js +10 -0
- package/dist/TerrenoProvider.js.map +1 -0
- package/dist/Text.d.ts +3 -0
- package/dist/Text.js +95 -0
- package/dist/Text.js.map +1 -0
- package/dist/TextArea.d.ts +3 -0
- package/dist/TextArea.js +6 -0
- package/dist/TextArea.js.map +1 -0
- package/dist/TextField.d.ts +3 -0
- package/dist/TextField.js +144 -0
- package/dist/TextField.js.map +1 -0
- package/dist/TextFieldNumberActionSheet.d.ts +7 -0
- package/dist/TextFieldNumberActionSheet.js +20 -0
- package/dist/TextFieldNumberActionSheet.js.map +1 -0
- package/dist/Theme.d.ts +96 -0
- package/dist/Theme.js +213 -0
- package/dist/Theme.js.map +1 -0
- package/dist/TimezonePicker.d.ts +11 -0
- package/dist/TimezonePicker.js +27 -0
- package/dist/TimezonePicker.js.map +1 -0
- package/dist/Toast.d.ts +23 -0
- package/dist/Toast.js +157 -0
- package/dist/Toast.js.map +1 -0
- package/dist/Tooltip.d.ts +3 -0
- package/dist/Tooltip.js +289 -0
- package/dist/Tooltip.js.map +1 -0
- package/dist/UnifiedAddressAutoComplete.d.ts +2 -0
- package/dist/UnifiedAddressAutoComplete.js +23 -0
- package/dist/UnifiedAddressAutoComplete.js.map +1 -0
- package/dist/Unifier.d.ts +43 -0
- package/dist/Unifier.js +154 -0
- package/dist/Unifier.js.map +1 -0
- package/dist/Utilities.d.ts +56 -0
- package/dist/Utilities.js +193 -0
- package/dist/Utilities.js.map +1 -0
- package/dist/WebAddressAutocomplete.d.ts +3 -0
- package/dist/WebAddressAutocomplete.js +61 -0
- package/dist/WebAddressAutocomplete.js.map +1 -0
- package/dist/fieldElements/FieldError.d.ts +6 -0
- package/dist/fieldElements/FieldError.js +9 -0
- package/dist/fieldElements/FieldError.js.map +1 -0
- package/dist/fieldElements/FieldHelperText.d.ts +6 -0
- package/dist/fieldElements/FieldHelperText.js +8 -0
- package/dist/fieldElements/FieldHelperText.js.map +1 -0
- package/dist/fieldElements/FieldTitle.d.ts +6 -0
- package/dist/fieldElements/FieldTitle.js +16 -0
- package/dist/fieldElements/FieldTitle.js.map +1 -0
- package/dist/fieldElements/index.d.ts +3 -0
- package/dist/fieldElements/index.js +4 -0
- package/dist/fieldElements/index.js.map +1 -0
- package/dist/icons/MobileIcon.d.ts +2 -0
- package/dist/icons/MobileIcon.js +18 -0
- package/dist/icons/MobileIcon.js.map +1 -0
- package/dist/icons/OfflineIcon.d.ts +2 -0
- package/dist/icons/OfflineIcon.js +18 -0
- package/dist/icons/OfflineIcon.js.map +1 -0
- package/dist/icons/OnlineIcon.d.ts +2 -0
- package/dist/icons/OnlineIcon.js +19 -0
- package/dist/icons/OnlineIcon.js.map +1 -0
- package/dist/icons/OutOfficeIcon.d.ts +2 -0
- package/dist/icons/OutOfficeIcon.js +18 -0
- package/dist/icons/OutOfficeIcon.js.map +1 -0
- package/dist/icons/index.d.ts +4 -0
- package/dist/icons/index.js +5 -0
- package/dist/icons/index.js.map +1 -0
- package/dist/index.d.ts +1328 -0
- package/dist/index.js +89 -0
- package/dist/index.js.map +1 -0
- package/dist/table/Table.d.ts +3 -0
- package/dist/table/Table.js +53 -0
- package/dist/table/Table.js.map +1 -0
- package/dist/table/TableBadge.d.ts +6 -0
- package/dist/table/TableBadge.js +23 -0
- package/dist/table/TableBadge.js.map +1 -0
- package/dist/table/TableBoolean.d.ts +6 -0
- package/dist/table/TableBoolean.js +37 -0
- package/dist/table/TableBoolean.js.map +1 -0
- package/dist/table/TableDate.d.ts +3 -0
- package/dist/table/TableDate.js +27 -0
- package/dist/table/TableDate.js.map +1 -0
- package/dist/table/TableHeader.d.ts +6 -0
- package/dist/table/TableHeader.js +10 -0
- package/dist/table/TableHeader.js.map +1 -0
- package/dist/table/TableHeaderCell.d.ts +6 -0
- package/dist/table/TableHeaderCell.js +54 -0
- package/dist/table/TableHeaderCell.js.map +1 -0
- package/dist/table/TableIconButton.d.ts +3 -0
- package/dist/table/TableIconButton.js +39 -0
- package/dist/table/TableIconButton.js.map +1 -0
- package/dist/table/TableNumber.d.ts +3 -0
- package/dist/table/TableNumber.js +18 -0
- package/dist/table/TableNumber.js.map +1 -0
- package/dist/table/TableRow.d.ts +6 -0
- package/dist/table/TableRow.js +22 -0
- package/dist/table/TableRow.js.map +1 -0
- package/dist/table/TableText.d.ts +3 -0
- package/dist/table/TableText.js +18 -0
- package/dist/table/TableText.js.map +1 -0
- package/dist/table/TableTitle.d.ts +3 -0
- package/dist/table/TableTitle.js +21 -0
- package/dist/table/TableTitle.js.map +1 -0
- package/dist/table/tableContext.d.ts +5 -0
- package/dist/table/tableContext.js +38 -0
- package/dist/table/tableContext.js.map +1 -0
- package/dist/useStoredState.d.ts +1 -0
- package/dist/useStoredState.js +49 -0
- package/dist/useStoredState.js.map +1 -0
- package/package.json +123 -0
- package/src/Accordion.test.tsx +104 -0
- package/src/Accordion.tsx +81 -0
- package/src/ActionSheet.tsx +881 -0
- package/src/AddressField.test.tsx +120 -0
- package/src/AddressField.tsx +122 -0
- package/src/Avatar.test.tsx +163 -0
- package/src/Avatar.tsx +298 -0
- package/src/Badge.test.tsx +116 -0
- package/src/Badge.tsx +136 -0
- package/src/Banner.tsx +200 -0
- package/src/Body.tsx +34 -0
- package/src/BooleanField.tsx +141 -0
- package/src/Box.test.tsx +662 -0
- package/src/Box.tsx +368 -0
- package/src/Button.tsx +196 -0
- package/src/Card.tsx +19 -0
- package/src/CheckBox.tsx +45 -0
- package/src/Common.ts +2787 -0
- package/src/CommonIconTypes.ts +2030 -0
- package/src/Constants.ts +3311 -0
- package/src/CustomSelectField.tsx +115 -0
- package/src/DataTable.tsx +674 -0
- package/src/DateTimeActionSheet.tsx +559 -0
- package/src/DateTimeField.test.tsx +393 -0
- package/src/DateTimeField.tsx +777 -0
- package/src/DateUtilities.test.ts +440 -0
- package/src/DateUtilities.tsx +370 -0
- package/src/DecimalRangeActionSheet.tsx +85 -0
- package/src/DismissButton.tsx +31 -0
- package/src/EmailField.tsx +66 -0
- package/src/EmojiSelector.test.tsx +61 -0
- package/src/EmojiSelector.tsx +510 -0
- package/src/ErrorBoundary.tsx +37 -0
- package/src/ErrorPage.tsx +41 -0
- package/src/Field.tsx +101 -0
- package/src/FlatList.tsx +2 -0
- package/src/Heading.tsx +66 -0
- package/src/HeightActionSheet.tsx +91 -0
- package/src/Hyperlink.tsx +179 -0
- package/src/Icon.tsx +36 -0
- package/src/IconButton.tsx +217 -0
- package/src/Image.tsx +51 -0
- package/src/ImageBackground.tsx +14 -0
- package/src/InfoModalIcon.tsx +42 -0
- package/src/InfoTooltipButton.tsx +16 -0
- package/src/Link.tsx +22 -0
- package/src/MarkdownView.tsx +67 -0
- package/src/MediaQuery.ts +46 -0
- package/src/MobileAddressAutoComplete.tsx +126 -0
- package/src/Modal.tsx +300 -0
- package/src/ModalSheet.tsx +58 -0
- package/src/MultiselectField.tsx +112 -0
- package/src/NumberField.tsx +67 -0
- package/src/NumberPickerActionSheet.tsx +51 -0
- package/src/OpenAPIContext.tsx +74 -0
- package/src/Page.tsx +105 -0
- package/src/Pagination.tsx +169 -0
- package/src/PasswordField.tsx +7 -0
- package/src/Permissions.ts +43 -0
- package/src/PhoneNumberField.tsx +109 -0
- package/src/PickerSelect.tsx +571 -0
- package/src/Radio.tsx +33 -0
- package/src/RadioField.tsx +43 -0
- package/src/ScrollView.tsx +2 -0
- package/src/SectionDivider.tsx +18 -0
- package/src/SegmentedControl.tsx +126 -0
- package/src/SelectBadge.tsx +280 -0
- package/src/SelectField.tsx +41 -0
- package/src/SideDrawer.tsx +56 -0
- package/src/Signature.native.tsx +57 -0
- package/src/Signature.tsx +44 -0
- package/src/SignatureField.tsx +92 -0
- package/src/Slider.tsx +199 -0
- package/src/Spinner.tsx +35 -0
- package/src/SplitPage.native.tsx +163 -0
- package/src/SplitPage.tsx +304 -0
- package/src/TapToEdit.tsx +292 -0
- package/src/TerrenoProvider.tsx +31 -0
- package/src/Text.tsx +123 -0
- package/src/TextArea.test.tsx +255 -0
- package/src/TextArea.tsx +8 -0
- package/src/TextField.test.tsx +487 -0
- package/src/TextField.tsx +260 -0
- package/src/TextFieldNumberActionSheet.tsx +46 -0
- package/src/Theme.tsx +248 -0
- package/src/TimezonePicker.tsx +45 -0
- package/src/Toast.tsx +234 -0
- package/src/Tooltip.tsx +407 -0
- package/src/UnifiedAddressAutoComplete.tsx +66 -0
- package/src/Unifier.ts +172 -0
- package/src/Utilities.tsx +329 -0
- package/src/WebAddressAutocomplete.tsx +84 -0
- package/src/__snapshots__/Accordion.test.tsx.snap +126 -0
- package/src/__snapshots__/AddressField.test.tsx.snap +1197 -0
- package/src/__snapshots__/Avatar.test.tsx.snap +57 -0
- package/src/__snapshots__/Badge.test.tsx.snap +55 -0
- package/src/__snapshots__/Box.test.tsx.snap +162 -0
- package/src/__snapshots__/EmojiSelector.test.tsx.snap +422 -0
- package/src/__snapshots__/TextArea.test.tsx.snap +521 -0
- package/src/__snapshots__/TextField.test.tsx.snap +569 -0
- package/src/bunSetup.ts +1235 -0
- package/src/fieldElements/FieldError.tsx +24 -0
- package/src/fieldElements/FieldHelperText.tsx +20 -0
- package/src/fieldElements/FieldTitle.tsx +31 -0
- package/src/fieldElements/index.tsx +3 -0
- package/src/icons/MobileIcon.tsx +40 -0
- package/src/icons/OfflineIcon.tsx +37 -0
- package/src/icons/OnlineIcon.tsx +39 -0
- package/src/icons/OutOfficeIcon.tsx +36 -0
- package/src/icons/index.ts +4 -0
- package/src/index.tsx +1375 -0
- package/src/polyfill.d.ts +11 -0
- package/src/table/Table.tsx +109 -0
- package/src/table/TableBadge.tsx +46 -0
- package/src/table/TableBoolean.tsx +70 -0
- package/src/table/TableDate.tsx +38 -0
- package/src/table/TableHeader.tsx +20 -0
- package/src/table/TableHeaderCell.tsx +94 -0
- package/src/table/TableIconButton.tsx +61 -0
- package/src/table/TableNumber.tsx +29 -0
- package/src/table/TableRow.tsx +67 -0
- package/src/table/TableText.tsx +29 -0
- package/src/table/TableTitle.tsx +31 -0
- package/src/table/tableContext.tsx +67 -0
- package/src/test-utils.tsx +27 -0
- package/src/types/react-native-swiper-flatlist.d.ts +56 -0
- package/src/useStoredState.test.tsx +143 -0
- package/src/useStoredState.ts +56 -0
package/src/Unifier.ts
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
2
|
+
import * as Clipboard from "expo-clipboard";
|
|
3
|
+
import * as Haptics from "expo-haptics";
|
|
4
|
+
import {Dimensions, Keyboard, Linking, Platform, Vibration} from "react-native";
|
|
5
|
+
|
|
6
|
+
import type {PermissionKind} from "./Common";
|
|
7
|
+
import {requestPermissions} from "./Permissions";
|
|
8
|
+
|
|
9
|
+
declare global {
|
|
10
|
+
interface Window {
|
|
11
|
+
google: any;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export type PlatformOS = "ios" | "android" | "web";
|
|
16
|
+
|
|
17
|
+
type Luminance = "light" | "lighter" | "dark" | "darker";
|
|
18
|
+
|
|
19
|
+
// Changes a color luminance
|
|
20
|
+
export function changeColorLuminance(hex: string, luminanceChange: Luminance) {
|
|
21
|
+
// Validate hex string, strip "#" if present.
|
|
22
|
+
hex = String(hex).replace(/[^0-9a-f]/gi, "");
|
|
23
|
+
if (hex.length === 3) {
|
|
24
|
+
hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
|
|
25
|
+
} else if (hex.length !== 6) {
|
|
26
|
+
throw new Error(`Invalid color hex: ${hex}`);
|
|
27
|
+
}
|
|
28
|
+
let luminance;
|
|
29
|
+
switch (luminanceChange) {
|
|
30
|
+
case "light":
|
|
31
|
+
luminance = -0.2;
|
|
32
|
+
break;
|
|
33
|
+
case "lighter":
|
|
34
|
+
luminance = -0.33;
|
|
35
|
+
break;
|
|
36
|
+
case "dark":
|
|
37
|
+
luminance = 0.2;
|
|
38
|
+
break;
|
|
39
|
+
case "darker":
|
|
40
|
+
luminance = 0.33;
|
|
41
|
+
break;
|
|
42
|
+
default:
|
|
43
|
+
throw new Error(`Cannot change luminance to ${luminanceChange}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Convert to decimal and change luminosity
|
|
47
|
+
let rgb = "#";
|
|
48
|
+
for (let i = 0; i < 3; i++) {
|
|
49
|
+
const decimal = parseInt(hex.substr(i * 2, 2), 16);
|
|
50
|
+
const appliedLuminance = Math.round(
|
|
51
|
+
Math.min(Math.max(0, decimal + decimal * luminance), 255)
|
|
52
|
+
).toString(16);
|
|
53
|
+
// 0 pad, if necessary.
|
|
54
|
+
rgb += `00${appliedLuminance}`.substr(appliedLuminance.length);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return rgb;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
class UnifierClass {
|
|
61
|
+
private _web = false;
|
|
62
|
+
|
|
63
|
+
private _dev = false;
|
|
64
|
+
|
|
65
|
+
get web(): boolean {
|
|
66
|
+
return this._web;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
get dev(): boolean {
|
|
70
|
+
return this._dev;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
navigation = {
|
|
74
|
+
dismissOverlay: () => {
|
|
75
|
+
console.warn("Dismiss overlay not supported.");
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// tracking: Tracking,
|
|
80
|
+
utils = {
|
|
81
|
+
copyToClipboard: (text: string) => {
|
|
82
|
+
Clipboard.setString(text);
|
|
83
|
+
},
|
|
84
|
+
dimensions: () => ({
|
|
85
|
+
height: Dimensions.get("window").height,
|
|
86
|
+
width: Dimensions.get("window").width,
|
|
87
|
+
}),
|
|
88
|
+
dismissKeyboard: () => {
|
|
89
|
+
Keyboard.dismiss();
|
|
90
|
+
},
|
|
91
|
+
haptic: () => {
|
|
92
|
+
if (Platform.OS !== "web") {
|
|
93
|
+
return Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
},
|
|
97
|
+
makePurchase: () => {
|
|
98
|
+
console.warn("Make purchase not supported yet.");
|
|
99
|
+
},
|
|
100
|
+
openUrl: async (url: string) => {
|
|
101
|
+
return Linking.openURL(url);
|
|
102
|
+
},
|
|
103
|
+
orientationChange: (callback: (orientation: "portrait" | "landscape") => void) => {
|
|
104
|
+
Dimensions.addEventListener("change", () => {
|
|
105
|
+
const screen = Dimensions.get("screen");
|
|
106
|
+
const isPortrait = screen.width < screen.height;
|
|
107
|
+
callback(isPortrait ? "portrait" : "landscape");
|
|
108
|
+
});
|
|
109
|
+
},
|
|
110
|
+
PaymentService: () => {
|
|
111
|
+
console.warn("Make purchase not supported yet.");
|
|
112
|
+
},
|
|
113
|
+
requestPermissions: async (_perm: PermissionKind) => {
|
|
114
|
+
return requestPermissions(_perm);
|
|
115
|
+
// return requestPermissions(perm);
|
|
116
|
+
},
|
|
117
|
+
vibrate: (pattern?: number[]) => {
|
|
118
|
+
Vibration.vibrate(pattern || [100], false);
|
|
119
|
+
},
|
|
120
|
+
// keepAwake: (activate: boolean) => {
|
|
121
|
+
// if (activate) {
|
|
122
|
+
// activateKeepAwake();
|
|
123
|
+
// } else {
|
|
124
|
+
// deactivateKeepAwake();
|
|
125
|
+
// }
|
|
126
|
+
// },
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
storage = {
|
|
130
|
+
getItem: async (key: string, defaultValue?: any) => {
|
|
131
|
+
try {
|
|
132
|
+
const jsonValue = await AsyncStorage.getItem(key);
|
|
133
|
+
if (jsonValue) {
|
|
134
|
+
const value = JSON.parse(jsonValue);
|
|
135
|
+
if (value === null || value === undefined) {
|
|
136
|
+
return defaultValue;
|
|
137
|
+
} else {
|
|
138
|
+
return value;
|
|
139
|
+
}
|
|
140
|
+
} else if (defaultValue !== undefined) {
|
|
141
|
+
return defaultValue;
|
|
142
|
+
} else {
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
} catch (error) {
|
|
146
|
+
console.error(`[storage] Error reading ${key}`, error);
|
|
147
|
+
return defaultValue || null;
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
setItem: async (key: string, item: any) => {
|
|
151
|
+
try {
|
|
152
|
+
const jsonValue = JSON.stringify(item);
|
|
153
|
+
await AsyncStorage.setItem(key, jsonValue);
|
|
154
|
+
} catch (error: any) {
|
|
155
|
+
console.error(`[storage] Error storing ${key}`, item, error);
|
|
156
|
+
throw new Error(error);
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
tracking = {
|
|
162
|
+
log: (message: string) => {
|
|
163
|
+
console.info(message);
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
initIcons = () => {
|
|
168
|
+
console.debug("[unifier] Initializing icons");
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export const Unifier = new UnifierClass();
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
// Originally based on https://github.com/pinterest/gestalt
|
|
2
|
+
// Forked, updated to Typescript, and added features.
|
|
3
|
+
import get from "lodash/get";
|
|
4
|
+
import {Platform} from "react-native";
|
|
5
|
+
|
|
6
|
+
import type {APIError, BaseProfile, IconSize} from "./Common";
|
|
7
|
+
import {COUNTY_AND_COUNTY_EQUIVALENT_ENTITIES} from "./Constants";
|
|
8
|
+
|
|
9
|
+
export function mergeInlineStyles(inlineStyle?: any, newStyle?: any) {
|
|
10
|
+
const inline = get(inlineStyle, "__style");
|
|
11
|
+
return {
|
|
12
|
+
__style: {
|
|
13
|
+
...inline,
|
|
14
|
+
...newStyle,
|
|
15
|
+
},
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function isTestUser(profile?: BaseProfile) {
|
|
20
|
+
return (
|
|
21
|
+
profile?.email &&
|
|
22
|
+
(profile.email.indexOf("nang.io") > -1 || profile.email.indexOf("example.com") > -1)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const iconNumberToSize = (size = 16): IconSize => {
|
|
27
|
+
let iconSize: IconSize;
|
|
28
|
+
if (size < 8) {
|
|
29
|
+
iconSize = "xs";
|
|
30
|
+
} else if (size < 12) {
|
|
31
|
+
iconSize = "sm";
|
|
32
|
+
} else if (size < 14) {
|
|
33
|
+
iconSize = "md";
|
|
34
|
+
} else if (size < 20) {
|
|
35
|
+
iconSize = "lg";
|
|
36
|
+
} else {
|
|
37
|
+
iconSize = "xl";
|
|
38
|
+
}
|
|
39
|
+
return iconSize;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
|
|
44
|
+
Style is a monoid that capture the "to-be-applied" styles (inline and classes)
|
|
45
|
+
for a Box. It's basically set that is closed under an associative binary
|
|
46
|
+
operation and has an identity element such that for all HA HA HA. Yes, it's a
|
|
47
|
+
monoid, which sounds scary but it's not really and actually super useful. All
|
|
48
|
+
that means is that basically you can do two things with it:
|
|
49
|
+
|
|
50
|
+
1. concat(concat(a, b), c) === concat(a, concat(b, c));
|
|
51
|
+
2. concat(identity(), a) === concat(a, identity()) === a;
|
|
52
|
+
|
|
53
|
+
What that means is that it's really easy to compose styles together and the
|
|
54
|
+
order in which you do so doesn't really matter.
|
|
55
|
+
|
|
56
|
+
*/
|
|
57
|
+
|
|
58
|
+
interface InlineStyle {
|
|
59
|
+
[key: string]: string | number | undefined;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// TODO: This type should be opaque, however the Babel parser doesn't support
|
|
63
|
+
// the opaque syntax yet.
|
|
64
|
+
export interface Style {
|
|
65
|
+
className: Set<string>;
|
|
66
|
+
inlineStyle: InlineStyle;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export const identity = (): Style => ({
|
|
70
|
+
className: new Set(),
|
|
71
|
+
inlineStyle: {},
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
export const fromClassName = (...classNames: string[]): Style => ({
|
|
75
|
+
className: new Set(classNames),
|
|
76
|
+
inlineStyle: {},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
export const fromInlineStyle = (inlineStyle: InlineStyle): Style => ({
|
|
80
|
+
className: new Set(),
|
|
81
|
+
inlineStyle,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export const concat = (styles: Style[]): Style =>
|
|
85
|
+
styles.reduce(
|
|
86
|
+
(
|
|
87
|
+
{className: classNameA, inlineStyle: inlineStyleA},
|
|
88
|
+
{className: classNameB, inlineStyle: inlineStyleB}
|
|
89
|
+
) => ({
|
|
90
|
+
className: new Set([...classNameA, ...classNameB]),
|
|
91
|
+
inlineStyle: {...inlineStyleA, ...inlineStyleB},
|
|
92
|
+
}),
|
|
93
|
+
identity()
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
export const mapClassName =
|
|
97
|
+
(fn: (x: string) => string) =>
|
|
98
|
+
({className, inlineStyle}: Style): Style => ({
|
|
99
|
+
className: new Set(Array.from(className).map(fn)),
|
|
100
|
+
inlineStyle,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
export const toProps = ({
|
|
104
|
+
className,
|
|
105
|
+
inlineStyle,
|
|
106
|
+
}: Style): {className: string; style: InlineStyle} => {
|
|
107
|
+
const props: any = {};
|
|
108
|
+
|
|
109
|
+
if (className.size > 0) {
|
|
110
|
+
// Sorting here ensures that classNames are always stable, reducing diff
|
|
111
|
+
// churn. Box usually has a small number of properties so it's not a perf
|
|
112
|
+
// concern.
|
|
113
|
+
props.className = Array.from(className).sort().join(" ");
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (Object.keys(inlineStyle).length > 0) {
|
|
117
|
+
props.style = inlineStyle;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return props;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/*
|
|
124
|
+
|
|
125
|
+
Transforms
|
|
126
|
+
|
|
127
|
+
These are a collection of a few functors that take values and returns Style's. OMG,
|
|
128
|
+
I used the word functor - it's really just a fancy word for function.
|
|
129
|
+
|
|
130
|
+
*/
|
|
131
|
+
type Functor<T> = (n: T) => Style;
|
|
132
|
+
|
|
133
|
+
// Adds a classname when a property is present.
|
|
134
|
+
//
|
|
135
|
+
// <Box top />
|
|
136
|
+
//
|
|
137
|
+
export const toggle =
|
|
138
|
+
(...classNames: string[]) =>
|
|
139
|
+
(val?: boolean) =>
|
|
140
|
+
val ? fromClassName(...classNames) : identity();
|
|
141
|
+
|
|
142
|
+
// Maps string values to classes
|
|
143
|
+
//
|
|
144
|
+
// <Box alignItems="center" />
|
|
145
|
+
//
|
|
146
|
+
export const mapping = (map: {[key: string]: string}) => (val: string) =>
|
|
147
|
+
Object.hasOwn(map, val) ? fromClassName(map[val]) : identity();
|
|
148
|
+
|
|
149
|
+
// Maps a range of integers to a range of classnames
|
|
150
|
+
//
|
|
151
|
+
// <Box padding={1} />
|
|
152
|
+
//
|
|
153
|
+
export const range =
|
|
154
|
+
(scale: string) =>
|
|
155
|
+
(n: number): Style =>
|
|
156
|
+
fromClassName(`${scale}${n < 0 ? `N${Math.abs(n)}` : n}`);
|
|
157
|
+
|
|
158
|
+
// Like `range`, maps a range of integers to a range of classnames, excluding
|
|
159
|
+
// zero values.
|
|
160
|
+
//
|
|
161
|
+
// <Box padding={0} />
|
|
162
|
+
export const rangeWithoutZero =
|
|
163
|
+
(scale: string) =>
|
|
164
|
+
(n: number): Style =>
|
|
165
|
+
n === 0 ? identity() : range(scale)(n);
|
|
166
|
+
|
|
167
|
+
// Binds a string classname to the value in an object. Useful when interacting
|
|
168
|
+
// with ranges that need to come dynamically from a style object. This is
|
|
169
|
+
// similar to the NPM package 'classnames/bind'.
|
|
170
|
+
export function bind<T>(
|
|
171
|
+
fn: Functor<T>,
|
|
172
|
+
scope:
|
|
173
|
+
| {
|
|
174
|
+
readonly [key: string]: string;
|
|
175
|
+
}
|
|
176
|
+
| any
|
|
177
|
+
): (val: T) => Style {
|
|
178
|
+
const map = mapClassName((name) => scope[name]);
|
|
179
|
+
return (val: T): Style => map(fn(val));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// This takes a series of the previously defined functors, runs them all
|
|
183
|
+
// against a value and returns the set of their classnames.
|
|
184
|
+
export const union =
|
|
185
|
+
<T,>(...fns: Functor<T>[]) =>
|
|
186
|
+
(val: T) =>
|
|
187
|
+
concat(fns.map((fn) => fn(val)));
|
|
188
|
+
|
|
189
|
+
export const isNative = (): boolean => {
|
|
190
|
+
return ["android", "ios"].includes(Platform.OS);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Find more information about the address component types here: https://developers.google.com/maps/documentation/javascript/place-autocomplete
|
|
194
|
+
export type AddressComponentType = {
|
|
195
|
+
long_name: string;
|
|
196
|
+
short_name: string;
|
|
197
|
+
types: string[];
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export const findAddressComponent = (components: AddressComponentType[], type: string): string => {
|
|
201
|
+
return (
|
|
202
|
+
components.find((component: AddressComponentType) => component.types.includes(type))
|
|
203
|
+
?.long_name ?? ""
|
|
204
|
+
);
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
interface ProcessAddressComponentOptions {
|
|
208
|
+
includeCounty?: boolean;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export const processAddressComponents = (
|
|
212
|
+
addressComponents: AddressComponentType[] | undefined,
|
|
213
|
+
options?: ProcessAddressComponentOptions
|
|
214
|
+
) => {
|
|
215
|
+
let processedAddressComponents: {
|
|
216
|
+
address1: string;
|
|
217
|
+
city: string;
|
|
218
|
+
state: string;
|
|
219
|
+
zipcode: string;
|
|
220
|
+
countyName?: string;
|
|
221
|
+
countyCode?: string;
|
|
222
|
+
} = {
|
|
223
|
+
address1: "",
|
|
224
|
+
city: "",
|
|
225
|
+
state: "",
|
|
226
|
+
zipcode: "",
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
if (!addressComponents || addressComponents.length === 0) {
|
|
230
|
+
console.warn("Invalid address components");
|
|
231
|
+
if (options?.includeCounty) {
|
|
232
|
+
return {
|
|
233
|
+
...processedAddressComponents,
|
|
234
|
+
countyCode: "",
|
|
235
|
+
countyName: "",
|
|
236
|
+
};
|
|
237
|
+
} else {
|
|
238
|
+
return processedAddressComponents;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const streetNumber = findAddressComponent(addressComponents, "street_number");
|
|
243
|
+
const streetName = findAddressComponent(addressComponents, "route");
|
|
244
|
+
const city = findAddressComponent(addressComponents, "locality");
|
|
245
|
+
const state = findAddressComponent(addressComponents, "administrative_area_level_1");
|
|
246
|
+
const zipcode = findAddressComponent(addressComponents, "postal_code");
|
|
247
|
+
|
|
248
|
+
processedAddressComponents = {
|
|
249
|
+
address1: `${streetNumber} ${streetName}`.trim(),
|
|
250
|
+
city,
|
|
251
|
+
state,
|
|
252
|
+
zipcode,
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
if (options?.includeCounty) {
|
|
256
|
+
const countyName = findAddressComponent(addressComponents, "administrative_area_level_2");
|
|
257
|
+
if (state && countyName) {
|
|
258
|
+
const countyCode = formattedCountyCode(state, countyName);
|
|
259
|
+
processedAddressComponents = {
|
|
260
|
+
...processedAddressComponents,
|
|
261
|
+
countyCode,
|
|
262
|
+
countyName,
|
|
263
|
+
};
|
|
264
|
+
} else {
|
|
265
|
+
processedAddressComponents = {
|
|
266
|
+
...processedAddressComponents,
|
|
267
|
+
countyName,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return processedAddressComponents;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
// Google does not provide a way to validate API keys, so we have to do it ourselves
|
|
275
|
+
export const isValidGoogleApiKey = (apiKey: string): boolean => {
|
|
276
|
+
if (typeof apiKey !== "string" || apiKey.trim().length === 0) {
|
|
277
|
+
console.warn("Google API key validation failed: key is not a string or is empty");
|
|
278
|
+
return false;
|
|
279
|
+
}
|
|
280
|
+
// Typical Google API keys are around 39 characters
|
|
281
|
+
if (apiKey.length < 30 || apiKey.length > 50) {
|
|
282
|
+
console.warn("Google API key validation failed: key is invalid length");
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
// Check the presence of alphanumeric characters and dashes
|
|
286
|
+
const apiKeyRegex = /^[A-Za-z0-9-_]+$/;
|
|
287
|
+
if (!apiKeyRegex.test(apiKey)) {
|
|
288
|
+
console.warn("Google API key validation failed: key contains invalid characters");
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
return true;
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
export function formattedCountyCode(state: string, countyName: string): string {
|
|
295
|
+
// Remove whitespace and convert to lowercase for comparison
|
|
296
|
+
const stateKey = state
|
|
297
|
+
.replace(/\s+/g, "")
|
|
298
|
+
.toLowerCase() as keyof typeof COUNTY_AND_COUNTY_EQUIVALENT_ENTITIES;
|
|
299
|
+
|
|
300
|
+
const stateData = COUNTY_AND_COUNTY_EQUIVALENT_ENTITIES[stateKey];
|
|
301
|
+
|
|
302
|
+
// Remove whitespace, periods, apostrophes, and dashes for comparison
|
|
303
|
+
const countyKey = countyName
|
|
304
|
+
.trim()
|
|
305
|
+
.toLowerCase()
|
|
306
|
+
.replace(/[\s.'-]/g, "") as keyof typeof stateData;
|
|
307
|
+
|
|
308
|
+
const countyData: {
|
|
309
|
+
stateFP: string;
|
|
310
|
+
countyFP: string;
|
|
311
|
+
} = stateData?.[countyKey];
|
|
312
|
+
if (!countyData) {
|
|
313
|
+
return "";
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return `${countyData.stateFP}${countyData.countyFP}`;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export function isAPIError(error: any): error is APIError {
|
|
320
|
+
return error?.data?.title;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
export function printAPIError(error: APIError, details = true): string {
|
|
324
|
+
let message = error.data?.title;
|
|
325
|
+
if (error.data?.detail && details) {
|
|
326
|
+
message = `${message}: ${error.data?.detail}`;
|
|
327
|
+
}
|
|
328
|
+
return message;
|
|
329
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import {type ReactElement, useEffect, useRef, useState} from "react";
|
|
2
|
+
|
|
3
|
+
import type {AddressAutocompleteProps} 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?.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
|
+
return;
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const WebAddressAutocomplete = ({
|
|
27
|
+
disabled,
|
|
28
|
+
googleMapsApiKey,
|
|
29
|
+
includeCounty,
|
|
30
|
+
inputValue,
|
|
31
|
+
handleAddressChange,
|
|
32
|
+
handleAutoCompleteChange,
|
|
33
|
+
}: AddressAutocompleteProps): ReactElement => {
|
|
34
|
+
const [scriptLoaded, setScriptLoaded] = useState(true);
|
|
35
|
+
const autocompleteInputRef = useRef(null);
|
|
36
|
+
|
|
37
|
+
// Load the Google Maps script and initialize the autocomplete.
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
const callbackName = "initAutocomplete";
|
|
40
|
+
if (!googleMapsApiKey) {
|
|
41
|
+
setScriptLoaded(false);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
loadGooglePlacesScript(googleMapsApiKey, callbackName)
|
|
45
|
+
.then(() => {
|
|
46
|
+
const autocomplete = new window.google.maps.places.Autocomplete(
|
|
47
|
+
autocompleteInputRef.current,
|
|
48
|
+
{
|
|
49
|
+
componentRestrictions: {country: GOOGLE_PLACES_API_RESTRICTIONS.components.country},
|
|
50
|
+
fields: Object.values(GOOGLE_PLACES_API_RESTRICTIONS.fields),
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
autocomplete.addListener("place_changed", () => {
|
|
54
|
+
const place = autocomplete.getPlace();
|
|
55
|
+
const addressComponents = place?.address_components;
|
|
56
|
+
const formattedAddressObject = processAddressComponents(addressComponents, {
|
|
57
|
+
includeCounty,
|
|
58
|
+
});
|
|
59
|
+
handleAutoCompleteChange(formattedAddressObject);
|
|
60
|
+
});
|
|
61
|
+
})
|
|
62
|
+
.catch((error) => {
|
|
63
|
+
console.warn(error);
|
|
64
|
+
setScriptLoaded(false);
|
|
65
|
+
});
|
|
66
|
+
// Cleanup
|
|
67
|
+
return () => {
|
|
68
|
+
(window as any)[callbackName] = null;
|
|
69
|
+
};
|
|
70
|
+
}, [googleMapsApiKey, includeCounty, handleAutoCompleteChange]);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<TextField
|
|
74
|
+
disabled={disabled}
|
|
75
|
+
inputRef={scriptLoaded ? (ref: any): void => (autocompleteInputRef.current = ref) : undefined}
|
|
76
|
+
onChange={(value): void => {
|
|
77
|
+
handleAddressChange(value);
|
|
78
|
+
}}
|
|
79
|
+
placeholder="Enter an address"
|
|
80
|
+
type="text"
|
|
81
|
+
value={inputValue}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
// Bun Snapshot v1, https://bun.sh/docs/test/snapshots
|
|
2
|
+
|
|
3
|
+
exports[`Accordion renders correctly with default props 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"$$typeof": Symbol(react.test.json),
|
|
6
|
+
"children": [
|
|
7
|
+
{
|
|
8
|
+
"$$typeof": Symbol(react.test.json),
|
|
9
|
+
"children": [
|
|
10
|
+
{
|
|
11
|
+
"$$typeof": Symbol(react.test.json),
|
|
12
|
+
"children": [
|
|
13
|
+
{
|
|
14
|
+
"$$typeof": Symbol(react.test.json),
|
|
15
|
+
"children": [
|
|
16
|
+
{
|
|
17
|
+
"$$typeof": Symbol(react.test.json),
|
|
18
|
+
"children": [
|
|
19
|
+
"Test Title",
|
|
20
|
+
],
|
|
21
|
+
"props": {
|
|
22
|
+
"numberOfLines": 0,
|
|
23
|
+
"style": {
|
|
24
|
+
"color": "#1C1C1C",
|
|
25
|
+
"fontFamily": "heading-bold",
|
|
26
|
+
"fontSize": 16,
|
|
27
|
+
},
|
|
28
|
+
"testID": undefined,
|
|
29
|
+
},
|
|
30
|
+
"type": "Text",
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
"props": {
|
|
34
|
+
"style": {
|
|
35
|
+
"alignItems": "center",
|
|
36
|
+
"flexDirection": "row",
|
|
37
|
+
},
|
|
38
|
+
"testID": undefined,
|
|
39
|
+
},
|
|
40
|
+
"type": "View",
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
"props": {
|
|
44
|
+
"style": {
|
|
45
|
+
"flexDirection": "column",
|
|
46
|
+
"gap": 4,
|
|
47
|
+
},
|
|
48
|
+
"testID": undefined,
|
|
49
|
+
},
|
|
50
|
+
"type": "View",
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"$$typeof": Symbol(react.test.json),
|
|
54
|
+
"children": [
|
|
55
|
+
{
|
|
56
|
+
"$$typeof": Symbol(react.test.json),
|
|
57
|
+
"children": null,
|
|
58
|
+
"props": {
|
|
59
|
+
"aria-role": "button",
|
|
60
|
+
"hitSlop": {
|
|
61
|
+
"bottom": 20,
|
|
62
|
+
"left": 20,
|
|
63
|
+
"right": 20,
|
|
64
|
+
"top": 20,
|
|
65
|
+
},
|
|
66
|
+
"onPress": [Function],
|
|
67
|
+
"testID": "accordion-toggle",
|
|
68
|
+
},
|
|
69
|
+
"type": "Pressable",
|
|
70
|
+
},
|
|
71
|
+
],
|
|
72
|
+
"props": {
|
|
73
|
+
"style": undefined,
|
|
74
|
+
"testID": undefined,
|
|
75
|
+
},
|
|
76
|
+
"type": "View",
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
"props": {
|
|
80
|
+
"style": {
|
|
81
|
+
"alignItems": "center",
|
|
82
|
+
"flexDirection": "row",
|
|
83
|
+
"justifyContent": "space-between",
|
|
84
|
+
},
|
|
85
|
+
"testID": undefined,
|
|
86
|
+
},
|
|
87
|
+
"type": "View",
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"$$typeof": Symbol(react.test.json),
|
|
91
|
+
"children": [
|
|
92
|
+
{
|
|
93
|
+
"$$typeof": Symbol(react.test.json),
|
|
94
|
+
"children": [
|
|
95
|
+
"Test Content",
|
|
96
|
+
],
|
|
97
|
+
"props": {
|
|
98
|
+
"style": undefined,
|
|
99
|
+
"testID": "test-content",
|
|
100
|
+
},
|
|
101
|
+
"type": "Text",
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
"props": {
|
|
105
|
+
"style": {
|
|
106
|
+
"marginTop": 8,
|
|
107
|
+
},
|
|
108
|
+
"testID": undefined,
|
|
109
|
+
},
|
|
110
|
+
"type": "View",
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
"props": {
|
|
114
|
+
"style": {
|
|
115
|
+
"borderBottomColor": "#CDCDCD",
|
|
116
|
+
"borderBottomWidth": 2,
|
|
117
|
+
"borderTopColor": "#CDCDCD",
|
|
118
|
+
"borderTopWidth": 2,
|
|
119
|
+
"padding": 16,
|
|
120
|
+
"width": "100%",
|
|
121
|
+
},
|
|
122
|
+
"testID": undefined,
|
|
123
|
+
},
|
|
124
|
+
"type": "View",
|
|
125
|
+
}
|
|
126
|
+
`;
|