import * as React from 'react' ; import { Keyboard , StyleProp , ViewStyle } from 'react-native' ; import ViewPager from '@react-native-community/viewpager' ; import Animated from 'react-native-reanimated' ; import { NavigationState , Route , Listener , PagerCommonProps , EventEmitterProps , } from 'react-native-tab-view/src/types' ; const AnimatedViewPager = Animated . createAnimatedComponent ( ViewPager ) ; type Props < T extends Route > = PagerCommonProps & { onIndexChange : ( index : number ) => void ; navigationState : NavigationState < T > ; children : ( props : EventEmitterProps & { position : Animated . Node < number > ; render : ( children : React . ReactNode ) => React . ReactNode ; jumpTo : ( key : string ) => void ; } ) => React . ReactNode ; style ? : StyleProp < ViewStyle > ; orientation ? : 'vertical' | 'horizontal' ; transition ? : 'scroll' | 'curl' ; showPageIndicator ? : boolean ; pageMargin ? : number ; overdrag ? : boolean ; overScrollMode ? : 'always' | 'never' | 'auto' ; } ; const { event , add } = Animated ; export default class ViewPagerBackend < T extends Route > extends React . Component < Props < T > > { static defaultProps = { onIndexChange : ( ) => { } , swipeEnabled : true , } ; componentDidUpdate ( prevProps ) { if ( prevProps . navigationState . index !== this . props . navigationState . index && ! this . justScrolled ) { this . jumpToIndex ( this . props . navigationState . index ) ; } this . justScrolled = false ; } private enterListeners : Listener [ ] = [ ] ; private jumpToIndex = ( index ) => { this . ref . current . getNode ( ) . setPage ( index ) ; } ; private jumpTo = ( key ) => { const { navigationState , keyboardDismissMode , onIndexChange } = this . props ; const index = navigationState . routes . findIndex ( ( route ) => route . key === key ) ; if ( navigationState . index !== index ) { onIndexChange ( index ) ; this . jumpToIndex ( index ) ; if ( keyboardDismissMode === 'auto' ) { Keyboard . dismiss ( ) ; } } } ; private addListener = ( type , listener ) => { switch ( type ) { case 'enter' : this . enterListeners . push ( listener ) ; break ; } } ; private removeListener = ( type , listener ) => { switch ( type ) { case 'enter' : { const index = this . enterListeners . indexOf ( listener ) ; if ( index > - 1 ) { this . enterListeners . splice ( index , 1 ) ; } break ; } } } ; private currentIndex = new Animated . Value ( this . props . navigationState . index ) ; private offset = new Animated . Value ( 0 ) ; private justScrolled = false ; private onPageScroll = event ( [ { nativeEvent : { position : this . currentIndex , offset : this . offset , } , } , ] ) ; onPageScrollStateChanged = ( state ) => { switch ( state ) { case 'Settling' : this . props . onSwipeEnd && this . props . onSwipeEnd ( ) ; return ; case 'Dragging' : this . props . onSwipeStart && this . props . onSwipeStart ( ) ; return ; } } ; private onIndexChange ( newPosition ) { if ( newPosition !== this . props . navigationState . index ) { this . justScrolled = true ; } this . props . onIndexChange ( newPosition ) ; } ref = React . createRef < any > ( ) ; render ( ) { const { style , keyboardDismissMode , swipeEnabled , children , orientation , transition , showPageIndicator , pageMargin , overdrag , overScrollMode , } = this . props ; return children ( { position : add ( this . currentIndex , this . offset ) , addListener : this . addListener , removeListener : this . removeListener , jumpTo : this . jumpTo , render : children => ( < AnimatedViewPager ref = { this . ref } lazy = { false } style = { [ { flex : 1 } , style ] } initialPage = { this . props . navigationState . index } keyboardDismissMode = { keyboardDismissMode === 'auto' ? 'on-drag' : keyboardDismissMode } onPageScroll = { this . onPageScroll } onPageSelected = { ( e ) => this . onIndexChange ( e . nativeEvent . position ) } onPageScrollStateChanged = { this . onPageScrollStateChanged } scrollEnabled = { swipeEnabled } orientation = { orientation } transitionStyle = { transition } showPageIndicator = { showPageIndicator } pageMargin = { pageMargin } overdrag = { overdrag } overScrollMode = { overScrollMode } > { children } < /AnimatedViewPager>), } ) ; } }