import { useCallback, useEffect, useMemo, useRef, useState, } from 'react'; import { Animated, Dimensions, type LayoutChangeEvent, ScrollView, View, } from 'react-native'; import { useZeroSheetContext } from './ZeroSheet'; const { height } = Dimensions.get('window'); interface ZeroSheetContentProps { children: React.ReactNode; duration?: number; scrollEnabled?: boolean; } const ZeroSheetContent: React.FC = ({ children, duration = 300, scrollEnabled, }) => { const { headerContentHeight, topInsets, buttonInsets, keyboardContentHeight, footerContentHeight, contentContentHeight, setContentContentHeight, draggableHeight, fixedContentHeight } = useZeroSheetContext(); const animatedHeight = useRef(new Animated.Value(0)).current; const lastLayoutHeight = useRef(0); const [actualContentHeight, setActualContentHeight] = useState(0); const limitHeight = useCallback((_height: number) => { let maxHeight = height; maxHeight = maxHeight - headerContentHeight - footerContentHeight - keyboardContentHeight - draggableHeight - topInsets - buttonInsets; if (_height > maxHeight) { return maxHeight; } return _height; }, [headerContentHeight, footerContentHeight, keyboardContentHeight, draggableHeight, topInsets, buttonInsets]); const resizeContent = useCallback(() => { let newHeight = lastLayoutHeight.current; if (fixedContentHeight) { let limitFixedContentHeight = limitHeight(fixedContentHeight); if (contentContentHeight !== limitFixedContentHeight) { setContentContentHeight(limitFixedContentHeight); } return; } newHeight = limitHeight(newHeight); if (newHeight !== contentContentHeight) { setContentContentHeight(newHeight); } }, [fixedContentHeight, contentContentHeight, setContentContentHeight, limitHeight]); const onLayout = useCallback((e: LayoutChangeEvent) => { let newHeight = Math.round(e.nativeEvent.layout.height); lastLayoutHeight.current = newHeight; setActualContentHeight(newHeight); resizeContent(); }, [resizeContent]); useEffect(() => { resizeContent(); }, [resizeContent]); useEffect(() => { Animated.timing(animatedHeight, { toValue: contentContentHeight, duration, useNativeDriver: false, // nativeDriver не поддерживает height }).start(() => { }) }, [contentContentHeight, duration, animatedHeight]); useEffect(() => { if (fixedContentHeight) { let limitFixedContentHeight = limitHeight(fixedContentHeight); if (contentContentHeight !== limitFixedContentHeight) { setContentContentHeight(limitFixedContentHeight); } } }, [fixedContentHeight]); // Вычисляем максимальную доступную высоту для контента const maxAvailableHeight = useMemo(() => { return height - headerContentHeight - footerContentHeight - keyboardContentHeight - draggableHeight - topInsets - buttonInsets; }, [headerContentHeight, footerContentHeight, keyboardContentHeight, draggableHeight, topInsets, buttonInsets]); // Включаем скролл только если реальная высота контента больше доступной области const shouldEnableScroll = useMemo(() => { return actualContentHeight > maxAvailableHeight; }, [actualContentHeight, maxAvailableHeight]); // Используем переданное значение scrollEnabled, если оно задано, иначе автоматическое вычисление const finalScrollEnabled = scrollEnabled !== undefined ? scrollEnabled : shouldEnableScroll; return ( {children} ); }; export default ZeroSheetContent;