react-native-toastier
Version:
A Fully Customizable Toast Component for React Native.
112 lines (101 loc) • 3.31 kB
Flow
import { useMemo, useRef } from "react";
import { Animated, Dimensions } from "react-native";
import { ToastProps } from "../types";
const width = Dimensions.get('window').width;
interface Props {
position: ToastProps['position'];
animation: ToastProps['animation'];
onClose: ToastProps['onClose'];
offset?: number;
}
const useToastState = ({ position, offset, animation = 'zoomIn', onClose }: Props) => {
const showToast = useRef(new Animated.Value(0)).current;
const zoomAnimation = useRef(new Animated.Value(0)).current;
const animatedValue = useMemo(() => {
if (animation === 'slide' && position === 'bottom') {
return offset || 100;
}
if (animation === 'slideLeft') {
return offset || -width;
}
if (animation === 'slideRight') {
return offset || width
}
return offset || -100
}, [animation, position, offset]);
const slideAnimation = new Animated.Value(animatedValue);
const _animations = [Animated.timing(showToast, {
toValue: 1,
duration: 300,
useNativeDriver: true
})];
const startAnimations = () => {
if (animation === 'zoomIn') {
_animations.push(
Animated.spring(zoomAnimation, {
toValue: 1,
friction: 6,
tension: 20,
useNativeDriver: true
})
)
}
if (['slide', 'slideLeft', 'slideRight'].includes(animation)) {
_animations.push(Animated.spring(slideAnimation, {
toValue: 0,
friction: 6,
tension: 20,
useNativeDriver: true
}))
}
Animated.parallel(_animations).start();
}
const finishAnimations = () => {
if (animation === 'zoomIn') {
_animations.push(
Animated.timing(zoomAnimation, {
toValue: 0,
duration: 300,
useNativeDriver: true
})
)
}
if (['slide', 'slideLeft', 'slideRight'].includes(animation)) {
_animations.push(Animated.timing(slideAnimation, {
toValue: animatedValue,
duration: 300,
useNativeDriver: true
}))
}
Animated.parallel(_animations).start(() => onClose?.());
}
const _animation = useMemo(() => {
if (animation === 'slide') {
return { transform: [{ translateY: slideAnimation }] }
}
if (['slideLeft', 'slideRight']?.includes(animation)) {
return { transform: [{ translateX: slideAnimation }] }
}
return {
transform: [
{
scale: zoomAnimation.interpolate({
inputRange: [0, 1],
outputRange: [0, 1]
})
}
]
}
}, [slideAnimation, zoomAnimation, animation, offset])
return {
state: {
showToast,
animation: _animation
},
action: {
startAnimations,
finishAnimations
}
}
}
export default useToastState;