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)