@fadyshawky/react-native-magic 2.0.9 → 2.1.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 (39) hide show
  1. package/.vscode/settings.json +2 -1
  2. package/README.md +55 -214
  3. package/package.json +9 -90
  4. package/scripts/askPackageName.js +165 -0
  5. package/template/.env.example +12 -0
  6. package/template/App.tsx +20 -16
  7. package/template/CHANGELOG.md +25 -0
  8. package/template/android/app/build.gradle +3 -3
  9. package/template/android/app/src/main/java/com/reactnativemagic/MainActivity.kt +8 -2
  10. package/template/android/app/src/main/java/com/reactnativemagic/MainApplication.kt +12 -29
  11. package/template/android/build.gradle +5 -5
  12. package/template/android/gradle/wrapper/gradle-wrapper.properties +1 -1
  13. package/template/docs/ARCHITECTURE.md +27 -0
  14. package/template/docs/BEST_PRACTICES.md +33 -0
  15. package/template/docs/CUSTOMIZATION.md +53 -0
  16. package/template/index.js +1 -0
  17. package/template/package.json +44 -89
  18. package/template/src/common/components/AppStatusBar.tsx +24 -0
  19. package/template/src/common/components/Cards.tsx +1 -1
  20. package/template/src/common/components/EmptyView.tsx +1 -1
  21. package/template/src/common/components/OTPInput.tsx +1 -1
  22. package/template/src/common/components/PrimaryButton.tsx +5 -5
  23. package/template/src/common/components/PrimaryTextInput.tsx +4 -4
  24. package/template/src/common/components/RadioButton.tsx +1 -1
  25. package/template/src/common/components/RadioIcon.tsx +4 -4
  26. package/template/src/common/components/SnackbarProvider.tsx +11 -0
  27. package/template/src/common/components/TryAgain.tsx +3 -3
  28. package/template/src/common/validations/errorValidations.ts +1 -1
  29. package/template/src/core/api/serverHeaders.ts +38 -9
  30. package/template/src/core/config/index.ts +13 -0
  31. package/template/src/core/store/store.tsx +3 -53
  32. package/template/src/core/theme/colors.ts +3 -0
  33. package/template/src/core/theme/commonSizes.ts +3 -0
  34. package/template/src/core/theme/fonts.ts +3 -0
  35. package/template/src/core/utils/stringUtils.ts +2 -45
  36. package/template/src/navigation/TabBar.tsx +5 -5
  37. package/template/src/screens/index.tsx +0 -15
  38. package/template/tsconfig.json +6 -1
  39. package/template.config.js +4 -2
package/template/App.tsx CHANGED
@@ -1,20 +1,20 @@
1
1
  /**
2
- * Sample React Native App
3
- * https://github.com/facebook/react-native
4
- *
5
2
  * @format
6
3
  */
7
4
  import React from 'react';
8
- import {LogBox, SafeAreaView, StatusBar} from 'react-native';
5
+ import {LogBox, View} from 'react-native';
9
6
  import {SheetProvider} from 'react-native-actions-sheet';
10
- import {SafeAreaProvider} from 'react-native-safe-area-context';
7
+ import {SafeAreaProvider, SafeAreaView} from 'react-native-safe-area-context';
11
8
  import {Provider} from 'react-redux';
12
9
  import {PersistGate} from 'redux-persist/integration/react';
10
+ import {AppStatusBar} from './src/common/components/AppStatusBar';
11
+ import {SnackbarProvider} from './src/common/components/SnackbarProvider';
13
12
  import {LocalizationProvider} from './src/common/localization/LocalizationProvider';
14
13
  import {RTLInitializer} from './src/common/localization/RTLInitializer';
15
14
  import {useAppSelector} from './src/core/store/reduxHelpers';
16
15
  import {persistor, store} from './src/core/store/store';
17
16
  import {ThemeProvider, useTheme} from './src/core/theme/ThemeProvider';
17
+ import {NaturalColors} from './src/core/theme/colors';
18
18
  import AppNavigator from './src/navigation/MainNavigation';
19
19
 
20
20
  LogBox.ignoreAllLogs();
@@ -27,14 +27,16 @@ const ThemedApp = () => {
27
27
  <RTLInitializer>
28
28
  <LocalizationProvider initialLanguage={language}>
29
29
  <SafeAreaProvider>
30
- <SafeAreaView style={{position: 'absolute'}} />
31
- <StatusBar
32
- barStyle={theme.mode === 'dark' ? 'light-content' : 'dark-content'}
33
- backgroundColor={theme.colors.background_2}
34
- />
35
- <SheetProvider>
36
- <AppNavigator />
37
- </SheetProvider>
30
+ <View style={{flex: 1, backgroundColor: theme?.colors?.background_2 ?? NaturalColors.background_2}}>
31
+ <SafeAreaView style={{position: 'absolute'}} />
32
+ <AppStatusBar
33
+ barStyle={theme?.mode === 'dark' ? 'light-content' : 'dark-content'}
34
+ backgroundColor={theme?.colors?.background_2 ?? NaturalColors.background_2}
35
+ />
36
+ <SheetProvider>
37
+ <AppNavigator />
38
+ </SheetProvider>
39
+ </View>
38
40
  </SafeAreaProvider>
39
41
  </LocalizationProvider>
40
42
  </RTLInitializer>
@@ -45,9 +47,11 @@ function App(): React.JSX.Element {
45
47
  return (
46
48
  <Provider store={store}>
47
49
  <PersistGate loading={null} persistor={persistor}>
48
- <ThemeProvider initialTheme="dark">
49
- <ThemedApp />
50
- </ThemeProvider>
50
+ <SnackbarProvider>
51
+ <ThemeProvider initialTheme="dark">
52
+ <ThemedApp />
53
+ </ThemeProvider>
54
+ </SnackbarProvider>
51
55
  </PersistGate>
52
56
  </Provider>
53
57
  );
@@ -0,0 +1,25 @@
1
+ # Changelog
2
+
3
+ ## [Unreleased]
4
+
5
+ ### Added
6
+
7
+ - Architecture aligned with Uprise-style layout: `common/`, `core/`, `navigation/`, `screens/`, `sheetManager/`.
8
+ - Single app config module (`src/core/config`) for API base URL and feature toggles; base URL from `.env` via react-native-config.
9
+ - `AppStatusBar` component to avoid deprecated Android status bar APIs.
10
+ - `.env.example` for API_BASE_URL and ENV; `.env` in `.gitignore`.
11
+ - Documentation: `docs/ARCHITECTURE.md`, `docs/CUSTOMIZATION.md`, `docs/BEST_PRACTICES.md`.
12
+
13
+ ### Changed
14
+
15
+ - Dependencies updated to caret (^) versions; React Native ^0.84, React ^19.2; Node >= 20.
16
+ - Store persist simplified: whitelist only `user` (accessToken, user) and `app` (language, isRTL); removed CryptoJS/deviceId encryption.
17
+ - API layer uses `src/core/config` for base URL; request interceptor adds Bearer token and locale; response interceptor handles 401 (logout).
18
+ - Theme: added “Customize for your brand” comments in `colors.ts`, `fonts.ts`, `commonSizes.ts`.
19
+ - Bootstrap order: Provider → PersistGate → SnackbarProvider → ThemeProvider → ThemedApp (RTLInitializer → LocalizationProvider → SafeAreaProvider → AppStatusBar → SheetProvider → AppNavigator).
20
+ - `index.js` imports `./src/sheetManager/sheets` so sheets are registered.
21
+
22
+ ### Template contract
23
+
24
+ - `template.config.js`: `placeholderName`, `titlePlaceholder`, `templateDir`.
25
+ - Bundle ID set at init via `--package-name`; app name and title replaced by CLI.
@@ -123,8 +123,8 @@ android {
123
123
  minSdkVersion rootProject.ext.minSdkVersion
124
124
  multiDexEnabled true
125
125
  targetSdkVersion rootProject.ext.targetSdkVersion
126
- versionCode project.env.get("ANDROID_VERSION_CODE").toInteger()
127
- versionName project.env.get("ANDROID_VERSION_NAME")
126
+ versionCode project.env.get("ANDROID_VERSION_CODE")?.toInteger() ?: 1
127
+ versionName project.env.get("ANDROID_VERSION_NAME") ?: "1.0.0"
128
128
  resValue "string", "build_config_package", project.env.get("ANDROID_APP_ID")
129
129
 
130
130
  ndk {
@@ -169,7 +169,7 @@ android {
169
169
  def projectName = project.env.get("PROJECT_NAME")
170
170
  def SEP = "_"
171
171
 
172
- def newApkName = projectName + SEP + project.env.get("ENV") + SEP + project.env.get("ANDROID_VERSION_NAME") + SEP + project.env.get("ANDROID_VERSION_CODE") + ".apk"
172
+ def newApkName = projectName + SEP + project.env.get("ENV") + SEP + (project.env.get("ANDROID_VERSION_NAME") ?: "1.0.0") + SEP + (project.env.get("ANDROID_VERSION_CODE")?.toInteger() ?: 1) + ".apk"
173
173
 
174
174
 
175
175
  println "Naming File ... " + newApkName
@@ -5,11 +5,17 @@ import com.facebook.react.ReactActivity
5
5
  import com.facebook.react.ReactActivityDelegate
6
6
  import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled
7
7
  import com.facebook.react.defaults.DefaultReactActivityDelegate
8
+ import com.swmansion.rnscreens.fragment.restoration.RNScreensFragmentFactory
8
9
 
9
10
  class MainActivity : ReactActivity() {
10
11
 
12
+ /**
13
+ * Prevents crash on activity recreation: "Screen fragments should never be restored".
14
+ * See https://github.com/software-mansion/react-native-screens/issues/17
15
+ */
11
16
  override fun onCreate(savedInstanceState: Bundle?) {
12
- super.onCreate(null)
17
+ supportFragmentManager.fragmentFactory = RNScreensFragmentFactory()
18
+ super.onCreate(savedInstanceState)
13
19
  }
14
20
 
15
21
  /**
@@ -24,4 +30,4 @@ class MainActivity : ReactActivity() {
24
30
  */
25
31
  override fun createReactActivityDelegate(): ReactActivityDelegate =
26
32
  DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled)
27
- }
33
+ }
@@ -4,41 +4,24 @@ import android.app.Application
4
4
  import com.facebook.react.PackageList
5
5
  import com.facebook.react.ReactApplication
6
6
  import com.facebook.react.ReactHost
7
- import com.facebook.react.ReactNativeHost
8
- import com.facebook.react.ReactPackage
9
- import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
7
+ import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
10
8
  import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
11
- import com.facebook.react.defaults.DefaultReactNativeHost
12
- import com.facebook.react.soloader.OpenSourceMergedSoMapping
13
- import com.facebook.soloader.SoLoader
14
9
 
15
10
  class MainApplication : Application(), ReactApplication {
16
11
 
17
- override val reactNativeHost: ReactNativeHost =
18
- object : DefaultReactNativeHost(this) {
19
- override fun getPackages(): List<ReactPackage> =
20
- PackageList(this).packages.apply {
21
- // Packages that cannot be autolinked yet can be added manually here, for example:
22
- // add(MyReactNativePackage())
23
- }
24
-
25
- override fun getJSMainModuleName(): String = "index"
26
-
27
- override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
28
-
29
- override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
30
- override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
31
- }
32
-
33
- override val reactHost: ReactHost
34
- get() = getDefaultReactHost(applicationContext, reactNativeHost)
12
+ override val reactHost: ReactHost by lazy {
13
+ getDefaultReactHost(
14
+ context = applicationContext,
15
+ packageList =
16
+ PackageList(this).packages.apply {
17
+ // Packages that cannot be autolinked yet can be added manually here, for example:
18
+ // add(MyReactNativePackage())
19
+ },
20
+ )
21
+ }
35
22
 
36
23
  override fun onCreate() {
37
24
  super.onCreate()
38
- SoLoader.init(this, OpenSourceMergedSoMapping)
39
- if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
40
- // If you opted-in for the New Architecture, we load the native entry point for this app.
41
- load()
42
- }
25
+ loadReactNative(this)
43
26
  }
44
27
  }
@@ -1,11 +1,11 @@
1
1
  buildscript {
2
2
  ext {
3
- buildToolsVersion = "35.0.0"
3
+ buildToolsVersion = "36.0.0"
4
4
  minSdkVersion = 24
5
- compileSdkVersion = 35
6
- targetSdkVersion = 34
7
- ndkVersion = "26.1.10909125"
8
- kotlinVersion = "1.9.24"
5
+ compileSdkVersion = 36
6
+ targetSdkVersion = 36
7
+ ndkVersion = "27.1.12297006"
8
+ kotlinVersion = "2.1.20"
9
9
  }
10
10
  repositories {
11
11
  google()
@@ -1,6 +1,6 @@
1
1
  distributionBase=GRADLE_USER_HOME
2
2
  distributionPath=wrapper/dists
3
- distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
3
+ distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
4
4
  networkTimeout=10000
5
5
  validateDistributionUrl=true
6
6
  zipStoreBase=GRADLE_USER_HOME
@@ -0,0 +1,27 @@
1
+ # Architecture
2
+
3
+ ## Overview
4
+
5
+ This app uses a layered structure: **UI** (screens, components) → **navigation** → **core** (store, api, theme, config) and **common** (components, localization, helpers).
6
+
7
+ ## Folder map
8
+
9
+ | Folder | Purpose |
10
+ |--------|--------|
11
+ | `src/common/` | Shared UI components, localization (i18n), helpers, validations, hooks, urls, utils |
12
+ | `src/core/` | Store (Redux + persist), API client, theme, config, services, hooks |
13
+ | `src/navigation/` | Navigator setup, auth stack, main stack, tab bar, header components |
14
+ | `src/screens/` | Feature screens (Login, Home, Profile, etc.); each may have local `components/` and `hooks/` |
15
+ | `src/sheetManager/` | Action sheet registration |
16
+
17
+ ## Data flow
18
+
19
+ - **Auth**: Token is stored in Redux (`user.accessToken`). Navigation shows Auth stack when there is no token, Main stack when there is.
20
+ - **API**: Single axios instance in `src/core/api/serverHeaders.ts`. Base URL comes from `src/core/config` (and `.env`). Request interceptor adds `Authorization: Bearer` and `locale`; response interceptor handles 401 (e.g. logout).
21
+ - **Redux**: Slices live under `src/core/store/<domain>/` (e.g. `app`, `user`). Persist whitelist controls what is saved to AsyncStorage.
22
+
23
+ ## SOLID mapping
24
+
25
+ - **SRP**: One domain per store folder; one primary concern per component file; theme split into colors, fonts, sizes, consts, styles.
26
+ - **OCP**: Extend by adding screens, slices, or routes without changing existing stack logic; extend theme by editing theme files.
27
+ - **DIP**: Core (API, store) does not depend on UI; screens depend on core via hooks/selectors; config abstracts environment.
@@ -0,0 +1,33 @@
1
+ # Best practices
2
+
3
+ ## Code style
4
+
5
+ - Use **TypeScript** strictly; avoid `any` where possible.
6
+ - Use typed Redux: `useAppSelector`, `useAppDispatch`, and `createAppAsyncThunk` with `RootState` / `AppDispatch`.
7
+ - Run `npm run lint` and fix issues.
8
+
9
+ ## Structure
10
+
11
+ - **Single responsibility**: One concern per module/folder; keep screens thin (logic in hooks or actions).
12
+ - Put shared UI in `src/common/components/`.
13
+ - Use the API helpers from `src/core/api` (get, post, put, deleteApi); do not create extra axios instances.
14
+
15
+ ## Testing
16
+
17
+ - Use **Jest** and **React Native Testing Library** for unit and component tests.
18
+ - Add tests for store logic and important components; run `npm test`.
19
+
20
+ ## Performance
21
+
22
+ - Avoid creating new objects/functions in render when they are passed as props to children.
23
+ - Use stable keys for list items.
24
+
25
+ ## Security
26
+
27
+ - Do not commit secrets; use `.env` for API keys and base URL (and add `.env` to `.gitignore`).
28
+ - Persist only necessary fields (use the persist whitelist in the store).
29
+
30
+ ## LTS / upgrades
31
+
32
+ - The template targets **Node >= 20** and current stable **React Native** (e.g. 0.84.x).
33
+ - To upgrade React Native, use [React Native Upgrade Helper](https://react-native-community.github.io/upgrade-helper/): select your current version and the target version, then apply the suggested changes to `package.json`, `android/`, `ios/`, and config files.
@@ -0,0 +1,53 @@
1
+ # Customization
2
+
3
+ ## App name and bundle ID
4
+
5
+ Set at project creation:
6
+
7
+ ```bash
8
+ npx @react-native-community/cli init YourAppName --template @fadyshawky/react-native-magic --package-name com.yourcompany.yourapp
9
+ ```
10
+
11
+ - **App name**: Replaces the template placeholder in `app.json` and file names.
12
+ - **Bundle ID** (`--package-name`): Sets Android `applicationId` and iOS `PRODUCT_BUNDLE_IDENTIFIER` and restructures Android package folders.
13
+
14
+ If you omit `--package-name`, the template will **prompt you** after init to enter a package name (e.g. `com.company.app`). You can enter it then, or press Enter to skip and set `APP_ID` / `ANDROID_APP_ID` in `.env` later and the iOS bundle ID in Xcode or via [react-native-rename](https://www.npmjs.com/package/react-native-rename).
15
+
16
+ ## API base URL and environment
17
+
18
+ 1. Copy `.env.example` to `.env`.
19
+ 2. Set `API_BASE_URL` (and any other keys) for your backend.
20
+ 3. The app reads these via `react-native-config`; `src/core/config/index.ts` re-exports them for type-safe use.
21
+
22
+ Optional: use multiple env files (e.g. `.env.development`, `.env.staging`, `.env.production`) and build variants so each build uses the right URL.
23
+
24
+ ## Theme
25
+
26
+ Edit these files for your brand (no need to touch components):
27
+
28
+ - **Colors**: `src/core/theme/colors.ts`
29
+ - **Fonts**: `src/core/theme/fonts.ts`
30
+ - **Sizes / spacing**: `src/core/theme/commonSizes.ts`
31
+
32
+ ## Adding a new language
33
+
34
+ 1. Add a new translation file under `src/common/localization/translations/`, e.g. `frLocalization.ts`, following the same shape as `commonLocalization.ts` or `loginLocalization.ts`.
35
+ 2. In `src/common/localization/localization.ts`, import the new file and add it to the `localization` object, e.g. `fr: new LocalizedStrings(frLocalization)`.
36
+ 3. Add the language to the `Languages` enum in `localization.ts` if you use it for switching (e.g. `fr = 'fr'`).
37
+ 4. Use the new keys in your components via the existing `t(key, section)` or the relevant `localization.*` object.
38
+
39
+ ## Adding a screen
40
+
41
+ 1. Create a folder under `src/screens/<Feature>/` with `Feature.tsx` and optional `components/` and `hooks/`.
42
+ 2. Register the screen in the right stack in `src/navigation/` (e.g. `AuthStack.tsx` or `MainStack.tsx`).
43
+ 3. Add the route and component to the stack’s screen list.
44
+
45
+ ## Adding a Redux slice
46
+
47
+ 1. Create a folder under `src/core/store/<domain>/` with `*State.ts`, `*Slice.ts`, and optionally `*Actions.ts`.
48
+ 2. Add the slice to `src/core/store/rootReducer.ts`.
49
+ 3. If the slice should persist, add a `createWhitelistFilter('<domain>', ['field1', 'field2'])` entry in `src/core/store/store.tsx` persist config.
50
+
51
+ ## Feature flags / app config
52
+
53
+ Toggle features or app-level constants in `src/core/config/index.ts` or via env vars read there (e.g. `enableRTL`).
package/template/index.js CHANGED
@@ -5,5 +5,6 @@ import 'react-native-gesture-handler';
5
5
  import {AppRegistry} from 'react-native';
6
6
  import App from './App';
7
7
  import {name as appName} from './app.json';
8
+ import './src/sheetManager/sheets';
8
9
 
9
10
  AppRegistry.registerComponent(appName, () => App);
@@ -1,116 +1,71 @@
1
1
  {
2
- "name": "@fadyshawky/react-native-magic",
2
+ "name": "reactnativemagic",
3
3
  "version": "0.0.1",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "android": "react-native run-android",
7
- "android:staging": "react-native run-android --variant=stagingDebug",
8
- "android:staging-release": "react-native run-android --variant=stagingRelease",
9
- "android:dev": "ENVFILE=.env.development react-native run-android --variant=developmentDebug",
10
- "android:dev-release": "ENVFILE=.env.development react-native run-android --variant=developmentRelease",
11
- "android:prod": "ENVFILE=.env.production react-native run-android --variant=productionDebug",
12
- "android:prod-release": "ENVFILE=.env.production react-native run-android --variant=productionRelease",
13
7
  "ios": "react-native run-ios",
14
8
  "lint": "eslint .",
15
9
  "start": "react-native start",
16
- "start:development": "ENVFILE=.env.development react-native start --reset-cache",
17
- "start:production": "ENVFILE=.env.production react-native start --reset-cache",
18
- "start:staging": "ENVFILE=.env.staging react-native start --reset-cache",
19
10
  "test": "jest"
20
11
  },
21
12
  "dependencies": {
22
- "@d11/react-native-fast-image": "^8.9.2",
23
- "@react-native-async-storage/async-storage": "^2.1.0",
24
- "@react-native-camera-roll/camera-roll": "^7.9.0",
25
- "@react-native-community/datetimepicker": "^8.2.0",
26
- "@react-native-community/image-editor": "^4.2.1",
27
- "@react-native-community/netinfo": "^11.4.1",
28
- "@react-native-community/slider": "^4.5.5",
29
- "@react-navigation/bottom-tabs": "^7.2.0",
30
- "@react-navigation/drawer": "^7.1.1",
31
- "@react-navigation/elements": "^2.2.5",
32
- "@react-navigation/material-top-tabs": "^7.1.0",
33
- "@react-navigation/native": "^7.0.14",
34
- "@react-navigation/native-stack": "^7.2.0",
35
- "@reduxjs/toolkit": "^2.5.0",
36
- "@shopify/flash-list": "^1.7.2",
37
- "@types/intl": "^1.2.2",
38
- "@types/jest": "^29.5.14",
39
- "@types/lodash": "^4.17.13",
40
- "@types/react-native-vector-icons": "^6.4.18",
41
- "@types/react-redux": "^7.1.34",
42
- "axios": "^1.7.9",
13
+ "@good-react-native/gradient-border": "^1.0.2",
14
+ "@react-native-async-storage/async-storage": "^3.0.1",
15
+ "@react-native-masked-view/masked-view": "^0.3.2",
16
+ "@react-navigation/bottom-tabs": "^7.15.5",
17
+ "@react-navigation/native": "^7.1.33",
18
+ "@react-navigation/native-stack": "^7.14.4",
19
+ "@reduxjs/toolkit": "^2.11.2",
20
+ "axios": "^1.13.6",
43
21
  "babel-plugin-transform-remove-console": "^6.9.4",
44
- "dayjs": "^1.11.13",
45
- "detox": "^20.28.0",
22
+ "dayjs": "^1.11.19",
46
23
  "intl": "^1.2.5",
47
- "lodash": "^4.17.21",
48
- "mime": "^4.0.6",
49
- "patch-package": "^8.0.0",
50
- "react": "^18.3.1",
51
- "react-native": "^0.76.5",
52
- "react-native-actions-sheet": "^0.9.7",
53
- "react-native-animated-pagination-dots": "^0.1.73",
54
- "react-native-calendars": "^1.1307.0",
55
- "react-native-config": "^1.5.3",
56
- "react-native-device-info": "^14.0.2",
57
- "react-native-dropdown-select-list": "^2.0.5",
58
- "react-native-gesture-handler": "^2.21.2",
59
- "react-native-image-crop-picker": "^0.41.6",
60
- "react-native-image-resource-generator": "^1.0.2",
61
- "react-native-in-app-review": "^4.3.3",
24
+ "lodash": "^4.17.23",
25
+ "react": "^19.2.3",
26
+ "react-dom": "^19.2.3",
27
+ "react-native": "^0.84.1",
28
+ "react-native-actions-sheet": "^10.1.2",
29
+ "react-native-config": "^1.6.1",
30
+ "react-native-device-info": "^15.0.2",
31
+ "react-native-gesture-handler": "^2.30.0",
62
32
  "react-native-keyboard-aware-scroll-view": "^0.9.5",
33
+ "react-native-linear-gradient": "^2.8.3",
63
34
  "react-native-localization": "^2.3.2",
64
- "react-native-mask-input": "^1.2.3",
65
- "react-native-orientation-locker": "^1.7.0",
66
- "react-native-pager-view": "^6.6.1",
67
- "react-native-permissions": "^5.2.1",
68
- "react-native-reanimated": "^3.16.6",
69
- "react-native-reanimated-carousel": "^3.5.1",
35
+ "react-native-reanimated": "^4.2.2",
70
36
  "react-native-restart": "^0.0.27",
71
- "react-native-safe-area-context": "^5.0.0",
72
- "react-native-screens": "^4.4.0",
37
+ "react-native-safe-area-context": "^5.7.0",
38
+ "react-native-screens": "^4.24.0",
73
39
  "react-native-sfsymbols": "^1.2.2",
74
- "react-native-share": "^12.0.3",
75
- "react-native-snackbar": "^2.8.0",
76
- "react-native-svg": "^15.10.1",
77
- "react-native-tab-view": "^4.0.5",
78
- "react-native-vector-icons": "^10.2.0",
79
- "react-native-vision-camera": "^4.6.3",
80
- "react-native-webview": "^13.12.5",
40
+ "react-native-snackbar": "^3.0.1",
41
+ "react-native-vector-icons": "^10.3.0",
42
+ "react-native-worklets": "^0.7.4",
81
43
  "react-redux": "^9.2.0",
82
44
  "redux": "^5.0.1",
83
45
  "redux-persist": "^6.0.0",
84
46
  "redux-persist-transform-filter": "^0.0.22"
85
47
  },
86
48
  "devDependencies": {
87
- "@babel/core": "^7.25.2",
88
- "@babel/preset-env": "^7.26.0",
89
- "@babel/runtime": "^7.26.0",
90
- "@jest/globals": "^29.7.0",
91
- "@react-native-community/cli": "15.0.1",
92
- "@react-native-community/cli-platform-android": "15.0.1",
93
- "@react-native-community/cli-platform-ios": "15.0.1",
94
- "@react-native/babel-preset": "^0.76.5",
95
- "@react-native/eslint-config": "^0.76.5",
96
- "@react-native/metro-config": "^0.76.5",
97
- "@react-native/typescript-config": "^0.76.5",
98
- "@types/react": "^18.3.18",
99
- "@types/react-test-renderer": "^18.3.1",
100
- "babel-jest": "^29.7.0",
101
- "eslint": "^8.57.1",
102
- "eslint-plugin-import": "^2.31.0",
103
- "eslint-plugin-jest": "^28.10.0",
104
- "eslint-plugin-react": "^7.37.2",
105
- "eslint-plugin-react-hooks": "^5.1.0",
106
- "eslint-plugin-react-native": "^4.1.0",
107
- "eslint-plugin-unused-imports": "^4.1.4",
108
- "jest": "^29.7.0",
109
- "prettier": "^2.8.8",
110
- "react-test-renderer": "^18.3.1",
111
- "typescript": "^5.0.4"
49
+ "@babel/core": "^7.29.0",
50
+ "@babel/preset-env": "^7.29.0",
51
+ "@babel/runtime": "^7.28.6",
52
+ "@react-native-community/cli": "^20.1.2",
53
+ "@react-native-community/cli-platform-android": "^20.1.2",
54
+ "@react-native-community/cli-platform-ios": "^20.1.2",
55
+ "@react-native/babel-preset": "^0.84.1",
56
+ "@react-native/eslint-config": "^0.84.1",
57
+ "@react-native/metro-config": "^0.84.1",
58
+ "@react-native/typescript-config": "^0.84.1",
59
+ "@types/jest": "^30.0.0",
60
+ "@types/react": "^19.2.14",
61
+ "@types/react-test-renderer": "^19.1.0",
62
+ "eslint": "^10.0.2",
63
+ "jest": "^30.2.0",
64
+ "prettier": "^3.8.1",
65
+ "react-test-renderer": "^19.2.3",
66
+ "typescript": "^5.9.3"
112
67
  },
113
68
  "engines": {
114
- "node": ">=18"
69
+ "node": ">=20"
115
70
  }
116
71
  }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * StatusBar wrapper that avoids deprecated Android APIs when using edge-to-edge.
3
+ * On Android 15+ with edge-to-edge, Window.setStatusBarColor/setNavigationBarColor
4
+ * are deprecated. Passing backgroundColor on Android triggers those APIs, so we
5
+ * only pass it on iOS.
6
+ */
7
+ import React from 'react';
8
+ import {Platform, StatusBar, StatusBarProps} from 'react-native';
9
+
10
+ type AppStatusBarProps = Omit<StatusBarProps, 'backgroundColor'> & {
11
+ backgroundColor?: string;
12
+ };
13
+
14
+ export function AppStatusBar({
15
+ backgroundColor,
16
+ ...rest
17
+ }: AppStatusBarProps): React.JSX.Element {
18
+ return (
19
+ <StatusBar
20
+ {...rest}
21
+ backgroundColor={Platform.OS === 'ios' ? backgroundColor : undefined}
22
+ />
23
+ );
24
+ }
@@ -80,7 +80,7 @@ const styles = StyleSheet.create({
80
80
  height: scaleHeight(100),
81
81
  },
82
82
  title: {
83
- fontSize: CommonSizes.fontSize.body2,
83
+ fontSize: CommonSizes.font.bodyMedium,
84
84
  textAlign: 'center',
85
85
  marginBottom: CommonSizes.spacing.small,
86
86
  },
@@ -22,7 +22,7 @@ const styles = StyleSheet.create({
22
22
  ...CommonStyles.normalText,
23
23
  fontWeight: '600',
24
24
  textAlign: 'center',
25
- marginBottom: CommonSizes.spacing.extraSmall,
25
+ marginBottom: CommonSizes.spacing.xSmall,
26
26
  } as TextStyle,
27
27
  description: {
28
28
  ...CommonStyles.normalText,
@@ -100,7 +100,7 @@ const styles = StyleSheet.create({
100
100
  },
101
101
  input: {
102
102
  flex: 1,
103
- height: CommonSizes.spacing.xxl,
103
+ height: CommonSizes.spacing.xxxLarge,
104
104
  borderWidth: 1,
105
105
  borderRadius: CommonSizes.borderRadius.medium,
106
106
  textAlign: 'center',
@@ -17,7 +17,7 @@ import {
17
17
  TouchablePlatformProps,
18
18
  } from '../../../types';
19
19
  import {useTheme} from '../../core/theme/ThemeProvider';
20
- import {BorderRadius, Spacing} from '../../core/theme/commonSizes';
20
+ import {CommonSizes} from '../../core/theme/commonSizes';
21
21
  import {createThemedStyles} from '../../core/theme/commonStyles';
22
22
  import {Theme} from '../../core/theme/types';
23
23
  import {IconPlatform} from './IconPlatform';
@@ -271,10 +271,10 @@ function createSmallSolidStyles(theme: Theme): IStyles {
271
271
  const commonStyles = createThemedStyles(theme);
272
272
  return StyleSheet.create({
273
273
  button: {
274
- padding: Spacing.medium,
274
+ padding: CommonSizes.spacing.medium,
275
275
  alignItems: 'center',
276
276
  justifyContent: 'center',
277
- borderRadius: BorderRadius.extraLarge,
277
+ borderRadius: CommonSizes.borderRadius.xLarge,
278
278
  flexDirection: 'row',
279
279
  backgroundColor: theme.colors.indigoBlue,
280
280
  // width: 175,
@@ -295,10 +295,10 @@ function createSmallOutlineStyles(theme: Theme): IStyles {
295
295
  const commonStyles = createThemedStyles(theme);
296
296
  return StyleSheet.create({
297
297
  button: {
298
- padding: Spacing.medium,
298
+ padding: CommonSizes.spacing.medium,
299
299
  alignItems: 'center',
300
300
  justifyContent: 'center',
301
- borderRadius: BorderRadius.extraLarge,
301
+ borderRadius: CommonSizes.borderRadius.xLarge,
302
302
  flexDirection: 'row',
303
303
  backgroundColor: 'transparent',
304
304
  width: 175,
@@ -22,7 +22,7 @@ import {
22
22
  ViewStyle,
23
23
  } from 'react-native';
24
24
  import {useTheme} from '../../core/theme/ThemeProvider';
25
- import {NewColors} from '../../core/theme/colors';
25
+ import {PrimaryColors, AlertColors} from '../../core/theme/colors';
26
26
  import {isIos} from '../../core/theme/commonConsts';
27
27
  import {CommonSizes} from '../../core/theme/commonSizes';
28
28
  import {CommonStyles} from '../../core/theme/commonStyles';
@@ -268,13 +268,13 @@ function getInputContainerStyle(
268
268
  }
269
269
  }
270
270
 
271
- const selectionColor = NewColors.blueNormalActive;
271
+ const selectionColor = PrimaryColors.PlatinateBlue_400;
272
272
 
273
273
  const commonInputContainer: TextStyle = {
274
274
  flexDirection: 'row',
275
275
  alignItems: 'center',
276
276
  justifyContent: 'center',
277
- minHeight: CommonSizes.spacing.extraLarge,
277
+ minHeight: CommonSizes.spacing.xxxLarge,
278
278
  textAlignVertical: 'center',
279
279
  textAlign: 'center',
280
280
  width: '100%',
@@ -307,7 +307,7 @@ const styles = StyleSheet.create({
307
307
  ...commonInputContainer,
308
308
  ...Platform.select({
309
309
  android: {
310
- borderColor: NewColors.red,
310
+ borderColor: AlertColors.error_400,
311
311
  },
312
312
  }),
313
313
  } as TextStyle,
@@ -46,7 +46,7 @@ export const RadioButton: FC<IProps> = memo(
46
46
  const commonLabel: TextStyle = {
47
47
  ...CommonStyles.normalText,
48
48
  flex: 1,
49
- paddingStart: CommonSizes.spacing.extraSmall,
49
+ paddingStart: CommonSizes.spacing.xSmall,
50
50
  };
51
51
 
52
52
  const styles = StyleSheet.create({