import * as React from 'react' import { NativeScrollEvent, NativeSyntheticEvent, ScrollView, StyleSheet, View, } from 'react-native' import { getHorizontalMonthOffset, getIndexFromVerticalOffset, getMonthHeight, getVerticalMonthsOffset, montHeaderHeight, } from './Month' import { SwiperProps, useYearChange } from './SwiperUtils' import { beginOffset, estimatedMonthHeight, totalMonths } from './dateUtils' import AutoSizer from './AutoSizer' const styles = StyleSheet.create({ viewPager: { flex: 1, }, inner: { position: 'relative', }, }) function getVisibleArray( i: number, { isHorizontal, height }: { isHorizontal: boolean; height: number } ) { if (isHorizontal || height < 700) { return [i - 1, i, i + 1] } return [i - 2, i - 1, i, i + 1, i + 2] } function Swiper(props: SwiperProps) { return ( {({ width, height }) => ( )} ) } function SwiperInner({ scrollMode, renderItem, renderHeader, renderFooter, selectedYear, initialIndex, width, height, }: SwiperProps & { width: number; height: number }) { const idx = React.useRef(initialIndex) const isHorizontal = scrollMode === 'horizontal' const [visibleIndexes, setVisibleIndexes] = React.useState( getVisibleArray(initialIndex, { isHorizontal, height }) ) const parentRef = React.useRef(null) const scrollTo = React.useCallback( (index: number, animated: boolean) => { idx.current = index setVisibleIndexes(getVisibleArray(index, { isHorizontal, height })) if (!parentRef.current) { return } const offset = isHorizontal ? getHorizontalMonthOffset(index, width) : getVerticalMonthsOffset(index) - montHeaderHeight if (isHorizontal) { parentRef.current.scrollTo({ y: 0, x: offset, animated, }) } else { parentRef.current.scrollTo({ y: offset, x: 0, animated, }) } }, [parentRef, isHorizontal, width, height] ) const onPrev = React.useCallback(() => { scrollTo(idx.current - 1, true) }, [scrollTo, idx]) const onNext = React.useCallback(() => { scrollTo(idx.current + 1, true) }, [scrollTo, idx]) const scrollToInitial = React.useCallback(() => { scrollTo(idx.current, false) }, [scrollTo]) const onMomentumScrollEnd = React.useCallback( (e: NativeSyntheticEvent) => { const contentOffset = e.nativeEvent.contentOffset const viewSize = e.nativeEvent.layoutMeasurement const newIndex = isHorizontal ? Math.floor(contentOffset.x / viewSize.width) : getIndexFromVerticalOffset(contentOffset.y - beginOffset) if (newIndex === 0) { return } if (idx.current !== newIndex) { idx.current = newIndex setVisibleIndexes(getVisibleArray(newIndex, { isHorizontal, height })) } }, [idx, height, isHorizontal] ) const renderProps = { index: 0, onPrev, onNext, } useYearChange( (newIndex) => { if (newIndex) { scrollTo(newIndex, false) } }, { selectedYear, currentIndexRef: idx, } ) return ( <> {visibleIndexes ? new Array(visibleIndexes.length).fill(undefined).map((_, vi) => ( {renderItem({ index: visibleIndexes[vi], onPrev: onPrev, onNext: onNext, })} )) : null} {renderHeader && renderHeader(renderProps)} {renderFooter && renderFooter(renderProps)} ) } export default React.memo(Swiper)