@croacroa/react-native-template 2.0.1 → 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 -0
  10. package/README.md +446 -399
  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 -0
  69. package/components/ui/UploadProgress.tsx +189 -0
  70. package/components/ui/VirtualizedList.tsx +288 -285
  71. package/components/ui/index.ts +28 -23
  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 -27
  89. package/hooks/useAnimatedEntry.ts +204 -0
  90. package/hooks/useApi.ts +64 -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 -0
  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 -175
  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
@@ -1,97 +1,135 @@
1
- import Constants from "expo-constants";
2
-
3
- // Environment detection
4
- export const IS_DEV = __DEV__;
5
- export const IS_PREVIEW =
6
- Constants.expoConfig?.extra?.APP_VARIANT === "preview";
7
- export const IS_PROD = !IS_DEV && !IS_PREVIEW;
8
-
9
- // API Configuration
10
- // TODO: Replace with your actual API URLs
11
- export const API_URL = IS_PROD
12
- ? "https://api.yourapp.com"
13
- : IS_PREVIEW
14
- ? "https://staging-api.yourapp.com"
15
- : "http://localhost:3000";
16
-
17
- // App Configuration
18
- export const APP_NAME = Constants.expoConfig?.name || "YourApp";
19
- export const APP_VERSION = Constants.expoConfig?.version || "1.0.0";
20
- export const APP_SCHEME = Constants.expoConfig?.scheme || "yourapp";
21
-
22
- // Feature Flags
23
- export const FEATURES = {
24
- ENABLE_ANALYTICS: IS_PROD,
25
- ENABLE_CRASH_REPORTING: IS_PROD,
26
- ENABLE_PUSH_NOTIFICATIONS: true,
27
- ENABLE_BIOMETRIC_AUTH: true,
28
- ENABLE_PERFORMANCE_MONITORING: IS_DEV || IS_PREVIEW,
29
- } as const;
30
-
31
- // Export individual flags for convenience
32
- export const ENABLE_ANALYTICS = FEATURES.ENABLE_ANALYTICS;
33
- export const ENABLE_CRASH_REPORTING = FEATURES.ENABLE_CRASH_REPORTING;
34
- export const ENABLE_PUSH_NOTIFICATIONS = FEATURES.ENABLE_PUSH_NOTIFICATIONS;
35
- export const ENABLE_BIOMETRIC_AUTH = FEATURES.ENABLE_BIOMETRIC_AUTH;
36
- export const ENABLE_PERFORMANCE_MONITORING =
37
- FEATURES.ENABLE_PERFORMANCE_MONITORING;
38
-
39
- // Timing Constants
40
- export const TIMING = {
41
- DEBOUNCE_MS: 300,
42
- ANIMATION_DURATION_MS: 200,
43
- TOAST_DURATION_MS: 3000,
44
- API_TIMEOUT_MS: 30000,
45
- } as const;
46
-
47
- // Storage Keys
48
- export const STORAGE_KEYS = {
49
- AUTH_TOKEN: "auth_token",
50
- USER: "auth_user",
51
- THEME: "theme_mode",
52
- ONBOARDING_COMPLETED: "onboarding_completed",
53
- PUSH_TOKEN: "push_token",
54
- } as const;
55
-
56
- // Security Configuration
57
- export const SECURITY = {
58
- /**
59
- * SSL Pinning configuration for enhanced network security.
60
- * Add your API server's certificate public key hashes here.
61
- *
62
- * To generate a pin from your certificate:
63
- * 1. Get your server's certificate: openssl s_client -connect api.yourapp.com:443
64
- * 2. Extract public key: openssl x509 -pubkey -noout -in cert.pem
65
- * 3. Generate hash: openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
66
- *
67
- * @example
68
- * SSL_PINS: {
69
- * "api.yourapp.com": [
70
- * "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", // Primary cert
71
- * "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", // Backup cert
72
- * ],
73
- * }
74
- */
75
- SSL_PINS: {
76
- // TODO: Add your production API certificate pins
77
- // "api.yourapp.com": [
78
- // "sha256/YOUR_CERTIFICATE_HASH_HERE=",
79
- // ],
80
- } as Record<string, string[]>,
81
-
82
- /**
83
- * Enable SSL pinning in production
84
- * Set to true once you've configured the SSL_PINS above
85
- */
86
- ENABLE_SSL_PINNING: IS_PROD && false, // Enable when pins are configured
87
-
88
- /**
89
- * Request signing configuration
90
- * Used to sign API requests for added security
91
- */
92
- REQUEST_SIGNING: {
93
- ENABLED: false,
94
- ALGORITHM: "sha256",
95
- HEADER_NAME: "X-Request-Signature",
96
- },
97
- } as const;
1
+ import Constants from "expo-constants";
2
+
3
+ // Environment detection
4
+ export const IS_DEV = __DEV__;
5
+ export const IS_PREVIEW =
6
+ Constants.expoConfig?.extra?.APP_VARIANT === "preview";
7
+ export const IS_PROD = !IS_DEV && !IS_PREVIEW;
8
+
9
+ // API Configuration
10
+ // TODO: Replace with your actual API URLs
11
+ export const API_URL = IS_PROD
12
+ ? "https://api.yourapp.com"
13
+ : IS_PREVIEW
14
+ ? "https://staging-api.yourapp.com"
15
+ : "http://localhost:3000";
16
+
17
+ // App Configuration
18
+ export const APP_NAME = Constants.expoConfig?.name || "YourApp";
19
+ export const APP_VERSION = Constants.expoConfig?.version || "1.0.0";
20
+ export const APP_SCHEME = Constants.expoConfig?.scheme || "yourapp";
21
+
22
+ // Feature Flags
23
+ export const FEATURES = {
24
+ ENABLE_ANALYTICS: IS_PROD,
25
+ ENABLE_CRASH_REPORTING: IS_PROD,
26
+ ENABLE_PUSH_NOTIFICATIONS: true,
27
+ ENABLE_BIOMETRIC_AUTH: true,
28
+ ENABLE_PERFORMANCE_MONITORING: IS_DEV || IS_PREVIEW,
29
+ ENABLE_SOCIAL_LOGIN: true,
30
+ ENABLE_PAYMENTS: false,
31
+ } as const;
32
+
33
+ // Export individual flags for convenience
34
+ export const ENABLE_ANALYTICS = FEATURES.ENABLE_ANALYTICS;
35
+ export const ENABLE_CRASH_REPORTING = FEATURES.ENABLE_CRASH_REPORTING;
36
+ export const ENABLE_PUSH_NOTIFICATIONS = FEATURES.ENABLE_PUSH_NOTIFICATIONS;
37
+ export const ENABLE_BIOMETRIC_AUTH = FEATURES.ENABLE_BIOMETRIC_AUTH;
38
+ export const ENABLE_PERFORMANCE_MONITORING =
39
+ FEATURES.ENABLE_PERFORMANCE_MONITORING;
40
+ export const ENABLE_SOCIAL_LOGIN = FEATURES.ENABLE_SOCIAL_LOGIN;
41
+ export const ENABLE_PAYMENTS = FEATURES.ENABLE_PAYMENTS;
42
+
43
+ // Timing Constants
44
+ export const TIMING = {
45
+ DEBOUNCE_MS: 300,
46
+ ANIMATION_DURATION_MS: 200,
47
+ TOAST_DURATION_MS: 3000,
48
+ API_TIMEOUT_MS: 30000,
49
+ } as const;
50
+
51
+ // Storage Keys
52
+ export const STORAGE_KEYS = {
53
+ AUTH_TOKEN: "auth_token",
54
+ USER: "auth_user",
55
+ THEME: "theme_mode",
56
+ ONBOARDING_COMPLETED: "onboarding_completed",
57
+ PUSH_TOKEN: "push_token",
58
+ PERMISSION_PREFIX: "@permission_asked_",
59
+ ANALYTICS_USER_ID: "@analytics_user_id",
60
+ } as const;
61
+
62
+ // Social Auth Configuration
63
+ export const socialAuth = {
64
+ google: {
65
+ clientId: process.env.EXPO_PUBLIC_GOOGLE_CLIENT_ID || "",
66
+ iosClientId: process.env.EXPO_PUBLIC_GOOGLE_IOS_CLIENT_ID || "",
67
+ androidClientId: process.env.EXPO_PUBLIC_GOOGLE_ANDROID_CLIENT_ID || "",
68
+ },
69
+ } as const;
70
+
71
+ // Force Update Configuration
72
+ export const FORCE_UPDATE = {
73
+ CHECK_URL: "", // Empty by default — set to your API endpoint
74
+ ENABLED: false,
75
+ } as const;
76
+
77
+ // In-App Review Configuration
78
+ export const IN_APP_REVIEW = {
79
+ MIN_SESSIONS: 5,
80
+ DAYS_BETWEEN_PROMPTS: 30,
81
+ } as const;
82
+
83
+ // Feature Flags (Remote)
84
+ export const FEATURE_FLAGS = {
85
+ REFRESH_INTERVAL_MS: 5 * 60 * 1000, // 5 minutes
86
+ ENABLED: true,
87
+ } as const;
88
+
89
+ // API Advanced Configuration
90
+ export const API_CONFIG = {
91
+ ENABLE_ETAG_CACHE: true,
92
+ } as const;
93
+
94
+ // Security Configuration
95
+ export const SECURITY = {
96
+ /**
97
+ * SSL Pinning configuration for enhanced network security.
98
+ * Add your API server's certificate public key hashes here.
99
+ *
100
+ * To generate a pin from your certificate:
101
+ * 1. Get your server's certificate: openssl s_client -connect api.yourapp.com:443
102
+ * 2. Extract public key: openssl x509 -pubkey -noout -in cert.pem
103
+ * 3. Generate hash: openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | openssl enc -base64
104
+ *
105
+ * @example
106
+ * SSL_PINS: {
107
+ * "api.yourapp.com": [
108
+ * "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=", // Primary cert
109
+ * "sha256/BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=", // Backup cert
110
+ * ],
111
+ * }
112
+ */
113
+ SSL_PINS: {
114
+ // TODO: Add your production API certificate pins
115
+ // "api.yourapp.com": [
116
+ // "sha256/YOUR_CERTIFICATE_HASH_HERE=",
117
+ // ],
118
+ } as Record<string, string[]>,
119
+
120
+ /**
121
+ * Enable SSL pinning in production
122
+ * Set to true once you've configured the SSL_PINS above
123
+ */
124
+ ENABLE_SSL_PINNING: IS_PROD && false, // Enable when pins are configured
125
+
126
+ /**
127
+ * Request signing configuration
128
+ * Used to sign API requests for added security
129
+ */
130
+ REQUEST_SIGNING: {
131
+ ENABLED: false,
132
+ ALGORITHM: "sha256",
133
+ HEADER_NAME: "X-Request-Signature",
134
+ },
135
+ } as const;
@@ -1,79 +1,79 @@
1
- # ADR-001: Use Zustand for State Management
2
-
3
- ## Status
4
-
5
- Accepted
6
-
7
- ## Date
8
-
9
- 2024-01-01
10
-
11
- ## Context
12
-
13
- We need a state management solution for our React Native application. The requirements are:
14
-
15
- 1. Simple API with minimal boilerplate
16
- 2. Good TypeScript support
17
- 3. Small bundle size (mobile performance matters)
18
- 4. Support for persistence
19
- 5. Devtools support for debugging
20
- 6. No need for complex middleware or actions
21
-
22
- Options considered:
23
-
24
- - **Redux Toolkit**: Industry standard, but verbose for our needs
25
- - **MobX**: Powerful but adds complexity with observables
26
- - **Jotai**: Atomic state, good for simple cases
27
- - **Zustand**: Simple, small, flexible
28
- - **React Context**: Built-in, but can cause performance issues
29
-
30
- ## Decision
31
-
32
- We chose **Zustand** for global state management.
33
-
34
- ## Rationale
35
-
36
- 1. **Simplicity**: Creating a store is just a function call
37
-
38
- ```ts
39
- const useStore = create((set) => ({
40
- count: 0,
41
- increment: () => set((s) => ({ count: s.count + 1 })),
42
- }));
43
- ```
44
-
45
- 2. **Bundle size**: ~1KB gzipped vs Redux's ~7KB
46
-
47
- 3. **TypeScript**: Excellent inference, minimal type annotations needed
48
-
49
- 4. **Persistence**: Easy integration with AsyncStorage via middleware
50
-
51
- 5. **No Providers**: Works outside React components, useful for API services
52
-
53
- 6. **Selective subscriptions**: Components only re-render when selected state changes
54
-
55
- ## Consequences
56
-
57
- ### Positive
58
-
59
- - Faster development with less boilerplate
60
- - Smaller bundle size
61
- - Easy to test stores
62
- - Can use stores outside React (e.g., in API handlers)
63
-
64
- ### Negative
65
-
66
- - Less structured than Redux (could lead to inconsistent patterns)
67
- - Smaller ecosystem than Redux
68
- - Team needs to establish conventions
69
-
70
- ### Mitigation
71
-
72
- - Document store patterns in CONTRIBUTING.md
73
- - Use TypeScript for store definitions
74
- - Keep stores focused (one concern per store)
75
-
76
- ## References
77
-
78
- - [Zustand Documentation](https://github.com/pmndrs/zustand)
79
- - [React Native Performance](https://reactnative.dev/docs/performance)
1
+ # ADR-001: Use Zustand for State Management
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Date
8
+
9
+ 2024-01-01
10
+
11
+ ## Context
12
+
13
+ We need a state management solution for our React Native application. The requirements are:
14
+
15
+ 1. Simple API with minimal boilerplate
16
+ 2. Good TypeScript support
17
+ 3. Small bundle size (mobile performance matters)
18
+ 4. Support for persistence
19
+ 5. Devtools support for debugging
20
+ 6. No need for complex middleware or actions
21
+
22
+ Options considered:
23
+
24
+ - **Redux Toolkit**: Industry standard, but verbose for our needs
25
+ - **MobX**: Powerful but adds complexity with observables
26
+ - **Jotai**: Atomic state, good for simple cases
27
+ - **Zustand**: Simple, small, flexible
28
+ - **React Context**: Built-in, but can cause performance issues
29
+
30
+ ## Decision
31
+
32
+ We chose **Zustand** for global state management.
33
+
34
+ ## Rationale
35
+
36
+ 1. **Simplicity**: Creating a store is just a function call
37
+
38
+ ```ts
39
+ const useStore = create((set) => ({
40
+ count: 0,
41
+ increment: () => set((s) => ({ count: s.count + 1 })),
42
+ }));
43
+ ```
44
+
45
+ 2. **Bundle size**: ~1KB gzipped vs Redux's ~7KB
46
+
47
+ 3. **TypeScript**: Excellent inference, minimal type annotations needed
48
+
49
+ 4. **Persistence**: Easy integration with AsyncStorage via middleware
50
+
51
+ 5. **No Providers**: Works outside React components, useful for API services
52
+
53
+ 6. **Selective subscriptions**: Components only re-render when selected state changes
54
+
55
+ ## Consequences
56
+
57
+ ### Positive
58
+
59
+ - Faster development with less boilerplate
60
+ - Smaller bundle size
61
+ - Easy to test stores
62
+ - Can use stores outside React (e.g., in API handlers)
63
+
64
+ ### Negative
65
+
66
+ - Less structured than Redux (could lead to inconsistent patterns)
67
+ - Smaller ecosystem than Redux
68
+ - Team needs to establish conventions
69
+
70
+ ### Mitigation
71
+
72
+ - Document store patterns in CONTRIBUTING.md
73
+ - Use TypeScript for store definitions
74
+ - Keep stores focused (one concern per store)
75
+
76
+ ## References
77
+
78
+ - [Zustand Documentation](https://github.com/pmndrs/zustand)
79
+ - [React Native Performance](https://reactnative.dev/docs/performance)
@@ -1,130 +1,130 @@
1
- # ADR-002: Use NativeWind (Tailwind CSS) for Styling
2
-
3
- ## Status
4
-
5
- Accepted
6
-
7
- ## Date
8
-
9
- 2024-01-01
10
-
11
- ## Context
12
-
13
- We need a consistent styling approach for our React Native application. The requirements are:
14
-
15
- 1. Developer productivity (fast to write styles)
16
- 2. Consistent design system
17
- 3. Dark mode support
18
- 4. Good performance
19
- 5. Familiar to web developers
20
-
21
- Options considered:
22
-
23
- - **StyleSheet.create**: React Native's built-in solution
24
- - **Styled Components**: CSS-in-JS, popular in web
25
- - **NativeWind**: Tailwind CSS for React Native
26
- - **Tamagui**: Universal design system
27
- - **Dripsy**: Responsive design system
28
-
29
- ## Decision
30
-
31
- We chose **NativeWind** (Tailwind CSS for React Native).
32
-
33
- ## Rationale
34
-
35
- 1. **Developer Experience**: Utility classes are fast to write
36
-
37
- ```tsx
38
- // NativeWind
39
- <View className="p-4 bg-white rounded-xl shadow-lg">
40
-
41
- // StyleSheet
42
- <View style={[styles.container, styles.rounded, styles.shadow]}>
43
- ```
44
-
45
- 2. **Design System**: Tailwind's design tokens ensure consistency
46
-
47
- 3. **Dark Mode**: Built-in support with `dark:` prefix
48
-
49
- ```tsx
50
- <View className="bg-white dark:bg-slate-900">
51
- ```
52
-
53
- 4. **Responsive Design**: Support for breakpoints
54
-
55
- ```tsx
56
- <View className="p-2 md:p-4 lg:p-6">
57
- ```
58
-
59
- 5. **Familiarity**: Web developers already know Tailwind
60
-
61
- 6. **Performance**: Compiled at build time, no runtime overhead
62
-
63
- ## Consequences
64
-
65
- ### Positive
66
-
67
- - Faster styling with utility classes
68
- - Consistent spacing, colors, typography
69
- - Easy dark mode implementation
70
- - Small runtime footprint
71
- - Web developers can contribute quickly
72
-
73
- ### Negative
74
-
75
- - Long className strings can be hard to read
76
- - Learning curve for Tailwind utilities
77
- - Some RN-specific styles need custom config
78
-
79
- ### Mitigation
80
-
81
- - Use `cn()` utility to organize classes
82
- - Create component abstractions for complex patterns
83
- - Document custom Tailwind config
84
-
85
- ## Implementation
86
-
87
- ### Configuration
88
-
89
- ```js
90
- // tailwind.config.js
91
- module.exports = {
92
- content: ["./app/**/*.{js,tsx}", "./components/**/*.{js,tsx}"],
93
- presets: [require("nativewind/preset")],
94
- theme: {
95
- extend: {
96
- colors: {
97
- primary: {
98
- /* ... */
99
- },
100
- background: { light: "#fff", dark: "#0f172a" },
101
- },
102
- },
103
- },
104
- };
105
- ```
106
-
107
- ### Usage Pattern
108
-
109
- ```tsx
110
- import { cn } from "@/utils/cn";
111
-
112
- function Card({ className, ...props }) {
113
- return (
114
- <View
115
- className={cn(
116
- "p-4 rounded-xl",
117
- "bg-white dark:bg-slate-800",
118
- "border border-gray-200 dark:border-gray-700",
119
- className
120
- )}
121
- {...props}
122
- />
123
- );
124
- }
125
- ```
126
-
127
- ## References
128
-
129
- - [NativeWind Documentation](https://www.nativewind.dev/)
130
- - [Tailwind CSS](https://tailwindcss.com/)
1
+ # ADR-002: Use NativeWind (Tailwind CSS) for Styling
2
+
3
+ ## Status
4
+
5
+ Accepted
6
+
7
+ ## Date
8
+
9
+ 2024-01-01
10
+
11
+ ## Context
12
+
13
+ We need a consistent styling approach for our React Native application. The requirements are:
14
+
15
+ 1. Developer productivity (fast to write styles)
16
+ 2. Consistent design system
17
+ 3. Dark mode support
18
+ 4. Good performance
19
+ 5. Familiar to web developers
20
+
21
+ Options considered:
22
+
23
+ - **StyleSheet.create**: React Native's built-in solution
24
+ - **Styled Components**: CSS-in-JS, popular in web
25
+ - **NativeWind**: Tailwind CSS for React Native
26
+ - **Tamagui**: Universal design system
27
+ - **Dripsy**: Responsive design system
28
+
29
+ ## Decision
30
+
31
+ We chose **NativeWind** (Tailwind CSS for React Native).
32
+
33
+ ## Rationale
34
+
35
+ 1. **Developer Experience**: Utility classes are fast to write
36
+
37
+ ```tsx
38
+ // NativeWind
39
+ <View className="p-4 bg-white rounded-xl shadow-lg">
40
+
41
+ // StyleSheet
42
+ <View style={[styles.container, styles.rounded, styles.shadow]}>
43
+ ```
44
+
45
+ 2. **Design System**: Tailwind's design tokens ensure consistency
46
+
47
+ 3. **Dark Mode**: Built-in support with `dark:` prefix
48
+
49
+ ```tsx
50
+ <View className="bg-white dark:bg-slate-900">
51
+ ```
52
+
53
+ 4. **Responsive Design**: Support for breakpoints
54
+
55
+ ```tsx
56
+ <View className="p-2 md:p-4 lg:p-6">
57
+ ```
58
+
59
+ 5. **Familiarity**: Web developers already know Tailwind
60
+
61
+ 6. **Performance**: Compiled at build time, no runtime overhead
62
+
63
+ ## Consequences
64
+
65
+ ### Positive
66
+
67
+ - Faster styling with utility classes
68
+ - Consistent spacing, colors, typography
69
+ - Easy dark mode implementation
70
+ - Small runtime footprint
71
+ - Web developers can contribute quickly
72
+
73
+ ### Negative
74
+
75
+ - Long className strings can be hard to read
76
+ - Learning curve for Tailwind utilities
77
+ - Some RN-specific styles need custom config
78
+
79
+ ### Mitigation
80
+
81
+ - Use `cn()` utility to organize classes
82
+ - Create component abstractions for complex patterns
83
+ - Document custom Tailwind config
84
+
85
+ ## Implementation
86
+
87
+ ### Configuration
88
+
89
+ ```js
90
+ // tailwind.config.js
91
+ module.exports = {
92
+ content: ["./app/**/*.{js,tsx}", "./components/**/*.{js,tsx}"],
93
+ presets: [require("nativewind/preset")],
94
+ theme: {
95
+ extend: {
96
+ colors: {
97
+ primary: {
98
+ /* ... */
99
+ },
100
+ background: { light: "#fff", dark: "#0f172a" },
101
+ },
102
+ },
103
+ },
104
+ };
105
+ ```
106
+
107
+ ### Usage Pattern
108
+
109
+ ```tsx
110
+ import { cn } from "@/utils/cn";
111
+
112
+ function Card({ className, ...props }) {
113
+ return (
114
+ <View
115
+ className={cn(
116
+ "p-4 rounded-xl",
117
+ "bg-white dark:bg-slate-800",
118
+ "border border-gray-200 dark:border-gray-700",
119
+ className
120
+ )}
121
+ {...props}
122
+ />
123
+ );
124
+ }
125
+ ```
126
+
127
+ ## References
128
+
129
+ - [NativeWind Documentation](https://www.nativewind.dev/)
130
+ - [Tailwind CSS](https://tailwindcss.com/)