import { useSharedValue, useAnimatedStyle, withSequence, withTiming, Easing, } from "react-native-reanimated"; /** * Horizontal-shake animation for invalid-input feedback. Wrap the target * in an `Animated.View` with the returned `animatedStyle`, then call * `shake()` to trigger. */ export function useShakeAnimation() { const rotation = useSharedValue(0); const flash = useSharedValue(0); const animatedStyle = useAnimatedStyle(() => ({ transform: [{ rotate: `${rotation.value}deg` }], })); const flashStyle = useAnimatedStyle(() => ({ opacity: flash.value, })); const shake = () => { rotation.value = withSequence( withTiming(-2.5, { duration: 55, easing: Easing.linear }), withTiming(2.5, { duration: 55, easing: Easing.linear }), withTiming(-2, { duration: 55, easing: Easing.linear }), withTiming(2, { duration: 55, easing: Easing.linear }), withTiming(-1, { duration: 45, easing: Easing.linear }), withTiming(0, { duration: 45, easing: Easing.linear }) ); flash.value = withSequence( withTiming(0.18, { duration: 120, easing: Easing.out(Easing.quad) }), withTiming(0, { duration: 380, easing: Easing.out(Easing.quad) }) ); }; return { animatedStyle, flashStyle, shake }; }