import React, { Children, FC, useEffect, useRef } from 'react'; import { Platform, ScrollView as RNScrollView } from 'react-native'; import { CarouselProps } from './types'; import useTheme from '../../context/theme/useTheme'; import { Box } from '../Box'; import { ScrollView } from '../ScrollView'; import { Touchable } from '../Touchable'; import { getLighten } from '../../utils'; export const Carousel: FC = ({ maxWidth, widthChild, sx, styles, renderDots, dotsBackground, variant = 'default', children = [], showScroll = false, withDots = variant !== 'ios', scrollViewProps = {}, rounded = variant === 'ios' && 1.2, ...restSxProps }) => { const [active, setActive] = React.useState(0); const ref = useRef(null); const theme = useTheme(); const width = maxWidth ?? theme.width; const isIos = variant === 'ios'; useEffect(() => { setTimeout(() => { ref.current.scrollTo({ y: 0, x: 0, animated: true }); }, 1); }, []); const onPressDot = (index: number) => { ref.current.scrollTo({ y: 0, x: (isIos ? Number(widthChild ?? width - 60) : width) * index, animated: true, }); }; return ( ({ android: 'fast', default: 0.8, })} sx={{ rounded, ...sx?.scrollView, ...restSxProps, }} contentContainerSx={sx?.scrollViewContent} style={styles?.scrollView} contentContainerStyle={styles?.scrollViewContent} onScroll={(event) => { const contentOffsetX = event.nativeEvent.contentOffset.x; setActive(Math.round(contentOffsetX / width)); }} alwaysBounceVertical={false} alwaysBounceHorizontal={false} showsHorizontalScrollIndicator={showScroll} showsVerticalScrollIndicator={showScroll} snapToInterval={isIos ? width - 47 : width} snapToAlignment="center" contentInset={{ top: 0, left: 0, bottom: 0, right: 0, }} {...scrollViewProps} > {Children.map(children, (child) => { return ( {child} ); })} {withDots && ( {Children.map(children, (_, index) => { const isActive = index === active; if (renderDots) { return renderDots({ isActive, index, onPress: onPressDot, totalItems: Children.count(children), }); } return ( onPressDot(index)} opacity={isActive ? 1 : 0.6} bg={ isActive ? dotsBackground?.active || 'white' : dotsBackground?.inactive || 'white' } sx={sx?.dot} style={styles?.dot} /> ); })} )} ); };