@varunindiit/create-rn-starter 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.
Files changed (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +93 -0
  3. package/bin/index.js +270 -0
  4. package/lib/prompt.js +63 -0
  5. package/lib/rename.js +239 -0
  6. package/lib/scaffold.js +110 -0
  7. package/lib/utils.js +122 -0
  8. package/package.json +38 -0
  9. package/template/.eslintrc.js +4 -0
  10. package/template/.prettierrc.js +5 -0
  11. package/template/.watchmanconfig +1 -0
  12. package/template/App.tsx +100 -0
  13. package/template/Gemfile +17 -0
  14. package/template/README.md +97 -0
  15. package/template/__tests__/App.test.tsx +13 -0
  16. package/template/_gitignore +75 -0
  17. package/template/android/app/build.gradle +119 -0
  18. package/template/android/app/debug.keystore +0 -0
  19. package/template/android/app/proguard-rules.pro +10 -0
  20. package/template/android/app/src/main/AndroidManifest.xml +45 -0
  21. package/template/android/app/src/main/assets/fonts/MonaSans-Black.ttf +0 -0
  22. package/template/android/app/src/main/assets/fonts/MonaSans-BlackItalic.ttf +0 -0
  23. package/template/android/app/src/main/assets/fonts/MonaSans-Bold.ttf +0 -0
  24. package/template/android/app/src/main/assets/fonts/MonaSans-BoldItalic.ttf +0 -0
  25. package/template/android/app/src/main/assets/fonts/MonaSans-ExtraBold.ttf +0 -0
  26. package/template/android/app/src/main/assets/fonts/MonaSans-ExtraBoldItalic.ttf +0 -0
  27. package/template/android/app/src/main/assets/fonts/MonaSans-ExtraLight.ttf +0 -0
  28. package/template/android/app/src/main/assets/fonts/MonaSans-ExtraLightItalic.ttf +0 -0
  29. package/template/android/app/src/main/assets/fonts/MonaSans-Italic.ttf +0 -0
  30. package/template/android/app/src/main/assets/fonts/MonaSans-Light.ttf +0 -0
  31. package/template/android/app/src/main/assets/fonts/MonaSans-LightItalic.ttf +0 -0
  32. package/template/android/app/src/main/assets/fonts/MonaSans-Medium.ttf +0 -0
  33. package/template/android/app/src/main/assets/fonts/MonaSans-MediumItalic.ttf +0 -0
  34. package/template/android/app/src/main/assets/fonts/MonaSans-Regular.ttf +0 -0
  35. package/template/android/app/src/main/assets/fonts/MonaSans-SemiBold.ttf +0 -0
  36. package/template/android/app/src/main/assets/fonts/MonaSans-SemiBoldItalic.ttf +0 -0
  37. package/template/android/app/src/main/java/com/awesomeproject/MainActivity.kt +22 -0
  38. package/template/android/app/src/main/java/com/awesomeproject/MainApplication.kt +27 -0
  39. package/template/android/app/src/main/res/drawable/launch_screen.png +0 -0
  40. package/template/android/app/src/main/res/drawable/rn_edit_text_material.xml +37 -0
  41. package/template/android/app/src/main/res/layout/launch_screen.xml +12 -0
  42. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
  43. package/template/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
  44. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
  45. package/template/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
  46. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
  47. package/template/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
  48. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
  49. package/template/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
  50. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
  51. package/template/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
  52. package/template/android/app/src/main/res/values/colors.xml +3 -0
  53. package/template/android/app/src/main/res/values/strings.xml +3 -0
  54. package/template/android/app/src/main/res/values/styles.xml +11 -0
  55. package/template/android/build.gradle +21 -0
  56. package/template/android/gradle/wrapper/gradle-wrapper.jar +0 -0
  57. package/template/android/gradle/wrapper/gradle-wrapper.properties +7 -0
  58. package/template/android/gradle.properties +44 -0
  59. package/template/android/gradlew +248 -0
  60. package/template/android/gradlew.bat +98 -0
  61. package/template/android/link-assets-manifest.json +69 -0
  62. package/template/android/settings.gradle +6 -0
  63. package/template/app.json +4 -0
  64. package/template/babel.config.js +4 -0
  65. package/template/declarations.d.ts +6 -0
  66. package/template/env.example +20 -0
  67. package/template/index.js +10 -0
  68. package/template/ios/.xcode.env +11 -0
  69. package/template/ios/.xcode.env.local +1 -0
  70. package/template/ios/AwesomeProject/AppDelegate.swift +60 -0
  71. package/template/ios/AwesomeProject/Images.xcassets/AppIcon.appiconset/Contents.json +53 -0
  72. package/template/ios/AwesomeProject/Images.xcassets/Contents.json +6 -0
  73. package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Contents.json +23 -0
  74. package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Splash@1x.png +0 -0
  75. package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Splash@2x.png +0 -0
  76. package/template/ios/AwesomeProject/Images.xcassets/Splash.imageset/Splash@3x.png +0 -0
  77. package/template/ios/AwesomeProject/Info.plist +89 -0
  78. package/template/ios/AwesomeProject/LaunchScreen.storyboard +40 -0
  79. package/template/ios/AwesomeProject/PrivacyInfo.xcprivacy +38 -0
  80. package/template/ios/AwesomeProject.xcodeproj/project.pbxproj +576 -0
  81. package/template/ios/AwesomeProject.xcodeproj/xcshareddata/xcschemes/AwesomeProject.xcscheme +88 -0
  82. package/template/ios/AwesomeProject.xcworkspace/contents.xcworkspacedata +10 -0
  83. package/template/ios/Podfile +68 -0
  84. package/template/ios/link-assets-manifest.json +69 -0
  85. package/template/jest.config.js +3 -0
  86. package/template/metro.config.js +24 -0
  87. package/template/package.json +68 -0
  88. package/template/react-native.config.js +7 -0
  89. package/template/src/assets/fonts/MonaSans-Black.ttf +0 -0
  90. package/template/src/assets/fonts/MonaSans-BlackItalic.ttf +0 -0
  91. package/template/src/assets/fonts/MonaSans-Bold.ttf +0 -0
  92. package/template/src/assets/fonts/MonaSans-BoldItalic.ttf +0 -0
  93. package/template/src/assets/fonts/MonaSans-ExtraBold.ttf +0 -0
  94. package/template/src/assets/fonts/MonaSans-ExtraBoldItalic.ttf +0 -0
  95. package/template/src/assets/fonts/MonaSans-ExtraLight.ttf +0 -0
  96. package/template/src/assets/fonts/MonaSans-ExtraLightItalic.ttf +0 -0
  97. package/template/src/assets/fonts/MonaSans-Italic.ttf +0 -0
  98. package/template/src/assets/fonts/MonaSans-Light.ttf +0 -0
  99. package/template/src/assets/fonts/MonaSans-LightItalic.ttf +0 -0
  100. package/template/src/assets/fonts/MonaSans-Medium.ttf +0 -0
  101. package/template/src/assets/fonts/MonaSans-MediumItalic.ttf +0 -0
  102. package/template/src/assets/fonts/MonaSans-Regular.ttf +0 -0
  103. package/template/src/assets/fonts/MonaSans-SemiBold.ttf +0 -0
  104. package/template/src/assets/fonts/MonaSans-SemiBoldItalic.ttf +0 -0
  105. package/template/src/assets/image/BackGroundAuth.png +0 -0
  106. package/template/src/assets/image/BackgroundVerification.png +0 -0
  107. package/template/src/assets/image/logo.png +0 -0
  108. package/template/src/assets/svg/add-circle.svg +5 -0
  109. package/template/src/assets/svg/airConditioning.svg +12 -0
  110. package/template/src/assets/svg/apple.svg +3 -0
  111. package/template/src/assets/svg/arrowDown.svg +3 -0
  112. package/template/src/assets/svg/back.svg +10 -0
  113. package/template/src/assets/svg/bag.svg +11 -0
  114. package/template/src/assets/svg/calender.svg +5 -0
  115. package/template/src/assets/svg/car.svg +10 -0
  116. package/template/src/assets/svg/carConfirm.svg +60 -0
  117. package/template/src/assets/svg/chatActive.svg +3 -0
  118. package/template/src/assets/svg/chatUnActive.svg +3 -0
  119. package/template/src/assets/svg/document-text.svg +6 -0
  120. package/template/src/assets/svg/gender.svg +11 -0
  121. package/template/src/assets/svg/google.svg +6 -0
  122. package/template/src/assets/svg/headphone.svg +3 -0
  123. package/template/src/assets/svg/homeActive.svg +3 -0
  124. package/template/src/assets/svg/homeUnActive.svg +3 -0
  125. package/template/src/assets/svg/logo.svg +18 -0
  126. package/template/src/assets/svg/logout.svg +5 -0
  127. package/template/src/assets/svg/maxBack.svg +4 -0
  128. package/template/src/assets/svg/message-text.svg +7 -0
  129. package/template/src/assets/svg/music.svg +5 -0
  130. package/template/src/assets/svg/noSmoking.svg +10 -0
  131. package/template/src/assets/svg/notification.svg +5 -0
  132. package/template/src/assets/svg/passenger.svg +4 -0
  133. package/template/src/assets/svg/phone.svg +3 -0
  134. package/template/src/assets/svg/rightArrow.svg +3 -0
  135. package/template/src/assets/svg/security-user.svg +5 -0
  136. package/template/src/assets/svg/star.svg +3 -0
  137. package/template/src/assets/svg/tick-circle.svg +4 -0
  138. package/template/src/assets/svg/trafficLight.svg +41 -0
  139. package/template/src/assets/svg/tripActive.svg +10 -0
  140. package/template/src/assets/svg/tripUnActive.svg +10 -0
  141. package/template/src/assets/svg/usbChargers.svg +3 -0
  142. package/template/src/assets/svg/user.svg +4 -0
  143. package/template/src/assets/svg/userActive.svg +3 -0
  144. package/template/src/assets/svg/userPlaceholder.svg +3 -0
  145. package/template/src/assets/svg/userUnActive.svg +3 -0
  146. package/template/src/components/AuthLayout/AuthLayout.tsx +170 -0
  147. package/template/src/components/AuthLayout/index.ts +1 -0
  148. package/template/src/components/BottomSheet/BottomSheet.tsx +73 -0
  149. package/template/src/components/BottomSheet/BottomSheetAlert.tsx +100 -0
  150. package/template/src/components/BottomSheet/CenterAlert.tsx +153 -0
  151. package/template/src/components/BottomSheet/index.ts +2 -0
  152. package/template/src/components/BottomTabBar/index.tsx +145 -0
  153. package/template/src/components/Button/RNButton.tsx +152 -0
  154. package/template/src/components/Button/index.ts +2 -0
  155. package/template/src/components/Common/Avatar.tsx +80 -0
  156. package/template/src/components/Common/Card.tsx +49 -0
  157. package/template/src/components/Common/CardBrandLogo.tsx +66 -0
  158. package/template/src/components/Common/Checkbox.tsx +65 -0
  159. package/template/src/components/Common/Chip.tsx +79 -0
  160. package/template/src/components/Common/CommonStyles.tsx +594 -0
  161. package/template/src/components/Common/Divider.tsx +33 -0
  162. package/template/src/components/Common/DriverTripCard.tsx +308 -0
  163. package/template/src/components/Common/Dropdown.tsx +161 -0
  164. package/template/src/components/Common/EmptyState.tsx +52 -0
  165. package/template/src/components/Common/FAB.tsx +68 -0
  166. package/template/src/components/Common/HeaderLocation.tsx +108 -0
  167. package/template/src/components/Common/Loader.tsx +23 -0
  168. package/template/src/components/Common/RatingStars.tsx +103 -0
  169. package/template/src/components/Common/RouteDots.tsx +98 -0
  170. package/template/src/components/Common/SegmentedControl.tsx +126 -0
  171. package/template/src/components/Common/SosButton.tsx +80 -0
  172. package/template/src/components/Common/SosSheet.tsx +344 -0
  173. package/template/src/components/Common/StarRating.tsx +58 -0
  174. package/template/src/components/Common/StatusBadge.tsx +56 -0
  175. package/template/src/components/Common/Toggle.tsx +66 -0
  176. package/template/src/components/Common/TripCard.tsx +247 -0
  177. package/template/src/components/Common/UploadBox.tsx +106 -0
  178. package/template/src/components/Container/MainContainer.tsx +76 -0
  179. package/template/src/components/Container/index.ts +1 -0
  180. package/template/src/components/Header/index.tsx +143 -0
  181. package/template/src/components/Icon/SvgIcons.tsx +1991 -0
  182. package/template/src/components/ImagePickerSheet/ImagePickerSheet.tsx +233 -0
  183. package/template/src/components/ImagePickerSheet/index.ts +2 -0
  184. package/template/src/components/Input/CountryDropdown.tsx +71 -0
  185. package/template/src/components/Input/OtpInput.tsx +117 -0
  186. package/template/src/components/Input/RNInput.tsx +138 -0
  187. package/template/src/components/Input/index.ts +4 -0
  188. package/template/src/components/Picker/DatePickerSheet.tsx +393 -0
  189. package/template/src/components/Picker/PassengerPickerSheet.tsx +237 -0
  190. package/template/src/components/Text/RNText.tsx +62 -0
  191. package/template/src/components/Text/index.ts +1 -0
  192. package/template/src/components/index.ts +44 -0
  193. package/template/src/hooks/useCurrentLocation.ts +72 -0
  194. package/template/src/localization/i18n.ts +29 -0
  195. package/template/src/localization/i18next.d.ts +11 -0
  196. package/template/src/localization/index.ts +4 -0
  197. package/template/src/localization/languageStorage.ts +27 -0
  198. package/template/src/localization/languages.ts +62 -0
  199. package/template/src/localization/resources/en.ts +703 -0
  200. package/template/src/localization/resources/fr.ts +703 -0
  201. package/template/src/localization/useLanguage.ts +42 -0
  202. package/template/src/navigation/AuthNavigation.tsx +23 -0
  203. package/template/src/navigation/BottomTabs.tsx +24 -0
  204. package/template/src/navigation/RootNavigation.tsx +27 -0
  205. package/template/src/navigation/RouteKey.ts +22 -0
  206. package/template/src/navigation/StackNavigation.tsx +52 -0
  207. package/template/src/navigation/paramLists.ts +25 -0
  208. package/template/src/redux/slice/app.ts +66 -0
  209. package/template/src/redux/slice/auth.ts +40 -0
  210. package/template/src/redux/slice/userProfile.ts +124 -0
  211. package/template/src/redux/store.ts +17 -0
  212. package/template/src/screen/auth/Login.tsx +69 -0
  213. package/template/src/screen/onboarding/LanguageSelection.tsx +231 -0
  214. package/template/src/screen/root/home/index.tsx +36 -0
  215. package/template/src/screen/root/profile/index.tsx +69 -0
  216. package/template/src/screen/shared/Chat.tsx +308 -0
  217. package/template/src/screen/shared/EditProfile.tsx +407 -0
  218. package/template/src/screen/shared/HelpSupport.tsx +678 -0
  219. package/template/src/screen/shared/LocationSearch.tsx +362 -0
  220. package/template/src/screen/shared/Messages.tsx +115 -0
  221. package/template/src/screen/shared/Notifications.tsx +86 -0
  222. package/template/src/screen/shared/PrivacyPolicy.tsx +297 -0
  223. package/template/src/screen/shared/Profile.tsx +118 -0
  224. package/template/src/screen/shared/Ratings.tsx +170 -0
  225. package/template/src/screen/shared/TermsConditions.tsx +315 -0
  226. package/template/src/screen/shared/profile/DriverProfile.tsx +262 -0
  227. package/template/src/screen/shared/profile/PassengerProfile.tsx +123 -0
  228. package/template/src/screen/shared/profile/ProfileParts.tsx +219 -0
  229. package/template/src/services/Config.ts +37 -0
  230. package/template/src/services/api.ts +37 -0
  231. package/template/src/services/index.ts +4 -0
  232. package/template/src/services/places.ts +320 -0
  233. package/template/src/services/storage.ts +33 -0
  234. package/template/src/theme/fonts.ts +30 -0
  235. package/template/src/theme/index.ts +3 -0
  236. package/template/src/theme/spacing.ts +66 -0
  237. package/template/src/theme/theme.ts +58 -0
  238. package/template/src/types/env.d.ts +8 -0
  239. package/template/src/types/index.ts +3 -0
  240. package/template/src/utils/card.ts +101 -0
  241. package/template/src/utils/constants.ts +39 -0
  242. package/template/src/utils/functions.ts +24 -0
  243. package/template/tsconfig.json +8 -0
@@ -0,0 +1,233 @@
1
+ import React, { useCallback, useMemo, useState } from "react";
2
+ import { Pressable, StyleSheet, View } from "react-native";
3
+ import ImageCropPicker, {
4
+ Image as PickedImage,
5
+ Options,
6
+ } from "react-native-image-crop-picker";
7
+ import { moderateScale } from "react-native-size-matters";
8
+ import { CameraIcon, GalleryIcon } from "../Icon/SvgIcons";
9
+ import { SPACING, THEME } from "../../theme";
10
+ import { showToast } from "../../utils/functions";
11
+ import { useLanguage } from "../../localization";
12
+ import BottomSheet from "../BottomSheet/BottomSheet";
13
+ import RNText from "../Text/RNText";
14
+
15
+ export interface ImagePickerSheetProps {
16
+ visible: boolean;
17
+ onClose: () => void;
18
+ onPicked: (image: PickedImage) => void;
19
+ title?: string;
20
+ subtitle?: string;
21
+ cropping?: boolean;
22
+ circular?: boolean;
23
+ width?: number;
24
+ height?: number;
25
+ compressImageQuality?: number;
26
+ }
27
+
28
+ const ImagePickerSheet: React.FC<ImagePickerSheetProps> = ({
29
+ visible,
30
+ onClose,
31
+ onPicked,
32
+ title,
33
+ subtitle,
34
+ cropping = true,
35
+ circular = false,
36
+ width = 1200,
37
+ height = 1200,
38
+ compressImageQuality = 0.85,
39
+ }) => {
40
+ const { t } = useLanguage();
41
+ const [busy, setBusy] = useState<"camera" | "gallery" | null>(null);
42
+
43
+ const titleText = title ?? t("imagePicker.updatePhoto");
44
+ const subtitleText = subtitle ?? t("imagePicker.subtitle");
45
+
46
+ const baseOptions: Options = useMemo(
47
+ () => ({
48
+ width,
49
+ height,
50
+ cropping,
51
+ cropperCircleOverlay: circular,
52
+ mediaType: "photo",
53
+ includeBase64: false,
54
+ compressImageQuality,
55
+ forceJpg: true,
56
+ cropperToolbarTitle: t("imagePicker.cropTitle"),
57
+ cropperActiveWidgetColor: THEME.primary,
58
+ cropperStatusBarLight: false,
59
+ cropperToolbarColor: THEME.background,
60
+ cropperToolbarWidgetColor: THEME.text,
61
+ }),
62
+ [width, height, cropping, circular, compressImageQuality, t],
63
+ );
64
+
65
+ const handleResult = useCallback(
66
+ (image: PickedImage) => {
67
+ onPicked(image);
68
+ onClose();
69
+ },
70
+ [onPicked, onClose],
71
+ );
72
+
73
+ const handleError = useCallback((err: any) => {
74
+ const code = err?.code ?? err?.message;
75
+ if (/cancel/i.test(String(code))) return;
76
+ if (
77
+ code === "E_NO_LIBRARY_PERMISSION" ||
78
+ code === "E_NO_CAMERA_PERMISSION"
79
+ ) {
80
+ showToast(t("imagePicker.permissionDenied"), "warning");
81
+ return;
82
+ }
83
+ showToast(t("common.somethingWrong"), "danger");
84
+ }, [t]);
85
+
86
+ const openCamera = useCallback(async () => {
87
+ if (busy) return;
88
+ setBusy("camera");
89
+ try {
90
+ const image = (await ImageCropPicker.openCamera(
91
+ baseOptions,
92
+ )) as PickedImage;
93
+ handleResult(image);
94
+ } catch (err) {
95
+ handleError(err);
96
+ } finally {
97
+ setBusy(null);
98
+ }
99
+ }, [busy, baseOptions, handleResult, handleError]);
100
+
101
+ const openGallery = useCallback(async () => {
102
+ if (busy) return;
103
+ setBusy("gallery");
104
+ try {
105
+ const image = (await ImageCropPicker.openPicker(
106
+ baseOptions,
107
+ )) as PickedImage;
108
+ handleResult(image);
109
+ } catch (err) {
110
+ handleError(err);
111
+ } finally {
112
+ setBusy(null);
113
+ }
114
+ }, [busy, baseOptions, handleResult, handleError]);
115
+
116
+ return (
117
+ <BottomSheet visible={visible} onClose={onClose}>
118
+ <RNText font="semibold" size={18} color={THEME.text}>
119
+ {titleText}
120
+ </RNText>
121
+ <RNText size={12} color={THEME.textMuted} style={styles.subtitle}>
122
+ {subtitleText}
123
+ </RNText>
124
+
125
+ <View style={styles.card}>
126
+ <Row
127
+ icon={
128
+ <CameraIcon size={moderateScale(20)} color={THEME.primary} />
129
+ }
130
+ label={t("imagePicker.openCamera")}
131
+ caption={t("imagePicker.openCameraCaption")}
132
+ onPress={openCamera}
133
+ disabled={!!busy}
134
+ />
135
+ <View style={styles.divider} />
136
+ <Row
137
+ icon={
138
+ <GalleryIcon size={moderateScale(20)} color={THEME.primary} />
139
+ }
140
+ label={t("imagePicker.chooseFromGallery")}
141
+ caption={t("imagePicker.galleryCaption")}
142
+ onPress={openGallery}
143
+ disabled={!!busy}
144
+ />
145
+ </View>
146
+
147
+ <Pressable onPress={onClose} style={styles.cancel}>
148
+ <RNText font="semibold" size={15} color={THEME.text}>
149
+ {t("common.cancel")}
150
+ </RNText>
151
+ </Pressable>
152
+ </BottomSheet>
153
+ );
154
+ };
155
+
156
+ const Row = ({
157
+ icon,
158
+ label,
159
+ caption,
160
+ onPress,
161
+ disabled,
162
+ }: {
163
+ icon: React.ReactNode;
164
+ label: string;
165
+ caption: string;
166
+ onPress: () => void;
167
+ disabled?: boolean;
168
+ }) => (
169
+ <Pressable
170
+ onPress={onPress}
171
+ disabled={disabled}
172
+ style={[styles.row, disabled && styles.rowDisabled]}
173
+ >
174
+ <View style={styles.iconBubble}>{icon}</View>
175
+ <View style={styles.rowBody}>
176
+ <RNText font="semibold" size={14} color={THEME.text}>
177
+ {label}
178
+ </RNText>
179
+ <RNText size={11} color={THEME.textMuted} style={styles.caption}>
180
+ {caption}
181
+ </RNText>
182
+ </View>
183
+ </Pressable>
184
+ );
185
+
186
+ export default ImagePickerSheet;
187
+
188
+ const styles = StyleSheet.create({
189
+ subtitle: { marginTop: moderateScale(4), marginBottom: SPACING.lg },
190
+ card: {
191
+ backgroundColor: THEME.backgroundAlt,
192
+ borderRadius: SPACING.radiusLg,
193
+ padding: moderateScale(6),
194
+ },
195
+ row: {
196
+ flexDirection: "row",
197
+ alignItems: "center",
198
+ paddingHorizontal: moderateScale(10),
199
+ paddingVertical: moderateScale(14),
200
+ gap: moderateScale(14),
201
+ borderRadius: SPACING.radiusMd,
202
+ },
203
+ rowDisabled: {
204
+ opacity: 0.5,
205
+ },
206
+ divider: {
207
+ height: 1,
208
+ backgroundColor: THEME.divider,
209
+ marginHorizontal: moderateScale(10),
210
+ },
211
+ rowBody: {
212
+ flex: 1,
213
+ },
214
+ caption: {
215
+ marginTop: moderateScale(2),
216
+ },
217
+ iconBubble: {
218
+ width: moderateScale(40),
219
+ height: moderateScale(40),
220
+ borderRadius: moderateScale(12),
221
+ backgroundColor: THEME.primaryFaint,
222
+ alignItems: "center",
223
+ justifyContent: "center",
224
+ },
225
+ cancel: {
226
+ marginTop: SPACING.md,
227
+ height: moderateScale(52),
228
+ borderRadius: SPACING.radiusPill,
229
+ backgroundColor: THEME.surfaceMuted,
230
+ alignItems: "center",
231
+ justifyContent: "center",
232
+ },
233
+ });
@@ -0,0 +1,2 @@
1
+ export { default as ImagePickerSheet } from "./ImagePickerSheet";
2
+ export type { ImagePickerSheetProps } from "./ImagePickerSheet";
@@ -0,0 +1,71 @@
1
+ import React from "react";
2
+ import {
3
+ StyleSheet,
4
+ TouchableOpacity,
5
+ View,
6
+ StyleProp,
7
+ ViewStyle,
8
+ } from "react-native";
9
+ import { moderateScale } from "react-native-size-matters";
10
+ import { SIZES, SPACING, THEME } from "../../theme";
11
+ import RNText from "../Text/RNText";
12
+ import { ChevronDownIcon } from "../Icon/SvgIcons";
13
+
14
+ export interface CountryItem {
15
+ name: string;
16
+ code: string;
17
+ flag: string;
18
+ }
19
+
20
+ interface CountryDropdownProps {
21
+ value: CountryItem;
22
+ onPress?: () => void;
23
+ containerStyle?: StyleProp<ViewStyle>;
24
+ compact?: boolean;
25
+ }
26
+
27
+ const CountryDropdown: React.FC<CountryDropdownProps> = ({
28
+ value,
29
+ onPress,
30
+ containerStyle,
31
+ compact,
32
+ }) => (
33
+ <TouchableOpacity
34
+ activeOpacity={0.85}
35
+ onPress={onPress}
36
+ style={[styles.container, containerStyle]}
37
+ >
38
+ <RNText size={18} style={styles.flag}>
39
+ {value.flag}
40
+ </RNText>
41
+ <RNText size={14} font="medium" color={THEME.text}>
42
+ {value.code}
43
+ </RNText>
44
+ <ChevronDownIcon size={moderateScale(14)} color={THEME.textMuted} />
45
+ {!compact && (
46
+ <View style={styles.spacer}>
47
+ <RNText size={14} color={THEME.text}>
48
+ {value.name}
49
+ </RNText>
50
+ </View>
51
+ )}
52
+ </TouchableOpacity>
53
+ );
54
+
55
+ export default CountryDropdown;
56
+
57
+ const styles = StyleSheet.create({
58
+ container: {
59
+ height: SIZES.inputHeight,
60
+ borderRadius: SPACING.radiusMd,
61
+ borderWidth: 1,
62
+ borderColor: THEME.inputBorder,
63
+ backgroundColor: THEME.surface,
64
+ paddingHorizontal: moderateScale(12),
65
+ flexDirection: "row",
66
+ alignItems: "center",
67
+ gap: moderateScale(6),
68
+ },
69
+ flag: { fontSize: moderateScale(18) },
70
+ spacer: { flex: 1, marginLeft: moderateScale(6) },
71
+ });
@@ -0,0 +1,117 @@
1
+ import React, { useRef, useState } from "react";
2
+ import {
3
+ NativeSyntheticEvent,
4
+ StyleSheet,
5
+ TextInput,
6
+ TextInputKeyPressEventData,
7
+ View,
8
+ } from "react-native";
9
+ import { moderateScale } from "react-native-size-matters";
10
+ import { FONTS, THEME } from "../../theme";
11
+
12
+ interface OtpInputProps {
13
+ length?: number;
14
+ value: string;
15
+ onChange: (val: string) => void;
16
+ autoFocus?: boolean;
17
+ placeholder?: string;
18
+ cellSize?: number;
19
+ }
20
+
21
+ const OtpInput: React.FC<OtpInputProps> = ({
22
+ length = 4,
23
+ value,
24
+ onChange,
25
+ autoFocus = false,
26
+ placeholder = "",
27
+ cellSize,
28
+ }) => {
29
+ const inputs = useRef<Array<TextInput | null>>([]);
30
+ const [focusIndex, setFocusIndex] = useState(autoFocus ? 0 : -1);
31
+
32
+ const setCharAt = (i: number, c: string) => {
33
+ const next = value.split("");
34
+ while (next.length < length) next.push("");
35
+ next[i] = c;
36
+ onChange(next.slice(0, length).join(""));
37
+ };
38
+
39
+ const handleChange = (text: string, index: number) => {
40
+ if (text.length > 1) {
41
+ const chars = text.replace(/\s/g, "").split("").slice(0, length);
42
+ onChange(chars.join("").padEnd(length, "").slice(0, length).trim());
43
+ const next = Math.min(chars.length, length - 1);
44
+ inputs.current[next]?.focus();
45
+ return;
46
+ }
47
+ setCharAt(index, text);
48
+ if (text && index < length - 1) inputs.current[index + 1]?.focus();
49
+ };
50
+
51
+ const handleKeyPress = (
52
+ e: NativeSyntheticEvent<TextInputKeyPressEventData>,
53
+ index: number,
54
+ ) => {
55
+ if (e.nativeEvent.key === "Backspace" && !value[index] && index > 0) {
56
+ inputs.current[index - 1]?.focus();
57
+ setCharAt(index - 1, "");
58
+ }
59
+ };
60
+
61
+ return (
62
+ <View style={styles.row}>
63
+ {Array.from({ length }).map((_, i) => {
64
+ const char = value[i] ?? "";
65
+ const active = focusIndex === i;
66
+ return (
67
+ <TextInput
68
+ allowFontScaling={false}
69
+ key={i}
70
+ ref={(r) => {
71
+ inputs.current[i] = r;
72
+ }}
73
+ value={char}
74
+ onChangeText={(t) => handleChange(t, i)}
75
+ onKeyPress={(e) => handleKeyPress(e, i)}
76
+ onFocus={() => setFocusIndex(i)}
77
+ onBlur={() => setFocusIndex(-1)}
78
+ keyboardType="number-pad"
79
+ maxLength={1}
80
+ autoFocus={autoFocus && i === 0}
81
+ placeholder={placeholder}
82
+ style={[
83
+ styles.cell,
84
+ cellSize
85
+ ? { width: cellSize, height: cellSize }
86
+ : null,
87
+ { borderColor: active ? THEME.primary : THEME.inputBorder },
88
+ ]}
89
+ selectionColor={THEME.primary}
90
+ placeholderTextColor={THEME.textPlaceholder}
91
+ />
92
+ );
93
+ })}
94
+ </View>
95
+ );
96
+ };
97
+
98
+ export default OtpInput;
99
+
100
+ const styles = StyleSheet.create({
101
+ row: {
102
+ flexDirection: "row",
103
+ gap: moderateScale(12),
104
+ },
105
+ cell: {
106
+ flex: 1,
107
+ height: moderateScale(60),
108
+ borderRadius: moderateScale(20),
109
+ borderWidth: 1,
110
+ backgroundColor: THEME.surface,
111
+ textAlign: "center",
112
+ color: THEME.text,
113
+ fontFamily: FONTS.regular,
114
+ fontWeight: "400",
115
+ fontSize: moderateScale(14, 0.3),
116
+ },
117
+ });
@@ -0,0 +1,138 @@
1
+ import React, { useCallback, useState } from "react";
2
+ import {
3
+ StyleProp,
4
+ StyleSheet,
5
+ TextInput,
6
+ TextInputProps,
7
+ TouchableOpacity,
8
+ View,
9
+ ViewStyle,
10
+ } from "react-native";
11
+ import { moderateScale } from "react-native-size-matters";
12
+ import { FONTS, SPACING, THEME } from "../../theme";
13
+ import RNText from "../Text/RNText";
14
+ import { EyeIcon, EyeOffIcon } from "../Icon/SvgIcons";
15
+
16
+ interface RNInputProps extends TextInputProps {
17
+ label?: string;
18
+ error?: string;
19
+ secure?: boolean;
20
+ containerStyle?: StyleProp<ViewStyle>;
21
+ inputContainerStyle?: StyleProp<ViewStyle>;
22
+ leftIcon?: React.ReactNode;
23
+ rightIcon?: React.ReactNode;
24
+ onPressRightIcon?: () => void;
25
+ focusedBorderColor?: string;
26
+ }
27
+
28
+ const RNInput: React.FC<RNInputProps> = ({
29
+ label,
30
+ error,
31
+ secure = false,
32
+ containerStyle,
33
+ inputContainerStyle,
34
+ leftIcon,
35
+ rightIcon,
36
+ onPressRightIcon,
37
+ focusedBorderColor = THEME.primary,
38
+ style,
39
+ onFocus,
40
+ onBlur,
41
+ ...rest
42
+ }) => {
43
+ const [secureVisible, setSecureVisible] = useState(false);
44
+ const [focused, setFocused] = useState(false);
45
+
46
+ const toggleSecure = useCallback(() => setSecureVisible((v) => !v), []);
47
+
48
+ const right = secure ? (
49
+ <TouchableOpacity onPress={toggleSecure} hitSlop={10}>
50
+ {secureVisible ? (
51
+ <EyeIcon color={THEME.textMuted} />
52
+ ) : (
53
+ <EyeOffIcon color={THEME.textMuted} />
54
+ )}
55
+ </TouchableOpacity>
56
+ ) : rightIcon ? (
57
+ <TouchableOpacity
58
+ onPress={onPressRightIcon}
59
+ hitSlop={10}
60
+ disabled={!onPressRightIcon}
61
+ >
62
+ {rightIcon}
63
+ </TouchableOpacity>
64
+ ) : null;
65
+
66
+ return (
67
+ <View style={[styles.wrap, containerStyle]}>
68
+ {label ? (
69
+ <RNText size={13} color={THEME.textSecondary} font="medium" style={styles.label}>
70
+ {label}
71
+ </RNText>
72
+ ) : null}
73
+ <View
74
+ style={[
75
+ styles.inputContainer,
76
+ {
77
+ borderColor: error
78
+ ? THEME.danger
79
+ : focused
80
+ ? focusedBorderColor
81
+ : THEME.border,
82
+ },
83
+ inputContainerStyle,
84
+ ]}
85
+ >
86
+ {leftIcon ? <View style={styles.left}>{leftIcon}</View> : null}
87
+ <TextInput
88
+ allowFontScaling={false}
89
+ {...rest}
90
+ onFocus={(e) => {
91
+ setFocused(true);
92
+ onFocus?.(e);
93
+ }}
94
+ onBlur={(e) => {
95
+ setFocused(false);
96
+ onBlur?.(e);
97
+ }}
98
+ placeholderTextColor={THEME.textPlaceholder}
99
+ secureTextEntry={secure && !secureVisible}
100
+ style={[styles.input, style]}
101
+ />
102
+ {right ? <View style={styles.right}>{right}</View> : null}
103
+ </View>
104
+ {error ? (
105
+ <RNText size={11} color={THEME.danger} style={styles.errorText}>
106
+ {error}
107
+ </RNText>
108
+ ) : null}
109
+ </View>
110
+ );
111
+ };
112
+
113
+ export default React.memo(RNInput);
114
+
115
+ const styles = StyleSheet.create({
116
+ wrap: { width: "100%" },
117
+ label: { marginBottom: moderateScale(6) },
118
+ inputContainer: {
119
+ height: moderateScale(50),
120
+ paddingHorizontal: moderateScale(18),
121
+ borderRadius: SPACING.radiusPill,
122
+ borderWidth: 1,
123
+ borderColor: THEME.border,
124
+ backgroundColor: THEME.surface,
125
+ flexDirection: "row",
126
+ alignItems: "center",
127
+ },
128
+ input: {
129
+ flex: 1,
130
+ color: THEME.text,
131
+ fontFamily: FONTS.regular,
132
+ fontSize: moderateScale(14, 0.3),
133
+ paddingVertical: 0,
134
+ },
135
+ left: { marginRight: moderateScale(10) },
136
+ right: { marginLeft: moderateScale(10) },
137
+ errorText: { marginTop: moderateScale(6) },
138
+ });
@@ -0,0 +1,4 @@
1
+ export { default as RNInput } from "./RNInput";
2
+ export { default as OtpInput } from "./OtpInput";
3
+ export { default as CountryDropdown } from "./CountryDropdown";
4
+ export type { CountryItem } from "./CountryDropdown";