Files
musicland/src/components/PressableScale.js
T
2025-10-03 10:43:08 +02:00

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>
);
}