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 +21 -21
- package/README.MD +221 -190
- package/babel.config.js +5 -5
- package/docs/demo.gif +0 -0
- package/example/App.js +193 -0
- package/index.js +60 -34
- package/jest.config.js +14 -14
- package/jest.setup.js +1 -1
- package/package.json +86 -43
- package/src/Toast.js +194 -114
- package/src/__tests__/Toast.test.js +54 -54
- package/src/components/BaseToast.js +163 -0
- package/src/components/CustomToast.js +58 -0
- package/src/components/CustomeToast.js +5 -28
- package/src/components/EmojiToast.js +142 -38
- package/src/components/ErrorToast.js +23 -52
- package/src/components/InfoToast.js +23 -0
- package/src/components/LoadingToast.js +24 -33
- package/src/components/ProgressBar.js +67 -0
- package/src/components/SuccessToast.js +23 -51
- package/src/components/WarningToast.js +23 -0
- package/src/components/icons/CheckIcon.js +98 -0
- package/src/components/icons/CrossIcon.js +84 -0
- package/src/components/icons/InfoIcon.js +71 -0
- package/src/components/icons/LoadingSpinner.js +78 -0
- package/src/components/icons/WarningIcon.js +84 -0
- package/src/components/icons/index.js +5 -0
- package/src/context/ToastContainer.js +223 -144
- package/src/context/ToastManager.js +150 -36
- package/src/hooks/useToast.js +123 -49
- package/src/types.d.ts +172 -0
- package/src/utils/Pixel/Index.js +28 -28
- package/src/utils/theme.js +81 -0
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { render, act } from '@testing-library/react-native';
|
|
3
|
-
import Toast from '../Toast'; // Adjust the import path as needed
|
|
4
|
-
|
|
5
|
-
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); // Mock for animated
|
|
6
|
-
|
|
7
|
-
describe('Toast Component', () => {
|
|
8
|
-
jest.useFakeTimers();
|
|
9
|
-
|
|
10
|
-
it('should render and show toast', () => {
|
|
11
|
-
const { getByText } = render(
|
|
12
|
-
<Toast visible={true} duration={2000} position="bottom">
|
|
13
|
-
Test Toast
|
|
14
|
-
</Toast>
|
|
15
|
-
);
|
|
16
|
-
|
|
17
|
-
expect(getByText('Test Toast')).toBeTruthy();
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it('should hide toast after duration', () => {
|
|
21
|
-
const onHideMock = jest.fn();
|
|
22
|
-
|
|
23
|
-
const { queryByText } = render(
|
|
24
|
-
<Toast visible={true} duration={2000} position="bottom" onHide={onHideMock}>
|
|
25
|
-
Test Toast
|
|
26
|
-
</Toast>
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
act(() => {
|
|
30
|
-
jest.advanceTimersByTime(2000);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
expect(queryByText('Test Toast')).toBeNull();
|
|
34
|
-
expect(onHideMock).toHaveBeenCalled();
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it('should apply correct styles based on position', () => {
|
|
38
|
-
const { getByText, rerender } = render(
|
|
39
|
-
<Toast visible={true} duration={2000} position="top">
|
|
40
|
-
Test Toast
|
|
41
|
-
</Toast>
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
expect(getByText('Test Toast').parent.parent.props.style).toContainEqual({ top: 0 });
|
|
45
|
-
|
|
46
|
-
rerender(
|
|
47
|
-
<Toast visible={true} duration={2000} position="bottom">
|
|
48
|
-
Test Toast
|
|
49
|
-
</Toast>
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
-
expect(getByText('Test Toast').parent.parent.props.style).toContainEqual({ bottom: 50 });
|
|
53
|
-
});
|
|
54
|
-
});
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, act } from '@testing-library/react-native';
|
|
3
|
+
import Toast from '../Toast'; // Adjust the import path as needed
|
|
4
|
+
|
|
5
|
+
jest.mock('react-native/Libraries/Animated/NativeAnimatedHelper'); // Mock for animated
|
|
6
|
+
|
|
7
|
+
describe('Toast Component', () => {
|
|
8
|
+
jest.useFakeTimers();
|
|
9
|
+
|
|
10
|
+
it('should render and show toast', () => {
|
|
11
|
+
const { getByText } = render(
|
|
12
|
+
<Toast visible={true} duration={2000} position="bottom">
|
|
13
|
+
Test Toast
|
|
14
|
+
</Toast>
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
expect(getByText('Test Toast')).toBeTruthy();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should hide toast after duration', () => {
|
|
21
|
+
const onHideMock = jest.fn();
|
|
22
|
+
|
|
23
|
+
const { queryByText } = render(
|
|
24
|
+
<Toast visible={true} duration={2000} position="bottom" onHide={onHideMock}>
|
|
25
|
+
Test Toast
|
|
26
|
+
</Toast>
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
act(() => {
|
|
30
|
+
jest.advanceTimersByTime(2000);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
expect(queryByText('Test Toast')).toBeNull();
|
|
34
|
+
expect(onHideMock).toHaveBeenCalled();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should apply correct styles based on position', () => {
|
|
38
|
+
const { getByText, rerender } = render(
|
|
39
|
+
<Toast visible={true} duration={2000} position="top">
|
|
40
|
+
Test Toast
|
|
41
|
+
</Toast>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
expect(getByText('Test Toast').parent.parent.props.style).toContainEqual({ top: 0 });
|
|
45
|
+
|
|
46
|
+
rerender(
|
|
47
|
+
<Toast visible={true} duration={2000} position="bottom">
|
|
48
|
+
Test Toast
|
|
49
|
+
</Toast>
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
expect(getByText('Test Toast').parent.parent.props.style).toContainEqual({ bottom: 50 });
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, Platform } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
heightPercentageToDP as hp,
|
|
5
|
+
widthPercentageToDP as wp,
|
|
6
|
+
} from '../utils/Pixel/Index';
|
|
7
|
+
import { TOAST_THEME, TOAST_COLORS } from '../utils/theme';
|
|
8
|
+
import ProgressBar from './ProgressBar';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* BaseToast — Premium shared layout for all built-in toast types.
|
|
12
|
+
*
|
|
13
|
+
* Design: Compact card with rounded icon badge, subtle accent,
|
|
14
|
+
* floating shadow, and an edge-to-edge progress indicator.
|
|
15
|
+
*/
|
|
16
|
+
const BaseToast = ({
|
|
17
|
+
icon,
|
|
18
|
+
title,
|
|
19
|
+
message,
|
|
20
|
+
accentColor,
|
|
21
|
+
toastType = 'info',
|
|
22
|
+
theme = 'light',
|
|
23
|
+
duration,
|
|
24
|
+
showProgress = true,
|
|
25
|
+
children,
|
|
26
|
+
}) => {
|
|
27
|
+
const isDark = theme === 'dark';
|
|
28
|
+
const themeColors = TOAST_THEME[isDark ? 'dark' : 'light'];
|
|
29
|
+
const colors = TOAST_COLORS[toastType] || TOAST_COLORS.info;
|
|
30
|
+
const iconBgColor = isDark ? colors.iconBgDark : colors.iconBg;
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<View
|
|
34
|
+
style={[
|
|
35
|
+
styles.container,
|
|
36
|
+
{
|
|
37
|
+
backgroundColor: themeColors.background,
|
|
38
|
+
borderColor: themeColors.border,
|
|
39
|
+
...Platform.select({
|
|
40
|
+
ios: {
|
|
41
|
+
shadowColor: themeColors.shadow,
|
|
42
|
+
shadowOffset: { width: 0, height: 8 },
|
|
43
|
+
shadowOpacity: isDark ? 0.6 : 1,
|
|
44
|
+
shadowRadius: 24,
|
|
45
|
+
},
|
|
46
|
+
android: {
|
|
47
|
+
elevation: 8,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
},
|
|
51
|
+
]}
|
|
52
|
+
accessibilityRole="alert"
|
|
53
|
+
accessibilityLiveRegion="polite"
|
|
54
|
+
accessibilityLabel={
|
|
55
|
+
[title, message].filter(Boolean).join('. ')
|
|
56
|
+
}
|
|
57
|
+
>
|
|
58
|
+
{/* Left Edge Accent */}
|
|
59
|
+
<View style={[styles.leftAccent, { backgroundColor: accentColor || colors.accent }]} />
|
|
60
|
+
|
|
61
|
+
{/* Content row */}
|
|
62
|
+
<View style={styles.body}>
|
|
63
|
+
{/* Icon wrapper without the heavy badge background */}
|
|
64
|
+
{icon && (
|
|
65
|
+
<View style={styles.iconContainer}>
|
|
66
|
+
{icon}
|
|
67
|
+
</View>
|
|
68
|
+
)}
|
|
69
|
+
|
|
70
|
+
{/* Text content */}
|
|
71
|
+
<View style={styles.textContainer}>
|
|
72
|
+
{title ? (
|
|
73
|
+
<Text
|
|
74
|
+
style={[styles.title, { color: themeColors.title }]}
|
|
75
|
+
numberOfLines={1}
|
|
76
|
+
ellipsizeMode="tail"
|
|
77
|
+
>
|
|
78
|
+
{title}
|
|
79
|
+
</Text>
|
|
80
|
+
) : null}
|
|
81
|
+
{message ? (
|
|
82
|
+
<Text
|
|
83
|
+
style={[
|
|
84
|
+
styles.message,
|
|
85
|
+
{ color: themeColors.message },
|
|
86
|
+
!title && styles.messageSolo,
|
|
87
|
+
]}
|
|
88
|
+
numberOfLines={2}
|
|
89
|
+
ellipsizeMode="tail"
|
|
90
|
+
>
|
|
91
|
+
{message}
|
|
92
|
+
</Text>
|
|
93
|
+
) : null}
|
|
94
|
+
{children}
|
|
95
|
+
</View>
|
|
96
|
+
</View>
|
|
97
|
+
|
|
98
|
+
{/* Progress bar — flush to bottom edge */}
|
|
99
|
+
{showProgress && duration && duration !== Infinity && (
|
|
100
|
+
<ProgressBar
|
|
101
|
+
duration={duration}
|
|
102
|
+
color={accentColor}
|
|
103
|
+
trackColor={themeColors.progressTrack}
|
|
104
|
+
/>
|
|
105
|
+
)}
|
|
106
|
+
</View>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const styles = StyleSheet.create({
|
|
111
|
+
container: {
|
|
112
|
+
width: wp(88),
|
|
113
|
+
maxWidth: 400,
|
|
114
|
+
borderRadius: 24,
|
|
115
|
+
overflow: 'hidden',
|
|
116
|
+
borderWidth: 1,
|
|
117
|
+
},
|
|
118
|
+
leftAccent: {
|
|
119
|
+
position: 'absolute',
|
|
120
|
+
left: 0,
|
|
121
|
+
top: 0,
|
|
122
|
+
bottom: 0,
|
|
123
|
+
width: 4,
|
|
124
|
+
},
|
|
125
|
+
body: {
|
|
126
|
+
flexDirection: 'row',
|
|
127
|
+
alignItems: 'center',
|
|
128
|
+
paddingHorizontal: 16,
|
|
129
|
+
paddingVertical: 14,
|
|
130
|
+
paddingLeft: 20,
|
|
131
|
+
},
|
|
132
|
+
iconContainer: {
|
|
133
|
+
width: 36,
|
|
134
|
+
height: 36,
|
|
135
|
+
alignItems: 'center',
|
|
136
|
+
justifyContent: 'center',
|
|
137
|
+
marginRight: 12,
|
|
138
|
+
},
|
|
139
|
+
textContainer: {
|
|
140
|
+
flex: 1,
|
|
141
|
+
justifyContent: 'center',
|
|
142
|
+
},
|
|
143
|
+
title: {
|
|
144
|
+
fontSize: 15,
|
|
145
|
+
fontWeight: '700',
|
|
146
|
+
letterSpacing: -0.2,
|
|
147
|
+
lineHeight: 20,
|
|
148
|
+
},
|
|
149
|
+
message: {
|
|
150
|
+
fontSize: 13,
|
|
151
|
+
fontWeight: '500',
|
|
152
|
+
marginTop: 2,
|
|
153
|
+
lineHeight: 18,
|
|
154
|
+
letterSpacing: -0.1,
|
|
155
|
+
},
|
|
156
|
+
messageSolo: {
|
|
157
|
+
fontSize: 14,
|
|
158
|
+
fontWeight: '600',
|
|
159
|
+
lineHeight: 20,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export default React.memo(BaseToast);
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { View, StyleSheet, Platform } from 'react-native';
|
|
3
|
+
import {
|
|
4
|
+
widthPercentageToDP as wp,
|
|
5
|
+
} from '../utils/Pixel/Index';
|
|
6
|
+
import { TOAST_THEME } from '../utils/theme';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* CustomToast — Wrapper for user-provided custom content.
|
|
10
|
+
* Matches the premium design system card style.
|
|
11
|
+
*/
|
|
12
|
+
const CustomToast = ({ content, theme = 'light' }) => {
|
|
13
|
+
const isDark = theme === 'dark';
|
|
14
|
+
const themeColors = TOAST_THEME[isDark ? 'dark' : 'light'];
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<View
|
|
18
|
+
style={[
|
|
19
|
+
styles.container,
|
|
20
|
+
{
|
|
21
|
+
backgroundColor: themeColors.background,
|
|
22
|
+
borderColor: themeColors.border,
|
|
23
|
+
...Platform.select({
|
|
24
|
+
ios: {
|
|
25
|
+
shadowColor: themeColors.shadow,
|
|
26
|
+
shadowOffset: { width: 0, height: 8 },
|
|
27
|
+
shadowOpacity: isDark ? 0.6 : 1,
|
|
28
|
+
shadowRadius: 24,
|
|
29
|
+
},
|
|
30
|
+
android: {
|
|
31
|
+
elevation: 8,
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
},
|
|
35
|
+
]}
|
|
36
|
+
accessibilityRole="alert"
|
|
37
|
+
accessibilityLiveRegion="polite"
|
|
38
|
+
>
|
|
39
|
+
{content}
|
|
40
|
+
</View>
|
|
41
|
+
);
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const styles = StyleSheet.create({
|
|
45
|
+
container: {
|
|
46
|
+
width: wp(88),
|
|
47
|
+
maxWidth: 400,
|
|
48
|
+
paddingHorizontal: 16,
|
|
49
|
+
paddingVertical: 14,
|
|
50
|
+
borderRadius: 24,
|
|
51
|
+
overflow: 'hidden',
|
|
52
|
+
flexDirection: 'row',
|
|
53
|
+
alignItems: 'center',
|
|
54
|
+
borderWidth: 1,
|
|
55
|
+
},
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
export default CustomToast;
|
|
@@ -1,28 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
} from '../utils/Pixel/Index';
|
|
7
|
-
|
|
8
|
-
const CustomToast = ({ content, theme = 'light' }) => {
|
|
9
|
-
const isDark = theme === 'dark';
|
|
10
|
-
const bg = isDark ? '#111827' : '#FFFFFF';
|
|
11
|
-
return (
|
|
12
|
-
<View style={[styles.customToast, { backgroundColor: bg }]}>
|
|
13
|
-
{content}
|
|
14
|
-
</View>
|
|
15
|
-
);
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const styles = StyleSheet.create({
|
|
19
|
-
customToast: {
|
|
20
|
-
padding: wp(1),
|
|
21
|
-
borderRadius: wp(2),
|
|
22
|
-
backgroundColor: 'white',
|
|
23
|
-
flexDirection: 'row',
|
|
24
|
-
alignItems: 'center',
|
|
25
|
-
},
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
export default CustomToast;
|
|
1
|
+
// Backward compatibility re-export
|
|
2
|
+
// The correct name is "CustomToast" — this file exists for consumers
|
|
3
|
+
// who imported the old misspelled name.
|
|
4
|
+
import CustomToast from './CustomToast';
|
|
5
|
+
export default CustomToast;
|
|
@@ -1,38 +1,142 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text, StyleSheet } from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
1
|
+
import React, { useEffect } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, Platform } from 'react-native';
|
|
3
|
+
import Animated, {
|
|
4
|
+
useSharedValue,
|
|
5
|
+
useAnimatedStyle,
|
|
6
|
+
withSpring,
|
|
7
|
+
} from 'react-native-reanimated';
|
|
8
|
+
import {
|
|
9
|
+
widthPercentageToDP as wp,
|
|
10
|
+
} from '../utils/Pixel/Index';
|
|
11
|
+
import { TOAST_THEME } from '../utils/theme';
|
|
12
|
+
import ProgressBar from './ProgressBar';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* EmojiToast — Toast with an emoji and bounce animation.
|
|
16
|
+
* Styled to match the premium design system.
|
|
17
|
+
*/
|
|
18
|
+
const EmojiToast = ({ title, message, emoji, theme = 'light', duration }) => {
|
|
19
|
+
const isDark = theme === 'dark';
|
|
20
|
+
const themeColors = TOAST_THEME[isDark ? 'dark' : 'light'];
|
|
21
|
+
const emojiScale = useSharedValue(0.3);
|
|
22
|
+
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
emojiScale.value = withSpring(1, { damping: 8, stiffness: 200 });
|
|
25
|
+
}, []);
|
|
26
|
+
|
|
27
|
+
const emojiAnimStyle = useAnimatedStyle(() => ({
|
|
28
|
+
transform: [{ scale: emojiScale.value }],
|
|
29
|
+
}));
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<View
|
|
33
|
+
style={[
|
|
34
|
+
styles.container,
|
|
35
|
+
{
|
|
36
|
+
backgroundColor: themeColors.background,
|
|
37
|
+
borderColor: themeColors.border,
|
|
38
|
+
...Platform.select({
|
|
39
|
+
ios: {
|
|
40
|
+
shadowColor: themeColors.shadow,
|
|
41
|
+
shadowOffset: { width: 0, height: 4 },
|
|
42
|
+
shadowOpacity: isDark ? 0.4 : 0.08,
|
|
43
|
+
shadowRadius: 12,
|
|
44
|
+
},
|
|
45
|
+
android: {
|
|
46
|
+
elevation: 6,
|
|
47
|
+
},
|
|
48
|
+
}),
|
|
49
|
+
},
|
|
50
|
+
]}
|
|
51
|
+
accessibilityRole="alert"
|
|
52
|
+
accessibilityLiveRegion="polite"
|
|
53
|
+
accessibilityLabel={[emoji, title, message].filter(Boolean).join('. ')}
|
|
54
|
+
>
|
|
55
|
+
<View style={styles.body}>
|
|
56
|
+
<Animated.View style={[styles.emojiBadge, emojiAnimStyle]}>
|
|
57
|
+
<Text style={styles.emojiText}>{emoji}</Text>
|
|
58
|
+
</Animated.View>
|
|
59
|
+
<View style={styles.textContainer}>
|
|
60
|
+
{title ? (
|
|
61
|
+
<Text
|
|
62
|
+
style={[styles.title, { color: themeColors.title }]}
|
|
63
|
+
numberOfLines={1}
|
|
64
|
+
>
|
|
65
|
+
{title}
|
|
66
|
+
</Text>
|
|
67
|
+
) : null}
|
|
68
|
+
{message ? (
|
|
69
|
+
<Text
|
|
70
|
+
style={[
|
|
71
|
+
styles.message,
|
|
72
|
+
{ color: themeColors.message },
|
|
73
|
+
!title && styles.messageSolo,
|
|
74
|
+
]}
|
|
75
|
+
numberOfLines={2}
|
|
76
|
+
>
|
|
77
|
+
{message}
|
|
78
|
+
</Text>
|
|
79
|
+
) : null}
|
|
80
|
+
</View>
|
|
81
|
+
</View>
|
|
82
|
+
{duration && duration !== Infinity && (
|
|
83
|
+
<ProgressBar
|
|
84
|
+
duration={duration}
|
|
85
|
+
color="#8B5CF6"
|
|
86
|
+
trackColor={themeColors.progressTrack}
|
|
87
|
+
/>
|
|
88
|
+
)}
|
|
89
|
+
</View>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
const styles = StyleSheet.create({
|
|
94
|
+
container: {
|
|
95
|
+
width: wp(92),
|
|
96
|
+
borderRadius: 16,
|
|
97
|
+
overflow: 'hidden',
|
|
98
|
+
borderWidth: 1,
|
|
99
|
+
},
|
|
100
|
+
body: {
|
|
101
|
+
flexDirection: 'row',
|
|
102
|
+
alignItems: 'center',
|
|
103
|
+
paddingHorizontal: 16,
|
|
104
|
+
paddingVertical: 14,
|
|
105
|
+
},
|
|
106
|
+
emojiBadge: {
|
|
107
|
+
width: 40,
|
|
108
|
+
height: 40,
|
|
109
|
+
borderRadius: 12,
|
|
110
|
+
backgroundColor: 'rgba(139, 92, 246, 0.1)',
|
|
111
|
+
alignItems: 'center',
|
|
112
|
+
justifyContent: 'center',
|
|
113
|
+
marginRight: 12,
|
|
114
|
+
},
|
|
115
|
+
emojiText: {
|
|
116
|
+
fontSize: 22,
|
|
117
|
+
},
|
|
118
|
+
textContainer: {
|
|
119
|
+
flex: 1,
|
|
120
|
+
justifyContent: 'center',
|
|
121
|
+
},
|
|
122
|
+
title: {
|
|
123
|
+
fontSize: 15,
|
|
124
|
+
fontWeight: '600',
|
|
125
|
+
letterSpacing: -0.2,
|
|
126
|
+
lineHeight: 20,
|
|
127
|
+
},
|
|
128
|
+
message: {
|
|
129
|
+
fontSize: 13,
|
|
130
|
+
fontWeight: '400',
|
|
131
|
+
marginTop: 2,
|
|
132
|
+
lineHeight: 18,
|
|
133
|
+
letterSpacing: -0.1,
|
|
134
|
+
},
|
|
135
|
+
messageSolo: {
|
|
136
|
+
fontSize: 14,
|
|
137
|
+
fontWeight: '500',
|
|
138
|
+
lineHeight: 20,
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
export default React.memo(EmojiToast);
|
|
@@ -1,52 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
<Text style={[styles.text, { color: textColor }]}>{message}</Text>
|
|
25
|
-
</View>
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const styles = StyleSheet.create({
|
|
30
|
-
container: {
|
|
31
|
-
width: wp(87),
|
|
32
|
-
height: hp(6.8),
|
|
33
|
-
paddingHorizontal: wp(4),
|
|
34
|
-
borderRadius: wp(4),
|
|
35
|
-
// backgroundColor: '#f8c4c4',
|
|
36
|
-
backgroundColor: '#F7F7FC',
|
|
37
|
-
alignItems: 'center',
|
|
38
|
-
flexDirection: 'row'
|
|
39
|
-
},
|
|
40
|
-
text: {
|
|
41
|
-
fontSize: hp(2.3),
|
|
42
|
-
color: 'black',
|
|
43
|
-
fontWeight: '500',
|
|
44
|
-
paddingHorizontal: wp(3)
|
|
45
|
-
},
|
|
46
|
-
lottie: {
|
|
47
|
-
width: wp(8.5),
|
|
48
|
-
height: hp(4.5),
|
|
49
|
-
},
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
export default ErrorToast;
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import BaseToast from './BaseToast';
|
|
3
|
+
import { CrossIcon } from './icons';
|
|
4
|
+
import { TOAST_COLORS, TOAST_DEFAULTS } from '../utils/theme';
|
|
5
|
+
|
|
6
|
+
const ErrorToast = ({ title, message, theme = 'light', duration }) => {
|
|
7
|
+
const isDark = theme === 'dark';
|
|
8
|
+
const colors = TOAST_COLORS.error;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<BaseToast
|
|
12
|
+
icon={<CrossIcon size={TOAST_DEFAULTS.iconSize} color={isDark ? colors.iconDark : colors.icon} />}
|
|
13
|
+
title={title || null}
|
|
14
|
+
message={message || null}
|
|
15
|
+
accentColor={colors.accent}
|
|
16
|
+
toastType="error"
|
|
17
|
+
theme={theme}
|
|
18
|
+
duration={duration}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default React.memo(ErrorToast);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import BaseToast from './BaseToast';
|
|
3
|
+
import { InfoIcon } from './icons';
|
|
4
|
+
import { TOAST_COLORS, TOAST_DEFAULTS } from '../utils/theme';
|
|
5
|
+
|
|
6
|
+
const InfoToast = ({ title, message, theme = 'light', duration }) => {
|
|
7
|
+
const isDark = theme === 'dark';
|
|
8
|
+
const colors = TOAST_COLORS.info;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<BaseToast
|
|
12
|
+
icon={<InfoIcon size={TOAST_DEFAULTS.iconSize} color={isDark ? colors.iconDark : colors.icon} />}
|
|
13
|
+
title={title || null}
|
|
14
|
+
message={message || null}
|
|
15
|
+
accentColor={colors.accent}
|
|
16
|
+
toastType="info"
|
|
17
|
+
theme={theme}
|
|
18
|
+
duration={duration}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default React.memo(InfoToast);
|