Files
musicland/src/components/PressableScale.js
T
2026-01-12 16:01:32 +01: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>
)
}