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