import React, { useEffect, useRef } from 'react' import { Animated, Dimensions, Modal, PanResponder, StyleSheet, View } from 'react-native' import { useSafeAreaInsets } from 'react-native-safe-area-context' import { useTheme } from '@utils/styles/ThemeManager' import { StyleConstants } from '@utils/styles/constants' import { ButtonRow } from '@components/Button' export interface Props { children: React.ReactNode visible: boolean handleDismiss: () => void } const BottomSheet: React.FC = ({ children, visible, handleDismiss }) => { const { theme } = useTheme() const insets = useSafeAreaInsets() const panY = useRef(new Animated.Value(Dimensions.get('screen').height)) .current const top = panY.interpolate({ inputRange: [-1, 0, 1], outputRange: [0, 0, 1] }) const resetModal = Animated.timing(panY, { toValue: 0, duration: 300, useNativeDriver: false }) const closeModal = Animated.timing(panY, { toValue: Dimensions.get('screen').height, duration: 350, useNativeDriver: false }) const panResponder = useRef( PanResponder.create({ onStartShouldSetPanResponder: () => true, onMoveShouldSetPanResponder: () => true, onPanResponderMove: Animated.event([null, { dy: panY }], { useNativeDriver: false }), onPanResponderRelease: (e, gs) => { if (gs.dy > 0 && gs.vy > 1) { return closeModal.start(() => handleDismiss()) } else if (gs.dy === 0 && gs.vy === 0) { return closeModal.start(() => handleDismiss()) } return resetModal.start() } }) ).current useEffect(() => { if (visible) { resetModal.start() } }, [visible]) return ( {children} closeModal.start(() => handleDismiss())} text='取消' /> ) } const styles = StyleSheet.create({ overlay: { flex: 1, justifyContent: 'flex-end' }, container: { paddingTop: StyleConstants.Spacing.M }, handle: { alignSelf: 'center', width: StyleConstants.Spacing.S * 8, height: StyleConstants.Spacing.S / 2, borderRadius: 100, top: -StyleConstants.Spacing.M * 2 } }) export default BottomSheet