import React from 'react'; import { View, SectionList, StyleSheet, SectionListProps } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Animated, { AnimatedProps, useAnimatedRef } from 'react-native-reanimated'; import FadingView from '../containers/FadingView'; import { useScrollContainerLogic } from './useScrollContainerLogic'; import type { SharedScrollContainerProps } from './types'; import type { DefaultSectionT } from 'react-native'; type AnimatedSectionListType = SectionListProps< ItemT, SectionT > & SharedScrollContainerProps; const AnimatedSectionList = Animated.createAnimatedComponent(SectionList) as React.ComponentClass< AnimatedProps>, any >; type SectionListWithHeadersProps = Omit< AnimatedSectionListType, 'onScroll' >; const SectionListWithHeaders = ({ largeHeaderShown, containerStyle, LargeHeaderSubtitleComponent, LargeHeaderComponent, largeHeaderContainerStyle, HeaderComponent, onLargeHeaderLayout, onScrollBeginDrag, onScrollEndDrag, onScrollWorklet, onMomentumScrollBegin, onMomentumScrollEnd, ignoreLeftSafeArea, ignoreRightSafeArea, disableAutoFixScroll = false, // We use this to ensure that the onScroll property isn't accidentally used. // @ts-ignore onScroll: _unusedOnScroll, absoluteHeader = false, initialAbsoluteHeaderHeight = 0, contentContainerStyle, automaticallyAdjustsScrollIndicatorInsets, headerFadeInThreshold = 1, disableLargeHeaderFadeAnim = false, scrollIndicatorInsets = {}, inverted, ...rest }: SectionListWithHeadersProps) => { if (_unusedOnScroll) { throw new Error( "The 'onScroll' property is not supported. Please use onScrollWorklet to track the scroll container's state." ); } const insets = useSafeAreaInsets(); const scrollRef = useAnimatedRef>(); const { scrollY, showNavBar, largeHeaderHeight, largeHeaderOpacity, scrollHandler, debouncedFixScroll, onAbsoluteHeaderLayout, scrollViewAdjustments, } = useScrollContainerLogic({ scrollRef, largeHeaderShown, disableAutoFixScroll, largeHeaderExists: !!LargeHeaderComponent, absoluteHeader, initialAbsoluteHeaderHeight, headerFadeInThreshold, inverted: !!inverted, onScrollWorklet, }); return ( {!absoluteHeader && HeaderComponent({ showNavBar, scrollY })} { debouncedFixScroll.cancel(); if (onScrollBeginDrag) onScrollBeginDrag(e); }} onScrollEndDrag={(e) => { debouncedFixScroll(); if (onScrollEndDrag) onScrollEndDrag(e); }} onMomentumScrollBegin={(e) => { debouncedFixScroll.cancel(); if (onMomentumScrollBegin) onMomentumScrollBegin(e); }} onMomentumScrollEnd={(e) => { debouncedFixScroll(); if (onMomentumScrollEnd) onMomentumScrollEnd(e); }} contentContainerStyle={[ scrollViewAdjustments.contentContainerStyle, // @ts-ignore // Unfortunately there are issues with Reanimated typings, so will ignore for now. contentContainerStyle, ]} automaticallyAdjustsScrollIndicatorInsets={ automaticallyAdjustsScrollIndicatorInsets !== undefined ? automaticallyAdjustsScrollIndicatorInsets : !absoluteHeader } scrollIndicatorInsets={{ ...scrollViewAdjustments.scrollIndicatorInsets, ...scrollIndicatorInsets, }} ListHeaderComponent={ <> {LargeHeaderComponent && ( { largeHeaderHeight.value = e.nativeEvent.layout.height; if (onLargeHeaderLayout) onLargeHeaderLayout(e.nativeEvent.layout); }} > {!disableLargeHeaderFadeAnim ? ( {LargeHeaderComponent({ scrollY, showNavBar })} ) : ( {LargeHeaderComponent({ scrollY, showNavBar })} )} )} {LargeHeaderSubtitleComponent && LargeHeaderSubtitleComponent({ showNavBar, scrollY })} } inverted={inverted} {...rest} /> {absoluteHeader && ( {HeaderComponent({ showNavBar, scrollY })} )} ); }; export default SectionListWithHeaders; const styles = StyleSheet.create({ container: { flex: 1 }, absoluteHeader: { position: 'absolute', top: 0, right: 0, left: 0 }, });