react-native-earl-toastify 1.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/CHANGELOG.md +71 -0
- package/LICENSE +21 -0
- package/README.md +513 -0
- package/dist/Toast.d.ts +12 -0
- package/dist/Toast.d.ts.map +1 -0
- package/dist/Toast.js +143 -0
- package/dist/Toast.js.map +1 -0
- package/dist/ToastContainer.d.ts +12 -0
- package/dist/ToastContainer.d.ts.map +1 -0
- package/dist/ToastContainer.js +46 -0
- package/dist/ToastContainer.js.map +1 -0
- package/dist/ToastProvider.d.ts +22 -0
- package/dist/ToastProvider.d.ts.map +1 -0
- package/dist/ToastProvider.js +163 -0
- package/dist/ToastProvider.js.map +1 -0
- package/dist/animations.d.ts +54 -0
- package/dist/animations.d.ts.map +1 -0
- package/dist/animations.js +118 -0
- package/dist/animations.js.map +1 -0
- package/dist/icons.d.ts +12 -0
- package/dist/icons.d.ts.map +1 -0
- package/dist/icons.js +110 -0
- package/dist/icons.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.d.ts +63 -0
- package/dist/styles.d.ts.map +1 -0
- package/dist/styles.js +182 -0
- package/dist/styles.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/useToast.d.ts +40 -0
- package/dist/useToast.d.ts.map +1 -0
- package/dist/useToast.js +48 -0
- package/dist/useToast.js.map +1 -0
- package/dist/useToastAnimation.d.ts +24 -0
- package/dist/useToastAnimation.d.ts.map +1 -0
- package/dist/useToastAnimation.js +59 -0
- package/dist/useToastAnimation.js.map +1 -0
- package/package.json +58 -0
- package/src/Toast.tsx +250 -0
- package/src/ToastContainer.tsx +70 -0
- package/src/ToastProvider.tsx +271 -0
- package/src/animations.ts +161 -0
- package/src/icons.tsx +152 -0
- package/src/index.ts +41 -0
- package/src/styles.ts +208 -0
- package/src/types.ts +157 -0
- package/src/useToast.ts +53 -0
- package/src/useToastAnimation.ts +108 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { Animated, Dimensions } from "react-native";
|
|
2
|
+
import { ToastAnimation, ToastPosition } from "./types";
|
|
3
|
+
|
|
4
|
+
const { width: SCREEN_WIDTH, height: SCREEN_HEIGHT } = Dimensions.get("window");
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Animation configuration
|
|
8
|
+
*/
|
|
9
|
+
export interface AnimationConfig {
|
|
10
|
+
duration: number;
|
|
11
|
+
useNativeDriver: boolean;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Default animation configuration
|
|
16
|
+
*/
|
|
17
|
+
export const DEFAULT_ANIMATION_CONFIG: AnimationConfig = {
|
|
18
|
+
duration: 300,
|
|
19
|
+
useNativeDriver: true,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Get initial animated values based on animation type
|
|
24
|
+
*/
|
|
25
|
+
export const getInitialAnimatedValues = (
|
|
26
|
+
animation: ToastAnimation,
|
|
27
|
+
position: ToastPosition,
|
|
28
|
+
): { opacity: number; translateX: number; translateY: number } => {
|
|
29
|
+
switch (animation) {
|
|
30
|
+
case "fade":
|
|
31
|
+
return { opacity: 0, translateX: 0, translateY: 0 };
|
|
32
|
+
case "up":
|
|
33
|
+
return {
|
|
34
|
+
opacity: 1,
|
|
35
|
+
translateX: 0,
|
|
36
|
+
translateY: position === "bottom" ? 100 : -100,
|
|
37
|
+
};
|
|
38
|
+
case "down":
|
|
39
|
+
return {
|
|
40
|
+
opacity: 1,
|
|
41
|
+
translateX: 0,
|
|
42
|
+
translateY: position === "top" ? -100 : 100,
|
|
43
|
+
};
|
|
44
|
+
case "left":
|
|
45
|
+
return { opacity: 1, translateX: -SCREEN_WIDTH, translateY: 0 };
|
|
46
|
+
case "right":
|
|
47
|
+
return { opacity: 1, translateX: SCREEN_WIDTH, translateY: 0 };
|
|
48
|
+
case "none":
|
|
49
|
+
default:
|
|
50
|
+
return { opacity: 1, translateX: 0, translateY: 0 };
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Get final animated values (visible state)
|
|
56
|
+
*/
|
|
57
|
+
export const getFinalAnimatedValues = (): {
|
|
58
|
+
opacity: number;
|
|
59
|
+
translateX: number;
|
|
60
|
+
translateY: number;
|
|
61
|
+
} => {
|
|
62
|
+
return { opacity: 1, translateX: 0, translateY: 0 };
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get exit animated values based on animation type
|
|
67
|
+
*/
|
|
68
|
+
export const getExitAnimatedValues = (
|
|
69
|
+
animation: ToastAnimation,
|
|
70
|
+
position: ToastPosition,
|
|
71
|
+
): { opacity: number; translateX: number; translateY: number } => {
|
|
72
|
+
switch (animation) {
|
|
73
|
+
case "fade":
|
|
74
|
+
return { opacity: 0, translateX: 0, translateY: 0 };
|
|
75
|
+
case "up":
|
|
76
|
+
return {
|
|
77
|
+
opacity: 1,
|
|
78
|
+
translateX: 0,
|
|
79
|
+
translateY: position === "top" ? -100 : 100,
|
|
80
|
+
};
|
|
81
|
+
case "down":
|
|
82
|
+
return {
|
|
83
|
+
opacity: 1,
|
|
84
|
+
translateX: 0,
|
|
85
|
+
translateY: position === "bottom" ? 100 : -100,
|
|
86
|
+
};
|
|
87
|
+
case "left":
|
|
88
|
+
return { opacity: 1, translateX: -SCREEN_WIDTH, translateY: 0 };
|
|
89
|
+
case "right":
|
|
90
|
+
return { opacity: 1, translateX: SCREEN_WIDTH, translateY: 0 };
|
|
91
|
+
case "none":
|
|
92
|
+
default:
|
|
93
|
+
return { opacity: 0, translateX: 0, translateY: 0 };
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Create enter animation
|
|
99
|
+
*/
|
|
100
|
+
export const createEnterAnimation = (
|
|
101
|
+
animatedValues: {
|
|
102
|
+
opacity: Animated.Value;
|
|
103
|
+
translateX: Animated.Value;
|
|
104
|
+
translateY: Animated.Value;
|
|
105
|
+
},
|
|
106
|
+
config: AnimationConfig = DEFAULT_ANIMATION_CONFIG,
|
|
107
|
+
): Animated.CompositeAnimation => {
|
|
108
|
+
const finalValues = getFinalAnimatedValues();
|
|
109
|
+
|
|
110
|
+
return Animated.parallel([
|
|
111
|
+
Animated.timing(animatedValues.opacity, {
|
|
112
|
+
toValue: finalValues.opacity,
|
|
113
|
+
duration: config.duration,
|
|
114
|
+
useNativeDriver: config.useNativeDriver,
|
|
115
|
+
}),
|
|
116
|
+
Animated.timing(animatedValues.translateX, {
|
|
117
|
+
toValue: finalValues.translateX,
|
|
118
|
+
duration: config.duration,
|
|
119
|
+
useNativeDriver: config.useNativeDriver,
|
|
120
|
+
}),
|
|
121
|
+
Animated.timing(animatedValues.translateY, {
|
|
122
|
+
toValue: finalValues.translateY,
|
|
123
|
+
duration: config.duration,
|
|
124
|
+
useNativeDriver: config.useNativeDriver,
|
|
125
|
+
}),
|
|
126
|
+
]);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Create exit animation
|
|
131
|
+
*/
|
|
132
|
+
export const createExitAnimation = (
|
|
133
|
+
animatedValues: {
|
|
134
|
+
opacity: Animated.Value;
|
|
135
|
+
translateX: Animated.Value;
|
|
136
|
+
translateY: Animated.Value;
|
|
137
|
+
},
|
|
138
|
+
animation: ToastAnimation,
|
|
139
|
+
position: ToastPosition,
|
|
140
|
+
config: AnimationConfig = DEFAULT_ANIMATION_CONFIG,
|
|
141
|
+
): Animated.CompositeAnimation => {
|
|
142
|
+
const exitValues = getExitAnimatedValues(animation, position);
|
|
143
|
+
|
|
144
|
+
return Animated.parallel([
|
|
145
|
+
Animated.timing(animatedValues.opacity, {
|
|
146
|
+
toValue: exitValues.opacity,
|
|
147
|
+
duration: config.duration,
|
|
148
|
+
useNativeDriver: config.useNativeDriver,
|
|
149
|
+
}),
|
|
150
|
+
Animated.timing(animatedValues.translateX, {
|
|
151
|
+
toValue: exitValues.translateX,
|
|
152
|
+
duration: config.duration,
|
|
153
|
+
useNativeDriver: config.useNativeDriver,
|
|
154
|
+
}),
|
|
155
|
+
Animated.timing(animatedValues.translateY, {
|
|
156
|
+
toValue: exitValues.translateY,
|
|
157
|
+
duration: config.duration,
|
|
158
|
+
useNativeDriver: config.useNativeDriver,
|
|
159
|
+
}),
|
|
160
|
+
]);
|
|
161
|
+
};
|
package/src/icons.tsx
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { View, Text, StyleSheet } from "react-native";
|
|
3
|
+
import { ToastType } from "./types";
|
|
4
|
+
|
|
5
|
+
interface IconProps {
|
|
6
|
+
color: string;
|
|
7
|
+
size: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Simple SVG-like icons using View and Text components
|
|
12
|
+
* These are minimal default icons - users can replace with any icon library
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const SuccessIcon: React.FC<IconProps> = ({ color, size }) => (
|
|
16
|
+
<View
|
|
17
|
+
style={[
|
|
18
|
+
styles.iconCircle,
|
|
19
|
+
{ width: size, height: size, borderColor: color },
|
|
20
|
+
]}
|
|
21
|
+
>
|
|
22
|
+
<Text style={[styles.iconText, { color, fontSize: size * 0.6 }]}>
|
|
23
|
+
✓
|
|
24
|
+
</Text>
|
|
25
|
+
</View>
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
const WarningIcon: React.FC<IconProps> = ({ color, size }) => (
|
|
29
|
+
<View style={[styles.iconTriangle, { borderBottomColor: color }]}>
|
|
30
|
+
<Text style={[styles.warningText, { fontSize: size * 0.5 }]}>!</Text>
|
|
31
|
+
</View>
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const ErrorIcon: React.FC<IconProps> = ({ color, size }) => (
|
|
35
|
+
<View
|
|
36
|
+
style={[
|
|
37
|
+
styles.iconCircle,
|
|
38
|
+
{
|
|
39
|
+
width: size,
|
|
40
|
+
height: size,
|
|
41
|
+
borderColor: color,
|
|
42
|
+
backgroundColor: color,
|
|
43
|
+
},
|
|
44
|
+
]}
|
|
45
|
+
>
|
|
46
|
+
<Text
|
|
47
|
+
style={[
|
|
48
|
+
styles.iconText,
|
|
49
|
+
{ color: "#FFFFFF", fontSize: size * 0.6 },
|
|
50
|
+
]}
|
|
51
|
+
>
|
|
52
|
+
✕
|
|
53
|
+
</Text>
|
|
54
|
+
</View>
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const InfoIcon: React.FC<IconProps> = ({ color, size }) => (
|
|
58
|
+
<View
|
|
59
|
+
style={[
|
|
60
|
+
styles.iconCircle,
|
|
61
|
+
{ width: size, height: size, borderColor: color },
|
|
62
|
+
]}
|
|
63
|
+
>
|
|
64
|
+
<Text
|
|
65
|
+
style={[
|
|
66
|
+
styles.iconText,
|
|
67
|
+
{ color, fontSize: size * 0.6, fontWeight: "bold" },
|
|
68
|
+
]}
|
|
69
|
+
>
|
|
70
|
+
i
|
|
71
|
+
</Text>
|
|
72
|
+
</View>
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const DefaultIcon: React.FC<IconProps> = ({ color, size }) => (
|
|
76
|
+
<View
|
|
77
|
+
style={[
|
|
78
|
+
styles.iconCircle,
|
|
79
|
+
{ width: size, height: size, borderColor: color },
|
|
80
|
+
]}
|
|
81
|
+
>
|
|
82
|
+
<Text style={[styles.iconText, { color, fontSize: size * 0.5 }]}>
|
|
83
|
+
●
|
|
84
|
+
</Text>
|
|
85
|
+
</View>
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
const CloseIcon: React.FC<IconProps> = ({ color, size }) => (
|
|
89
|
+
<View
|
|
90
|
+
style={{
|
|
91
|
+
width: size,
|
|
92
|
+
height: size,
|
|
93
|
+
alignItems: "center",
|
|
94
|
+
justifyContent: "center",
|
|
95
|
+
}}
|
|
96
|
+
>
|
|
97
|
+
<Text
|
|
98
|
+
style={{
|
|
99
|
+
color,
|
|
100
|
+
fontSize: size,
|
|
101
|
+
lineHeight: size,
|
|
102
|
+
fontWeight: "300",
|
|
103
|
+
}}
|
|
104
|
+
>
|
|
105
|
+
×
|
|
106
|
+
</Text>
|
|
107
|
+
</View>
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Default icons for each toast type
|
|
112
|
+
*/
|
|
113
|
+
export const DefaultIcons: Record<ToastType | "close", React.FC<IconProps>> = {
|
|
114
|
+
success: SuccessIcon,
|
|
115
|
+
warning: WarningIcon,
|
|
116
|
+
error: ErrorIcon,
|
|
117
|
+
info: InfoIcon,
|
|
118
|
+
default: DefaultIcon,
|
|
119
|
+
custom: DefaultIcon,
|
|
120
|
+
close: CloseIcon,
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
const styles = StyleSheet.create({
|
|
124
|
+
iconCircle: {
|
|
125
|
+
borderWidth: 2,
|
|
126
|
+
borderRadius: 999,
|
|
127
|
+
alignItems: "center",
|
|
128
|
+
justifyContent: "center",
|
|
129
|
+
},
|
|
130
|
+
iconText: {
|
|
131
|
+
textAlign: "center",
|
|
132
|
+
includeFontPadding: false,
|
|
133
|
+
textAlignVertical: "center",
|
|
134
|
+
},
|
|
135
|
+
iconTriangle: {
|
|
136
|
+
width: 0,
|
|
137
|
+
height: 0,
|
|
138
|
+
borderLeftWidth: 10,
|
|
139
|
+
borderRightWidth: 10,
|
|
140
|
+
borderBottomWidth: 18,
|
|
141
|
+
borderLeftColor: "transparent",
|
|
142
|
+
borderRightColor: "transparent",
|
|
143
|
+
alignItems: "center",
|
|
144
|
+
justifyContent: "flex-end",
|
|
145
|
+
},
|
|
146
|
+
warningText: {
|
|
147
|
+
color: "#FFFFFF",
|
|
148
|
+
fontWeight: "bold",
|
|
149
|
+
position: "absolute",
|
|
150
|
+
bottom: -16,
|
|
151
|
+
},
|
|
152
|
+
});
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Main exports
|
|
2
|
+
export { ToastProvider } from "./ToastProvider";
|
|
3
|
+
export { useToast } from "./useToast";
|
|
4
|
+
export { Toast } from "./Toast";
|
|
5
|
+
export { ToastContainer } from "./ToastContainer";
|
|
6
|
+
|
|
7
|
+
// Types
|
|
8
|
+
export type {
|
|
9
|
+
ToastType,
|
|
10
|
+
ToastAnimation,
|
|
11
|
+
ToastPosition,
|
|
12
|
+
ToastConfig,
|
|
13
|
+
Toast as ToastData,
|
|
14
|
+
ToastContextValue,
|
|
15
|
+
ToastProviderConfig,
|
|
16
|
+
} from "./types";
|
|
17
|
+
|
|
18
|
+
// Styles (for customization)
|
|
19
|
+
export {
|
|
20
|
+
TOAST_COLORS,
|
|
21
|
+
getToastColors,
|
|
22
|
+
baseToastStyle,
|
|
23
|
+
getPositionalStyle,
|
|
24
|
+
getContainerStyle,
|
|
25
|
+
} from "./styles";
|
|
26
|
+
|
|
27
|
+
// Animation utilities (for advanced customization)
|
|
28
|
+
export {
|
|
29
|
+
getInitialAnimatedValues,
|
|
30
|
+
getFinalAnimatedValues,
|
|
31
|
+
getExitAnimatedValues,
|
|
32
|
+
createEnterAnimation,
|
|
33
|
+
createExitAnimation,
|
|
34
|
+
DEFAULT_ANIMATION_CONFIG,
|
|
35
|
+
} from "./animations";
|
|
36
|
+
|
|
37
|
+
// Animation hook
|
|
38
|
+
export { useToastAnimation } from "./useToastAnimation";
|
|
39
|
+
|
|
40
|
+
// Icons (for reference or custom implementations)
|
|
41
|
+
export { DefaultIcons } from "./icons";
|
package/src/styles.ts
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import { ViewStyle, TextStyle } from "react-native";
|
|
2
|
+
import { ToastType, ToastPosition } from "./types";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Color configuration for each toast type
|
|
6
|
+
* All colors meet WCAG 2.1 AA contrast requirements (4.5:1 minimum)
|
|
7
|
+
*/
|
|
8
|
+
export interface ToastColors {
|
|
9
|
+
background: string;
|
|
10
|
+
text: string;
|
|
11
|
+
icon: string;
|
|
12
|
+
border: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Toast type color schemes - accessible and visually distinct
|
|
17
|
+
*/
|
|
18
|
+
export const TOAST_COLORS: Record<ToastType, ToastColors> = {
|
|
19
|
+
success: {
|
|
20
|
+
background: "#ECFDF5",
|
|
21
|
+
text: "#065F46",
|
|
22
|
+
icon: "#10B981",
|
|
23
|
+
border: "#10B981",
|
|
24
|
+
},
|
|
25
|
+
warning: {
|
|
26
|
+
background: "#FFFBEB",
|
|
27
|
+
text: "#92400E",
|
|
28
|
+
icon: "#F59E0B",
|
|
29
|
+
border: "#F59E0B",
|
|
30
|
+
},
|
|
31
|
+
error: {
|
|
32
|
+
background: "#FEF2F2",
|
|
33
|
+
text: "#991B1B",
|
|
34
|
+
icon: "#EF4444",
|
|
35
|
+
border: "#EF4444",
|
|
36
|
+
},
|
|
37
|
+
info: {
|
|
38
|
+
background: "#EFF6FF",
|
|
39
|
+
text: "#1E40AF",
|
|
40
|
+
icon: "#3B82F6",
|
|
41
|
+
border: "#3B82F6",
|
|
42
|
+
},
|
|
43
|
+
default: {
|
|
44
|
+
background: "#F9FAFB",
|
|
45
|
+
text: "#374151",
|
|
46
|
+
icon: "#6B7280",
|
|
47
|
+
border: "#D1D5DB",
|
|
48
|
+
},
|
|
49
|
+
custom: {
|
|
50
|
+
background: "#F9FAFB",
|
|
51
|
+
text: "#374151",
|
|
52
|
+
icon: "#6B7280",
|
|
53
|
+
border: "#D1D5DB",
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get colors for a specific toast type
|
|
59
|
+
*/
|
|
60
|
+
export const getToastColors = (type: ToastType): ToastColors => {
|
|
61
|
+
return TOAST_COLORS[type] || TOAST_COLORS.default;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Base toast container styles
|
|
66
|
+
*/
|
|
67
|
+
export const baseToastStyle: ViewStyle = {
|
|
68
|
+
flexDirection: "row",
|
|
69
|
+
alignItems: "center",
|
|
70
|
+
paddingVertical: 14,
|
|
71
|
+
paddingHorizontal: 16,
|
|
72
|
+
minHeight: 52,
|
|
73
|
+
borderLeftWidth: 4,
|
|
74
|
+
shadowColor: "#000",
|
|
75
|
+
shadowOffset: { width: 0, height: 2 },
|
|
76
|
+
shadowOpacity: 0.1,
|
|
77
|
+
shadowRadius: 8,
|
|
78
|
+
elevation: 5,
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get toast style based on position
|
|
83
|
+
* Top/Bottom: Full width, no rounded corners
|
|
84
|
+
* Center: Rounded corners with margin
|
|
85
|
+
*/
|
|
86
|
+
export const getPositionalStyle = (position: ToastPosition): ViewStyle => {
|
|
87
|
+
if (position === "center") {
|
|
88
|
+
return {
|
|
89
|
+
marginHorizontal: 16,
|
|
90
|
+
borderRadius: 12,
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// Top or bottom - full width, no rounded corners
|
|
95
|
+
return {
|
|
96
|
+
marginHorizontal: 0,
|
|
97
|
+
borderRadius: 0,
|
|
98
|
+
};
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Container positioning styles
|
|
103
|
+
*/
|
|
104
|
+
export const getContainerStyle = (position: ToastPosition): ViewStyle => {
|
|
105
|
+
const baseContainer: ViewStyle = {
|
|
106
|
+
position: "absolute",
|
|
107
|
+
left: 0,
|
|
108
|
+
right: 0,
|
|
109
|
+
zIndex: 9999,
|
|
110
|
+
elevation: 9999,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
switch (position) {
|
|
114
|
+
case "top":
|
|
115
|
+
return {
|
|
116
|
+
...baseContainer,
|
|
117
|
+
top: 0,
|
|
118
|
+
};
|
|
119
|
+
case "bottom":
|
|
120
|
+
return {
|
|
121
|
+
...baseContainer,
|
|
122
|
+
bottom: 0,
|
|
123
|
+
};
|
|
124
|
+
case "center":
|
|
125
|
+
return {
|
|
126
|
+
...baseContainer,
|
|
127
|
+
top: 0,
|
|
128
|
+
bottom: 0,
|
|
129
|
+
justifyContent: "center",
|
|
130
|
+
};
|
|
131
|
+
default:
|
|
132
|
+
return {
|
|
133
|
+
...baseContainer,
|
|
134
|
+
top: 0,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Toast title text style (primary text, larger)
|
|
141
|
+
*/
|
|
142
|
+
export const titleStyle: TextStyle = {
|
|
143
|
+
fontSize: 15,
|
|
144
|
+
fontWeight: "600",
|
|
145
|
+
lineHeight: 20,
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Toast description text style (secondary text, smaller)
|
|
150
|
+
*/
|
|
151
|
+
export const descriptionStyle: TextStyle = {
|
|
152
|
+
fontSize: 13,
|
|
153
|
+
fontWeight: "400",
|
|
154
|
+
lineHeight: 18,
|
|
155
|
+
marginTop: 2,
|
|
156
|
+
opacity: 0.85,
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Toast message text style (when no title, used as main text)
|
|
161
|
+
*/
|
|
162
|
+
export const messageStyle: TextStyle = {
|
|
163
|
+
fontSize: 15,
|
|
164
|
+
fontWeight: "500",
|
|
165
|
+
flex: 1,
|
|
166
|
+
lineHeight: 20,
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Text container style for title + description
|
|
171
|
+
*/
|
|
172
|
+
export const textContainerStyle: ViewStyle = {
|
|
173
|
+
flex: 1,
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Toast icon container style
|
|
178
|
+
*/
|
|
179
|
+
export const iconContainerStyle: ViewStyle = {
|
|
180
|
+
marginRight: 12,
|
|
181
|
+
width: 24,
|
|
182
|
+
height: 24,
|
|
183
|
+
alignItems: "center",
|
|
184
|
+
justifyContent: "center",
|
|
185
|
+
};
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Close button style
|
|
189
|
+
*/
|
|
190
|
+
export const closeButtonStyle: ViewStyle = {
|
|
191
|
+
marginLeft: 12,
|
|
192
|
+
padding: 4,
|
|
193
|
+
borderRadius: 4,
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Safe area padding for different positions
|
|
198
|
+
*/
|
|
199
|
+
export const getSafeAreaPadding = (position: ToastPosition): ViewStyle => {
|
|
200
|
+
switch (position) {
|
|
201
|
+
case "top":
|
|
202
|
+
return { paddingTop: 50 }; // Account for status bar
|
|
203
|
+
case "bottom":
|
|
204
|
+
return { paddingBottom: 34 }; // Account for home indicator
|
|
205
|
+
default:
|
|
206
|
+
return {};
|
|
207
|
+
}
|
|
208
|
+
};
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ViewStyle, TextStyle } from "react-native";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Toast type determines the color scheme and default icon
|
|
6
|
+
*/
|
|
7
|
+
export type ToastType =
|
|
8
|
+
| "success"
|
|
9
|
+
| "warning"
|
|
10
|
+
| "error"
|
|
11
|
+
| "default"
|
|
12
|
+
| "info"
|
|
13
|
+
| "custom";
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Animation type for toast enter/exit
|
|
17
|
+
*/
|
|
18
|
+
export type ToastAnimation = "fade" | "up" | "down" | "left" | "right" | "none";
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Position of the toast on screen
|
|
22
|
+
*/
|
|
23
|
+
export type ToastPosition = "top" | "bottom" | "center";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Configuration options for a toast notification
|
|
27
|
+
*/
|
|
28
|
+
export interface ToastConfig {
|
|
29
|
+
/** Title to display in the toast (primary text, larger) */
|
|
30
|
+
title?: string;
|
|
31
|
+
|
|
32
|
+
/** Message/description to display in the toast (secondary text, smaller) */
|
|
33
|
+
message: string;
|
|
34
|
+
|
|
35
|
+
/** Type of toast - determines color scheme */
|
|
36
|
+
type?: ToastType;
|
|
37
|
+
|
|
38
|
+
/** Position on screen */
|
|
39
|
+
position?: ToastPosition;
|
|
40
|
+
|
|
41
|
+
/** Duration in milliseconds before auto-dismiss (0 = no auto-dismiss) */
|
|
42
|
+
duration?: number;
|
|
43
|
+
|
|
44
|
+
/** Animation type for entering */
|
|
45
|
+
animationIn?: ToastAnimation;
|
|
46
|
+
|
|
47
|
+
/** Animation type for exiting */
|
|
48
|
+
animationOut?: ToastAnimation;
|
|
49
|
+
|
|
50
|
+
/** Animation duration in milliseconds */
|
|
51
|
+
animationDuration?: number;
|
|
52
|
+
|
|
53
|
+
/** Whether toast can be dismissed by tapping */
|
|
54
|
+
dismissable?: boolean;
|
|
55
|
+
|
|
56
|
+
/** Custom icon element (e.g., from react-native-lucide) */
|
|
57
|
+
icon?: ReactNode;
|
|
58
|
+
|
|
59
|
+
/** Hide the default icon */
|
|
60
|
+
hideIcon?: boolean;
|
|
61
|
+
|
|
62
|
+
/** Custom background color (for 'custom' type) */
|
|
63
|
+
backgroundColor?: string;
|
|
64
|
+
|
|
65
|
+
/** Custom text color (for 'custom' type) */
|
|
66
|
+
textColor?: string;
|
|
67
|
+
|
|
68
|
+
/** Custom border color (for 'custom' type) */
|
|
69
|
+
borderColor?: string;
|
|
70
|
+
|
|
71
|
+
/** Custom container style */
|
|
72
|
+
style?: ViewStyle;
|
|
73
|
+
|
|
74
|
+
/** Custom text style */
|
|
75
|
+
textStyle?: TextStyle;
|
|
76
|
+
|
|
77
|
+
/** Callback when toast is shown */
|
|
78
|
+
onShow?: () => void;
|
|
79
|
+
|
|
80
|
+
/** Callback when toast is hidden */
|
|
81
|
+
onHide?: () => void;
|
|
82
|
+
|
|
83
|
+
/** Callback when toast is pressed */
|
|
84
|
+
onPress?: () => void;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Internal toast data with unique ID
|
|
89
|
+
*/
|
|
90
|
+
export interface Toast extends ToastConfig {
|
|
91
|
+
id: string;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Toast context value for useToast hook
|
|
96
|
+
*/
|
|
97
|
+
export interface ToastContextValue {
|
|
98
|
+
/** Show a toast with configuration */
|
|
99
|
+
show: (config: ToastConfig) => string;
|
|
100
|
+
|
|
101
|
+
/** Show a success toast - can be (message) or (title, description) */
|
|
102
|
+
success: (
|
|
103
|
+
titleOrMessage: string,
|
|
104
|
+
descriptionOrConfig?: string | Partial<ToastConfig>,
|
|
105
|
+
config?: Partial<ToastConfig>,
|
|
106
|
+
) => string;
|
|
107
|
+
|
|
108
|
+
/** Show a warning toast - can be (message) or (title, description) */
|
|
109
|
+
warning: (
|
|
110
|
+
titleOrMessage: string,
|
|
111
|
+
descriptionOrConfig?: string | Partial<ToastConfig>,
|
|
112
|
+
config?: Partial<ToastConfig>,
|
|
113
|
+
) => string;
|
|
114
|
+
|
|
115
|
+
/** Show an error toast - can be (message) or (title, description) */
|
|
116
|
+
error: (
|
|
117
|
+
titleOrMessage: string,
|
|
118
|
+
descriptionOrConfig?: string | Partial<ToastConfig>,
|
|
119
|
+
config?: Partial<ToastConfig>,
|
|
120
|
+
) => string;
|
|
121
|
+
|
|
122
|
+
/** Show an info toast - can be (message) or (title, description) */
|
|
123
|
+
info: (
|
|
124
|
+
titleOrMessage: string,
|
|
125
|
+
descriptionOrConfig?: string | Partial<ToastConfig>,
|
|
126
|
+
config?: Partial<ToastConfig>,
|
|
127
|
+
) => string;
|
|
128
|
+
|
|
129
|
+
/** Hide a specific toast by ID */
|
|
130
|
+
hide: (id: string) => void;
|
|
131
|
+
|
|
132
|
+
/** Hide all toasts */
|
|
133
|
+
hideAll: () => void;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Global configuration for ToastProvider
|
|
138
|
+
*/
|
|
139
|
+
export interface ToastProviderConfig {
|
|
140
|
+
/** Default position for all toasts */
|
|
141
|
+
defaultPosition?: ToastPosition;
|
|
142
|
+
|
|
143
|
+
/** Default duration for all toasts */
|
|
144
|
+
defaultDuration?: number;
|
|
145
|
+
|
|
146
|
+
/** Default animation in */
|
|
147
|
+
defaultAnimationIn?: ToastAnimation;
|
|
148
|
+
|
|
149
|
+
/** Default animation out */
|
|
150
|
+
defaultAnimationOut?: ToastAnimation;
|
|
151
|
+
|
|
152
|
+
/** Default animation duration */
|
|
153
|
+
defaultAnimationDuration?: number;
|
|
154
|
+
|
|
155
|
+
/** Maximum number of toasts visible at once */
|
|
156
|
+
maxToasts?: number;
|
|
157
|
+
}
|