-
Notifications
You must be signed in to change notification settings - Fork 0
/
Toast.tsx
103 lines (95 loc) · 2.31 KB
/
Toast.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import * as React from 'react';
import { Animated, Text } from 'react-native';
import { useThemeContext } from '../contexts/ThemeContext';
import createStyleSheet from '../styles/createStyleSheet';
import type { ToastType } from '../types';
import { LocalIcon } from './Icon';
type ToastProps = React.PropsWithChildren<{
top?: number | undefined;
bottom?: number | undefined;
visible: boolean;
type: ToastType;
children: string;
}>;
const useOpacity = () => {
const opacity = React.useRef(new Animated.Value(0)).current;
const transition = React.useCallback(
(value: number) =>
Animated.timing(opacity, {
toValue: value,
duration: 500,
useNativeDriver: true,
}).start(),
[opacity]
);
return {
opacity,
show: () => transition(1),
hide: () => transition(0),
};
};
export default function Toast({
visible,
type,
children,
top,
bottom,
}: ToastProps): JSX.Element {
const { colors, fonts } = useThemeContext();
const { opacity, show, hide } = useOpacity();
const color = React.useMemo(() => {
if (type === 'error') {
return colors.error;
}
if (type === 'success') {
return colors.card.background;
}
return 'transparent';
}, [colors.card.background, colors.error, type]);
React.useEffect(() => {
const isVisible = (visible: boolean) => (visible ? show() : hide());
isVisible(visible);
}, [hide, show, visible]);
return (
<Animated.View
pointerEvents="none"
style={[
styles.container,
{ opacity, top, bottom, backgroundColor: 'rgba(0, 0, 0, 0.6)' },
]}
>
{type !== 'normal' && (
<LocalIcon
name={type === 'success' ? 'alert_success' : 'alert_error'}
color={color}
containerStyle={styles.icon}
/>
)}
<Text
numberOfLines={2}
style={[styles.text, { color: 'white' }, fonts.body]}
>
{children}
</Text>
</Animated.View>
);
}
const styles = createStyleSheet({
container: {
position: 'absolute',
paddingHorizontal: 12,
paddingVertical: 12,
justifyContent: 'center',
alignItems: 'center',
alignSelf: 'center',
borderRadius: 12,
flexDirection: 'row',
},
icon: {
marginRight: 4,
},
text: {
maxWidth: 240,
paddingHorizontal: 4,
},
});