import React, { useEffect, useMemo } from "react"; import { Platform, StyleSheet } from "react-native"; import Animated, { runOnJS, useAnimatedRef, useAnimatedScrollHandler, useSharedValue, } from "react-native-reanimated"; import { useHeaderTabContext } from "../context"; // Dynamic import for FlashList to handle optional dependency let FlashList: any; try { const flashListModule = require("@shopify/flash-list"); FlashList = flashListModule.FlashList; } catch { // FlashList is optional, will be undefined if not installed } const AnimatePageView = FlashList ? Platform.OS === "web" ? FlashList : Animated.createAnimatedComponent(FlashList) : null; export type TabFlashListProps = { index: number; data: readonly T[] | null | undefined; renderItem: any; estimatedItemSize?: number; [key: string]: any; }; function FlashListComponent(props: TabFlashListProps, ref: any) { if (!AnimatePageView) { throw new Error( "TabFlashList requires @shopify/flash-list to be installed. Please run: yarn add @shopify/flash-list" ); } const { index, onScroll, contentContainerStyle, ...restProps } = props; const flashListRef = useAnimatedRef(); const { shareAnimatedValue, updateSceneInfo, scrollViewPaddingTop } = useHeaderTabContext(); const scrollY = useSharedValue(0); const onScrollHandler = useAnimatedScrollHandler( { onScroll: (event) => { scrollY.value = event.contentOffset.y; shareAnimatedValue.value = event.contentOffset.y; if (onScroll) { runOnJS(onScroll as any)({ nativeEvent: event }); } }, }, [onScroll] ); // Register scene info - useAnimatedRef will be attached by React useEffect(() => { updateSceneInfo({ scrollRef: flashListRef, index, scrollY, }); }, [flashListRef, index, scrollY, updateSceneInfo]); const mergedRefs = (instance: any) => { // useAnimatedRef must be called as a function, not assigned to .current if (flashListRef) { (flashListRef as any)(instance); } if (ref) { if (typeof ref === "function") { ref(instance); } else { ref.current = instance; } } // Re-register scene info when ref is set if (instance) { updateSceneInfo({ scrollRef: flashListRef, index, scrollY, }); } }; const mergedContentContainerStyle = useMemo( () => [ contentContainerStyle, { paddingTop: scrollViewPaddingTop, }, ], [contentContainerStyle, scrollViewPaddingTop] ); return ( ); } const styles = StyleSheet.create({ container: { flex: 1, }, }); export const TabFlashList = React.forwardRef(FlashListComponent) as ( props: TabFlashListProps & { ref?: React.Ref; } ) => React.ReactElement;