rn-toastify 1.0.11 โ†’ 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Mukesh Prajapati
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Mukesh Prajapati
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.MD CHANGED
@@ -1,190 +1,221 @@
1
- # React Native Toastify
2
-
3
- A highly customizable and performant toast notification library for React Native. Featuring smooth animations, swipe gestures, and flexible styling options.
4
-
5
- ![Demo GIF](https://github.com/muku534/react-native-toast/blob/master/docs/Toast.gif)
6
-
7
- ---
8
-
9
- ## ๐Ÿš€ Features
10
-
11
- - **Single-root container**: Mount once at the app root.
12
- - **Imperative API**: Use `useToast` hook anywhere in your app.
13
- - **Light/Dark Theme**: System-aware with optional forced theme.
14
- - **Promise Helper**: Show loading, success, and error states.
15
- - **Customizable**: Add custom content, styles, and emojis.
16
-
17
- ---
18
-
19
- ## ๐Ÿ“ฆ Installation
20
-
21
- Install the package using npm or yarn:
22
-
23
- ```bash
24
- npm install rn-toastify
25
- ```
26
-
27
- Or:
28
-
29
- ```bash
30
- yarn add rn-toastify
31
- ```
32
-
33
- ### Peer Dependencies
34
-
35
- Ensure the following peer dependencies are installed:
36
-
37
- - `react`
38
- - `react-native`
39
- - `react-native-reanimated` (v2+)
40
- - `lottie-react-native`
41
-
42
- For iOS, run:
43
-
44
- ```bash
45
- cd ios && pod install
46
- ```
47
-
48
- ---
49
-
50
- ## ๐Ÿ› ๏ธ Quick Start
51
-
52
- ### Step 1: Mount the Toast Container
53
-
54
- Add the `ToastContainer` to your app's root component (e.g., `App.js`):
55
-
56
- ```javascript
57
- import React from 'react';
58
- import { NavigationContainer } from '@react-navigation/native';
59
- import MainNavigator from './src/navigation';
60
- import { ToastContainer } from 'rn-toastify';
61
-
62
- export default function App() {
63
- return (
64
- <>
65
- <NavigationContainer>
66
- <MainNavigator />
67
- </NavigationContainer>
68
- <ToastContainer theme="dark" /> {/* Optional: Force theme */}
69
- </>
70
- );
71
- }
72
- ```
73
-
74
- ### Step 2: Use the `useToast` Hook
75
-
76
- Call toast methods anywhere in your app:
77
-
78
- ```javascript
79
- import React from 'react';
80
- import { View, Button } from 'react-native';
81
- import useToast from 'rn-toastify';
82
-
83
- export default function HomeScreen() {
84
- const { success, error } = useToast();
85
-
86
- return (
87
- <View>
88
- <Button title="Show Success" onPress={() => success('Operation successful!')} />
89
- <Button title="Show Error" onPress={() => error('Something went wrong.', { position: 'top' })} />
90
- </View>
91
- );
92
- }
93
- ```
94
-
95
- ---
96
-
97
- ## ๐Ÿ“– API Reference
98
-
99
- ### `useToast` Hook
100
-
101
- The `useToast` hook provides the following methods:
102
-
103
- | Method | Description |
104
- |----------|--------------------------------------|
105
- | `show` | Display a custom toast. |
106
- | `success`| Show a success toast. |
107
- | `error` | Show an error toast. |
108
- | `custom` | Render a custom React element. |
109
- | `emoji` | Display a toast with an emoji. |
110
- | `promise`| Handle promise states with toasts. |
111
-
112
- ### Common Options
113
-
114
- | Option | Type | Description |
115
- |------------|----------|--------------------------------------|
116
- | `duration` | `number` | Duration in milliseconds. |
117
- | `position` | `string` | `'top' | 'bottom' | 'center'`. |
118
- | `style` | `object` | Custom styles for the toast wrapper. |
119
-
120
- ### `promise` Method Options
121
-
122
- | Option | Type | Description |
123
- |------------|----------|--------------------------------------|
124
- | `loading` | `string` | Message during loading. |
125
- | `success` | `string` | Message on success. |
126
- | `error` | `string` | Message on error. |
127
-
128
- ---
129
-
130
- ## ๐ŸŒˆ Examples
131
-
132
- ### Success Toast
133
-
134
- ```javascript
135
- const { success } = useToast();
136
- success('Operation successful!', { duration: 1500, position: 'top' });
137
- ```
138
-
139
- ### Promise Helper
140
-
141
- ```javascript
142
- const { promise } = useToast();
143
-
144
- const myPromise = fetch('/api/save');
145
-
146
- promise(myPromise, {
147
- loading: 'Savingโ€ฆ',
148
- success: 'Saved successfully!',
149
- error: 'Save failed.',
150
- });
151
- ```
152
-
153
- ### Custom Content
154
-
155
- ```javascript
156
- const { custom } = useToast();
157
- custom(<MyCustomComponent />, { duration: 2000 });
158
- ```
159
-
160
- ### Emoji Toast
161
-
162
- ```javascript
163
- const { emoji } = useToast();
164
- emoji('Great job!', '๐ŸŽ‰', { duration: 1300 });
165
- ```
166
-
167
- ---
168
-
169
- ## ๐ŸŽจ Theme Support
170
-
171
- - **Automatic**: Detects system theme (light/dark).
172
- - **Forced**: Pass `theme="light"` or `theme="dark"` to `ToastContainer`.
173
-
174
- If the system theme is unavailable, the default is `light`.
175
-
176
- ---
177
-
178
- ## ๐Ÿ› Troubleshooting
179
-
180
- ### Common Issues
181
-
182
- - **Toasts not showing**: Ensure `ToastContainer` is mounted at the app root.
183
- - **Reanimated errors**: Add the Reanimated Babel plugin and rebuild.
184
- - **Lottie issues on iOS**: Run `cd ios && pod install`.
185
-
186
- ---
187
-
188
- ## ๐Ÿ“œ License
189
-
190
- MIT License. See [LICENSE](./LICENSE) for details.
1
+ # ๐Ÿž rn-toastify
2
+
3
+ <p align="center">
4
+ <img src="./docs/demo.gif" alt="rn-toastify Demo" width="350" style="border-radius: 20px; box-shadow: 0 10px 30px rgba(0,0,0,0.2);" />
5
+ </p>
6
+
7
+ <p align="center">
8
+ <strong>A professional, production-ready toast notification library for React Native.</strong><br/>
9
+ Featuring a premium floating pill design, glassmorphic backgrounds, smooth spring animations, swipe-to-dismiss gestures, and seamless queue management.
10
+ </p>
11
+
12
+ <p align="center">
13
+ <a href="https://www.npmjs.com/package/rn-toastify"><img src="https://img.shields.io/npm/v/rn-toastify.svg?style=flat-square&color=6366F1" alt="npm version"></a>
14
+ <a href="LICENSE"><img src="https://img.shields.io/npm/l/rn-toastify.svg?style=flat-square&color=10B981" alt="license"></a>
15
+ <img src="https://img.shields.io/badge/platform-iOS%20%7C%20Android-3B82F6.svg?style=flat-square" alt="Platform">
16
+ </p>
17
+
18
+ ---
19
+
20
+ ## โœจ What's New in v2: The Premium Redesign
21
+
22
+ We completely overhauled rn-toastify to feel like a **native, premium OS feature** rather than a basic third-party library.
23
+
24
+ - ๐Ÿ’Ž **Ultra-Premium Design**: Compact "floating pill" layout with soft, multi-layered drop shadows.
25
+ - ๐Ÿชž **Glassmorphism**: Semi-transparent backgrounds that beautifully blend with your app's content in both light and dark modes.
26
+ - ๐ŸŽจ **Edge Accents**: Elegant left-edge color indicators for Success, Error, Info, and Warning states.
27
+ - ๐ŸŒŠ **Fluid Physics**: Powered by `react-native-reanimated` for 60fps spring animations and interactive pan gestures.
28
+ - ๐Ÿ“ฆ **Zero Asset Bloat**: Completely removed Lottie dependencies. All icons are now built-in, lightweight animated components.
29
+
30
+ ---
31
+
32
+ ## ๐Ÿš€ Core Features
33
+
34
+ | Feature | Description |
35
+ |---------|-------------|
36
+ | ๐ŸŽจ **6 Built-in Types** | Success, Error, Info, Warning, Loading, Emoji, plus full Custom support. |
37
+ | ๐Ÿ‘† **Interactive Swipes** | Swipe horizontally or vertically to intuitively dismiss alerts. |
38
+ | ๐Ÿ“Š **Progress Bar** | Animated, flush-to-bottom countdown indicator for auto-dismissal. |
39
+ | ๐ŸŽญ **System Theme** | Automatically adapts to Light/Dark mode, or can be forced via props. |
40
+ | ๐Ÿ“š **Smart Queue** | Set a `maxVisible` limit; excess toasts automatically queue up. |
41
+ | โณ **Promise API** | Elegant loading โ†’ success/error state management for async tasks. |
42
+ | โŒจ๏ธ **Keyboard Aware** | Bottom toasts intelligently shift up when the keyboard appears. |
43
+ | ๐Ÿ”ท **TypeScript** | Built with TS for full type safety and autocompletion. |
44
+
45
+ ---
46
+
47
+ ## ๐Ÿ“ฆ Installation
48
+
49
+ ```bash
50
+ npm install rn-toastify
51
+ ```
52
+
53
+ ```bash
54
+ yarn add rn-toastify
55
+ ```
56
+
57
+ ### Required Peer Dependency
58
+
59
+ This library relies on the amazing `react-native-reanimated` for 60fps performance.
60
+
61
+ ```bash
62
+ npm install react-native-reanimated
63
+ ```
64
+
65
+ > **Note:** Follow the [Reanimated installation guide](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/) and add the Babel plugin to your `babel.config.js`.
66
+
67
+ For iOS, don't forget to install pods:
68
+ ```bash
69
+ cd ios && pod install
70
+ ```
71
+
72
+ ---
73
+
74
+ ## ๐Ÿ Quick Start
75
+
76
+ ### Step 1: Mount the Container
77
+ Add `ToastContainer` at the very root of your app structure (e.g., in `App.js` or your main navigation wrapper).
78
+
79
+ ```jsx
80
+ import React from 'react';
81
+ import { NavigationContainer } from '@react-navigation/native';
82
+ import { ToastContainer } from 'rn-toastify';
83
+
84
+ export default function App() {
85
+ return (
86
+ <>
87
+ <NavigationContainer>
88
+ <MainNavigator />
89
+ </NavigationContainer>
90
+
91
+ {/* Mount it once at the top level */}
92
+ <ToastContainer maxVisible={3} />
93
+ </>
94
+ );
95
+ }
96
+ ```
97
+
98
+ ### Step 2: Show Toasts Anywhere!
99
+ Use the `useToast` hook inside any of your functional components.
100
+
101
+ ```jsx
102
+ import React from 'react';
103
+ import { View, TouchableOpacity, Text } from 'react-native';
104
+ import useToast from 'rn-toastify';
105
+
106
+ export default function ProfileScreen() {
107
+ const toast = useToast();
108
+
109
+ const handleSave = () => {
110
+ toast.success('Your profile changes have been saved.', {
111
+ title: 'Success!',
112
+ duration: 3500,
113
+ });
114
+ };
115
+
116
+ return (
117
+ <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
118
+ <TouchableOpacity onPress={handleSave}>
119
+ <Text>Save Profile</Text>
120
+ </TouchableOpacity>
121
+ </View>
122
+ );
123
+ }
124
+ ```
125
+
126
+ ---
127
+
128
+ ## ๐Ÿ“– API Reference
129
+
130
+ ### The `useToast()` Hook
131
+
132
+ | Method | Returns | Description |
133
+ |--------|---------|-------------|
134
+ | `success(message, options?)` | `string` (id) | Show a green success toast |
135
+ | `error(message, options?)` | `string` (id) | Show a red error toast |
136
+ | `info(message, options?)` | `string` (id) | Show a blue info toast |
137
+ | `warning(message, options?)` | `string` (id) | Show an amber warning toast |
138
+ | `emoji(message, emoji, options?)` | `string` (id) | Show a toast with a custom emoji |
139
+ | `custom(content, options?)` | `string` (id) | Render entirely custom React nodes |
140
+ | `promise(promise, messages, options?)` | `Promise` | Automatically handle async states |
141
+ | `dismiss(id)` | `void` | Dismiss a specific toast |
142
+ | `dismissAll()` | `void` | Clear the screen of all toasts |
143
+
144
+ ### Toast Options
145
+
146
+ Pass these options as the second argument to customize individual toasts:
147
+
148
+ | Option | Type | Default | Description |
149
+ |--------|------|---------|-------------|
150
+ | `title` | `string` | `undefined` | Bold title text displayed above the message |
151
+ | `duration` | `number` | `3000` | Delay in ms before auto-dismissing. Use `Infinity` to disable. |
152
+ | `position` | `'top' \| 'bottom' \| 'center'` | `'top'` | Screen positioning |
153
+
154
+ ---
155
+
156
+ ## ๐ŸŒŸ Beautiful Examples
157
+
158
+ ### Promise Handling (Async Tasks)
159
+ Let rn-toastify handle your loading, success, and error states automatically:
160
+
161
+ ```jsx
162
+ const updateProfile = fetch('/api/user', { method: 'PUT', body: data });
163
+
164
+ toast.promise(updateProfile, {
165
+ loading: 'Saving your changes...',
166
+ success: 'Changes saved successfully!',
167
+ error: 'Failed to save. Please try again.',
168
+ });
169
+ ```
170
+
171
+ ### Dynamic Promise Messages
172
+ You can pass functions to dynamically render the success/error messages based on the response:
173
+
174
+ ```jsx
175
+ toast.promise(fetchUserData(), {
176
+ loading: 'Loading profile...',
177
+ success: (user) => `Welcome back, ${user.firstName}!`,
178
+ error: (err) => `Error: ${err.message}`,
179
+ });
180
+ ```
181
+
182
+ ### Persistent Toasts
183
+ Want a toast that never goes away until the user interacts with it?
184
+
185
+ ```jsx
186
+ const id = toast.warning('Please verify your email address.', {
187
+ title: 'Action Required',
188
+ duration: Infinity,
189
+ });
190
+
191
+ // Dismiss it later via code
192
+ toast.dismiss(id);
193
+ ```
194
+
195
+ ---
196
+
197
+ ## ๐Ÿ›  ToastContainer Props
198
+
199
+ Customize global settings on the `<ToastContainer />`:
200
+
201
+ | Prop | Type | Default | Description |
202
+ |------|------|---------|-------------|
203
+ | `theme` | `'light' \| 'dark'` | system | Force a specific theme instead of following OS |
204
+ | `maxVisible` | `number` | `3` | Max number of toasts on screen (excess are queued) |
205
+ | `defaultPosition` | `'top' \| 'bottom' \| 'center'` | `'top'` | Default positioning for all toasts |
206
+ | `topOffset` | `number` | `0` | Extra padding from the top edge |
207
+ | `bottomOffset` | `number` | `0` | Extra padding from the bottom edge |
208
+
209
+ ---
210
+
211
+ ## ๐Ÿค Contributing
212
+ Contributions, issues, and feature requests are welcome!
213
+ Feel free to check the [issues page](https://github.com/muku534/react-native-toast/issues).
214
+
215
+ ## ๐Ÿ“œ License
216
+ This project is [MIT](./LICENSE) licensed.
217
+
218
+ ---
219
+ <p align="center">
220
+ <b>Crafted with โค๏ธ by <a href="https://github.com/muku534">Mukesh Prajapati</a></b>
221
+ </p>
package/babel.config.js CHANGED
@@ -1,6 +1,6 @@
1
- module.exports = {
2
- plugins: [
3
- ...
4
- 'react-native-reanimated/plugin',
5
- ],
1
+ module.exports = {
2
+ plugins: [
3
+ ...
4
+ 'react-native-reanimated/plugin',
5
+ ],
6
6
  };
package/docs/demo.gif ADDED
Binary file
package/example/App.js ADDED
@@ -0,0 +1,193 @@
1
+ /**
2
+ * rn-toastify v2.0 โ€” Example / Demo App
3
+ *
4
+ * To test this, create a new React Native project:
5
+ * npx react-native init ToastDemo
6
+ * cd ToastDemo
7
+ * npm install react-native-reanimated
8
+ *
9
+ * Then copy this file as App.js and copy/link the rn-toastify package.
10
+ */
11
+ import React from 'react';
12
+ import {
13
+ View,
14
+ Text,
15
+ TouchableOpacity,
16
+ StyleSheet,
17
+ SafeAreaView,
18
+ ScrollView,
19
+ StatusBar,
20
+ } from 'react-native';
21
+
22
+ // In a real app: import useToast, { ToastContainer } from 'rn-toastify';
23
+ const useToast = require('./index');
24
+ const { ToastContainer } = require('./index');
25
+
26
+ const BUTTON_DATA = [
27
+ {
28
+ label: 'โœ… Success Toast',
29
+ color: '#10B981',
30
+ action: (toast) =>
31
+ toast.success('Your changes have been saved successfully.', {
32
+ title: 'Success!',
33
+ duration: 3500,
34
+ }),
35
+ },
36
+ {
37
+ label: 'โŒ Error Toast',
38
+ color: '#EF4444',
39
+ action: (toast) =>
40
+ toast.error('Failed to save your changes. Please try again.', {
41
+ title: 'Something went wrong',
42
+ duration: 4000,
43
+ }),
44
+ },
45
+ {
46
+ label: 'โ„น๏ธ Info Toast',
47
+ color: '#3B82F6',
48
+ action: (toast) =>
49
+ toast.info('Version 2.0 is now available for download.', {
50
+ title: 'Update Available',
51
+ duration: 3500,
52
+ }),
53
+ },
54
+ {
55
+ label: 'โš ๏ธ Warning Toast',
56
+ color: '#F59E0B',
57
+ action: (toast) =>
58
+ toast.warning('Only 2 GB of storage remaining on your device.', {
59
+ title: 'Low Storage',
60
+ duration: 3500,
61
+ }),
62
+ },
63
+ {
64
+ label: 'โณ Loading Toast',
65
+ color: '#6366F1',
66
+ action: (toast) => {
67
+ const id = toast.show(
68
+ React.createElement(
69
+ require('./src/components/LoadingToast').default,
70
+ { message: 'Processing your request...' }
71
+ ),
72
+ { duration: Infinity }
73
+ );
74
+ setTimeout(() => toast.dismiss(id), 3000);
75
+ },
76
+ },
77
+ {
78
+ label: '๐ŸŽ‰ Emoji Toast',
79
+ color: '#8B5CF6',
80
+ action: (toast) =>
81
+ toast.emoji('You completed the onboarding tutorial!', '๐ŸŽ‰', {
82
+ title: 'Achievement Unlocked',
83
+ duration: 4000,
84
+ }),
85
+ },
86
+ {
87
+ label: '๐Ÿ”„ Promise Toast',
88
+ color: '#EC4899',
89
+ action: (toast) => {
90
+ const fakePromise = new Promise((resolve) =>
91
+ setTimeout(() => resolve({ name: 'Mukesh' }), 2000)
92
+ );
93
+ toast.promise(fakePromise, {
94
+ loading: 'Saving your profile...',
95
+ success: 'Profile saved successfully!',
96
+ error: 'Failed to save profile.',
97
+ });
98
+ },
99
+ },
100
+ {
101
+ label: '๐Ÿ“Œ Message Only (no title)',
102
+ color: '#6B7280',
103
+ action: (toast) =>
104
+ toast.success('This toast has no title โ€” just a message.', {
105
+ duration: 3000,
106
+ }),
107
+ },
108
+ {
109
+ label: 'โฌ‡๏ธ Bottom Position',
110
+ color: '#0EA5E9',
111
+ action: (toast) =>
112
+ toast.info('This appears at the bottom!', {
113
+ title: 'Bottom Toast',
114
+ position: 'bottom',
115
+ duration: 3000,
116
+ }),
117
+ },
118
+ {
119
+ label: '๐Ÿงน Dismiss All',
120
+ color: '#374151',
121
+ action: (toast) => toast.dismissAll(),
122
+ },
123
+ ];
124
+
125
+ const ExampleApp = () => {
126
+ const toast = useToast();
127
+
128
+ return (
129
+ <>
130
+ <StatusBar barStyle="dark-content" />
131
+ <SafeAreaView style={styles.safe}>
132
+ <ScrollView contentContainerStyle={styles.scrollContent}>
133
+ <Text style={styles.heading}>๐Ÿž rn-toastify</Text>
134
+ <Text style={styles.subheading}>v2.0 โ€” Demo</Text>
135
+ <View style={styles.grid}>
136
+ {BUTTON_DATA.map((btn, i) => (
137
+ <TouchableOpacity
138
+ key={i}
139
+ style={[styles.button, { backgroundColor: btn.color }]}
140
+ activeOpacity={0.8}
141
+ onPress={() => btn.action(toast)}
142
+ >
143
+ <Text style={styles.buttonText}>{btn.label}</Text>
144
+ </TouchableOpacity>
145
+ ))}
146
+ </View>
147
+ </ScrollView>
148
+ </SafeAreaView>
149
+ <ToastContainer theme="light" maxVisible={3} />
150
+ </>
151
+ );
152
+ };
153
+
154
+ const styles = StyleSheet.create({
155
+ safe: {
156
+ flex: 1,
157
+ backgroundColor: '#F9FAFB',
158
+ },
159
+ scrollContent: {
160
+ padding: 24,
161
+ paddingTop: 40,
162
+ },
163
+ heading: {
164
+ fontSize: 32,
165
+ fontWeight: '800',
166
+ color: '#111827',
167
+ textAlign: 'center',
168
+ },
169
+ subheading: {
170
+ fontSize: 16,
171
+ fontWeight: '500',
172
+ color: '#6B7280',
173
+ textAlign: 'center',
174
+ marginTop: 4,
175
+ marginBottom: 32,
176
+ },
177
+ grid: {
178
+ gap: 12,
179
+ },
180
+ button: {
181
+ paddingVertical: 16,
182
+ paddingHorizontal: 20,
183
+ borderRadius: 12,
184
+ alignItems: 'center',
185
+ },
186
+ buttonText: {
187
+ fontSize: 16,
188
+ fontWeight: '600',
189
+ color: '#FFFFFF',
190
+ },
191
+ });
192
+
193
+ export default ExampleApp;