@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.
- package/MMTemplate/.eslintrc.js +95 -1
- package/MMTemplate/.husky/pre-commit +2 -0
- package/MMTemplate/.prettierrc.js +2 -0
- package/MMTemplate/App.tsx +27 -21
- package/MMTemplate/README.md +76 -35
- package/MMTemplate/__tests__/App.test.tsx +5 -3
- package/MMTemplate/babel.config.js +24 -1
- package/MMTemplate/index.js +1 -0
- package/MMTemplate/package.json +22 -2
- package/MMTemplate/src/components/AnimationView.tsx +54 -69
- package/MMTemplate/src/components/AppText.tsx +7 -4
- package/MMTemplate/src/components/CustomAlert.tsx +203 -0
- package/MMTemplate/src/components/CustomToast.tsx +2 -1
- package/MMTemplate/src/components/ErrorBoundaryFallback.tsx +127 -0
- package/MMTemplate/src/components/FeatureItem.tsx +8 -6
- package/MMTemplate/src/components/FullScreenContainer.tsx +9 -7
- package/MMTemplate/src/components/InfoCard.tsx +8 -6
- package/MMTemplate/src/components/LanguageSwitcher.tsx +8 -6
- package/MMTemplate/src/components/TextInput.tsx +25 -15
- package/MMTemplate/src/components/ThemeSwitcher.tsx +4 -3
- package/MMTemplate/src/context/AuthContext.tsx +5 -4
- package/MMTemplate/src/context/ThemeContext.tsx +10 -19
- package/MMTemplate/src/locales/en.json +4 -1
- package/MMTemplate/src/locales/hi.json +4 -1
- package/MMTemplate/src/navigation/AppNavigator.tsx +7 -8
- package/MMTemplate/src/navigation/AppStack.tsx +6 -6
- package/MMTemplate/src/navigation/AuthCheck.tsx +11 -10
- package/MMTemplate/src/navigation/AuthStack.tsx +6 -4
- package/MMTemplate/src/navigation/MainTab.tsx +19 -13
- package/MMTemplate/src/screens/AddNoteScreen.tsx +20 -14
- package/MMTemplate/src/screens/HomeScreen.tsx +21 -15
- package/MMTemplate/src/screens/LoginScreen.tsx +21 -18
- package/MMTemplate/src/screens/NoteScreen.tsx +18 -16
- package/MMTemplate/src/screens/ProfileScreen.tsx +16 -13
- package/MMTemplate/src/screens/SettingsScreen.tsx +14 -11
- package/MMTemplate/src/screens/WelcomeScreen.tsx +19 -13
- package/MMTemplate/src/services/axiosInstance.ts +7 -5
- package/MMTemplate/src/services/note.query.ts +7 -5
- package/MMTemplate/src/theme/{Colors.ts → colors.ts} +6 -0
- package/MMTemplate/src/types/components.types.ts +38 -0
- package/MMTemplate/src/types/navigation.types.ts +1 -1
- package/MMTemplate/src/utils/i18n.ts +8 -6
- package/MMTemplate/src/utils/navigationUtils.ts +2 -1
- package/MMTemplate/src/utils/storageHelper.ts +8 -8
- package/MMTemplate/src/utils/utilsHelper.ts +1 -0
- package/MMTemplate/tsconfig.json +27 -0
- package/README.md +3 -1
- package/package.json +1 -1
package/MMTemplate/.eslintrc.js
CHANGED
|
@@ -1,4 +1,98 @@
|
|
|
1
1
|
module.exports = {
|
|
2
2
|
root: true,
|
|
3
|
-
extends:
|
|
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
|
};
|
package/MMTemplate/App.tsx
CHANGED
|
@@ -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
|
-
|
|
11
|
-
import {
|
|
12
|
-
import '
|
|
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
|
-
<
|
|
40
|
-
<
|
|
41
|
-
<
|
|
42
|
-
<
|
|
43
|
-
<
|
|
44
|
-
<
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
|
package/MMTemplate/README.md
CHANGED
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
|
45
|
-
|
|
|
46
|
-
| **`assets/`**
|
|
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/`**
|
|
49
|
-
| **`locales/`**
|
|
50
|
-
| **`mock/`**
|
|
51
|
-
| **`navigation/`** | `src/navigation/` | Contains all navigation-related configuration.
|
|
52
|
-
| **`screens/`**
|
|
53
|
-
| **`services/`**
|
|
54
|
-
| **`theme/`**
|
|
55
|
-
| **`types/`**
|
|
56
|
-
| **`utils/`**
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
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
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
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
|
-
|
|
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
|
|
11
|
-
|
|
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: [
|
|
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
|
};
|
package/MMTemplate/index.js
CHANGED
package/MMTemplate/package.json
CHANGED
|
@@ -6,8 +6,11 @@
|
|
|
6
6
|
"android": "react-native run-android",
|
|
7
7
|
"ios": "react-native run-ios",
|
|
8
8
|
"lint": "eslint .",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
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
|
-
|
|
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
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
49
|
+
transform: [{ rotate: animValue.value + 'deg' }],
|
|
62
50
|
};
|
|
63
51
|
case 'SlideInDown':
|
|
64
52
|
return {
|
|
65
|
-
transform: [{ translateY:
|
|
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
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
|