@modhamanish/rn-mm-template 1.0.4 → 1.0.5

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 (48) hide show
  1. package/MMTemplate/.eslintrc.js +95 -1
  2. package/MMTemplate/.husky/pre-commit +2 -0
  3. package/MMTemplate/.prettierrc.js +2 -0
  4. package/MMTemplate/App.tsx +27 -21
  5. package/MMTemplate/README.md +76 -35
  6. package/MMTemplate/__tests__/App.test.tsx +5 -3
  7. package/MMTemplate/babel.config.js +24 -1
  8. package/MMTemplate/index.js +1 -0
  9. package/MMTemplate/package.json +22 -2
  10. package/MMTemplate/src/components/AnimationView.tsx +54 -69
  11. package/MMTemplate/src/components/AppText.tsx +7 -4
  12. package/MMTemplate/src/components/CustomAlert.tsx +203 -0
  13. package/MMTemplate/src/components/CustomToast.tsx +2 -1
  14. package/MMTemplate/src/components/ErrorBoundaryFallback.tsx +127 -0
  15. package/MMTemplate/src/components/FeatureItem.tsx +8 -6
  16. package/MMTemplate/src/components/FullScreenContainer.tsx +9 -7
  17. package/MMTemplate/src/components/InfoCard.tsx +8 -6
  18. package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -6
  19. package/MMTemplate/src/components/TextInput.tsx +25 -15
  20. package/MMTemplate/src/components/ThemeSwitcher.tsx +4 -3
  21. package/MMTemplate/src/context/AuthContext.tsx +5 -4
  22. package/MMTemplate/src/context/ThemeContext.tsx +10 -19
  23. package/MMTemplate/src/locales/en.json +4 -1
  24. package/MMTemplate/src/locales/hi.json +4 -1
  25. package/MMTemplate/src/navigation/AppNavigator.tsx +7 -8
  26. package/MMTemplate/src/navigation/AppStack.tsx +6 -6
  27. package/MMTemplate/src/navigation/AuthCheck.tsx +11 -10
  28. package/MMTemplate/src/navigation/AuthStack.tsx +6 -4
  29. package/MMTemplate/src/navigation/MainTab.tsx +19 -13
  30. package/MMTemplate/src/screens/AddNoteScreen.tsx +20 -14
  31. package/MMTemplate/src/screens/HomeScreen.tsx +21 -15
  32. package/MMTemplate/src/screens/LoginScreen.tsx +21 -18
  33. package/MMTemplate/src/screens/NoteScreen.tsx +18 -16
  34. package/MMTemplate/src/screens/ProfileScreen.tsx +16 -13
  35. package/MMTemplate/src/screens/SettingsScreen.tsx +14 -11
  36. package/MMTemplate/src/screens/WelcomeScreen.tsx +19 -13
  37. package/MMTemplate/src/services/axiosInstance.ts +7 -5
  38. package/MMTemplate/src/services/note.query.ts +7 -5
  39. package/MMTemplate/src/theme/{Colors.ts → colors.ts} +6 -0
  40. package/MMTemplate/src/types/components.types.ts +38 -0
  41. package/MMTemplate/src/types/navigation.types.ts +1 -1
  42. package/MMTemplate/src/utils/i18n.ts +8 -6
  43. package/MMTemplate/src/utils/navigationUtils.ts +2 -1
  44. package/MMTemplate/src/utils/storageHelper.ts +8 -8
  45. package/MMTemplate/src/utils/utilsHelper.ts +1 -0
  46. package/MMTemplate/tsconfig.json +27 -0
  47. package/README.md +3 -1
  48. package/package.json +1 -1
@@ -1,4 +1,98 @@
1
1
  module.exports = {
2
2
  root: true,
3
- extends: '@react-native',
3
+ extends: [
4
+ '@react-native',
5
+ 'plugin:import/recommended',
6
+ 'plugin:import/typescript',
7
+ 'plugin:prettier/recommended',
8
+ ],
9
+ plugins: ['import', 'prettier'],
10
+ settings: {
11
+ 'import/resolver': {
12
+ typescript: {
13
+ alwaysTryTypes: true,
14
+ project: './tsconfig.json',
15
+ },
16
+ },
17
+ },
18
+ rules: {
19
+ 'prettier/prettier': 'error',
20
+ 'import/order': [
21
+ 'error',
22
+ {
23
+ groups: [
24
+ 'builtin',
25
+ 'external',
26
+ 'internal',
27
+ ['parent', 'sibling', 'index'],
28
+ 'object',
29
+ 'type',
30
+ ],
31
+ pathGroups: [
32
+ {
33
+ pattern: 'react+(|-native)',
34
+ group: 'external',
35
+ position: 'before',
36
+ },
37
+ {
38
+ pattern: '@src/**',
39
+ group: 'internal',
40
+ },
41
+ {
42
+ pattern: '@assets/**',
43
+ group: 'internal',
44
+ },
45
+ {
46
+ pattern: '@components/**',
47
+ group: 'internal',
48
+ },
49
+ {
50
+ pattern: '@context/**',
51
+ group: 'internal',
52
+ },
53
+ {
54
+ pattern: '@locales/**',
55
+ group: 'internal',
56
+ },
57
+ {
58
+ pattern: '@mock/**',
59
+ group: 'internal',
60
+ },
61
+ {
62
+ pattern: '@navigation/**',
63
+ group: 'internal',
64
+ },
65
+ {
66
+ pattern: '@screens/**',
67
+ group: 'internal',
68
+ },
69
+ {
70
+ pattern: '@services/**',
71
+ group: 'internal',
72
+ },
73
+ {
74
+ pattern: '@theme/**',
75
+ group: 'internal',
76
+ },
77
+ {
78
+ pattern: '@app-types/**',
79
+ group: 'internal',
80
+ },
81
+ {
82
+ pattern: '@utils/**',
83
+ group: 'internal',
84
+ },
85
+ ],
86
+ pathGroupsExcludedImportTypes: ['react'],
87
+ 'newlines-between': 'always',
88
+ alphabetize: {
89
+ order: 'asc',
90
+ caseInsensitive: true,
91
+ },
92
+ },
93
+ ],
94
+ 'import/no-unresolved': 'error',
95
+ 'no-console': 'error',
96
+ '@typescript-eslint/no-explicit-any': 'error',
97
+ },
4
98
  };
@@ -0,0 +1,2 @@
1
+ cd "$(dirname "$0")/.."
2
+ npx lint-staged
@@ -2,4 +2,6 @@ module.exports = {
2
2
  arrowParens: 'avoid',
3
3
  singleQuote: true,
4
4
  trailingComma: 'all',
5
+ bracketSpacing: true,
6
+ tabWidth: 2,
5
7
  };
@@ -1,15 +1,18 @@
1
1
  import React from 'react';
2
- import { SafeAreaProvider } from 'react-native-safe-area-context';
3
- import { KeyboardProvider } from 'react-native-keyboard-controller';
4
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
5
-
6
- import { ThemeProvider } from './src/context/ThemeContext';
7
- import AppNavigator from './src/navigation/AppNavigator';
8
2
 
3
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
4
+ import ErrorBoundary from 'react-native-error-boundary';
5
+ import { KeyboardProvider } from 'react-native-keyboard-controller';
6
+ import { SafeAreaProvider } from 'react-native-safe-area-context';
9
7
  import Toast, { ToastConfigParams } from 'react-native-toast-message';
10
- import { CustomToast } from './src/components/CustomToast';
11
- import { AuthProvider } from './src/context/AuthContext';
12
- import './src/utils/i18n';
8
+
9
+ import { CustomToast } from '@components/CustomToast';
10
+ import ErrorBoundaryFallback from '@components/ErrorBoundaryFallback';
11
+ import { AuthProvider } from '@context/AuthContext';
12
+ import { ThemeProvider } from '@context/ThemeContext';
13
+ import AppNavigator from '@navigation/AppNavigator';
14
+ import CustomAlert from '@src/components/CustomAlert';
15
+ import '@utils/i18n';
13
16
 
14
17
  const queryClient = new QueryClient({
15
18
  defaultOptions: {
@@ -36,18 +39,21 @@ const toastConfig = {
36
39
 
37
40
  const App = () => {
38
41
  return (
39
- <KeyboardProvider>
40
- <SafeAreaProvider>
41
- <ThemeProvider>
42
- <AuthProvider>
43
- <QueryClientProvider client={queryClient}>
44
- <AppNavigator />
45
- </QueryClientProvider>
46
- </AuthProvider>
47
- </ThemeProvider>
48
- <Toast config={toastConfig} />
49
- </SafeAreaProvider>
50
- </KeyboardProvider>
42
+ <ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
43
+ <KeyboardProvider>
44
+ <SafeAreaProvider>
45
+ <ThemeProvider>
46
+ <AuthProvider>
47
+ <QueryClientProvider client={queryClient}>
48
+ <AppNavigator />
49
+ <CustomAlert />
50
+ <Toast config={toastConfig} />
51
+ </QueryClientProvider>
52
+ </AuthProvider>
53
+ </ThemeProvider>
54
+ </SafeAreaProvider>
55
+ </KeyboardProvider>
56
+ </ErrorBoundary>
51
57
  );
52
58
  };
53
59
 
@@ -6,19 +6,21 @@ Welcome to **MMTemplate**! This is a robust and modern React Native template bui
6
6
 
7
7
  This template includes the following key libraries and configurations:
8
8
 
9
- * **Core**: React Native (0.83.1), React (19.2.0)
10
- * **Language**: TypeScript (v5) for static type checking
11
- * **Navigation**: [React Navigation v7](https://reactnavigation.org/) (Native Stack)
12
- * **Internationalization**: [react-i18next](https://react.i18next.com/) with multi-language support (English/Hindi)
13
- * **Storage**: [react-native-mmkv](https://github.com/mrousavy/react-native-mmkv) for high-performance persistence
14
- * **Animations**: [React Native Reanimated v4](https://docs.swmansion.com/react-native-reanimated/) & Worklets
15
- * **UI/UX**:
16
- * **Theme Support**: Light/Dark mode with persistence
17
- * **Authentication**: Pre-configured login and profile flow
18
- * [React Native Safe Area Context](https://github.com/th3rdwave/react-native-safe-area-context) for handling safe areas
19
- * [React Native Keyboard Controller](https://github.com/kirillzyusko/react-native-keyboard-controller) for advanced keyboard handling
20
- * [React Native Toast Message](https://github.com/calintamas/react-native-toast-message) for in-app notifications
21
- * **Testing**: Jest & React Test Renderer
9
+ - **Core**: React Native (0.83.1), React (19.2.0)
10
+ - **Language**: TypeScript (v5) for static type checking
11
+ - **Navigation**: [React Navigation v7](https://reactnavigation.org/) (Native Stack & Bottom Tabs)
12
+ - **Internationalization**: [react-i18next](https://react.i18next.com/) with multi-language support (English/Hindi)
13
+ - **Storage**: [react-native-mmkv](https://github.com/mrousavy/react-native-mmkv) for high-performance persistence
14
+ - **Forms**: [Formik](https://formik.org/) & [Yup](https://github.com/jquense/yup) for form state management and validation
15
+ - **Animations**: [React Native Reanimated v4](https://docs.swmansion.com/react-native-reanimated/) & Worklets
16
+ - **UI/UX**:
17
+ - **Theme Support**: Light/Dark mode with persistence
18
+ - **Authentication**: Pre-configured login and profile flow
19
+ - [React Native Safe Area Context](https://github.com/th3rdwave/react-native-safe-area-context) for handling safe areas
20
+ - [React Native Keyboard Controller](https://github.com/kirillzyusko/react-native-keyboard-controller) for advanced keyboard handling
21
+ - [React Native Toast Message](https://github.com/calintamas/react-native-toast-message) for in-app notifications
22
+ - **Error Handling**: [react-native-error-boundary](https://github.com/cawfree/react-native-error-boundary) for robust error catching
23
+ - **Testing**: Jest & React Test Renderer
22
24
 
23
25
  ## 📂 Project Structure
24
26
 
@@ -41,22 +43,51 @@ src/
41
43
 
42
44
  ### Key Files & Directories
43
45
 
44
- | Directory / File | Path | Description |
45
- | :--- | :--- | :--- |
46
- | **`assets/`** | `src/assets/` | Stores static assets such as images, fonts, and icons. |
46
+ | Directory / File | Path | Description |
47
+ | :---------------- | :---------------- | :--------------------------------------------------------------- |
48
+ | **`assets/`** | `src/assets/` | Stores static assets such as images, fonts, and icons. |
47
49
  | **`components/`** | `src/components/` | Contains reusable UI components used throughout the application. |
48
- | **`context/`** | `src/context/` | Holds React Context definitions for global state management. |
49
- | **`locales/`** | `src/locales/` | Contains translation files for internationalization. |
50
- | **`mock/`** | `src/mock/` | Stores mock data used for development and testing. |
51
- | **`navigation/`** | `src/navigation/` | Contains all navigation-related configuration. |
52
- | **`screens/`** | `src/screens/` | Contains all the screen components (pages) of the application. |
53
- | **`services/`** | `src/services/` | Data fetching layer using **React Query** and **Axios**. |
54
- | **`theme/`** | `src/theme/` | Centralized theme configuration (e.g., Colors, Typography). |
55
- | **`types/`** | `src/types/` | Stores TypeScript type definitions and interfaces. |
56
- | **`utils/`** | `src/utils/` | Contains utility functions and helper classes. |
50
+ | **`context/`** | `src/context/` | Holds React Context definitions for global state management. |
51
+ | **`locales/`** | `src/locales/` | Contains translation files for internationalization. |
52
+ | **`mock/`** | `src/mock/` | Stores mock data used for development and testing. |
53
+ | **`navigation/`** | `src/navigation/` | Contains all navigation-related configuration. |
54
+ | **`screens/`** | `src/screens/` | Contains all the screen components (pages) of the application. |
55
+ | **`services/`** | `src/services/` | Data fetching layer using **React Query** and **Axios**. |
56
+ | **`theme/`** | `src/theme/` | Centralized theme configuration (e.g., Colors, Typography). |
57
+ | **`types/`** | `src/types/` | Stores TypeScript type definitions and interfaces. |
58
+ | **`utils/`** | `src/utils/` | Contains utility functions and helper classes. |
59
+
60
+ ## 🔐 Authentication Flow
61
+
62
+ MMTemplate comes with a pre-configured authentication flow managed via React Context.
63
+
64
+ ### 1. State Management
65
+
66
+ Authentication state is managed globally using `AuthContext` (`src/context/AuthContext.tsx`). You can access user data and authentication methods anywhere in the app:
67
+
68
+ ```tsx
69
+ const { user, updateUser, handleLogout, isUserLoggedIn } = useAuth();
70
+ ```
71
+
72
+ ### 2. Navigation Logic
73
+
74
+ - **`AuthCheck`**: The entry point component that checks if a user is already logged in (via `react-native-mmkv` persistence).
75
+ - **`AuthStack`**: contains screens for non-authenticated users (Welcome, Login).
76
+ - **`AppStack`**: contains the main application screens (Home, Profile, Settings).
57
77
 
58
78
  Navigation automatically switches between these stacks based on the `user` state in `AuthContext`.
59
79
 
80
+ ### 3. Mock Credentials
81
+
82
+ For testing purposes, you can use the following credentials (defined in `src/mock/index.ts`):
83
+
84
+ - **Email**: `user@gmail.com`
85
+ - **Password**: `123456`
86
+
87
+ ### 4. Storage Persistence
88
+
89
+ User sessions are persisted locally using `react-native-mmkv`, ensuring users stay logged in even after closing the app.
90
+
60
91
  ---
61
92
 
62
93
  ## 🚀 Data Fetching (React Query)
@@ -64,11 +95,13 @@ Navigation automatically switches between these stacks based on the `user` state
64
95
  MMTemplate uses **TanStack Query (React Query) v5** for server state management and **Axios** for API requests.
65
96
 
66
97
  ### 1. Services Structure
98
+
67
99
  - **`axiosInstance.ts`**: Configured Axios instance with base URL and interceptors.
68
100
  - **`queryKeys.ts`**: Centralized keys for consistency and easy invalidation.
69
101
  - **`*.query.ts`**: Feature-specific hooks for fetching and mutating data.
70
102
 
71
103
  ### 2. Usage Example
104
+
72
105
  To fetch data, use a query hook defined in `src/services`:
73
106
 
74
107
  ```tsx
@@ -87,6 +120,7 @@ const handleSave = () => mutate({ title: 'New Note', content: '...' });
87
120
  ```
88
121
 
89
122
  ### 3. Global Configuration
123
+
90
124
  The `QueryClient` is pre-configured in `App.tsx` with optimized defaults (e.g., `refetchOnWindowFocus: false`).
91
125
 
92
126
  ---
@@ -95,17 +129,18 @@ The `QueryClient` is pre-configured in `App.tsx` with optimized defaults (e.g.,
95
129
 
96
130
  Before you begin, ensure you have the following installed on your machine:
97
131
 
98
- * [Node.js](https://nodejs.org/) (>= 20)
99
- * [Watchman](https://facebook.github.io/watchman/)
100
- * [Ruby](https://www.ruby-lang.org/en/) (for iOS CocoaPods)
101
- * **Android Studio** (for Android development)
102
- * **Xcode** (for iOS development, macOS only)
132
+ - [Node.js](https://nodejs.org/) (>= 20)
133
+ - [Watchman](https://facebook.github.io/watchman/)
134
+ - [Ruby](https://www.ruby-lang.org/en/) (for iOS CocoaPods)
135
+ - **Android Studio** (for Android development)
136
+ - **Xcode** (for iOS development, macOS only)
103
137
 
104
138
  > **Note**: For a detailed environment setup guide, refer to the [official React Native documentation](https://reactnative.dev/docs/set-up-your-environment).
105
139
 
106
140
  ## 📦 Installation
107
141
 
108
142
  1. **Install Dependencies**:
143
+
109
144
  ```bash
110
145
  yarn install
111
146
  # OR
@@ -123,17 +158,21 @@ Before you begin, ensure you have the following installed on your machine:
123
158
  ## 🏃‍♂️ Running the App
124
159
 
125
160
  ### Start Metro Bundler
161
+
126
162
  First, start the Metro bundler in a dedicated terminal:
163
+
127
164
  ```bash
128
165
  yarn start
129
166
  ```
130
167
 
131
168
  ### Run on Android
169
+
132
170
  ```bash
133
171
  yarn android
134
172
  ```
135
173
 
136
174
  ### Run on iOS
175
+
137
176
  ```bash
138
177
  yarn ios
139
178
  ```
@@ -141,9 +180,11 @@ yarn ios
141
180
  ## 🔧 Customization
142
181
 
143
182
  ### Renaming the App
183
+
144
184
  To rename the application from "MMTemplate" to your own project name, you can use `react-native-rename` or manually rename the files.
145
185
 
146
186
  **Using `react-native-rename`:**
187
+
147
188
  1. `npx react-native-rename "YourAppName" -b com.yourcompany.yourappname`
148
189
  2. Edit `package.json` to update the name.
149
190
  3. Delete `ios/Pods` and `node_modules`.
@@ -151,11 +192,11 @@ To rename the application from "MMTemplate" to your own project name, you can us
151
192
 
152
193
  ## 📝 Scripts
153
194
 
154
- * `yarn start`: Starts the Metro Bundler.
155
- * `yarn android`: Builds and runs the Android app.
156
- * `yarn ios`: Builds and runs the iOS app.
157
- * `yarn lint`: Lints the project files.
158
- * `yarn test`: Runs Jest tests.
195
+ - `yarn start`: Starts the Metro Bundler.
196
+ - `yarn android`: Builds and runs the Android app.
197
+ - `yarn ios`: Builds and runs the iOS app.
198
+ - `yarn lint`: Lints the project files.
199
+ - `yarn test`: Runs Jest tests.
159
200
 
160
201
  ---
161
202
 
@@ -3,11 +3,13 @@
3
3
  */
4
4
 
5
5
  import React from 'react';
6
- import ReactTestRenderer from 'react-test-renderer';
6
+
7
+ import { act, create } from 'react-test-renderer';
8
+
7
9
  import App from '../App';
8
10
 
9
11
  test('renders correctly', async () => {
10
- await ReactTestRenderer.act(() => {
11
- ReactTestRenderer.create(<App />);
12
+ await act(() => {
13
+ create(<App />);
12
14
  });
13
15
  });
@@ -4,5 +4,28 @@ const workletsPluginOptions = {
4
4
 
5
5
  module.exports = {
6
6
  presets: ['module:@react-native/babel-preset'],
7
- plugins: [['react-native-worklets/plugin', workletsPluginOptions]],
7
+ plugins: [
8
+ ['react-native-worklets/plugin', workletsPluginOptions],
9
+ [
10
+ 'module-resolver',
11
+ {
12
+ root: ['./src'],
13
+ extensions: ['.ios.js', '.android.js', '.js', '.ts', '.tsx', '.json'],
14
+ alias: {
15
+ '@src': './src',
16
+ '@assets': './src/assets',
17
+ '@components': './src/components',
18
+ '@context': './src/context',
19
+ '@locales': './src/locales',
20
+ '@mock': './src/mock',
21
+ '@navigation': './src/navigation',
22
+ '@screens': './src/screens',
23
+ '@services': './src/services',
24
+ '@theme': './src/theme',
25
+ '@app-types': './src/types',
26
+ '@utils': './src/utils',
27
+ },
28
+ },
29
+ ],
30
+ ],
8
31
  };
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { AppRegistry } from 'react-native';
6
+
6
7
  import App from './App';
7
8
  import { name as appName } from './app.json';
8
9
 
@@ -6,8 +6,11 @@
6
6
  "android": "react-native run-android",
7
7
  "ios": "react-native run-ios",
8
8
  "lint": "eslint .",
9
- "start": "react-native start",
10
- "test": "jest"
9
+ "lint:fix": "eslint . --fix",
10
+ "format": "prettier --write .",
11
+ "start": "react-native start --reset-cache",
12
+ "test": "jest",
13
+ "prepare": "husky"
11
14
  },
12
15
  "dependencies": {
13
16
  "@react-native/new-app-screen": "0.83.1",
@@ -21,6 +24,7 @@
21
24
  "react": "19.2.0",
22
25
  "react-i18next": "^16.5.1",
23
26
  "react-native": "0.83.1",
27
+ "react-native-error-boundary": "^3.1.0",
24
28
  "react-native-keyboard-controller": "^1.20.3",
25
29
  "react-native-mmkv": "^4.1.2",
26
30
  "react-native-nitro-modules": "^0.33.9",
@@ -46,13 +50,29 @@
46
50
  "@types/jest": "^29.5.13",
47
51
  "@types/react": "^19.2.0",
48
52
  "@types/react-test-renderer": "^19.1.0",
53
+ "babel-plugin-module-resolver": "^5.0.2",
49
54
  "eslint": "^8.19.0",
55
+ "eslint-config-prettier": "^10.1.8",
56
+ "eslint-import-resolver-typescript": "^4.4.4",
57
+ "eslint-plugin-import": "^2.32.0",
58
+ "eslint-plugin-prettier": "^5.5.5",
59
+ "husky": "^9.1.7",
50
60
  "jest": "^29.6.3",
61
+ "lint-staged": "^16.2.7",
51
62
  "prettier": "2.8.8",
52
63
  "react-test-renderer": "19.2.0",
53
64
  "typescript": "^5.8.3"
54
65
  },
55
66
  "engines": {
56
67
  "node": ">=20"
68
+ },
69
+ "lint-staged": {
70
+ "*.{ts,tsx}": [
71
+ "eslint --fix",
72
+ "prettier --write"
73
+ ],
74
+ "*.{js,jsx,json,md}": [
75
+ "prettier --write"
76
+ ]
57
77
  }
58
78
  }
@@ -1,4 +1,5 @@
1
- import React, { memo, useEffect } from 'react';
1
+ import React, { FC, memo, useEffect } from 'react';
2
+
2
3
  import Animated, {
3
4
  Easing,
4
5
  useAnimatedStyle,
@@ -7,62 +8,49 @@ import Animated, {
7
8
  withTiming,
8
9
  } from 'react-native-reanimated';
9
10
 
10
- const AnimationView = ({
11
+ import { AnimationViewProps } from '@src/types/components.types';
12
+
13
+ const AnimationView: FC<AnimationViewProps> = ({
11
14
  children,
12
15
  animType,
13
16
  duration = 500,
14
17
  delay = 0,
15
18
  rotateValue = 360,
16
19
  style,
17
- }: {
18
- children: React.ReactNode;
19
- animType:
20
- | 'FadeIn'
21
- | 'FadeOut'
22
- | 'ZoomIn'
23
- | 'ZoomOut'
24
- | 'RotateIn'
25
- | 'RotateOut'
26
- | 'SlideInDown';
27
- duration?: number;
28
- delay?: number;
29
- rotateValue?: number;
30
- style?: any;
31
20
  }) => {
32
- const fadeAnim = useSharedValue(0);
33
- const zoomAnim = useSharedValue(0);
34
- const rotateAnim = useSharedValue(0);
35
- const translateAnim = useSharedValue(-100);
21
+ const getInitialValue = () => {
22
+ switch (animType) {
23
+ case 'SlideInDown':
24
+ return -100;
25
+ case 'FadeOut':
26
+ case 'ZoomOut':
27
+ return 1;
28
+ default:
29
+ return 0;
30
+ }
31
+ };
32
+ const animValue = useSharedValue(getInitialValue());
36
33
 
37
34
  const animStyle = useAnimatedStyle(() => {
38
35
  switch (animType) {
39
36
  case 'FadeIn':
40
- return {
41
- opacity: fadeAnim.value,
42
- };
43
37
  case 'FadeOut':
44
38
  return {
45
- opacity: fadeAnim.value,
39
+ opacity: animValue.value,
46
40
  };
47
41
  case 'ZoomIn':
48
- return {
49
- transform: [{ scale: zoomAnim.value }],
50
- };
51
42
  case 'ZoomOut':
52
43
  return {
53
- transform: [{ scale: zoomAnim.value }],
44
+ transform: [{ scale: animValue.value }],
54
45
  };
55
46
  case 'RotateIn':
56
- return {
57
- transform: [{ rotate: rotateAnim.value + 'deg' }],
58
- };
59
47
  case 'RotateOut':
60
48
  return {
61
- transform: [{ rotate: rotateAnim.value + 'deg' }],
49
+ transform: [{ rotate: animValue.value + 'deg' }],
62
50
  };
63
51
  case 'SlideInDown':
64
52
  return {
65
- transform: [{ translateY: translateAnim.value }],
53
+ transform: [{ translateY: animValue.value }],
66
54
  };
67
55
  default:
68
56
  return {};
@@ -70,43 +58,40 @@ const AnimationView = ({
70
58
  });
71
59
 
72
60
  useEffect(() => {
73
- if (animType === 'FadeIn') {
74
- fadeAnim.value = withDelay(delay, withTiming(1, { duration: duration }));
75
- } else if (animType === 'FadeOut') {
76
- fadeAnim.value = withDelay(delay, withTiming(0, { duration: duration }));
77
- } else if (animType === 'ZoomIn') {
78
- zoomAnim.value = withDelay(
79
- delay,
80
- withTiming(1, { duration: duration, easing: Easing.elastic(1) }),
81
- );
82
- } else if (animType === 'ZoomOut') {
83
- zoomAnim.value = withDelay(
84
- delay,
85
- withTiming(0, { duration: duration, easing: Easing.elastic(1) }),
86
- );
87
- } else if (animType === 'RotateIn') {
88
- rotateAnim.value = withDelay(
89
- delay,
90
- withTiming(rotateValue, {
91
- duration: duration,
92
- easing: Easing.elastic(1),
93
- }),
94
- );
95
- } else if (animType === 'RotateOut') {
96
- rotateAnim.value = withDelay(
97
- delay,
98
- withTiming(rotateValue, {
99
- duration: duration,
100
- easing: Easing.elastic(1),
101
- }),
102
- );
103
- } else if (animType === 'SlideInDown') {
104
- translateAnim.value = withDelay(
105
- delay,
106
- withTiming(0, { duration: duration, easing: Easing.elastic(1) }),
107
- );
61
+ let targetValue = 0;
62
+ let easing = Easing.inOut(Easing.ease);
63
+
64
+ switch (animType) {
65
+ case 'FadeIn':
66
+ targetValue = 1;
67
+ break;
68
+ case 'FadeOut':
69
+ targetValue = 0;
70
+ break;
71
+ case 'ZoomIn':
72
+ targetValue = 1;
73
+ easing = Easing.elastic(1);
74
+ break;
75
+ case 'ZoomOut':
76
+ targetValue = 0;
77
+ easing = Easing.elastic(1);
78
+ break;
79
+ case 'RotateIn':
80
+ case 'RotateOut':
81
+ targetValue = rotateValue;
82
+ easing = Easing.elastic(1);
83
+ break;
84
+ case 'SlideInDown':
85
+ targetValue = 0;
86
+ easing = Easing.elastic(1);
87
+ break;
108
88
  }
109
- }, [animType, duration, delay, rotateValue]);
89
+
90
+ animValue.value = withDelay(
91
+ delay,
92
+ withTiming(targetValue, { duration, easing }),
93
+ );
94
+ }, [animType, duration, delay, rotateValue, animValue]);
110
95
  return <Animated.View style={[animStyle, style]}>{children}</Animated.View>;
111
96
  };
112
97