UNPKG

react-native-pressable-scale

Version:

A <PressableScale> and a supercharged <NativePressableScale> components for React Native

47 lines (46 loc) 2.1 kB
import React, { useCallback, useMemo } from 'react'; import { TouchableWithoutFeedback, View } from 'react-native'; import Reanimated, { useAnimatedStyle, useSharedValue, withSpring } from 'react-native-reanimated'; const ReanimatedTouchableWithoutFeedback = Reanimated.createAnimatedComponent(TouchableWithoutFeedback); /** * A Pressable that scales down when pressed. Uses the JS Pressability API. */ export function PressableScale(props) { const { activeScale = 0.95, weight = 'heavy', damping = 15, stiffness = 150, overshootClamping = true, restSpeedThreshold = 0.001, restDisplacementThreshold = 0.001, style, onPressIn: _onPressIn, onPressOut: _onPressOut, delayPressIn = 0, children, ...passThroughProps } = props; const mass = useMemo(() => { switch (weight) { case 'light': return 0.15; case 'medium': return 0.2; case 'heavy': default: return 0.3; } }, [weight]); const isPressedIn = useSharedValue(false); const springConfig = useMemo(() => ({ damping, mass, stiffness, overshootClamping, restSpeedThreshold, restDisplacementThreshold, }), [damping, mass, overshootClamping, restDisplacementThreshold, restSpeedThreshold, stiffness]); const touchableStyle = useAnimatedStyle(() => ({ transform: [{ scale: withSpring(isPressedIn.value ? activeScale : 1, springConfig) }] }), [ activeScale, isPressedIn, springConfig, ]); const onPressIn = useCallback((event) => { isPressedIn.value = true; _onPressIn?.(event); }, [_onPressIn, isPressedIn]); const onPressOut = useCallback((event) => { isPressedIn.value = false; _onPressOut?.(event); }, [_onPressOut, isPressedIn]); return (<ReanimatedTouchableWithoutFeedback delayPressIn={delayPressIn} onPressIn={onPressIn} onPressOut={onPressOut} style={touchableStyle} {...passThroughProps}> <View style={style}>{children}</View> </ReanimatedTouchableWithoutFeedback>); }