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.
@@ -1,33 +1,24 @@
1
- // src/components/ToastHelpers/LoadingToast.js
2
- import React from 'react';
3
- import { View, Text, StyleSheet, ActivityIndicator } from 'react-native';
4
- import {
5
- heightPercentageToDP as hp,
6
- widthPercentageToDP as wp,
7
- } from '../utils/Pixel/Index';
8
-
9
- const LoadingToast = ({ message, theme = 'light' }) => {
10
- const isDark = theme === 'dark';
11
- const bg = isDark ? '#111827' : '#FFFFFF';
12
- const indicatorColor = isDark ? '#9CA3AF' : '#6B7280';
13
-
14
- return (
15
- <View style={[styles.toast, { backgroundColor: bg }]}>
16
- <ActivityIndicator size="small" color={indicatorColor} />
17
- {/** <Text style={styles.text}>{message}</Text> */}
18
- </View>
19
- );
20
- }
21
- const styles = StyleSheet.create({
22
- toast: {
23
- padding: wp(1),
24
- borderRadius: wp(10),
25
- backgroundColor: 'white',
26
- },
27
- text: {
28
- fontSize: hp(2.2),
29
- color: 'black',
30
- },
31
- });
32
-
33
- export default LoadingToast;
1
+ import React from 'react';
2
+ import BaseToast from './BaseToast';
3
+ import { LoadingSpinner } from './icons';
4
+ import { TOAST_COLORS, TOAST_DEFAULTS } from '../utils/theme';
5
+
6
+ const LoadingToast = ({ title, message, theme = 'light', duration }) => {
7
+ const isDark = theme === 'dark';
8
+ const colors = TOAST_COLORS.loading;
9
+
10
+ return (
11
+ <BaseToast
12
+ icon={<LoadingSpinner size={TOAST_DEFAULTS.iconSize - 2} color={isDark ? colors.iconDark : colors.icon} />}
13
+ title={title || null}
14
+ message={message || null}
15
+ accentColor={colors.accent}
16
+ toastType="loading"
17
+ theme={theme}
18
+ duration={duration}
19
+ showProgress={false}
20
+ />
21
+ );
22
+ };
23
+
24
+ export default React.memo(LoadingToast);
@@ -0,0 +1,67 @@
1
+ import React, { useEffect } from 'react';
2
+ import { StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withTiming,
7
+ withDelay,
8
+ Easing,
9
+ } from 'react-native-reanimated';
10
+
11
+ /**
12
+ * ProgressBar — flush edge-to-edge countdown indicator.
13
+ * Sits at the very bottom of the toast card, no padding.
14
+ */
15
+ const ProgressBar = ({ duration, color = '#22C55E', trackColor = 'rgba(0,0,0,0.05)' }) => {
16
+ const progress = useSharedValue(1);
17
+ const barOpacity = useSharedValue(0);
18
+
19
+ useEffect(() => {
20
+ if (duration && duration !== Infinity) {
21
+ barOpacity.value = withDelay(200, withTiming(1, { duration: 250 }));
22
+ progress.value = withTiming(0, {
23
+ duration: duration,
24
+ easing: Easing.linear,
25
+ });
26
+ }
27
+ }, [duration]);
28
+
29
+ const barStyle = useAnimatedStyle(() => ({
30
+ width: `${progress.value * 100}%`,
31
+ opacity: barOpacity.value,
32
+ }));
33
+
34
+ if (!duration || duration === Infinity) return null;
35
+
36
+ return (
37
+ <Animated.View style={styles.track}>
38
+ <Animated.View style={[styles.trackBg, { backgroundColor: trackColor }]} />
39
+ <Animated.View
40
+ style={[
41
+ styles.bar,
42
+ { backgroundColor: color },
43
+ barStyle,
44
+ ]}
45
+ />
46
+ </Animated.View>
47
+ );
48
+ };
49
+
50
+ const styles = StyleSheet.create({
51
+ track: {
52
+ height: 3,
53
+ width: '100%',
54
+ position: 'relative',
55
+ },
56
+ trackBg: {
57
+ ...StyleSheet.absoluteFillObject,
58
+ },
59
+ bar: {
60
+ height: '100%',
61
+ position: 'absolute',
62
+ left: 0,
63
+ top: 0,
64
+ },
65
+ });
66
+
67
+ export default React.memo(ProgressBar);
@@ -1,51 +1,23 @@
1
- import LottieView from 'lottie-react-native';
2
- import React from 'react';
3
- import { View, Text, StyleSheet } from 'react-native';
4
- import {
5
- heightPercentageToDP as hp,
6
- widthPercentageToDP as wp,
7
- } from '../utils/Pixel/Index';
8
-
9
- const SuccessToast = ({ message, theme = 'light' }) => {
10
- const isDark = theme === 'dark';
11
- const containerBg = isDark ? '#111827' : '#F7F7FC';
12
- const textColor = isDark ? '#F3F4F6' : '#064E3B';
13
-
14
- return (
15
- <View style={[styles.container, { backgroundColor: containerBg }]}>
16
- <LottieView
17
- source={require('../../assets/animated_Icon/SuccessAnimation.json')} // Replace with your success Lottie animation path
18
- autoPlay
19
- loop={false}
20
- style={styles.lottie}
21
- speed={1.2}
22
- />
23
- <Text style={[styles.text, { color: textColor }]}>{message}</Text>
24
- </View>
25
- );
26
- };
27
-
28
- const styles = StyleSheet.create({
29
- container: {
30
- width: wp(87),
31
- height: hp(6.8),
32
- paddingHorizontal: wp(4),
33
- borderRadius: wp(4),
34
- // backgroundColor: '#d2f7d2',
35
- backgroundColor: '#F7F7FC',
36
- alignItems: 'center',
37
- flexDirection: 'row',
38
- },
39
- text: {
40
- fontSize: hp(2.3),
41
- color: 'black',
42
- fontWeight: '500',
43
- paddingHorizontal: wp(3)
44
- },
45
- lottie: {
46
- width: wp(8),
47
- height: hp(4),
48
- },
49
- });
50
-
51
- export default SuccessToast;
1
+ import React from 'react';
2
+ import BaseToast from './BaseToast';
3
+ import { CheckIcon } from './icons';
4
+ import { TOAST_COLORS, TOAST_DEFAULTS } from '../utils/theme';
5
+
6
+ const SuccessToast = ({ title, message, theme = 'light', duration }) => {
7
+ const isDark = theme === 'dark';
8
+ const colors = TOAST_COLORS.success;
9
+
10
+ return (
11
+ <BaseToast
12
+ icon={<CheckIcon size={TOAST_DEFAULTS.iconSize} color={isDark ? colors.iconDark : colors.icon} />}
13
+ title={title || null}
14
+ message={message || null}
15
+ accentColor={colors.accent}
16
+ toastType="success"
17
+ theme={theme}
18
+ duration={duration}
19
+ />
20
+ );
21
+ };
22
+
23
+ export default React.memo(SuccessToast);
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import BaseToast from './BaseToast';
3
+ import { WarningIcon } from './icons';
4
+ import { TOAST_COLORS, TOAST_DEFAULTS } from '../utils/theme';
5
+
6
+ const WarningToast = ({ title, message, theme = 'light', duration }) => {
7
+ const isDark = theme === 'dark';
8
+ const colors = TOAST_COLORS.warning;
9
+
10
+ return (
11
+ <BaseToast
12
+ icon={<WarningIcon size={TOAST_DEFAULTS.iconSize} color={isDark ? colors.iconDark : colors.icon} />}
13
+ title={title || null}
14
+ message={message || null}
15
+ accentColor={colors.accent}
16
+ toastType="warning"
17
+ theme={theme}
18
+ duration={duration}
19
+ />
20
+ );
21
+ };
22
+
23
+ export default React.memo(WarningToast);
@@ -0,0 +1,98 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withTiming,
7
+ withDelay,
8
+ withSpring,
9
+ Easing,
10
+ interpolate,
11
+ } from 'react-native-reanimated';
12
+
13
+ /**
14
+ * CheckIcon — Animated checkmark.
15
+ * Clean two-stroke design that draws in sequentially.
16
+ */
17
+ const CheckIcon = ({ size = 22, color = '#16A34A', animated = true }) => {
18
+ const progress = useSharedValue(animated ? 0 : 1);
19
+
20
+ useEffect(() => {
21
+ if (animated) {
22
+ progress.value = withDelay(
23
+ 100,
24
+ withTiming(1, { duration: 450, easing: Easing.out(Easing.cubic) })
25
+ );
26
+ }
27
+ }, [animated]);
28
+
29
+ const stroke = Math.max(2, size * 0.12);
30
+ const shortLen = size * 0.3;
31
+ const longLen = size * 0.5;
32
+
33
+ const leftBarStyle = useAnimatedStyle(() => {
34
+ const p = interpolate(progress.value, [0, 0.45], [0, 1], 'clamp');
35
+ return {
36
+ transform: [{ rotate: '45deg' }, { scaleY: p }],
37
+ opacity: p,
38
+ };
39
+ });
40
+
41
+ const rightBarStyle = useAnimatedStyle(() => {
42
+ const p = interpolate(progress.value, [0.3, 1], [0, 1], 'clamp');
43
+ return {
44
+ transform: [{ rotate: '-45deg' }, { scaleY: p }],
45
+ opacity: p,
46
+ };
47
+ });
48
+
49
+ return (
50
+ <View style={[styles.container, { width: size, height: size }]}>
51
+ <View style={[styles.checkWrap, { width: size * 0.6, height: size * 0.6 }]}>
52
+ <Animated.View
53
+ style={[
54
+ {
55
+ position: 'absolute',
56
+ bottom: 0,
57
+ left: 0,
58
+ width: stroke,
59
+ height: shortLen,
60
+ backgroundColor: color,
61
+ borderRadius: stroke,
62
+ transformOrigin: 'bottom',
63
+ },
64
+ leftBarStyle,
65
+ ]}
66
+ />
67
+ <Animated.View
68
+ style={[
69
+ {
70
+ position: 'absolute',
71
+ bottom: 0,
72
+ left: stroke * 0.4,
73
+ width: stroke,
74
+ height: longLen,
75
+ backgroundColor: color,
76
+ borderRadius: stroke,
77
+ transformOrigin: 'bottom',
78
+ },
79
+ rightBarStyle,
80
+ ]}
81
+ />
82
+ </View>
83
+ </View>
84
+ );
85
+ };
86
+
87
+ const styles = StyleSheet.create({
88
+ container: {
89
+ alignItems: 'center',
90
+ justifyContent: 'center',
91
+ },
92
+ checkWrap: {
93
+ alignItems: 'center',
94
+ justifyContent: 'center',
95
+ },
96
+ });
97
+
98
+ export default React.memo(CheckIcon);
@@ -0,0 +1,84 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withTiming,
7
+ withDelay,
8
+ Easing,
9
+ interpolate,
10
+ } from 'react-native-reanimated';
11
+
12
+ /**
13
+ * CrossIcon — Animated X mark.
14
+ * Two strokes that draw in sequentially with a cross shape.
15
+ */
16
+ const CrossIcon = ({ size = 22, color = '#DC2626', animated = true }) => {
17
+ const progress = useSharedValue(animated ? 0 : 1);
18
+
19
+ useEffect(() => {
20
+ if (animated) {
21
+ progress.value = withDelay(
22
+ 100,
23
+ withTiming(1, { duration: 400, easing: Easing.out(Easing.cubic) })
24
+ );
25
+ }
26
+ }, [animated]);
27
+
28
+ const stroke = Math.max(2, size * 0.12);
29
+ const barLen = size * 0.5;
30
+
31
+ const bar1Style = useAnimatedStyle(() => {
32
+ const p = interpolate(progress.value, [0, 0.55], [0, 1], 'clamp');
33
+ return {
34
+ transform: [{ rotate: '45deg' }, { scaleY: p }],
35
+ opacity: p,
36
+ };
37
+ });
38
+
39
+ const bar2Style = useAnimatedStyle(() => {
40
+ const p = interpolate(progress.value, [0.3, 1], [0, 1], 'clamp');
41
+ return {
42
+ transform: [{ rotate: '-45deg' }, { scaleY: p }],
43
+ opacity: p,
44
+ };
45
+ });
46
+
47
+ return (
48
+ <View style={[styles.container, { width: size, height: size }]}>
49
+ <Animated.View
50
+ style={[
51
+ {
52
+ position: 'absolute',
53
+ width: stroke,
54
+ height: barLen,
55
+ backgroundColor: color,
56
+ borderRadius: stroke,
57
+ },
58
+ bar1Style,
59
+ ]}
60
+ />
61
+ <Animated.View
62
+ style={[
63
+ {
64
+ position: 'absolute',
65
+ width: stroke,
66
+ height: barLen,
67
+ backgroundColor: color,
68
+ borderRadius: stroke,
69
+ },
70
+ bar2Style,
71
+ ]}
72
+ />
73
+ </View>
74
+ );
75
+ };
76
+
77
+ const styles = StyleSheet.create({
78
+ container: {
79
+ alignItems: 'center',
80
+ justifyContent: 'center',
81
+ },
82
+ });
83
+
84
+ export default React.memo(CrossIcon);
@@ -0,0 +1,71 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withTiming,
7
+ withDelay,
8
+ Easing,
9
+ } from 'react-native-reanimated';
10
+
11
+ /**
12
+ * InfoIcon — Animated "i" information symbol.
13
+ * Dot + vertical bar that fade in.
14
+ */
15
+ const InfoIcon = ({ size = 22, color = '#2563EB', animated = true }) => {
16
+ const opacity = useSharedValue(animated ? 0 : 1);
17
+
18
+ useEffect(() => {
19
+ if (animated) {
20
+ opacity.value = withDelay(
21
+ 100,
22
+ withTiming(1, { duration: 350, easing: Easing.out(Easing.cubic) })
23
+ );
24
+ }
25
+ }, [animated]);
26
+
27
+ const contentStyle = useAnimatedStyle(() => ({
28
+ opacity: opacity.value,
29
+ }));
30
+
31
+ const dotSize = Math.max(3, size * 0.16);
32
+ const barW = Math.max(2, size * 0.12);
33
+ const barH = size * 0.35;
34
+
35
+ return (
36
+ <View style={[styles.container, { width: size, height: size }]}>
37
+ <Animated.View style={[styles.content, contentStyle]}>
38
+ <View
39
+ style={{
40
+ width: dotSize,
41
+ height: dotSize,
42
+ borderRadius: dotSize / 2,
43
+ backgroundColor: color,
44
+ marginBottom: size * 0.08,
45
+ }}
46
+ />
47
+ <View
48
+ style={{
49
+ width: barW,
50
+ height: barH,
51
+ backgroundColor: color,
52
+ borderRadius: barW,
53
+ }}
54
+ />
55
+ </Animated.View>
56
+ </View>
57
+ );
58
+ };
59
+
60
+ const styles = StyleSheet.create({
61
+ container: {
62
+ alignItems: 'center',
63
+ justifyContent: 'center',
64
+ },
65
+ content: {
66
+ alignItems: 'center',
67
+ justifyContent: 'center',
68
+ },
69
+ });
70
+
71
+ export default React.memo(InfoIcon);
@@ -0,0 +1,78 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withRepeat,
7
+ withTiming,
8
+ Easing,
9
+ } from 'react-native-reanimated';
10
+
11
+ /**
12
+ * LoadingSpinner — Smooth spinning arc.
13
+ * Thin track with a spinning colored arc segment.
14
+ */
15
+ const LoadingSpinner = ({ size = 22, color = '#7C3AED' }) => {
16
+ const rotation = useSharedValue(0);
17
+
18
+ useEffect(() => {
19
+ rotation.value = withRepeat(
20
+ withTiming(360, { duration: 850, easing: Easing.linear }),
21
+ -1,
22
+ false
23
+ );
24
+ }, []);
25
+
26
+ const spinStyle = useAnimatedStyle(() => ({
27
+ transform: [{ rotate: `${rotation.value}deg` }],
28
+ }));
29
+
30
+ const arcW = Math.max(2, size * 0.11);
31
+
32
+ return (
33
+ <View style={[styles.container, { width: size, height: size }]}>
34
+ <View
35
+ style={[
36
+ styles.track,
37
+ {
38
+ width: size,
39
+ height: size,
40
+ borderRadius: size / 2,
41
+ borderWidth: arcW,
42
+ borderColor: color + '20',
43
+ },
44
+ ]}
45
+ />
46
+ <Animated.View
47
+ style={[
48
+ styles.arc,
49
+ {
50
+ width: size,
51
+ height: size,
52
+ borderRadius: size / 2,
53
+ borderWidth: arcW,
54
+ borderColor: 'transparent',
55
+ borderTopColor: color,
56
+ borderRightColor: color + '50',
57
+ },
58
+ spinStyle,
59
+ ]}
60
+ />
61
+ </View>
62
+ );
63
+ };
64
+
65
+ const styles = StyleSheet.create({
66
+ container: {
67
+ alignItems: 'center',
68
+ justifyContent: 'center',
69
+ },
70
+ track: {
71
+ position: 'absolute',
72
+ },
73
+ arc: {
74
+ position: 'absolute',
75
+ },
76
+ });
77
+
78
+ export default React.memo(LoadingSpinner);
@@ -0,0 +1,84 @@
1
+ import React, { useEffect } from 'react';
2
+ import { View, StyleSheet } from 'react-native';
3
+ import Animated, {
4
+ useSharedValue,
5
+ useAnimatedStyle,
6
+ withTiming,
7
+ withDelay,
8
+ withSequence,
9
+ Easing,
10
+ } from 'react-native-reanimated';
11
+
12
+ /**
13
+ * WarningIcon — Animated exclamation mark with subtle shake.
14
+ * Bar + dot that fade in, followed by a quick shake.
15
+ */
16
+ const WarningIcon = ({ size = 22, color = '#D97706', animated = true }) => {
17
+ const opacity = useSharedValue(animated ? 0 : 1);
18
+ const shake = useSharedValue(0);
19
+
20
+ useEffect(() => {
21
+ if (animated) {
22
+ opacity.value = withDelay(
23
+ 100,
24
+ withTiming(1, { duration: 350, easing: Easing.out(Easing.cubic) })
25
+ );
26
+ shake.value = withDelay(
27
+ 350,
28
+ withSequence(
29
+ withTiming(-2.5, { duration: 40 }),
30
+ withTiming(2.5, { duration: 40 }),
31
+ withTiming(-1.5, { duration: 40 }),
32
+ withTiming(1.5, { duration: 40 }),
33
+ withTiming(0, { duration: 40 })
34
+ )
35
+ );
36
+ }
37
+ }, [animated]);
38
+
39
+ const contentStyle = useAnimatedStyle(() => ({
40
+ opacity: opacity.value,
41
+ transform: [{ translateX: shake.value }],
42
+ }));
43
+
44
+ const barW = Math.max(2, size * 0.12);
45
+ const barH = size * 0.35;
46
+ const dotSize = Math.max(3, size * 0.16);
47
+
48
+ return (
49
+ <View style={[styles.container, { width: size, height: size }]}>
50
+ <Animated.View style={[styles.content, contentStyle]}>
51
+ <View
52
+ style={{
53
+ width: barW,
54
+ height: barH,
55
+ backgroundColor: color,
56
+ borderRadius: barW,
57
+ marginBottom: size * 0.08,
58
+ }}
59
+ />
60
+ <View
61
+ style={{
62
+ width: dotSize,
63
+ height: dotSize,
64
+ borderRadius: dotSize / 2,
65
+ backgroundColor: color,
66
+ }}
67
+ />
68
+ </Animated.View>
69
+ </View>
70
+ );
71
+ };
72
+
73
+ const styles = StyleSheet.create({
74
+ container: {
75
+ alignItems: 'center',
76
+ justifyContent: 'center',
77
+ },
78
+ content: {
79
+ alignItems: 'center',
80
+ justifyContent: 'center',
81
+ },
82
+ });
83
+
84
+ export default React.memo(WarningIcon);
@@ -0,0 +1,5 @@
1
+ export { default as CheckIcon } from './CheckIcon';
2
+ export { default as CrossIcon } from './CrossIcon';
3
+ export { default as InfoIcon } from './InfoIcon';
4
+ export { default as WarningIcon } from './WarningIcon';
5
+ export { default as LoadingSpinner } from './LoadingSpinner';