69 lines
1.4 KiB
JavaScript
69 lines
1.4 KiB
JavaScript
import React, { useCallback, useEffect } from "react";
|
|
import { Pressable } from "react-native";
|
|
import Animated, {
|
|
cancelAnimation,
|
|
useAnimatedStyle,
|
|
useSharedValue,
|
|
withSpring,
|
|
} from "react-native-reanimated";
|
|
|
|
export default function PressableScale({
|
|
children,
|
|
onPress,
|
|
style,
|
|
contentStyle,
|
|
hitSlop = 8,
|
|
disabled = false,
|
|
scaleTo = 1.5,
|
|
spring = { damping: 18, stiffness: 220, mass: 0.8 },
|
|
...rest
|
|
}) {
|
|
const sv = useSharedValue(1);
|
|
|
|
const rStyle = useAnimatedStyle(() => ({
|
|
transform: [{ scale: sv.value }],
|
|
}));
|
|
|
|
const pressIn = useCallback(() => {
|
|
if (disabled) return;
|
|
cancelAnimation(sv);
|
|
sv.value = 1;
|
|
sv.value = withSpring(scaleTo, spring);
|
|
}, [disabled, scaleTo, spring, sv]);
|
|
|
|
const reset = useCallback(() => {
|
|
cancelAnimation(sv);
|
|
sv.value = withSpring(1, spring);
|
|
}, [spring, sv]);
|
|
|
|
useEffect(
|
|
() => () => {
|
|
cancelAnimation(sv);
|
|
sv.value = 1;
|
|
},
|
|
[sv]
|
|
);
|
|
|
|
return (
|
|
<Pressable
|
|
onPressIn={pressIn}
|
|
onPressOut={reset}
|
|
onTouchCancel={reset}
|
|
onHoverOut={reset} // web
|
|
onMouseUp={reset} // web
|
|
onMouseLeave={reset} // web
|
|
onBlur={reset}
|
|
onPress={(e) => {
|
|
onPress?.(e);
|
|
reset();
|
|
}}
|
|
hitSlop={hitSlop}
|
|
disabled={disabled}
|
|
style={style}
|
|
{...rest}
|
|
>
|
|
<Animated.View style={[contentStyle, rStyle]}>{children}</Animated.View>
|
|
</Pressable>
|
|
);
|
|
}
|