@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.
- package/.env.example +5 -0
- package/.eslintrc.js +8 -0
- package/.github/workflows/ci.yml +187 -187
- package/.github/workflows/eas-build.yml +55 -55
- package/.github/workflows/eas-update.yml +50 -50
- package/.github/workflows/npm-publish.yml +57 -0
- package/CHANGELOG.md +195 -106
- package/CONTRIBUTING.md +377 -377
- package/LICENSE +21 -21
- package/README.md +446 -402
- package/__tests__/accessibility/components.test.tsx +285 -0
- package/__tests__/components/Button.test.tsx +2 -4
- package/__tests__/components/__snapshots__/snapshots.test.tsx.snap +512 -0
- package/__tests__/components/snapshots.test.tsx +131 -131
- package/__tests__/helpers/a11y.ts +54 -0
- package/__tests__/hooks/useAnalytics.test.ts +100 -0
- package/__tests__/hooks/useAnimations.test.ts +70 -0
- package/__tests__/hooks/useAuth.test.tsx +71 -28
- package/__tests__/hooks/useMedia.test.ts +318 -0
- package/__tests__/hooks/usePayments.test.tsx +307 -0
- package/__tests__/hooks/usePermission.test.ts +230 -0
- package/__tests__/hooks/useWebSocket.test.ts +329 -0
- package/__tests__/integration/auth-api.test.tsx +224 -227
- package/__tests__/performance/VirtualizedList.perf.test.tsx +385 -362
- package/__tests__/services/api.test.ts +24 -6
- package/app/(auth)/home.tsx +11 -9
- package/app/(auth)/profile.tsx +8 -6
- package/app/(auth)/settings.tsx +11 -9
- package/app/(public)/forgot-password.tsx +25 -15
- package/app/(public)/login.tsx +48 -12
- package/app/(public)/onboarding.tsx +5 -5
- package/app/(public)/register.tsx +24 -15
- package/app/_layout.tsx +6 -3
- package/app.config.ts +27 -2
- package/assets/images/.gitkeep +7 -7
- package/assets/images/adaptive-icon.png +0 -0
- package/assets/images/favicon.png +0 -0
- package/assets/images/icon.png +0 -0
- package/assets/images/notification-icon.png +0 -0
- package/assets/images/splash.png +0 -0
- package/components/ErrorBoundary.tsx +73 -28
- package/components/auth/SocialLoginButtons.tsx +168 -0
- package/components/forms/FormInput.tsx +5 -3
- package/components/onboarding/OnboardingScreen.tsx +370 -370
- package/components/onboarding/index.ts +2 -2
- package/components/providers/AnalyticsProvider.tsx +67 -0
- package/components/providers/SuspenseBoundary.tsx +359 -357
- package/components/providers/index.ts +24 -21
- package/components/ui/AnimatedButton.tsx +1 -9
- package/components/ui/AnimatedList.tsx +98 -0
- package/components/ui/AnimatedScreen.tsx +89 -0
- package/components/ui/Avatar.tsx +319 -316
- package/components/ui/Badge.tsx +416 -416
- package/components/ui/BottomSheet.tsx +307 -307
- package/components/ui/Button.tsx +11 -3
- package/components/ui/Checkbox.tsx +261 -261
- package/components/ui/FeatureGate.tsx +57 -0
- package/components/ui/ForceUpdateScreen.tsx +108 -0
- package/components/ui/ImagePickerButton.tsx +180 -0
- package/components/ui/Input.stories.tsx +2 -10
- package/components/ui/Input.tsx +2 -10
- package/components/ui/OptimizedImage.tsx +369 -369
- package/components/ui/Paywall.tsx +253 -0
- package/components/ui/PermissionGate.tsx +155 -0
- package/components/ui/PurchaseButton.tsx +84 -0
- package/components/ui/Select.tsx +240 -240
- package/components/ui/Skeleton.tsx +3 -1
- package/components/ui/Toast.tsx +427 -418
- package/components/ui/UploadProgress.tsx +189 -0
- package/components/ui/VirtualizedList.tsx +288 -285
- package/components/ui/index.ts +28 -30
- package/constants/config.ts +135 -97
- package/docs/adr/001-state-management.md +79 -79
- package/docs/adr/002-styling-approach.md +130 -130
- package/docs/adr/003-data-fetching.md +155 -155
- package/docs/adr/004-auth-adapter-pattern.md +144 -144
- package/docs/adr/README.md +78 -78
- package/docs/guides/analytics-posthog.md +121 -0
- package/docs/guides/auth-supabase.md +162 -0
- package/docs/guides/feature-flags-launchdarkly.md +150 -0
- package/docs/guides/payments-revenuecat.md +169 -0
- package/docs/plans/2026-02-22-phase6-implementation.md +3222 -0
- package/docs/plans/2026-02-22-phase6-template-completion-design.md +196 -0
- package/docs/plans/2026-02-23-npm-publish-design.md +31 -0
- package/docs/plans/2026-02-23-phase7-polish-documentation-design.md +79 -0
- package/docs/plans/2026-02-23-phase8-additional-features-design.md +136 -0
- package/eas.json +2 -1
- package/hooks/index.ts +70 -40
- package/hooks/useAnimatedEntry.ts +204 -0
- package/hooks/useApi.ts +5 -4
- package/hooks/useAuth.tsx +7 -3
- package/hooks/useBiometrics.ts +295 -295
- package/hooks/useChannel.ts +111 -0
- package/hooks/useDeepLinking.ts +256 -256
- package/hooks/useExperiment.ts +36 -0
- package/hooks/useFeatureFlag.ts +59 -0
- package/hooks/useForceUpdate.ts +91 -0
- package/hooks/useImagePicker.ts +281 -375
- package/hooks/useInAppReview.ts +64 -0
- package/hooks/useMFA.ts +509 -499
- package/hooks/useParallax.ts +142 -0
- package/hooks/usePerformance.ts +434 -434
- package/hooks/usePermission.ts +190 -0
- package/hooks/usePresence.ts +129 -0
- package/hooks/useProducts.ts +36 -0
- package/hooks/usePurchase.ts +103 -0
- package/hooks/useRateLimit.ts +70 -0
- package/hooks/useSubscription.ts +49 -0
- package/hooks/useTrackEvent.ts +52 -0
- package/hooks/useTrackScreen.ts +40 -0
- package/hooks/useUpdates.ts +358 -358
- package/hooks/useUpload.ts +165 -0
- package/hooks/useWebSocket.ts +111 -0
- package/i18n/index.ts +197 -194
- package/i18n/locales/ar.json +170 -101
- package/i18n/locales/de.json +170 -101
- package/i18n/locales/en.json +170 -101
- package/i18n/locales/es.json +170 -101
- package/i18n/locales/fr.json +170 -101
- package/jest.config.js +1 -1
- package/maestro/README.md +113 -113
- package/maestro/config.yaml +35 -35
- package/maestro/flows/login.yaml +62 -62
- package/maestro/flows/mfa-login.yaml +92 -92
- package/maestro/flows/mfa-setup.yaml +86 -86
- package/maestro/flows/navigation.yaml +68 -68
- package/maestro/flows/offline-conflict.yaml +101 -101
- package/maestro/flows/offline-sync.yaml +128 -128
- package/maestro/flows/offline.yaml +60 -60
- package/maestro/flows/register.yaml +94 -94
- package/package.json +188 -176
- package/scripts/generate-placeholders.js +38 -0
- package/services/analytics/adapters/console.ts +50 -0
- package/services/analytics/analytics-adapter.ts +94 -0
- package/services/analytics/types.ts +73 -0
- package/services/analytics.ts +428 -428
- package/services/api.ts +419 -340
- package/services/auth/social/apple.ts +110 -0
- package/services/auth/social/google.ts +159 -0
- package/services/auth/social/social-auth.ts +100 -0
- package/services/auth/social/types.ts +80 -0
- package/services/authAdapter.ts +333 -333
- package/services/backgroundSync.ts +652 -626
- package/services/feature-flags/adapters/mock.ts +108 -0
- package/services/feature-flags/feature-flag-adapter.ts +174 -0
- package/services/feature-flags/types.ts +79 -0
- package/services/force-update.ts +140 -0
- package/services/index.ts +116 -54
- package/services/media/compression.ts +91 -0
- package/services/media/media-picker.ts +151 -0
- package/services/media/media-upload.ts +160 -0
- package/services/payments/adapters/mock.ts +159 -0
- package/services/payments/payment-adapter.ts +118 -0
- package/services/payments/types.ts +131 -0
- package/services/permissions/permission-manager.ts +284 -0
- package/services/permissions/types.ts +104 -0
- package/services/realtime/types.ts +100 -0
- package/services/realtime/websocket-manager.ts +441 -0
- package/services/security.ts +289 -286
- package/services/sentry.ts +4 -4
- package/stores/appStore.ts +9 -0
- package/stores/notificationStore.ts +3 -1
- package/tailwind.config.js +47 -47
- package/tsconfig.json +37 -13
- package/types/user.ts +1 -1
- package/utils/accessibility.ts +446 -446
- package/utils/animations/presets.ts +182 -0
- package/utils/animations/transitions.ts +62 -0
- package/utils/index.ts +63 -52
- package/utils/toast.ts +9 -2
- package/utils/validation.ts +4 -1
- package/utils/withAccessibility.tsx +272 -272
package/constants/config.ts
CHANGED
|
@@ -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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
export const
|
|
35
|
-
export const
|
|
36
|
-
export const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
export const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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/)
|