import React, { useRef, useState, useCallback, useEffect } from 'react'; import { View, StyleSheet, Animated, Pressable } from 'react-native'; import { isNil, isUndefined } from 'lodash'; import ShouldRender from '../ShouldRender'; import createStyle from './styles/descriptions.style'; import { useTheme } from '../Theme/Theme'; import { DescriptionsProps } from './interface'; import { renderTextLikeJSX } from '../../core/helpers'; import { IconXRightsmall1 } from '../../icons'; import { getComputedTitleAndContentStyles } from '../../core/descriptions/helper'; const Descriptions = ({ bordered = false, extra, expanded = true, value, defaultValue = true, onChange, style, horizontal, title, titleStyle, items, itemStyle, itemTitleStyle, itemContentStyle, selectable = true, }: DescriptionsProps) => { const token = useTheme(); const styles = createStyle(token); const arrowAnim = useRef(new Animated.Value(0)).current; const [isExpanded, setIsExpaned] = useState(defaultValue); const isFirst = useRef(true); // 首次渲染动画问题 const onExpand = useCallback(() => { Animated.parallel([ Animated.timing(arrowAnim, { toValue: 1, duration: isFirst.current ? 0 : 150, useNativeDriver: true, }), ]).start(); isFirst.current = false; }, [arrowAnim, isFirst]); const onClose = useCallback(() => { Animated.parallel([ Animated.timing(arrowAnim, { toValue: 0, duration: isFirst.current ? 0 : 150, useNativeDriver: true, }), ]).start(); isFirst.current = false; }, [arrowAnim, isFirst]); useEffect(() => { if (value ?? isExpanded) { onExpand(); } else { onClose(); } }, [value, isExpanded, onClose, onExpand]); const onPress = () => { if (!expanded) return; //不允许操作展开收起 const nextValue = !(value ?? isExpanded); onChange?.(nextValue); if (isUndefined(value)) { setIsExpaned(nextValue); } }; const header = ( {renderTextLikeJSX(title, [styles.title, titleStyle])} {renderTextLikeJSX(extra, [styles.extra])} ); const listMaxIndex = (items?.length ?? 0) - 1; const lists = ( <> {items?.map((item, i) => { const computedTitleAndContentStyles = getComputedTitleAndContentStyles( item?.title, item?.content, horizontal ); return ( {renderTextLikeJSX(item?.title, [ styles.itemTitle, horizontal && styles.itemTitleRow, horizontal && computedTitleAndContentStyles.titleStyle, itemTitleStyle, ])} {renderTextLikeJSX( item?.content, [ styles.itemContent, horizontal && styles.itemContentRow, horizontal && computedTitleAndContentStyles.contentStyle, itemContentStyle, ], { selectable, } )} ); })} ); return ( {header} {lists} ); }; export default Descriptions;