@fruits-chain/react-native-xiaoshu
Version:
React Native UI library
124 lines (113 loc) • 3.95 kB
JavaScript
import React, { useRef, useCallback, useState, memo } from 'react';
import { Animated, View, TouchableHighlight } from 'react-native';
import { getArrowOutline } from '../icon/helper/arrow';
import { usePersistFn, useUpdateEffect } from '../hooks';
import { easing, renderTextLikeJSX, isValue } from '../helpers';
import { useTheme, widthStyle } from '../theme';
import { createStyles } from './style';
/**
* Collapse 折叠面板
*/
const Collapse = _ref => {
let {
children,
title,
titleStyle,
titleTextStyle,
iconStyle,
iconColor,
iconSize,
bodyStyle,
renderTitle,
renderBody,
defaultCollapse,
collapse,
onAnimationEnd,
bodyPadding = true
} = _ref;
const THEME_VAR = useTheme();
const STYLES = widthStyle(THEME_VAR, createStyles);
const onAnimationEndPersistFn = usePersistFn(v => {
onAnimationEnd === null || onAnimationEnd === void 0 ? void 0 : onAnimationEnd(v);
});
/** 记录当前是否课件,在不断 onLayout 的时候可以有一个判断的依据 */
const Visible = useRef(isValue(collapse) ? collapse : isValue(defaultCollapse) ? defaultCollapse : false);
const HeightMap = useRef({
start: 0,
end: 0
});
const [show, setShow] = useState(Visible.current);
const AnimatedValue = useRef(new Animated.Value(0)).current;
const setVisible = useCallback(v => {
Visible.current = v; // 展开的时候立即响应
if (v) {
setShow(v);
}
const action = Animated.timing(AnimatedValue, {
toValue: v ? HeightMap.current.start + HeightMap.current.end : HeightMap.current.start,
duration: THEME_VAR.collapse_transition_duration,
useNativeDriver: false,
easing: v ? easing.easeOutCirc : easing.easeInCubic
});
action.start(_ref2 => {
let {
finished
} = _ref2;
if (finished) {
// 收起的时候等待动画结束再响应
if (!v) {
setShow(v);
}
onAnimationEndPersistFn(v);
}
});
}, [AnimatedValue, onAnimationEndPersistFn, THEME_VAR.collapse_transition_duration]);
useUpdateEffect(() => {
if (collapse !== Visible.current) {
// 同步外界状态
setVisible(!Visible.current);
}
}, [collapse, setVisible]); // title 是否要自定义渲染
if (renderTitle) {
title = renderTitle(show);
}
const onPressTitle = useCallback(() => {
setVisible(!Visible.current);
}, [setVisible]);
const onLayoutTitle = useCallback(e => {
HeightMap.current.start = e.nativeEvent.layout.height;
if (!Visible.current) {
setVisible(false);
}
}, [setVisible]);
const onLayoutBody = useCallback(e => {
// 有点疑惑,折叠的过程中,高度在动态变化
HeightMap.current.end = e.nativeEvent.layout.height;
if (Visible.current) {
setVisible(true);
}
}, [setVisible]);
const titleJSX = renderTextLikeJSX(title, [STYLES.title_text, titleTextStyle]);
const ArrowOutline = getArrowOutline(show ? 'up' : 'down');
return /*#__PURE__*/React.createElement(Animated.View, {
style: [STYLES.collapse, {
height: AnimatedValue
}]
}, /*#__PURE__*/React.createElement(TouchableHighlight, {
underlayColor: THEME_VAR.cell_active_color,
onPress: onPressTitle,
onLayout: onLayoutTitle
}, /*#__PURE__*/React.createElement(View, {
style: [STYLES.title, titleStyle]
}, titleJSX, /*#__PURE__*/React.createElement(ArrowOutline, {
style: iconStyle,
color: isValue(iconColor) ? iconColor : THEME_VAR.collapse_title_icon_color,
size: isValue(iconSize) ? iconSize : THEME_VAR.collapse_title_icon_size
}))), /*#__PURE__*/React.createElement(View, {
collapsable: false,
onLayout: onLayoutBody,
style: [STYLES.body, bodyPadding ? STYLES.body_padding : null, bodyStyle]
}, renderBody ? renderBody(show) : children));
};
export default /*#__PURE__*/memo(Collapse);
//# sourceMappingURL=index.js.map