forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1import {
2 Pressable,
3 type PressableProps,
4 type StyleProp,
5 type ViewStyle,
6} from 'react-native'
7import Animated, {
8 cancelAnimation,
9 useAnimatedStyle,
10 useReducedMotion,
11 useSharedValue,
12 withTiming,
13} from 'react-native-reanimated'
14
15import {isTouchDevice} from '#/lib/browser'
16import {isNative} from '#/platform/detection'
17
18const DEFAULT_TARGET_SCALE = isNative || isTouchDevice ? 0.98 : 1
19
20const AnimatedPressable = Animated.createAnimatedComponent(Pressable)
21
22export function PressableScale({
23 targetScale = DEFAULT_TARGET_SCALE,
24 children,
25 style,
26 onPressIn,
27 onPressOut,
28 ...rest
29}: {
30 targetScale?: number
31 style?: StyleProp<ViewStyle>
32} & Exclude<PressableProps, 'onPressIn' | 'onPressOut' | 'style'>) {
33 const reducedMotion = useReducedMotion()
34
35 const scale = useSharedValue(1)
36
37 const animatedStyle = useAnimatedStyle(() => ({
38 transform: [{scale: scale.get()}],
39 }))
40
41 return (
42 <AnimatedPressable
43 accessibilityRole="button"
44 onPressIn={e => {
45 if (onPressIn) {
46 onPressIn(e)
47 }
48 cancelAnimation(scale)
49 scale.set(() => withTiming(targetScale, {duration: 100}))
50 }}
51 onPressOut={e => {
52 if (onPressOut) {
53 onPressOut(e)
54 }
55 cancelAnimation(scale)
56 scale.set(() => withTiming(1, {duration: 100}))
57 }}
58 style={[!reducedMotion && animatedStyle, style]}
59 {...rest}>
60 {children}
61 </AnimatedPressable>
62 )
63}