mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
1import React from 'react'
2import {Animated, StyleProp, View, ViewStyle} from 'react-native'
3import {useAnimatedValue} from 'lib/hooks/useAnimatedValue'
4
5type CreateAnimFn = (interp: Animated.Value) => Animated.CompositeAnimation
6type FinishCb = () => void
7
8interface TriggeredAnimation {
9 start: CreateAnimFn
10 style: (
11 interp: Animated.Value,
12 ) => Animated.WithAnimatedValue<StyleProp<ViewStyle>>
13}
14
15export interface TriggerableAnimatedRef {
16 trigger: (anim: TriggeredAnimation, onFinish?: FinishCb) => void
17}
18
19type TriggerableAnimatedProps = React.PropsWithChildren<{}>
20
21type PropsInner = TriggerableAnimatedProps & {
22 anim: TriggeredAnimation
23 onFinish: () => void
24}
25
26export const TriggerableAnimated = React.forwardRef<
27 TriggerableAnimatedRef,
28 TriggerableAnimatedProps
29>(({children, ...props}, ref) => {
30 const [anim, setAnim] = React.useState<TriggeredAnimation | undefined>(
31 undefined,
32 )
33 const [finishCb, setFinishCb] = React.useState<FinishCb | undefined>(
34 undefined,
35 )
36 React.useImperativeHandle(ref, () => ({
37 trigger(v: TriggeredAnimation, cb?: FinishCb) {
38 setFinishCb(() => cb) // note- wrap in function due to react behaviors around setstate
39 setAnim(v)
40 },
41 }))
42 const onFinish = () => {
43 finishCb?.()
44 setAnim(undefined)
45 setFinishCb(undefined)
46 }
47 return (
48 <View key="triggerable">
49 {anim ? (
50 <AnimatingView anim={anim} onFinish={onFinish} {...props}>
51 {children}
52 </AnimatingView>
53 ) : (
54 children
55 )}
56 </View>
57 )
58})
59
60function AnimatingView({
61 anim,
62 onFinish,
63 children,
64}: React.PropsWithChildren<PropsInner>) {
65 const interp = useAnimatedValue(0)
66 React.useEffect(() => {
67 anim?.start(interp).start(() => {
68 onFinish()
69 })
70 })
71 const animStyle = anim?.style(interp)
72 return <Animated.View style={animStyle}>{children}</Animated.View>
73}