import { LinearGradient } from "expo-linear-gradient"; import type { PropsWithChildren, ReactElement } from "react"; import { type NativeScrollEvent, View, type ViewProps } from "react-native"; import Animated, { interpolate, useAnimatedRef, useAnimatedStyle, useScrollViewOffset, } from "react-native-reanimated"; interface Props extends ViewProps { headerImage: ReactElement; logo?: ReactElement; episodePoster?: ReactElement; headerHeight?: number; onEndReached?: (() => void) | null | undefined; } export const ParallaxScrollView: React.FC> = ({ children, headerImage, episodePoster, headerHeight = 400, logo, onEndReached, ...props }: Props) => { const scrollRef = useAnimatedRef(); const scrollOffset = useScrollViewOffset(scrollRef); const headerAnimatedStyle = useAnimatedStyle(() => { return { transform: [ { translateY: interpolate( scrollOffset.value, [-headerHeight, 0, headerHeight], [-headerHeight / 2, 0, headerHeight * 0.75], ), }, { scale: interpolate( scrollOffset.value, [-headerHeight, 0, headerHeight], [2, 1, 1], ), }, ], }; }); function isCloseToBottom({ layoutMeasurement, contentOffset, contentSize, }: NativeScrollEvent) { return ( layoutMeasurement.height + contentOffset.y >= contentSize.height - 20 ); } return ( { if (isCloseToBottom(e.nativeEvent)) onEndReached?.(); }} > {logo && ( {logo} )} {headerImage} {children} ); };