@croacroa/react-native-template 2.1.0 → 3.2.0

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 (172) hide show
  1. package/.env.example +5 -0
  2. package/.eslintrc.js +8 -0
  3. package/.github/workflows/ci.yml +187 -187
  4. package/.github/workflows/eas-build.yml +55 -55
  5. package/.github/workflows/eas-update.yml +50 -50
  6. package/.github/workflows/npm-publish.yml +57 -0
  7. package/CHANGELOG.md +195 -106
  8. package/CONTRIBUTING.md +377 -377
  9. package/LICENSE +21 -21
  10. package/README.md +446 -402
  11. package/__tests__/accessibility/components.test.tsx +285 -0
  12. package/__tests__/components/Button.test.tsx +2 -4
  13. package/__tests__/components/__snapshots__/snapshots.test.tsx.snap +512 -0
  14. package/__tests__/components/snapshots.test.tsx +131 -131
  15. package/__tests__/helpers/a11y.ts +54 -0
  16. package/__tests__/hooks/useAnalytics.test.ts +100 -0
  17. package/__tests__/hooks/useAnimations.test.ts +70 -0
  18. package/__tests__/hooks/useAuth.test.tsx +71 -28
  19. package/__tests__/hooks/useMedia.test.ts +318 -0
  20. package/__tests__/hooks/usePayments.test.tsx +307 -0
  21. package/__tests__/hooks/usePermission.test.ts +230 -0
  22. package/__tests__/hooks/useWebSocket.test.ts +329 -0
  23. package/__tests__/integration/auth-api.test.tsx +224 -227
  24. package/__tests__/performance/VirtualizedList.perf.test.tsx +385 -362
  25. package/__tests__/services/api.test.ts +24 -6
  26. package/app/(auth)/home.tsx +11 -9
  27. package/app/(auth)/profile.tsx +8 -6
  28. package/app/(auth)/settings.tsx +11 -9
  29. package/app/(public)/forgot-password.tsx +25 -15
  30. package/app/(public)/login.tsx +48 -12
  31. package/app/(public)/onboarding.tsx +5 -5
  32. package/app/(public)/register.tsx +24 -15
  33. package/app/_layout.tsx +6 -3
  34. package/app.config.ts +27 -2
  35. package/assets/images/.gitkeep +7 -7
  36. package/assets/images/adaptive-icon.png +0 -0
  37. package/assets/images/favicon.png +0 -0
  38. package/assets/images/icon.png +0 -0
  39. package/assets/images/notification-icon.png +0 -0
  40. package/assets/images/splash.png +0 -0
  41. package/components/ErrorBoundary.tsx +73 -28
  42. package/components/auth/SocialLoginButtons.tsx +168 -0
  43. package/components/forms/FormInput.tsx +5 -3
  44. package/components/onboarding/OnboardingScreen.tsx +370 -370
  45. package/components/onboarding/index.ts +2 -2
  46. package/components/providers/AnalyticsProvider.tsx +67 -0
  47. package/components/providers/SuspenseBoundary.tsx +359 -357
  48. package/components/providers/index.ts +24 -21
  49. package/components/ui/AnimatedButton.tsx +1 -9
  50. package/components/ui/AnimatedList.tsx +98 -0
  51. package/components/ui/AnimatedScreen.tsx +89 -0
  52. package/components/ui/Avatar.tsx +319 -316
  53. package/components/ui/Badge.tsx +416 -416
  54. package/components/ui/BottomSheet.tsx +307 -307
  55. package/components/ui/Button.tsx +11 -3
  56. package/components/ui/Checkbox.tsx +261 -261
  57. package/components/ui/FeatureGate.tsx +57 -0
  58. package/components/ui/ForceUpdateScreen.tsx +108 -0
  59. package/components/ui/ImagePickerButton.tsx +180 -0
  60. package/components/ui/Input.stories.tsx +2 -10
  61. package/components/ui/Input.tsx +2 -10
  62. package/components/ui/OptimizedImage.tsx +369 -369
  63. package/components/ui/Paywall.tsx +253 -0
  64. package/components/ui/PermissionGate.tsx +155 -0
  65. package/components/ui/PurchaseButton.tsx +84 -0
  66. package/components/ui/Select.tsx +240 -240
  67. package/components/ui/Skeleton.tsx +3 -1
  68. package/components/ui/Toast.tsx +427 -418
  69. package/components/ui/UploadProgress.tsx +189 -0
  70. package/components/ui/VirtualizedList.tsx +288 -285
  71. package/components/ui/index.ts +28 -30
  72. package/constants/config.ts +135 -97
  73. package/docs/adr/001-state-management.md +79 -79
  74. package/docs/adr/002-styling-approach.md +130 -130
  75. package/docs/adr/003-data-fetching.md +155 -155
  76. package/docs/adr/004-auth-adapter-pattern.md +144 -144
  77. package/docs/adr/README.md +78 -78
  78. package/docs/guides/analytics-posthog.md +121 -0
  79. package/docs/guides/auth-supabase.md +162 -0
  80. package/docs/guides/feature-flags-launchdarkly.md +150 -0
  81. package/docs/guides/payments-revenuecat.md +169 -0
  82. package/docs/plans/2026-02-22-phase6-implementation.md +3222 -0
  83. package/docs/plans/2026-02-22-phase6-template-completion-design.md +196 -0
  84. package/docs/plans/2026-02-23-npm-publish-design.md +31 -0
  85. package/docs/plans/2026-02-23-phase7-polish-documentation-design.md +79 -0
  86. package/docs/plans/2026-02-23-phase8-additional-features-design.md +136 -0
  87. package/eas.json +2 -1
  88. package/hooks/index.ts +70 -40
  89. package/hooks/useAnimatedEntry.ts +204 -0
  90. package/hooks/useApi.ts +5 -4
  91. package/hooks/useAuth.tsx +7 -3
  92. package/hooks/useBiometrics.ts +295 -295
  93. package/hooks/useChannel.ts +111 -0
  94. package/hooks/useDeepLinking.ts +256 -256
  95. package/hooks/useExperiment.ts +36 -0
  96. package/hooks/useFeatureFlag.ts +59 -0
  97. package/hooks/useForceUpdate.ts +91 -0
  98. package/hooks/useImagePicker.ts +281 -375
  99. package/hooks/useInAppReview.ts +64 -0
  100. package/hooks/useMFA.ts +509 -499
  101. package/hooks/useParallax.ts +142 -0
  102. package/hooks/usePerformance.ts +434 -434
  103. package/hooks/usePermission.ts +190 -0
  104. package/hooks/usePresence.ts +129 -0
  105. package/hooks/useProducts.ts +36 -0
  106. package/hooks/usePurchase.ts +103 -0
  107. package/hooks/useRateLimit.ts +70 -0
  108. package/hooks/useSubscription.ts +49 -0
  109. package/hooks/useTrackEvent.ts +52 -0
  110. package/hooks/useTrackScreen.ts +40 -0
  111. package/hooks/useUpdates.ts +358 -358
  112. package/hooks/useUpload.ts +165 -0
  113. package/hooks/useWebSocket.ts +111 -0
  114. package/i18n/index.ts +197 -194
  115. package/i18n/locales/ar.json +170 -101
  116. package/i18n/locales/de.json +170 -101
  117. package/i18n/locales/en.json +170 -101
  118. package/i18n/locales/es.json +170 -101
  119. package/i18n/locales/fr.json +170 -101
  120. package/jest.config.js +1 -1
  121. package/maestro/README.md +113 -113
  122. package/maestro/config.yaml +35 -35
  123. package/maestro/flows/login.yaml +62 -62
  124. package/maestro/flows/mfa-login.yaml +92 -92
  125. package/maestro/flows/mfa-setup.yaml +86 -86
  126. package/maestro/flows/navigation.yaml +68 -68
  127. package/maestro/flows/offline-conflict.yaml +101 -101
  128. package/maestro/flows/offline-sync.yaml +128 -128
  129. package/maestro/flows/offline.yaml +60 -60
  130. package/maestro/flows/register.yaml +94 -94
  131. package/package.json +188 -176
  132. package/scripts/generate-placeholders.js +38 -0
  133. package/services/analytics/adapters/console.ts +50 -0
  134. package/services/analytics/analytics-adapter.ts +94 -0
  135. package/services/analytics/types.ts +73 -0
  136. package/services/analytics.ts +428 -428
  137. package/services/api.ts +419 -340
  138. package/services/auth/social/apple.ts +110 -0
  139. package/services/auth/social/google.ts +159 -0
  140. package/services/auth/social/social-auth.ts +100 -0
  141. package/services/auth/social/types.ts +80 -0
  142. package/services/authAdapter.ts +333 -333
  143. package/services/backgroundSync.ts +652 -626
  144. package/services/feature-flags/adapters/mock.ts +108 -0
  145. package/services/feature-flags/feature-flag-adapter.ts +174 -0
  146. package/services/feature-flags/types.ts +79 -0
  147. package/services/force-update.ts +140 -0
  148. package/services/index.ts +116 -54
  149. package/services/media/compression.ts +91 -0
  150. package/services/media/media-picker.ts +151 -0
  151. package/services/media/media-upload.ts +160 -0
  152. package/services/payments/adapters/mock.ts +159 -0
  153. package/services/payments/payment-adapter.ts +118 -0
  154. package/services/payments/types.ts +131 -0
  155. package/services/permissions/permission-manager.ts +284 -0
  156. package/services/permissions/types.ts +104 -0
  157. package/services/realtime/types.ts +100 -0
  158. package/services/realtime/websocket-manager.ts +441 -0
  159. package/services/security.ts +289 -286
  160. package/services/sentry.ts +4 -4
  161. package/stores/appStore.ts +9 -0
  162. package/stores/notificationStore.ts +3 -1
  163. package/tailwind.config.js +47 -47
  164. package/tsconfig.json +37 -13
  165. package/types/user.ts +1 -1
  166. package/utils/accessibility.ts +446 -446
  167. package/utils/animations/presets.ts +182 -0
  168. package/utils/animations/transitions.ts +62 -0
  169. package/utils/index.ts +63 -52
  170. package/utils/toast.ts +9 -2
  171. package/utils/validation.ts +4 -1
  172. package/utils/withAccessibility.tsx +272 -272
@@ -0,0 +1,189 @@
1
+ /**
2
+ * @fileoverview Upload progress bar component
3
+ * Displays upload progress with percentage, cancel, retry, and error states.
4
+ * @module components/ui/UploadProgress
5
+ */
6
+
7
+ import { View, Text, Pressable } from "react-native";
8
+ import { Ionicons } from "@expo/vector-icons";
9
+ import { useTranslation } from "react-i18next";
10
+ import { useTheme } from "@/hooks/useTheme";
11
+ import type { UploadProgress as UploadProgressType } from "@/services/media/media-upload";
12
+ import { cn } from "@/utils/cn";
13
+
14
+ /**
15
+ * Props for the UploadProgress component
16
+ */
17
+ interface UploadProgressProps {
18
+ /** Current upload progress */
19
+ progress: UploadProgressType | null;
20
+ /** Whether an upload is currently in progress */
21
+ isUploading: boolean;
22
+ /** Error message if the upload failed */
23
+ error?: string | null;
24
+ /** Callback to cancel the upload */
25
+ onCancel?: () => void;
26
+ /** Callback to retry a failed upload */
27
+ onRetry?: () => void;
28
+ /** Additional class name for the container */
29
+ className?: string;
30
+ }
31
+
32
+ /**
33
+ * Upload progress indicator with error and cancel/retry support.
34
+ * Returns null when there is nothing to show (not uploading, no error).
35
+ *
36
+ * @example
37
+ * ```tsx
38
+ * function FileUploader() {
39
+ * const { upload, progress, isUploading, error, cancel, reset } = useUpload({
40
+ * url: 'https://api.example.com/upload',
41
+ * });
42
+ *
43
+ * return (
44
+ * <View>
45
+ * <Button onPress={() => upload(fileUri)}>Upload</Button>
46
+ * <UploadProgress
47
+ * progress={progress}
48
+ * isUploading={isUploading}
49
+ * error={error}
50
+ * onCancel={cancel}
51
+ * onRetry={() => upload(fileUri)}
52
+ * />
53
+ * </View>
54
+ * );
55
+ * }
56
+ * ```
57
+ */
58
+ export function UploadProgress({
59
+ progress,
60
+ isUploading,
61
+ error,
62
+ onCancel,
63
+ onRetry,
64
+ className,
65
+ }: UploadProgressProps) {
66
+ const { isDark } = useTheme();
67
+ const { t } = useTranslation();
68
+
69
+ // Nothing to show
70
+ if (!isUploading && !error) {
71
+ return null;
72
+ }
73
+
74
+ // Error state
75
+ if (error) {
76
+ return (
77
+ <View
78
+ className={cn(
79
+ "flex-row items-center rounded-lg px-4 py-3",
80
+ isDark ? "bg-red-900/30" : "bg-red-50",
81
+ className
82
+ )}
83
+ >
84
+ <Ionicons
85
+ name="alert-circle"
86
+ size={20}
87
+ color={isDark ? "#fca5a5" : "#ef4444"}
88
+ />
89
+ <Text
90
+ className={cn(
91
+ "ml-2 flex-1 text-sm font-medium",
92
+ isDark ? "text-red-300" : "text-red-600"
93
+ )}
94
+ numberOfLines={2}
95
+ >
96
+ {t("upload.failed")}
97
+ </Text>
98
+ {onRetry && (
99
+ <Pressable
100
+ onPress={onRetry}
101
+ className={cn(
102
+ "ml-2 rounded-md px-3 py-1.5",
103
+ isDark
104
+ ? "bg-red-800/50 active:bg-red-800"
105
+ : "bg-red-100 active:bg-red-200"
106
+ )}
107
+ >
108
+ <Text
109
+ className={cn(
110
+ "text-sm font-semibold",
111
+ isDark ? "text-red-300" : "text-red-600"
112
+ )}
113
+ >
114
+ {t("upload.retry")}
115
+ </Text>
116
+ </Pressable>
117
+ )}
118
+ </View>
119
+ );
120
+ }
121
+
122
+ // Uploading state
123
+ const percentage = progress?.percentage ?? 0;
124
+
125
+ return (
126
+ <View
127
+ className={cn(
128
+ "rounded-lg px-4 py-3",
129
+ isDark ? "bg-gray-800" : "bg-gray-50",
130
+ className
131
+ )}
132
+ >
133
+ {/* Header row */}
134
+ <View className="mb-2 flex-row items-center justify-between">
135
+ <View className="flex-row items-center">
136
+ <Text
137
+ className={cn(
138
+ "text-sm font-medium",
139
+ isDark ? "text-gray-200" : "text-gray-700"
140
+ )}
141
+ >
142
+ {t("upload.uploading")}
143
+ </Text>
144
+ <Text
145
+ className={cn(
146
+ "ml-2 text-sm",
147
+ isDark ? "text-gray-400" : "text-gray-500"
148
+ )}
149
+ >
150
+ {percentage}%
151
+ </Text>
152
+ </View>
153
+ {onCancel && (
154
+ <Pressable
155
+ onPress={onCancel}
156
+ className={cn(
157
+ "rounded-md px-3 py-1",
158
+ isDark
159
+ ? "bg-gray-700 active:bg-gray-600"
160
+ : "bg-gray-200 active:bg-gray-300"
161
+ )}
162
+ >
163
+ <Text
164
+ className={cn(
165
+ "text-xs font-semibold",
166
+ isDark ? "text-gray-300" : "text-gray-600"
167
+ )}
168
+ >
169
+ Cancel
170
+ </Text>
171
+ </Pressable>
172
+ )}
173
+ </View>
174
+
175
+ {/* Progress bar */}
176
+ <View
177
+ className={cn(
178
+ "h-2 overflow-hidden rounded-full",
179
+ isDark ? "bg-gray-700" : "bg-gray-200"
180
+ )}
181
+ >
182
+ <View
183
+ className="h-full rounded-full bg-primary-500"
184
+ style={{ width: `${percentage}%` }}
185
+ />
186
+ </View>
187
+ </View>
188
+ );
189
+ }