import isNil from 'lodash.isnil'; import React, { useEffect, useRef, forwardRef } from 'react'; import { ViewStyle, LayoutAnimation, UIManager, Platform } from 'react-native'; import { Box, IBoxProps } from '../../primitives'; export type ICollapseProps = IBoxProps & { style?: ViewStyle; endingHeight?: number; startingHeight?: number; duration?: number; animateOpacity?: boolean; isOpen?: boolean; onAnimationEnd?: Function; onAnimationStart?: Function; }; function usePrevious(value: any) { const ref = useRef(); function updatePrevious(newVal: any) { ref.current = newVal; } useEffect(() => { updatePrevious(value); }, [value]); return { value: ref.current, updatePrevious }; } const Collapse = ( { endingHeight, startingHeight, duration, // animateOpacity, isOpen, onAnimationEnd, onAnimationStart, ...props }: ICollapseProps, ref?: any ) => { if (Platform.OS === 'android') { UIManager.setLayoutAnimationEnabledExperimental && UIManager.setLayoutAnimationEnabledExperimental(true); } const CustomLayoutLinear = { duration: duration ? duration : 400, create: { type: LayoutAnimation.Types.easeInEaseOut, property: LayoutAnimation.Properties.opacity, }, update: { type: LayoutAnimation.Types.easeInEaseOut, }, }; const defaultStartHeight: any = isOpen ? endingHeight : startingHeight ? startingHeight : 1; let animatedStyle = { height: defaultStartHeight }; const animateView = () => { if (onAnimationStart) { onAnimationStart(); } animatedStyle = { height: isOpen ? endingHeight : defaultStartHeight, }; let callback = onAnimationEnd ? onAnimationEnd : () => {}; LayoutAnimation.configureNext(CustomLayoutLinear, callback()); }; let wasOpen = usePrevious(isOpen); if (!isNil(wasOpen.value) && wasOpen.value !== isOpen) { animateView(); wasOpen.updatePrevious(isOpen); } const [size, setSize] = React.useState(startingHeight ?? 0); const provideSize = (layoutSize: any) => { setSize(layoutSize.height); }; const _web = { transition: `height ${duration ?? '400'}ms`, height: isOpen ? endingHeight || size : startingHeight || 0, }; return ( provideSize(e.nativeEvent.layout)} {...props} /> ); }; export default React.memo(forwardRef(Collapse));