import React from 'react' ; import { AnimatableProps } from './style' ; import { useAnimation } from './useAnimation' ; export interface AnimateAPI { setVelocity < Prop extends keyof AnimatableProps > ( prop , value ) : void ; setCurrentValue < Prop extends keyof AnimatableProps > ( prop , value ) : void ; getCurrentValue < Prop extends keyof AnimatableProps > ( prop ) : AnimatableProps [ Prop ] ; } export const Animate = React . forwardRef ( ( { animate = true , tension = 230 , friction = 22 , delay = 0 , displacementThreshold = 0.001 , speedThreshold = 0.001 , clamp = false , onStart , onEnd , children , ... props } , forwardedRef ) => { const ref = React . useRef < HTMLElement > ( ) ; const animating = React . useRef ( false ) ; const [ , setState ] = React . useState ( null ) ; const latestChildren = React . useRef ( children ) ; latestChildren . current = children ; const springs = useAnimation ( ref , props , { animate , tension , friction , delay , displacementThreshold , speedThreshold , clamp , onStart ( ) { animating . current = true ; if ( typeof latestChildren . current === 'function' ) { setState ( null ) ; } onStart && onStart ( ) ; } , onEnd ( ) { animating . current = false ; if ( typeof latestChildren . current === 'function' ) { setState ( null ) ; } onEnd && onEnd ( ) ; } , } ) ; React . useImperativeHandle ( forwardedRef , ( ) => ( { setVelocity < Prop extends keyof AnimatableProps > ( prop , value ) { const spring = springs [ prop ] ; spring && spring . setVelocity ( value as any ) ; } , setCurrentValue < Prop extends keyof AnimatableProps > ( prop , value ) { const spring = springs [ prop ] ; spring && spring . setCurrentValue ( value as any ) ; } , getCurrentValue < Prop extends keyof AnimatableProps > ( prop ) { const spring = springs [ prop ] ; return spring && ( spring . getCurrentValue ( ) as AnimatableProps [ keyof AnimatableProps ] ) ; } , } ) , [ springs ] ) ; if ( typeof children === 'function' ) { children = children ( animating . current ) ; } const child = React . Children . only ( children ) ; return React . cloneElement ( child , { ref : ( element ) => { ref . current = element ; if ( child . ref && 'current' in child . ref ) { child . ref . current = element ; } else if ( typeof child . ref === 'function' ) { child . ref ( element ) ; } } , } ) ; } ) ; Animate . displayName = 'Animate' ;