import type { PanGestureHandlerGestureEvent } from 'react-native-gesture-handler'; import { SharedValue, runOnJS, useAnimatedGestureHandler, withTiming, } from 'react-native-reanimated'; import { useAMAContext } from '../providers/AMAProvider'; type UseBottomSheetGestureHandler = { translateY: SharedValue; contentHeight: SharedValue; dragOpacity: SharedValue; closeDistance: number; overlayOpacity: number; onClose: () => void; minVelocityToClose: number; }; export const useBottomSheetGestureHandler = ({ translateY, closeDistance, contentHeight, onClose, dragOpacity, overlayOpacity, minVelocityToClose, }: UseBottomSheetGestureHandler) => { const { isReduceMotionEnabled } = useAMAContext(); const gestureHandler = useAnimatedGestureHandler< PanGestureHandlerGestureEvent, { y: number } >({ onStart: (_, context) => { context.y = translateY.value; }, onActive: (event, context) => { translateY.value = Math.max(0, context.y + event.translationY); const distance = contentHeight.value - translateY.value; const opacity = Math.min(distance / contentHeight.value, overlayOpacity); dragOpacity.value = opacity; }, onEnd: event => { const minimumDistanceToClose = contentHeight.value * closeDistance; const shouldCloseBottomSheet = translateY.value >= minimumDistanceToClose || event.velocityY >= minVelocityToClose; if (shouldCloseBottomSheet) { runOnJS(onClose)(); } else { translateY.value = withTiming(0, { duration: isReduceMotionEnabled ? 0 : 300, }); } }, }); return { gestureHandler, }; };