import React, { forwardRef, useCallback, useImperativeHandle } from 'react'; import { Animated, View } from 'react-native'; import Constants from '../../constants'; import { useWheelPicker } from '../../hooks'; import WheelPickerElement from './WheelPickerElement'; import styles from './WheelPickerStyles'; import type { WheelPickerProps, WheelPickerRef } from './WheelPickerTypes'; export const wheelPickerRef = React.createRef(); /** * The wheel picker component * @param selectedIndex - The index of the selected value * @param data - The data to be displayed in the wheel picker * @param onChangeValue - Function to handle the value change * @param elementHeight - The height of each element in the wheel picker * @param restElements - The number of elements to be displayed above and below the selected element * @param decelerationRate - The deceleration rate of the scroll view * @param loopCount - The number of times the data should be looped * @param selectedLayoutStyle - The style of the selected layout * @param containerStyle - The style of the container * @param elementContainerStyle - The style of the element container * @param elementTextStyle - The style of the element text * @param containerProps - The props for the container * @param flatListProps - The props for the flat list */ const WheelPicker = forwardRef( ( { selectedIndex, data, onChangeValue, elementHeight = Constants.elementHeight, restElements = Constants.restElements, decelerationRate = Constants.decelerationRate, loopCount = Constants.loopCount, selectedLayoutStyle = {}, containerStyle = {}, elementContainerStyle = {}, elementTextStyle = {}, containerProps = {}, flatListProps = {}, infiniteScroll = true, initialSelectedIndex = 0, }, ref ) => { const { currentScrollIndex, containerHeight, flatListRef, arrayElements, scrollY, onScrollListener, handleMomentumScrollEnd, offsets, } = useWheelPicker({ loopCount, onChangeValue, selectedIndex, data, restElements, decelerationRate, elementHeight, infiniteScroll, initialSelectedIndex, }); useImperativeHandle(ref ?? wheelPickerRef, () => ({ scrollToIndex: (index: number) => { flatListRef.current?.scrollToIndex({ index, animated: false, }); const originalValue = data[index]; onChangeValue(index ?? 0, originalValue?.toString() ?? ''); }, })); const renderItem = useCallback( ({ item, index }: { item: string | null; index: number }) => ( ), [ currentScrollIndex, restElements, elementContainerStyle, elementTextStyle, elementHeight, ] ); return ( {...flatListProps} nestedScrollEnabled ref={flatListRef} style={styles.flatListStyle} maxToRenderPerBatch={arrayElements?.length * 2} updateCellsBatchingPeriod={200} showsVerticalScrollIndicator={false} data={arrayElements as Array} keyExtractor={(_item, index) => index.toString()} renderItem={renderItem} snapToOffsets={offsets} decelerationRate={decelerationRate} getItemLayout={(_data, index) => ({ length: elementHeight, offset: elementHeight * index, index, })} onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: scrollY } } }], { useNativeDriver: true, listener: onScrollListener, } )} onMomentumScrollEnd={handleMomentumScrollEnd} /> ); } ); export default WheelPicker;