@modhamanish/rn-mm-template 1.0.3 → 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 +117 -23
  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 +24 -4
  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 +37 -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
 
@@ -33,26 +35,112 @@ src/
33
35
  ├── mock/ # Mock data for testing and development
34
36
  ├── navigation/ # Navigation configuration (Stacks, Stacks, etc.)
35
37
  ├── screens/ # Screen components (Views)
38
+ ├── services/ # Data fetching and API services (React Query)
36
39
  ├── theme/ # Theme configuration (Colors, Typography, Spacing)
37
40
  ├── types/ # Global TypeScript types and interfaces
38
41
  └── utils/ # Helper functions and utilities
39
42
  ```
40
43
 
44
+ ### Key Files & Directories
45
+
46
+ | Directory / File | Path | Description |
47
+ | :---------------- | :---------------- | :--------------------------------------------------------------- |
48
+ | **`assets/`** | `src/assets/` | Stores static assets such as images, fonts, and icons. |
49
+ | **`components/`** | `src/components/` | Contains reusable UI components used throughout the application. |
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).
77
+
78
+ Navigation automatically switches between these stacks based on the `user` state in `AuthContext`.
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
+
91
+ ---
92
+
93
+ ## 🚀 Data Fetching (React Query)
94
+
95
+ MMTemplate uses **TanStack Query (React Query) v5** for server state management and **Axios** for API requests.
96
+
97
+ ### 1. Services Structure
98
+
99
+ - **`axiosInstance.ts`**: Configured Axios instance with base URL and interceptors.
100
+ - **`queryKeys.ts`**: Centralized keys for consistency and easy invalidation.
101
+ - **`*.query.ts`**: Feature-specific hooks for fetching and mutating data.
102
+
103
+ ### 2. Usage Example
104
+
105
+ To fetch data, use a query hook defined in `src/services`:
106
+
107
+ ```tsx
108
+ import { useGetNotesQuery } from '../services/note.query';
109
+
110
+ const { data, isLoading, error } = useGetNotesQuery();
111
+ ```
112
+
113
+ To update data, use a mutation hook:
114
+
115
+ ```tsx
116
+ import { useAddNoteMutation } from '../services/note.query';
117
+
118
+ const { mutate, isPending } = useAddNoteMutation();
119
+ const handleSave = () => mutate({ title: 'New Note', content: '...' });
120
+ ```
121
+
122
+ ### 3. Global Configuration
123
+
124
+ The `QueryClient` is pre-configured in `App.tsx` with optimized defaults (e.g., `refetchOnWindowFocus: false`).
125
+
126
+ ---
127
+
41
128
  ## 🛠 Prerequisites
42
129
 
43
130
  Before you begin, ensure you have the following installed on your machine:
44
131
 
45
- * [Node.js](https://nodejs.org/) (>= 20)
46
- * [Watchman](https://facebook.github.io/watchman/)
47
- * [Ruby](https://www.ruby-lang.org/en/) (for iOS CocoaPods)
48
- * **Android Studio** (for Android development)
49
- * **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)
50
137
 
51
138
  > **Note**: For a detailed environment setup guide, refer to the [official React Native documentation](https://reactnative.dev/docs/set-up-your-environment).
52
139
 
53
140
  ## 📦 Installation
54
141
 
55
142
  1. **Install Dependencies**:
143
+
56
144
  ```bash
57
145
  yarn install
58
146
  # OR
@@ -70,17 +158,21 @@ Before you begin, ensure you have the following installed on your machine:
70
158
  ## 🏃‍♂️ Running the App
71
159
 
72
160
  ### Start Metro Bundler
161
+
73
162
  First, start the Metro bundler in a dedicated terminal:
163
+
74
164
  ```bash
75
165
  yarn start
76
166
  ```
77
167
 
78
168
  ### Run on Android
169
+
79
170
  ```bash
80
171
  yarn android
81
172
  ```
82
173
 
83
174
  ### Run on iOS
175
+
84
176
  ```bash
85
177
  yarn ios
86
178
  ```
@@ -88,9 +180,11 @@ yarn ios
88
180
  ## 🔧 Customization
89
181
 
90
182
  ### Renaming the App
183
+
91
184
  To rename the application from "MMTemplate" to your own project name, you can use `react-native-rename` or manually rename the files.
92
185
 
93
186
  **Using `react-native-rename`:**
187
+
94
188
  1. `npx react-native-rename "YourAppName" -b com.yourcompany.yourappname`
95
189
  2. Edit `package.json` to update the name.
96
190
  3. Delete `ios/Pods` and `node_modules`.
@@ -98,11 +192,11 @@ To rename the application from "MMTemplate" to your own project name, you can us
98
192
 
99
193
  ## 📝 Scripts
100
194
 
101
- * `yarn start`: Starts the Metro Bundler.
102
- * `yarn android`: Builds and runs the Android app.
103
- * `yarn ios`: Builds and runs the iOS app.
104
- * `yarn lint`: Lints the project files.
105
- * `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.
106
200
 
107
201
  ---
108
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,9 +24,10 @@
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
- "react-native-mmkv": "^4.1.0",
26
- "react-native-nitro-modules": "^0.32.0",
29
+ "react-native-mmkv": "^4.1.2",
30
+ "react-native-nitro-modules": "^0.33.9",
27
31
  "react-native-reanimated": "^4.2.1",
28
32
  "react-native-safe-area-context": "^5.6.2",
29
33
  "react-native-screens": "^4.19.0",
@@ -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