import React, { ReactElement, useMemo, useState } from 'react'; import { Animated, View } from 'react-native'; import { Text } from '../Text'; import { useCollapse } from './Context'; import { CollapseInternalItemProps, CollapseItemProps, KeyType } from './types'; import Header from './Header'; import createSxStyle from '../../lib/sx'; import useTheme from '../../context/theme/useTheme'; import { Box } from '../Box'; import { isChildrenCollapse } from './utils'; const animationDuration = 100; const Panel: React.FC = (props) => { const theme = useTheme(); const [nestedKey, setNestedKey] = useState([]); const fadeAnimation = React.useRef(new Animated.Value(0)).current; const heightAnimation = React.useRef(new Animated.Value(0)).current; const [contentHeight, setContentHeight] = useState(0); const { openKeys, onChange, contentColor } = useCollapse(); const { id, title, disabled, children, subTitle, styleHeader, styleContent, isFirstElement, isLastElement, } = props as CollapseInternalItemProps; const collapsed = !openKeys.includes(id); const startInAnimation = React.useCallback(() => { Animated.parallel([ Animated.timing(heightAnimation, { toValue: contentHeight, duration: animationDuration, useNativeDriver: false, }), Animated.timing(fadeAnimation, { toValue: 1, delay: animationDuration, duration: animationDuration, useNativeDriver: false, }), ]).start(); }, [contentHeight, fadeAnimation, heightAnimation]); const startOutAnimation = React.useCallback(() => { Animated.parallel([ Animated.timing(fadeAnimation, { toValue: 0, duration: animationDuration, useNativeDriver: false, }), Animated.timing(heightAnimation, { toValue: 0, delay: animationDuration / 3, duration: animationDuration, useNativeDriver: false, }), ]).start(); }, [fadeAnimation, heightAnimation]); const onInternalChange = () => { onChange(id); }; React.useEffect(() => { collapsed ? startOutAnimation() : startInAnimation(); }, [collapsed, startInAnimation, startOutAnimation]); const contentStyle = { px: 2, pt: 1, pb: 3, }; const isNestedCollapse = useMemo( () => isChildrenCollapse(children), [children] ); return (
{/* only for cal height for animation */} { const height = event.nativeEvent.layout.height; setContentHeight(height); }} sx={{ position: 'absolute', opacity: 0, zIndex: -1, ...contentStyle, }} > {typeof children === 'string' || typeof children === 'number' ? ( {children} ) : isNestedCollapse ? ( React.cloneElement<{ openKeys: KeyType[] }>( children as ReactElement<{ openKeys: KeyType[] }>, { openKeys: nestedKey, } ) ) : ( children )} {/* only for cal height for animation */} {typeof children === 'string' || typeof children === 'number' ? ( {children} ) : isNestedCollapse ? ( React.cloneElement( children as ReactElement<{ onStateChange: (keys: KeyType[]) => void; }>, { onStateChange(keys) { setNestedKey(keys); }, } ) ) : ( children )} ); }; export default Panel;