UNPKG

react-native-modern-elements

Version:

A modern, customizable UI component library for React Native

158 lines (157 loc) 6.22 kB
import React, { memo, useEffect } from "react"; import { BackHandler, Modal, StatusBar, StyleSheet, TouchableWithoutFeedback, } from "react-native"; import Animated, { useAnimatedStyle, useSharedValue, withSpring, } from "react-native-reanimated"; const Modals = ({ visible, children, animation, onClose, modalContainer, }) => { const [showModal, setShowModal] = React.useState(visible); const translateX = useSharedValue(0); const translateY = useSharedValue(500); const scaleValue = useSharedValue(0); // open and close animation useEffect(() => { if (visible) { setShowModal(true); // Opening animations if (animation === "LeftToCenterCloseToRight") { // Start position (off-screen left) translateX.value = -500; // Animate to center (0) translateX.value = withSpring(0, { damping: 11.9, // smooth stiffness: 80, // smooth mass: 0.9, }); } else if (animation === "center") { scaleValue.value = 0; scaleValue.value = withSpring(1, { damping: 8, stiffness: 80, mass: 0.8, }); } else if (animation === "BottomToCenterCloseToBottom") { translateY.value = 500; translateY.value = withSpring(0, { damping: 10, stiffness: 70, mass: 0.8, }); } else if (animation === "RightToCenterCloseToLeft") { translateX.value = 500; // start from right translateX.value = withSpring(0, { damping: 11.9, stiffness: 80, mass: 0.9, }); } else if (animation === "LeftToCenterCloseToLeft") { translateX.value = -500; translateX.value = withSpring(0, { damping: 11.9, stiffness: 80, mass: 0.9, }); } else if (animation === "RightToCenterCloseToRight") { translateX.value = 500; translateX.value = withSpring(0, { damping: 11.9, stiffness: 80, mass: 0.9, }); } const backHandler = BackHandler.addEventListener("hardwareBackPress", () => { onClose(); return true; }); return () => backHandler.remove(); } else { // Closing animations if (animation === "LeftToCenterCloseToRight") { translateX.value = withSpring(500, { damping: 8, // smooth stiffness: 80, // smooth mass: 0.8, }); } else if (animation === "center") { scaleValue.value = withSpring(0, { damping: 14, stiffness: 90, mass: 1, }); } else if (animation === "BottomToCenterCloseToBottom") { translateY.value = withSpring(700, { damping: 10, stiffness: 80, mass: 0.8, }); } else if (animation === "RightToCenterCloseToLeft") { translateX.value = withSpring(-500, { damping: 11.9, stiffness: 80, mass: 0.9, }); // close to left } else if (animation === "LeftToCenterCloseToLeft") { translateX.value = withSpring(-500, { damping: 11.9, stiffness: 80, mass: 0.9, }); } else if (animation === "RightToCenterCloseToRight") { translateX.value = withSpring(500, { damping: 11.9, stiffness: 80, mass: 0.9, }); } setTimeout(() => setShowModal(false), 350); } }, [visible, animation, onClose, scaleValue, translateX, translateY]); const modalStyle = useAnimatedStyle(() => { let transformStyles = []; if (animation === "center") { transformStyles = [{ scale: scaleValue.value }]; } else if (animation === "LeftToCenterCloseToRight" || animation === "RightToCenterCloseToLeft" || animation === "LeftToCenterCloseToLeft" || animation === "RightToCenterCloseToRight") { transformStyles = [{ translateX: translateX.value }]; } else if (animation === "BottomToCenterCloseToBottom") { transformStyles = [{ translateY: translateY.value }]; } return { transform: transformStyles }; }); return (React.createElement(Modal, { transparent: true, visible: showModal, onRequestClose: onClose, statusBarTranslucent: true }, showModal && (React.createElement(StatusBar, { backgroundColor: "#797777", barStyle: "light-content", animated: true })), React.createElement(TouchableWithoutFeedback, { onPress: onClose }, React.createElement(Animated.View, { style: styles.modalBackground }, React.createElement(TouchableWithoutFeedback, null, React.createElement(Animated.View, { style: [styles.modalContainer, modalStyle, modalContainer] }, children)))))); }; const styles = StyleSheet.create({ modalBackground: { flex: 1, backgroundColor: "rgba(0, 0, 0, 0.5)", justifyContent: "center", alignItems: "center", overflow: "hidden", }, modalContainer: { width: "80%", backgroundColor: "white", paddingHorizontal: 20, paddingVertical: 30, borderRadius: 20, elevation: 20, }, }); export default memo(Modals);