@selimh/react-native-toast 0.2.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 +20 -0
- package/README.md +98 -0
- package/lib/module/Toast.js +181 -0
- package/lib/module/Toast.js.map +1 -0
- package/lib/module/ToastProvider.js +56 -0
- package/lib/module/ToastProvider.js.map +1 -0
- package/lib/module/icons.js +59 -0
- package/lib/module/icons.js.map +1 -0
- package/lib/module/index.js +7 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/Toast.d.ts +4 -0
- package/lib/typescript/src/Toast.d.ts.map +1 -0
- package/lib/typescript/src/ToastProvider.d.ts +9 -0
- package/lib/typescript/src/ToastProvider.d.ts.map +1 -0
- package/lib/typescript/src/icons.d.ts +5 -0
- package/lib/typescript/src/icons.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +5 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +33 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +169 -0
- package/src/Toast.tsx +215 -0
- package/src/ToastProvider.tsx +67 -0
- package/src/icons.tsx +52 -0
- package/src/index.tsx +4 -0
- package/src/types.ts +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Selim Hamzaoğulları
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# react-native-toast
|
|
2
|
+
|
|
3
|
+
A beautifully animated, highly customizable, and imperative Toast library for React Native based on `react-native-reanimated`.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install react-native-toast
|
|
11
|
+
# or
|
|
12
|
+
yarn add react-native-toast
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
You also need to install the peer dependencies:
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
yarn add react-native-reanimated react-native-safe-area-context
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> **Note:** Make sure to follow the installation instructions for `react-native-reanimated` (e.g., adding the babel plugin) and `react-native-safe-area-context`.
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
1. Wrap your root directory with `ToastProvider`:
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { ToastProvider } from 'react-native-toast';
|
|
29
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
30
|
+
|
|
31
|
+
export default function App() {
|
|
32
|
+
return (
|
|
33
|
+
<SafeAreaProvider>
|
|
34
|
+
{/*
|
|
35
|
+
theme can be 'light', 'dark', or 'system' (default: 'system')
|
|
36
|
+
It will automatically detect user's device preferences.
|
|
37
|
+
*/}
|
|
38
|
+
<ToastProvider theme="system">
|
|
39
|
+
{/* Your app components */}
|
|
40
|
+
</ToastProvider>
|
|
41
|
+
</SafeAreaProvider>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
2. Call `Toast.show` from anywhere in your app:
|
|
47
|
+
|
|
48
|
+
```tsx
|
|
49
|
+
import { Toast } from 'react-native-toast';
|
|
50
|
+
|
|
51
|
+
Toast.show({
|
|
52
|
+
type: 'success',
|
|
53
|
+
text1: 'Hello',
|
|
54
|
+
text2: 'This is an awesome toast',
|
|
55
|
+
position: 'top',
|
|
56
|
+
visibilityTime: 4000,
|
|
57
|
+
});
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Dark Mode (Theme) Support
|
|
61
|
+
`react-native-toast` perfectly supports light and dark modes out of the box.
|
|
62
|
+
|
|
63
|
+
1. **System Dependant (Default):** If you pass `theme="system"` to `ToastProvider` or omit it, the toast will automatically adapt to the user's iOS/Android theme.
|
|
64
|
+
2. **Forced Theme:** You can override the theme dynamically on a per-toast basis:
|
|
65
|
+
```tsx
|
|
66
|
+
Toast.show({
|
|
67
|
+
type: 'info',
|
|
68
|
+
theme: 'dark', // 'light' | 'dark' | 'system'
|
|
69
|
+
text1: 'Always Dark',
|
|
70
|
+
});
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## APIs
|
|
74
|
+
|
|
75
|
+
### `Toast.show(options: ToastOptions)`
|
|
76
|
+
|
|
77
|
+
| Option | Type | Default | Description |
|
|
78
|
+
| --- | --- | --- | --- |
|
|
79
|
+
| `type` | `'success' \| 'error' \| 'info' \| 'warning'` | `'info'` | Type of the toast |
|
|
80
|
+
| `text1` | `string` | `undefined` | Primary text |
|
|
81
|
+
| `text2` | `string` | `undefined` | Secondary description |
|
|
82
|
+
| `position` | `'top' \| 'bottom'` | `'top'` | Position of the toast |
|
|
83
|
+
| `theme` | `'light' \| 'dark' \| 'system'` | `'system'` | Toast visual theme |
|
|
84
|
+
| `visibilityTime` | `number` | `3000` | Duration in ms |
|
|
85
|
+
| `topOffset` | `number` | `40` | Offset from top edge |
|
|
86
|
+
| `bottomOffset` | `number` | `40` | Offset from bottom edge |
|
|
87
|
+
| `autoHide` | `boolean` | `true` | If false, toast will not hide automatically |
|
|
88
|
+
| `customView` | `React.ReactNode` | `undefined` | Render a completely custom component |
|
|
89
|
+
| `onPress` | `() => void` | `undefined` | Called when toast is tapped |
|
|
90
|
+
| `onShow` | `() => void` | `undefined` | Called when animation finishes showing |
|
|
91
|
+
| `onHide` | `() => void` | `undefined` | Called when animation finishes hiding |
|
|
92
|
+
|
|
93
|
+
### `Toast.hide()`
|
|
94
|
+
Hides the currently visible toast.
|
|
95
|
+
|
|
96
|
+
## License
|
|
97
|
+
|
|
98
|
+
MIT
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useEffect } from 'react';
|
|
4
|
+
import { StyleSheet, Text, View, TouchableOpacity, useColorScheme } from 'react-native';
|
|
5
|
+
import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, runOnJS } from 'react-native-reanimated';
|
|
6
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
7
|
+
import { SuccessIcon, ErrorIcon, InfoIcon, WarningIcon } from "./icons.js";
|
|
8
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
9
|
+
export const Toast = ({
|
|
10
|
+
isVisible,
|
|
11
|
+
type = 'info',
|
|
12
|
+
text1,
|
|
13
|
+
text2,
|
|
14
|
+
position = 'top',
|
|
15
|
+
topOffset = 10,
|
|
16
|
+
bottomOffset = 10,
|
|
17
|
+
theme,
|
|
18
|
+
providerTheme = 'system',
|
|
19
|
+
onPress,
|
|
20
|
+
onAnimationEnd,
|
|
21
|
+
customView
|
|
22
|
+
}) => {
|
|
23
|
+
const insets = useSafeAreaInsets();
|
|
24
|
+
const systemTheme = useColorScheme();
|
|
25
|
+
const activeTheme = theme && theme !== 'system' ? theme : providerTheme !== 'system' ? providerTheme : systemTheme;
|
|
26
|
+
const isDark = activeTheme === 'dark';
|
|
27
|
+
const translateY = useSharedValue(position === 'top' ? -150 : 150);
|
|
28
|
+
const opacity = useSharedValue(0);
|
|
29
|
+
useEffect(() => {
|
|
30
|
+
if (isVisible) {
|
|
31
|
+
// Reset position instantly before starting the animation
|
|
32
|
+
translateY.value = position === 'top' ? -150 : 150;
|
|
33
|
+
opacity.value = withTiming(1, {
|
|
34
|
+
duration: 300
|
|
35
|
+
});
|
|
36
|
+
translateY.value = withSpring(0, {
|
|
37
|
+
damping: 40,
|
|
38
|
+
stiffness: 250
|
|
39
|
+
}, finished => {
|
|
40
|
+
if (finished && onAnimationEnd) {
|
|
41
|
+
runOnJS(onAnimationEnd)(true);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
} else {
|
|
45
|
+
opacity.value = withTiming(0, {
|
|
46
|
+
duration: 300
|
|
47
|
+
});
|
|
48
|
+
translateY.value = withTiming(position === 'top' ? -150 : 150, {
|
|
49
|
+
duration: 300
|
|
50
|
+
}, finished => {
|
|
51
|
+
if (finished && onAnimationEnd) {
|
|
52
|
+
runOnJS(onAnimationEnd)(false);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}, [isVisible, opacity, translateY, position, onAnimationEnd]);
|
|
57
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
58
|
+
return {
|
|
59
|
+
opacity: opacity.value,
|
|
60
|
+
transform: [{
|
|
61
|
+
translateY: translateY.value
|
|
62
|
+
}]
|
|
63
|
+
};
|
|
64
|
+
});
|
|
65
|
+
const getIcon = () => {
|
|
66
|
+
switch (type) {
|
|
67
|
+
case 'success':
|
|
68
|
+
return /*#__PURE__*/_jsx(SuccessIcon, {});
|
|
69
|
+
case 'error':
|
|
70
|
+
return /*#__PURE__*/_jsx(ErrorIcon, {});
|
|
71
|
+
case 'warning':
|
|
72
|
+
return /*#__PURE__*/_jsx(WarningIcon, {});
|
|
73
|
+
case 'info':
|
|
74
|
+
default:
|
|
75
|
+
return /*#__PURE__*/_jsx(InfoIcon, {});
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
const getContainerStyle = () => {
|
|
79
|
+
const isTop = position === 'top';
|
|
80
|
+
return [styles.container, isTop ? {
|
|
81
|
+
top: insets.top + topOffset
|
|
82
|
+
} : {
|
|
83
|
+
bottom: insets.bottom + bottomOffset
|
|
84
|
+
}, animatedStyle];
|
|
85
|
+
};
|
|
86
|
+
const contentStyle = [styles.content, isDark ? styles.contentDark : styles.contentLight];
|
|
87
|
+
const text1Style = [styles.text1, isDark ? styles.text1Dark : styles.text1Light];
|
|
88
|
+
const text2Style = [styles.text2, isDark ? styles.text2Dark : styles.text2Light];
|
|
89
|
+
return /*#__PURE__*/_jsx(Animated.View, {
|
|
90
|
+
// @ts-ignore - TS2589 bypass
|
|
91
|
+
style: getContainerStyle(),
|
|
92
|
+
pointerEvents: isVisible ? 'box-none' : 'none',
|
|
93
|
+
children: /*#__PURE__*/_jsx(TouchableOpacity, {
|
|
94
|
+
activeOpacity: 0.9,
|
|
95
|
+
onPress: onPress,
|
|
96
|
+
disabled: !onPress,
|
|
97
|
+
style: customView ? styles.customContent : contentStyle,
|
|
98
|
+
children: customView ? customView : /*#__PURE__*/_jsxs(_Fragment, {
|
|
99
|
+
children: [/*#__PURE__*/_jsx(View, {
|
|
100
|
+
style: styles.iconContainer,
|
|
101
|
+
children: getIcon()
|
|
102
|
+
}), /*#__PURE__*/_jsxs(View, {
|
|
103
|
+
style: styles.textContainer,
|
|
104
|
+
children: [text1 && /*#__PURE__*/_jsx(Text, {
|
|
105
|
+
style: text1Style,
|
|
106
|
+
children: text1
|
|
107
|
+
}), text2 && /*#__PURE__*/_jsx(Text, {
|
|
108
|
+
style: text2Style,
|
|
109
|
+
children: text2
|
|
110
|
+
})]
|
|
111
|
+
})]
|
|
112
|
+
})
|
|
113
|
+
})
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
const styles = StyleSheet.create({
|
|
117
|
+
container: {
|
|
118
|
+
position: 'absolute',
|
|
119
|
+
left: 16,
|
|
120
|
+
right: 16,
|
|
121
|
+
zIndex: 9999,
|
|
122
|
+
alignItems: 'center'
|
|
123
|
+
},
|
|
124
|
+
customContent: {
|
|
125
|
+
width: '100%',
|
|
126
|
+
maxWidth: 400
|
|
127
|
+
},
|
|
128
|
+
content: {
|
|
129
|
+
flexDirection: 'row',
|
|
130
|
+
borderRadius: 12,
|
|
131
|
+
padding: 16,
|
|
132
|
+
width: '100%',
|
|
133
|
+
shadowOffset: {
|
|
134
|
+
width: 0,
|
|
135
|
+
height: 4
|
|
136
|
+
},
|
|
137
|
+
shadowOpacity: 0.1,
|
|
138
|
+
shadowRadius: 12,
|
|
139
|
+
elevation: 5,
|
|
140
|
+
alignItems: 'center',
|
|
141
|
+
maxWidth: 400
|
|
142
|
+
},
|
|
143
|
+
contentLight: {
|
|
144
|
+
backgroundColor: '#ffffff',
|
|
145
|
+
shadowColor: '#000'
|
|
146
|
+
},
|
|
147
|
+
contentDark: {
|
|
148
|
+
backgroundColor: '#1f2937',
|
|
149
|
+
shadowColor: '#000',
|
|
150
|
+
borderWidth: 1,
|
|
151
|
+
borderColor: '#374151'
|
|
152
|
+
},
|
|
153
|
+
iconContainer: {
|
|
154
|
+
marginRight: 12
|
|
155
|
+
},
|
|
156
|
+
textContainer: {
|
|
157
|
+
flex: 1,
|
|
158
|
+
justifyContent: 'center'
|
|
159
|
+
},
|
|
160
|
+
text1: {
|
|
161
|
+
fontSize: 15,
|
|
162
|
+
fontWeight: '600',
|
|
163
|
+
marginBottom: 4
|
|
164
|
+
},
|
|
165
|
+
text1Light: {
|
|
166
|
+
color: '#1f2937'
|
|
167
|
+
},
|
|
168
|
+
text1Dark: {
|
|
169
|
+
color: '#f9fafb'
|
|
170
|
+
},
|
|
171
|
+
text2: {
|
|
172
|
+
fontSize: 13
|
|
173
|
+
},
|
|
174
|
+
text2Light: {
|
|
175
|
+
color: '#6b7280'
|
|
176
|
+
},
|
|
177
|
+
text2Dark: {
|
|
178
|
+
color: '#9ca3af'
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
//# sourceMappingURL=Toast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useEffect","StyleSheet","Text","View","TouchableOpacity","useColorScheme","Animated","useSharedValue","useAnimatedStyle","withSpring","withTiming","runOnJS","useSafeAreaInsets","SuccessIcon","ErrorIcon","InfoIcon","WarningIcon","jsx","_jsx","jsxs","_jsxs","Fragment","_Fragment","Toast","isVisible","type","text1","text2","position","topOffset","bottomOffset","theme","providerTheme","onPress","onAnimationEnd","customView","insets","systemTheme","activeTheme","isDark","translateY","opacity","value","duration","damping","stiffness","finished","animatedStyle","transform","getIcon","getContainerStyle","isTop","styles","container","top","bottom","contentStyle","content","contentDark","contentLight","text1Style","text1Dark","text1Light","text2Style","text2Dark","text2Light","style","pointerEvents","children","activeOpacity","disabled","customContent","iconContainer","textContainer","create","left","right","zIndex","alignItems","width","maxWidth","flexDirection","borderRadius","padding","shadowOffset","height","shadowOpacity","shadowRadius","elevation","backgroundColor","shadowColor","borderWidth","borderColor","marginRight","flex","justifyContent","fontSize","fontWeight","marginBottom","color"],"sourceRoot":"../../src","sources":["Toast.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
|
4
|
+
import { Toast } from "./Toast.js";
|
|
5
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
6
|
+
export const ToastRefWrapper = /*#__PURE__*/React.createRef();
|
|
7
|
+
export const ToastProvider = ({
|
|
8
|
+
children,
|
|
9
|
+
theme = 'system'
|
|
10
|
+
}) => {
|
|
11
|
+
const [options, setOptions] = useState({});
|
|
12
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
13
|
+
const hideTimeoutRef = useRef(null);
|
|
14
|
+
const show = useCallback(opts => {
|
|
15
|
+
setOptions(opts);
|
|
16
|
+
setIsVisible(true);
|
|
17
|
+
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
18
|
+
const autoHide = opts.autoHide ?? true;
|
|
19
|
+
const visibilityTime = opts.visibilityTime ?? 3000;
|
|
20
|
+
if (autoHide) {
|
|
21
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
22
|
+
setIsVisible(false);
|
|
23
|
+
}, visibilityTime);
|
|
24
|
+
}
|
|
25
|
+
}, []);
|
|
26
|
+
const hide = useCallback(() => {
|
|
27
|
+
setIsVisible(false);
|
|
28
|
+
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
29
|
+
}, []);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
ToastRefWrapper.current = {
|
|
32
|
+
show,
|
|
33
|
+
hide
|
|
34
|
+
};
|
|
35
|
+
}, [show, hide]);
|
|
36
|
+
const onAnimationEnd = useCallback(visible => {
|
|
37
|
+
if (!visible) {
|
|
38
|
+
options.onHide?.();
|
|
39
|
+
} else {
|
|
40
|
+
options.onShow?.();
|
|
41
|
+
}
|
|
42
|
+
}, [options]);
|
|
43
|
+
return /*#__PURE__*/_jsxs(_Fragment, {
|
|
44
|
+
children: [children, /*#__PURE__*/_jsx(Toast, {
|
|
45
|
+
...options,
|
|
46
|
+
isVisible: isVisible,
|
|
47
|
+
onAnimationEnd: onAnimationEnd,
|
|
48
|
+
providerTheme: theme
|
|
49
|
+
})]
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
export const ToastService = {
|
|
53
|
+
show: options => ToastRefWrapper.current?.show(options),
|
|
54
|
+
hide: () => ToastRefWrapper.current?.hide()
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=ToastProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","useState","useCallback","useRef","useEffect","Toast","jsx","_jsx","Fragment","_Fragment","jsxs","_jsxs","ToastRefWrapper","createRef","ToastProvider","children","theme","options","setOptions","isVisible","setIsVisible","hideTimeoutRef","show","opts","current","clearTimeout","autoHide","visibilityTime","setTimeout","hide","onAnimationEnd","visible","onHide","onShow","providerTheme","ToastService"],"sourceRoot":"../../src","sources":["ToastProvider.tsx"],"mappings":";;AAAA,OAAOA,KAAK,IAAIC,QAAQ,EAAEC,WAAW,EAAEC,MAAM,EAAEC,SAAS,QAAQ,OAAO;AACvE,SAASC,KAAK,QAAQ,YAAS;AAAC,SAAAC,GAAA,IAAAC,IAAA,EAAAC,QAAA,IAAAC,SAAA,EAAAC,IAAA,IAAAC,KAAA;AAGhC,OAAO,MAAMC,eAAe,gBAAGZ,KAAK,CAACa,SAAS,CAAW,CAAC;AAE1D,OAAO,MAAMC,aAAa,GAAGA,CAAC;EAC5BC,QAAQ;EACRC,KAAK,GAAG;AACU,CAAC,KAAK;EACxB,MAAM,CAACC,OAAO,EAAEC,UAAU,CAAC,GAAGjB,QAAQ,CAAe,CAAC,CAAC,CAAC;EACxD,MAAM,CAACkB,SAAS,EAAEC,YAAY,CAAC,GAAGnB,QAAQ,CAAC,KAAK,CAAC;EACjD,MAAMoB,cAAc,GAAGlB,MAAM,CAAwB,IAAI,CAAC;EAE1D,MAAMmB,IAAI,GAAGpB,WAAW,CAAEqB,IAAkB,IAAK;IAC/CL,UAAU,CAACK,IAAI,CAAC;IAChBH,YAAY,CAAC,IAAI,CAAC;IAElB,IAAIC,cAAc,CAACG,OAAO,EAAEC,YAAY,CAACJ,cAAc,CAACG,OAAO,CAAC;IAEhE,MAAME,QAAQ,GAAGH,IAAI,CAACG,QAAQ,IAAI,IAAI;IACtC,MAAMC,cAAc,GAAGJ,IAAI,CAACI,cAAc,IAAI,IAAI;IAElD,IAAID,QAAQ,EAAE;MACZL,cAAc,CAACG,OAAO,GAAGI,UAAU,CAAC,MAAM;QACxCR,YAAY,CAAC,KAAK,CAAC;MACrB,CAAC,EAAEO,cAAc,CAAC;IACpB;EACF,CAAC,EAAE,EAAE,CAAC;EAEN,MAAME,IAAI,GAAG3B,WAAW,CAAC,MAAM;IAC7BkB,YAAY,CAAC,KAAK,CAAC;IACnB,IAAIC,cAAc,CAACG,OAAO,EAAEC,YAAY,CAACJ,cAAc,CAACG,OAAO,CAAC;EAClE,CAAC,EAAE,EAAE,CAAC;EAENpB,SAAS,CAAC,MAAM;IACbQ,eAAe,CAASY,OAAO,GAAG;MAAEF,IAAI;MAAEO;IAAK,CAAC;EACnD,CAAC,EAAE,CAACP,IAAI,EAAEO,IAAI,CAAC,CAAC;EAEhB,MAAMC,cAAc,GAAG5B,WAAW,CAC/B6B,OAAgB,IAAK;IACpB,IAAI,CAACA,OAAO,EAAE;MACZd,OAAO,CAACe,MAAM,GAAG,CAAC;IACpB,CAAC,MAAM;MACLf,OAAO,CAACgB,MAAM,GAAG,CAAC;IACpB;EACF,CAAC,EACD,CAAChB,OAAO,CACV,CAAC;EAED,oBACEN,KAAA,CAAAF,SAAA;IAAAM,QAAA,GACGA,QAAQ,eACTR,IAAA,CAACF,KAAK;MAAA,GACAY,OAAO;MACXE,SAAS,EAAEA,SAAU;MACrBW,cAAc,EAAEA,cAAe;MAC/BI,aAAa,EAAElB;IAAM,CACtB,CAAC;EAAA,CACF,CAAC;AAEP,CAAC;AAED,OAAO,MAAMmB,YAAY,GAAG;EAC1Bb,IAAI,EAAGL,OAAqB,IAAKL,eAAe,CAACY,OAAO,EAAEF,IAAI,CAACL,OAAO,CAAC;EACvEY,IAAI,EAAEA,CAAA,KAAMjB,eAAe,CAACY,OAAO,EAAEK,IAAI,CAAC;AAC5C,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { Text, View, StyleSheet } from 'react-native';
|
|
4
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
5
|
+
export const SuccessIcon = () => /*#__PURE__*/_jsx(View, {
|
|
6
|
+
style: [styles.container, styles.success],
|
|
7
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
8
|
+
style: styles.icon,
|
|
9
|
+
children: "\u2713"
|
|
10
|
+
})
|
|
11
|
+
});
|
|
12
|
+
export const ErrorIcon = () => /*#__PURE__*/_jsx(View, {
|
|
13
|
+
style: [styles.container, styles.error],
|
|
14
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
15
|
+
style: styles.icon,
|
|
16
|
+
children: "\u2715"
|
|
17
|
+
})
|
|
18
|
+
});
|
|
19
|
+
export const InfoIcon = () => /*#__PURE__*/_jsx(View, {
|
|
20
|
+
style: [styles.container, styles.info],
|
|
21
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
22
|
+
style: styles.icon,
|
|
23
|
+
children: "i"
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
export const WarningIcon = () => /*#__PURE__*/_jsx(View, {
|
|
27
|
+
style: [styles.container, styles.warning],
|
|
28
|
+
children: /*#__PURE__*/_jsx(Text, {
|
|
29
|
+
style: styles.icon,
|
|
30
|
+
children: "!"
|
|
31
|
+
})
|
|
32
|
+
});
|
|
33
|
+
const styles = StyleSheet.create({
|
|
34
|
+
container: {
|
|
35
|
+
width: 24,
|
|
36
|
+
height: 24,
|
|
37
|
+
borderRadius: 12,
|
|
38
|
+
justifyContent: 'center',
|
|
39
|
+
alignItems: 'center'
|
|
40
|
+
},
|
|
41
|
+
icon: {
|
|
42
|
+
color: '#fff',
|
|
43
|
+
fontSize: 14,
|
|
44
|
+
fontWeight: 'bold'
|
|
45
|
+
},
|
|
46
|
+
success: {
|
|
47
|
+
backgroundColor: '#4ade80'
|
|
48
|
+
},
|
|
49
|
+
error: {
|
|
50
|
+
backgroundColor: '#f87171'
|
|
51
|
+
},
|
|
52
|
+
info: {
|
|
53
|
+
backgroundColor: '#60a5fa'
|
|
54
|
+
},
|
|
55
|
+
warning: {
|
|
56
|
+
backgroundColor: '#fbbf24'
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
//# sourceMappingURL=icons.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Text","View","StyleSheet","jsx","_jsx","SuccessIcon","style","styles","container","success","children","icon","ErrorIcon","error","InfoIcon","info","WarningIcon","warning","create","width","height","borderRadius","justifyContent","alignItems","color","fontSize","fontWeight","backgroundColor"],"sourceRoot":"../../src","sources":["icons.tsx"],"mappings":";;AAAA,SAASA,IAAI,EAAEC,IAAI,EAAEC,UAAU,QAAQ,cAAc;AAAC,SAAAC,GAAA,IAAAC,IAAA;AAEtD,OAAO,MAAMC,WAAW,GAAGA,CAAA,kBACzBD,IAAA,CAACH,IAAI;EAACK,KAAK,EAAE,CAACC,MAAM,CAACC,SAAS,EAAED,MAAM,CAACE,OAAO,CAAE;EAAAC,QAAA,eAC9CN,IAAA,CAACJ,IAAI;IAACM,KAAK,EAAEC,MAAM,CAACI,IAAK;IAAAD,QAAA,EAAC;EAAC,CAAM;AAAC,CAC9B,CACP;AAED,OAAO,MAAME,SAAS,GAAGA,CAAA,kBACvBR,IAAA,CAACH,IAAI;EAACK,KAAK,EAAE,CAACC,MAAM,CAACC,SAAS,EAAED,MAAM,CAACM,KAAK,CAAE;EAAAH,QAAA,eAC5CN,IAAA,CAACJ,IAAI;IAACM,KAAK,EAAEC,MAAM,CAACI,IAAK;IAAAD,QAAA,EAAC;EAAC,CAAM;AAAC,CAC9B,CACP;AAED,OAAO,MAAMI,QAAQ,GAAGA,CAAA,kBACtBV,IAAA,CAACH,IAAI;EAACK,KAAK,EAAE,CAACC,MAAM,CAACC,SAAS,EAAED,MAAM,CAACQ,IAAI,CAAE;EAAAL,QAAA,eAC3CN,IAAA,CAACJ,IAAI;IAACM,KAAK,EAAEC,MAAM,CAACI,IAAK;IAAAD,QAAA,EAAC;EAAC,CAAM;AAAC,CAC9B,CACP;AAED,OAAO,MAAMM,WAAW,GAAGA,CAAA,kBACzBZ,IAAA,CAACH,IAAI;EAACK,KAAK,EAAE,CAACC,MAAM,CAACC,SAAS,EAAED,MAAM,CAACU,OAAO,CAAE;EAAAP,QAAA,eAC9CN,IAAA,CAACJ,IAAI;IAACM,KAAK,EAAEC,MAAM,CAACI,IAAK;IAAAD,QAAA,EAAC;EAAC,CAAM;AAAC,CAC9B,CACP;AAED,MAAMH,MAAM,GAAGL,UAAU,CAACgB,MAAM,CAAC;EAC/BV,SAAS,EAAE;IACTW,KAAK,EAAE,EAAE;IACTC,MAAM,EAAE,EAAE;IACVC,YAAY,EAAE,EAAE;IAChBC,cAAc,EAAE,QAAQ;IACxBC,UAAU,EAAE;EACd,CAAC;EACDZ,IAAI,EAAE;IACJa,KAAK,EAAE,MAAM;IACbC,QAAQ,EAAE,EAAE;IACZC,UAAU,EAAE;EACd,CAAC;EACDjB,OAAO,EAAE;IACPkB,eAAe,EAAE;EACnB,CAAC;EACDd,KAAK,EAAE;IACLc,eAAe,EAAE;EACnB,CAAC;EACDZ,IAAI,EAAE;IACJY,eAAe,EAAE;EACnB,CAAC;EACDV,OAAO,EAAE;IACPU,eAAe,EAAE;EACnB;AACF,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["ToastService","Toast","CustomToast"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,cAAc,YAAS;AACvB,cAAc,oBAAiB;AAC/B,SAASA,YAAY,IAAIC,KAAK,QAAQ,oBAAiB;AACvD,SAASA,KAAK,IAAIC,WAAW,QAAQ,YAAS","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.ts"],"mappings":"","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Toast.d.ts","sourceRoot":"","sources":["../../../src/Toast.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAoB,MAAM,OAAO,CAAC;AAgBzC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAG1C,eAAO,MAAM,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,UAAU,CAoItC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { ToastOptions, ToastRef, ToastProviderProps } from './types';
|
|
3
|
+
export declare const ToastRefWrapper: React.RefObject<ToastRef | null>;
|
|
4
|
+
export declare const ToastProvider: ({ children, theme, }: ToastProviderProps) => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare const ToastService: {
|
|
6
|
+
show: (options: ToastOptions) => void | undefined;
|
|
7
|
+
hide: () => void | undefined;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=ToastProvider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToastProvider.d.ts","sourceRoot":"","sources":["../../../src/ToastProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAExE,OAAO,KAAK,EAAE,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAE1E,eAAO,MAAM,eAAe,kCAA8B,CAAC;AAE3D,eAAO,MAAM,aAAa,GAAI,sBAG3B,kBAAkB,4CAoDpB,CAAC;AAEF,eAAO,MAAM,YAAY;oBACP,YAAY;;CAE7B,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const SuccessIcon: () => import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare const ErrorIcon: () => import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare const InfoIcon: () => import("react/jsx-runtime").JSX.Element;
|
|
4
|
+
export declare const WarningIcon: () => import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
//# sourceMappingURL=icons.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icons.d.ts","sourceRoot":"","sources":["../../../src/icons.tsx"],"names":[],"mappings":"AAEA,eAAO,MAAM,WAAW,+CAIvB,CAAC;AAEF,eAAO,MAAM,SAAS,+CAIrB,CAAC;AAEF,eAAO,MAAM,QAAQ,+CAIpB,CAAC;AAEF,eAAO,MAAM,WAAW,+CAIvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,OAAO,EAAE,YAAY,IAAI,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export type ToastType = 'success' | 'error' | 'info' | 'warning';
|
|
2
|
+
export type ToastPosition = 'top' | 'bottom';
|
|
3
|
+
export type ToastTheme = 'light' | 'dark' | 'system';
|
|
4
|
+
export interface ToastOptions {
|
|
5
|
+
type?: ToastType;
|
|
6
|
+
text1?: string;
|
|
7
|
+
text2?: string;
|
|
8
|
+
duration?: number;
|
|
9
|
+
position?: ToastPosition;
|
|
10
|
+
topOffset?: number;
|
|
11
|
+
bottomOffset?: number;
|
|
12
|
+
visibilityTime?: number;
|
|
13
|
+
autoHide?: boolean;
|
|
14
|
+
theme?: ToastTheme;
|
|
15
|
+
onPress?: () => void;
|
|
16
|
+
onShow?: () => void;
|
|
17
|
+
onHide?: () => void;
|
|
18
|
+
customView?: React.ReactNode;
|
|
19
|
+
}
|
|
20
|
+
export interface ToastProps extends ToastOptions {
|
|
21
|
+
isVisible: boolean;
|
|
22
|
+
providerTheme?: ToastTheme;
|
|
23
|
+
onAnimationEnd: (isVisible: boolean) => void;
|
|
24
|
+
}
|
|
25
|
+
export interface ToastProviderProps {
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
theme?: ToastTheme;
|
|
28
|
+
}
|
|
29
|
+
export interface ToastRef {
|
|
30
|
+
show: (options: ToastOptions) => void;
|
|
31
|
+
hide: () => void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,CAAC;AAEjE,MAAM,MAAM,aAAa,GAAG,KAAK,GAAG,QAAQ,CAAC;AAE7C,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAC;AAErD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,aAAa,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAED,MAAM,WAAW,UAAW,SAAQ,YAAY;IAC9C,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,UAAU,CAAC;IAC3B,cAAc,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,KAAK,CAAC,EAAE,UAAU,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,CAAC,OAAO,EAAE,YAAY,KAAK,IAAI,CAAC;IACtC,IAAI,EAAE,MAAM,IAAI,CAAC;CAClB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@selimh/react-native-toast",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A beautifully animated, highly customizable, imperative Toast library for React Native.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react-native",
|
|
7
|
+
"react-native-toast",
|
|
8
|
+
"toast",
|
|
9
|
+
"reanimated",
|
|
10
|
+
"alert",
|
|
11
|
+
"notification",
|
|
12
|
+
"snackbar",
|
|
13
|
+
"toast-message"
|
|
14
|
+
],
|
|
15
|
+
"main": "./lib/module/index.js",
|
|
16
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"source": "./src/index.tsx",
|
|
20
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
21
|
+
"default": "./lib/module/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"src",
|
|
27
|
+
"lib",
|
|
28
|
+
"android",
|
|
29
|
+
"ios",
|
|
30
|
+
"cpp",
|
|
31
|
+
"*.podspec",
|
|
32
|
+
"react-native.config.js",
|
|
33
|
+
"!ios/build",
|
|
34
|
+
"!android/build",
|
|
35
|
+
"!android/gradle",
|
|
36
|
+
"!android/gradlew",
|
|
37
|
+
"!android/gradlew.bat",
|
|
38
|
+
"!android/local.properties",
|
|
39
|
+
"!**/__tests__",
|
|
40
|
+
"!**/__fixtures__",
|
|
41
|
+
"!**/__mocks__",
|
|
42
|
+
"!**/.*"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"example": "yarn workspace react-native-toast-example",
|
|
46
|
+
"clean": "del-cli lib",
|
|
47
|
+
"prepare": "bob build",
|
|
48
|
+
"typecheck": "tsc",
|
|
49
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
50
|
+
"test": "jest",
|
|
51
|
+
"release": "release-it --only-version"
|
|
52
|
+
},
|
|
53
|
+
"repository": {
|
|
54
|
+
"type": "git",
|
|
55
|
+
"url": "git+https://github.com/selimhamzaogullari/react-native-toast.git"
|
|
56
|
+
},
|
|
57
|
+
"author": "Selim Hamzaoğulları <selimhamzaogullari@hotmail.com> (https://github.com/selimhamzaogullari)",
|
|
58
|
+
"license": "MIT",
|
|
59
|
+
"bugs": {
|
|
60
|
+
"url": "https://github.com/selimhamzaogullari/react-native-toast/issues"
|
|
61
|
+
},
|
|
62
|
+
"homepage": "https://github.com/selimhamzaogullari/react-native-toast#readme",
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"registry": "https://registry.npmjs.org/",
|
|
65
|
+
"access": "public"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@commitlint/config-conventional": "^19.8.1",
|
|
69
|
+
"@eslint/compat": "^1.3.2",
|
|
70
|
+
"@eslint/eslintrc": "^3.3.1",
|
|
71
|
+
"@eslint/js": "^9.35.0",
|
|
72
|
+
"@react-native/babel-preset": "0.83.0",
|
|
73
|
+
"@react-native/eslint-config": "0.83.0",
|
|
74
|
+
"@release-it/conventional-changelog": "^10.0.1",
|
|
75
|
+
"@types/jest": "^29.5.14",
|
|
76
|
+
"@types/react": "^19.1.12",
|
|
77
|
+
"commitlint": "^19.8.1",
|
|
78
|
+
"del-cli": "^6.0.0",
|
|
79
|
+
"eslint": "^9.35.0",
|
|
80
|
+
"eslint-config-prettier": "^10.1.8",
|
|
81
|
+
"eslint-plugin-prettier": "^5.5.4",
|
|
82
|
+
"jest": "^29.7.0",
|
|
83
|
+
"lefthook": "^2.0.3",
|
|
84
|
+
"prettier": "^2.8.8",
|
|
85
|
+
"react": "19.2.0",
|
|
86
|
+
"react-native": "0.83.2",
|
|
87
|
+
"react-native-builder-bob": "^0.40.18",
|
|
88
|
+
"react-native-reanimated": "3.16.7",
|
|
89
|
+
"react-native-safe-area-context": "^5.7.0",
|
|
90
|
+
"release-it": "^19.0.4",
|
|
91
|
+
"turbo": "^2.5.6",
|
|
92
|
+
"typescript": "^5.9.2"
|
|
93
|
+
},
|
|
94
|
+
"peerDependencies": {
|
|
95
|
+
"react": "*",
|
|
96
|
+
"react-native": "*"
|
|
97
|
+
},
|
|
98
|
+
"workspaces": [
|
|
99
|
+
"example"
|
|
100
|
+
],
|
|
101
|
+
"packageManager": "yarn@4.11.0",
|
|
102
|
+
"react-native-builder-bob": {
|
|
103
|
+
"source": "src",
|
|
104
|
+
"output": "lib",
|
|
105
|
+
"targets": [
|
|
106
|
+
[
|
|
107
|
+
"module",
|
|
108
|
+
{
|
|
109
|
+
"esm": true
|
|
110
|
+
}
|
|
111
|
+
],
|
|
112
|
+
[
|
|
113
|
+
"typescript",
|
|
114
|
+
{
|
|
115
|
+
"project": "tsconfig.build.json"
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
"prettier": {
|
|
121
|
+
"quoteProps": "consistent",
|
|
122
|
+
"singleQuote": true,
|
|
123
|
+
"tabWidth": 2,
|
|
124
|
+
"trailingComma": "es5",
|
|
125
|
+
"useTabs": false
|
|
126
|
+
},
|
|
127
|
+
"jest": {
|
|
128
|
+
"preset": "react-native",
|
|
129
|
+
"modulePathIgnorePatterns": [
|
|
130
|
+
"<rootDir>/example/node_modules",
|
|
131
|
+
"<rootDir>/lib/"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
"commitlint": {
|
|
135
|
+
"extends": [
|
|
136
|
+
"@commitlint/config-conventional"
|
|
137
|
+
]
|
|
138
|
+
},
|
|
139
|
+
"release-it": {
|
|
140
|
+
"git": {
|
|
141
|
+
"commitMessage": "chore: release ${version}",
|
|
142
|
+
"tagName": "v${version}"
|
|
143
|
+
},
|
|
144
|
+
"npm": {
|
|
145
|
+
"publish": true
|
|
146
|
+
},
|
|
147
|
+
"github": {
|
|
148
|
+
"release": true
|
|
149
|
+
},
|
|
150
|
+
"plugins": {
|
|
151
|
+
"@release-it/conventional-changelog": {
|
|
152
|
+
"preset": {
|
|
153
|
+
"name": "angular"
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
"create-react-native-library": {
|
|
159
|
+
"type": "library",
|
|
160
|
+
"languages": "js",
|
|
161
|
+
"tools": [
|
|
162
|
+
"eslint",
|
|
163
|
+
"jest",
|
|
164
|
+
"lefthook",
|
|
165
|
+
"release-it"
|
|
166
|
+
],
|
|
167
|
+
"version": "0.57.2"
|
|
168
|
+
}
|
|
169
|
+
}
|
package/src/Toast.tsx
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
StyleSheet,
|
|
4
|
+
Text,
|
|
5
|
+
View,
|
|
6
|
+
TouchableOpacity,
|
|
7
|
+
useColorScheme,
|
|
8
|
+
} from 'react-native';
|
|
9
|
+
import Animated, {
|
|
10
|
+
useSharedValue,
|
|
11
|
+
useAnimatedStyle,
|
|
12
|
+
withSpring,
|
|
13
|
+
withTiming,
|
|
14
|
+
runOnJS,
|
|
15
|
+
} from 'react-native-reanimated';
|
|
16
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
17
|
+
import type { ToastProps } from './types';
|
|
18
|
+
import { SuccessIcon, ErrorIcon, InfoIcon, WarningIcon } from './icons';
|
|
19
|
+
|
|
20
|
+
export const Toast: React.FC<ToastProps> = ({
|
|
21
|
+
isVisible,
|
|
22
|
+
type = 'info',
|
|
23
|
+
text1,
|
|
24
|
+
text2,
|
|
25
|
+
position = 'top',
|
|
26
|
+
topOffset = 10,
|
|
27
|
+
bottomOffset = 10,
|
|
28
|
+
theme,
|
|
29
|
+
providerTheme = 'system',
|
|
30
|
+
onPress,
|
|
31
|
+
onAnimationEnd,
|
|
32
|
+
customView,
|
|
33
|
+
}) => {
|
|
34
|
+
const insets = useSafeAreaInsets();
|
|
35
|
+
const systemTheme = useColorScheme();
|
|
36
|
+
|
|
37
|
+
const activeTheme =
|
|
38
|
+
theme && theme !== 'system'
|
|
39
|
+
? theme
|
|
40
|
+
: providerTheme !== 'system'
|
|
41
|
+
? providerTheme
|
|
42
|
+
: systemTheme;
|
|
43
|
+
|
|
44
|
+
const isDark = activeTheme === 'dark';
|
|
45
|
+
|
|
46
|
+
const translateY = useSharedValue(position === 'top' ? -150 : 150);
|
|
47
|
+
const opacity = useSharedValue(0);
|
|
48
|
+
|
|
49
|
+
useEffect(() => {
|
|
50
|
+
if (isVisible) {
|
|
51
|
+
// Reset position instantly before starting the animation
|
|
52
|
+
translateY.value = position === 'top' ? -150 : 150;
|
|
53
|
+
|
|
54
|
+
opacity.value = withTiming(1, { duration: 300 });
|
|
55
|
+
translateY.value = withSpring(
|
|
56
|
+
0,
|
|
57
|
+
{
|
|
58
|
+
damping: 40,
|
|
59
|
+
stiffness: 250,
|
|
60
|
+
},
|
|
61
|
+
(finished) => {
|
|
62
|
+
if (finished && onAnimationEnd) {
|
|
63
|
+
runOnJS(onAnimationEnd)(true);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
} else {
|
|
68
|
+
opacity.value = withTiming(0, { duration: 300 });
|
|
69
|
+
translateY.value = withTiming(
|
|
70
|
+
position === 'top' ? -150 : 150,
|
|
71
|
+
{ duration: 300 },
|
|
72
|
+
(finished) => {
|
|
73
|
+
if (finished && onAnimationEnd) {
|
|
74
|
+
runOnJS(onAnimationEnd)(false);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
}, [isVisible, opacity, translateY, position, onAnimationEnd]);
|
|
80
|
+
|
|
81
|
+
const animatedStyle = useAnimatedStyle(() => {
|
|
82
|
+
return {
|
|
83
|
+
opacity: opacity.value,
|
|
84
|
+
transform: [{ translateY: translateY.value }],
|
|
85
|
+
};
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const getIcon = () => {
|
|
89
|
+
switch (type) {
|
|
90
|
+
case 'success':
|
|
91
|
+
return <SuccessIcon />;
|
|
92
|
+
case 'error':
|
|
93
|
+
return <ErrorIcon />;
|
|
94
|
+
case 'warning':
|
|
95
|
+
return <WarningIcon />;
|
|
96
|
+
case 'info':
|
|
97
|
+
default:
|
|
98
|
+
return <InfoIcon />;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const getContainerStyle = () => {
|
|
103
|
+
const isTop = position === 'top';
|
|
104
|
+
return [
|
|
105
|
+
styles.container,
|
|
106
|
+
isTop
|
|
107
|
+
? { top: insets.top + topOffset }
|
|
108
|
+
: { bottom: insets.bottom + bottomOffset },
|
|
109
|
+
animatedStyle,
|
|
110
|
+
] as any;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
const contentStyle = [
|
|
114
|
+
styles.content,
|
|
115
|
+
isDark ? styles.contentDark : styles.contentLight,
|
|
116
|
+
];
|
|
117
|
+
const text1Style = [
|
|
118
|
+
styles.text1,
|
|
119
|
+
isDark ? styles.text1Dark : styles.text1Light,
|
|
120
|
+
];
|
|
121
|
+
const text2Style = [
|
|
122
|
+
styles.text2,
|
|
123
|
+
isDark ? styles.text2Dark : styles.text2Light,
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
return (
|
|
127
|
+
<Animated.View
|
|
128
|
+
// @ts-ignore - TS2589 bypass
|
|
129
|
+
style={getContainerStyle()}
|
|
130
|
+
pointerEvents={isVisible ? 'box-none' : 'none'}
|
|
131
|
+
>
|
|
132
|
+
<TouchableOpacity
|
|
133
|
+
activeOpacity={0.9}
|
|
134
|
+
onPress={onPress}
|
|
135
|
+
disabled={!onPress}
|
|
136
|
+
style={customView ? styles.customContent : contentStyle}
|
|
137
|
+
>
|
|
138
|
+
{customView ? (
|
|
139
|
+
customView
|
|
140
|
+
) : (
|
|
141
|
+
<>
|
|
142
|
+
<View style={styles.iconContainer}>{getIcon()}</View>
|
|
143
|
+
<View style={styles.textContainer}>
|
|
144
|
+
{text1 && <Text style={text1Style}>{text1}</Text>}
|
|
145
|
+
{text2 && <Text style={text2Style}>{text2}</Text>}
|
|
146
|
+
</View>
|
|
147
|
+
</>
|
|
148
|
+
)}
|
|
149
|
+
</TouchableOpacity>
|
|
150
|
+
</Animated.View>
|
|
151
|
+
);
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
const styles = StyleSheet.create({
|
|
155
|
+
container: {
|
|
156
|
+
position: 'absolute',
|
|
157
|
+
left: 16,
|
|
158
|
+
right: 16,
|
|
159
|
+
zIndex: 9999,
|
|
160
|
+
alignItems: 'center',
|
|
161
|
+
},
|
|
162
|
+
customContent: {
|
|
163
|
+
width: '100%',
|
|
164
|
+
maxWidth: 400,
|
|
165
|
+
},
|
|
166
|
+
content: {
|
|
167
|
+
flexDirection: 'row',
|
|
168
|
+
borderRadius: 12,
|
|
169
|
+
padding: 16,
|
|
170
|
+
width: '100%',
|
|
171
|
+
shadowOffset: { width: 0, height: 4 },
|
|
172
|
+
shadowOpacity: 0.1,
|
|
173
|
+
shadowRadius: 12,
|
|
174
|
+
elevation: 5,
|
|
175
|
+
alignItems: 'center',
|
|
176
|
+
maxWidth: 400,
|
|
177
|
+
},
|
|
178
|
+
contentLight: {
|
|
179
|
+
backgroundColor: '#ffffff',
|
|
180
|
+
shadowColor: '#000',
|
|
181
|
+
},
|
|
182
|
+
contentDark: {
|
|
183
|
+
backgroundColor: '#1f2937',
|
|
184
|
+
shadowColor: '#000',
|
|
185
|
+
borderWidth: 1,
|
|
186
|
+
borderColor: '#374151',
|
|
187
|
+
},
|
|
188
|
+
iconContainer: {
|
|
189
|
+
marginRight: 12,
|
|
190
|
+
},
|
|
191
|
+
textContainer: {
|
|
192
|
+
flex: 1,
|
|
193
|
+
justifyContent: 'center',
|
|
194
|
+
},
|
|
195
|
+
text1: {
|
|
196
|
+
fontSize: 15,
|
|
197
|
+
fontWeight: '600',
|
|
198
|
+
marginBottom: 4,
|
|
199
|
+
},
|
|
200
|
+
text1Light: {
|
|
201
|
+
color: '#1f2937',
|
|
202
|
+
},
|
|
203
|
+
text1Dark: {
|
|
204
|
+
color: '#f9fafb',
|
|
205
|
+
},
|
|
206
|
+
text2: {
|
|
207
|
+
fontSize: 13,
|
|
208
|
+
},
|
|
209
|
+
text2Light: {
|
|
210
|
+
color: '#6b7280',
|
|
211
|
+
},
|
|
212
|
+
text2Dark: {
|
|
213
|
+
color: '#9ca3af',
|
|
214
|
+
},
|
|
215
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { useState, useCallback, useRef, useEffect } from 'react';
|
|
2
|
+
import { Toast } from './Toast';
|
|
3
|
+
import type { ToastOptions, ToastRef, ToastProviderProps } from './types';
|
|
4
|
+
|
|
5
|
+
export const ToastRefWrapper = React.createRef<ToastRef>();
|
|
6
|
+
|
|
7
|
+
export const ToastProvider = ({
|
|
8
|
+
children,
|
|
9
|
+
theme = 'system',
|
|
10
|
+
}: ToastProviderProps) => {
|
|
11
|
+
const [options, setOptions] = useState<ToastOptions>({});
|
|
12
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
13
|
+
const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
14
|
+
|
|
15
|
+
const show = useCallback((opts: ToastOptions) => {
|
|
16
|
+
setOptions(opts);
|
|
17
|
+
setIsVisible(true);
|
|
18
|
+
|
|
19
|
+
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
20
|
+
|
|
21
|
+
const autoHide = opts.autoHide ?? true;
|
|
22
|
+
const visibilityTime = opts.visibilityTime ?? 3000;
|
|
23
|
+
|
|
24
|
+
if (autoHide) {
|
|
25
|
+
hideTimeoutRef.current = setTimeout(() => {
|
|
26
|
+
setIsVisible(false);
|
|
27
|
+
}, visibilityTime);
|
|
28
|
+
}
|
|
29
|
+
}, []);
|
|
30
|
+
|
|
31
|
+
const hide = useCallback(() => {
|
|
32
|
+
setIsVisible(false);
|
|
33
|
+
if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current);
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
(ToastRefWrapper as any).current = { show, hide };
|
|
38
|
+
}, [show, hide]);
|
|
39
|
+
|
|
40
|
+
const onAnimationEnd = useCallback(
|
|
41
|
+
(visible: boolean) => {
|
|
42
|
+
if (!visible) {
|
|
43
|
+
options.onHide?.();
|
|
44
|
+
} else {
|
|
45
|
+
options.onShow?.();
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
[options]
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<>
|
|
53
|
+
{children}
|
|
54
|
+
<Toast
|
|
55
|
+
{...options}
|
|
56
|
+
isVisible={isVisible}
|
|
57
|
+
onAnimationEnd={onAnimationEnd}
|
|
58
|
+
providerTheme={theme}
|
|
59
|
+
/>
|
|
60
|
+
</>
|
|
61
|
+
);
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
export const ToastService = {
|
|
65
|
+
show: (options: ToastOptions) => ToastRefWrapper.current?.show(options),
|
|
66
|
+
hide: () => ToastRefWrapper.current?.hide(),
|
|
67
|
+
};
|
package/src/icons.tsx
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Text, View, StyleSheet } from 'react-native';
|
|
2
|
+
|
|
3
|
+
export const SuccessIcon = () => (
|
|
4
|
+
<View style={[styles.container, styles.success]}>
|
|
5
|
+
<Text style={styles.icon}>✓</Text>
|
|
6
|
+
</View>
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export const ErrorIcon = () => (
|
|
10
|
+
<View style={[styles.container, styles.error]}>
|
|
11
|
+
<Text style={styles.icon}>✕</Text>
|
|
12
|
+
</View>
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export const InfoIcon = () => (
|
|
16
|
+
<View style={[styles.container, styles.info]}>
|
|
17
|
+
<Text style={styles.icon}>i</Text>
|
|
18
|
+
</View>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
export const WarningIcon = () => (
|
|
22
|
+
<View style={[styles.container, styles.warning]}>
|
|
23
|
+
<Text style={styles.icon}>!</Text>
|
|
24
|
+
</View>
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
const styles = StyleSheet.create({
|
|
28
|
+
container: {
|
|
29
|
+
width: 24,
|
|
30
|
+
height: 24,
|
|
31
|
+
borderRadius: 12,
|
|
32
|
+
justifyContent: 'center',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
},
|
|
35
|
+
icon: {
|
|
36
|
+
color: '#fff',
|
|
37
|
+
fontSize: 14,
|
|
38
|
+
fontWeight: 'bold',
|
|
39
|
+
},
|
|
40
|
+
success: {
|
|
41
|
+
backgroundColor: '#4ade80',
|
|
42
|
+
},
|
|
43
|
+
error: {
|
|
44
|
+
backgroundColor: '#f87171',
|
|
45
|
+
},
|
|
46
|
+
info: {
|
|
47
|
+
backgroundColor: '#60a5fa',
|
|
48
|
+
},
|
|
49
|
+
warning: {
|
|
50
|
+
backgroundColor: '#fbbf24',
|
|
51
|
+
},
|
|
52
|
+
});
|
package/src/index.tsx
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export type ToastType = 'success' | 'error' | 'info' | 'warning';
|
|
2
|
+
|
|
3
|
+
export type ToastPosition = 'top' | 'bottom';
|
|
4
|
+
|
|
5
|
+
export type ToastTheme = 'light' | 'dark' | 'system';
|
|
6
|
+
|
|
7
|
+
export interface ToastOptions {
|
|
8
|
+
type?: ToastType;
|
|
9
|
+
text1?: string;
|
|
10
|
+
text2?: string;
|
|
11
|
+
duration?: number;
|
|
12
|
+
position?: ToastPosition;
|
|
13
|
+
topOffset?: number;
|
|
14
|
+
bottomOffset?: number;
|
|
15
|
+
visibilityTime?: number;
|
|
16
|
+
autoHide?: boolean;
|
|
17
|
+
theme?: ToastTheme;
|
|
18
|
+
onPress?: () => void;
|
|
19
|
+
onShow?: () => void;
|
|
20
|
+
onHide?: () => void;
|
|
21
|
+
customView?: React.ReactNode;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface ToastProps extends ToastOptions {
|
|
25
|
+
isVisible: boolean;
|
|
26
|
+
providerTheme?: ToastTheme;
|
|
27
|
+
onAnimationEnd: (isVisible: boolean) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface ToastProviderProps {
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
theme?: ToastTheme;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface ToastRef {
|
|
36
|
+
show: (options: ToastOptions) => void;
|
|
37
|
+
hide: () => void;
|
|
38
|
+
}
|