UNPKG

react-native-pressable-opacity

Version:

A <PressableOpacity> and a supercharged <NativePressableOpacity> components for React Native

48 lines (47 loc) 2.04 kB
import React, { useMemo } from 'react'; import { Gesture, GestureDetector } from 'react-native-gesture-handler'; import Reanimated, { withDelay, Easing, useAnimatedStyle, useSharedValue, withTiming, useDerivedValue, runOnJS, } from 'react-native-reanimated'; import { PRESSABLE_IN_LIST_DELAY } from './Constants'; /** * A Pressable that lowers opacity when pressed. Uses the native responder system from react-native-gesture-handler instead of the JS Pressability API. */ export function NativePressableOpacity(props) { const { activeOpacity = 0.2, isInList, duration = 50, easing = Easing.linear, disabled = false, disabledOpacity = 0.3, ref, style, onPress, ...passThroughProps } = props; const isPressed = useSharedValue(false); const timingConfig = useMemo(() => ({ duration, easing }), [duration, easing]); const opacity = useDerivedValue(() => { if (disabled) { return withTiming(disabledOpacity, timingConfig); } else { if (isPressed.value) { if (isInList) { return withDelay(PRESSABLE_IN_LIST_DELAY, withTiming(activeOpacity, timingConfig)); } else { return withTiming(activeOpacity, timingConfig); } } else { return withTiming(1, timingConfig); } } }, [disabled, disabledOpacity, timingConfig, isPressed, isInList, activeOpacity]); const animatedStyle = useAnimatedStyle(() => ({ opacity: opacity.value }), [opacity]); let tap = Gesture.Tap() .onStart(() => { isPressed.value = true; }) .onEnd(() => { runOnJS(onPress)(); }) .onFinalize(() => { isPressed.value = false; }).enabled(!disabled).shouldCancelWhenOutside(true); if (ref != null) { tap = tap.withRef(ref); } return (<GestureDetector gesture={tap}> <Reanimated.View style={[style, animatedStyle]} {...passThroughProps}/> </GestureDetector>); }