@fruits-chain/react-native-xiaoshu
Version:
🌈 React Native UI library
139 lines (131 loc) • 4.69 kB
JavaScript
import isUndefined from 'lodash/isUndefined';
import React, { useRef, useCallback, useEffect, memo } from 'react';
import { Animated, View } from 'react-native';
import Card from '../card';
import Cell from '../cell';
import Divider from '../divider';
import { easing, getDefaultValue } from '../helpers';
import { usePersistFn, useControllableValue } from '../hooks';
import { getArrowOutline } from '../icon/helper/arrow';
import Theme from '../theme';
import { varCreator, styleCreator } from './style';
/**
* Collapse 折叠面板
*/
const Collapse = _ref => {
let {
children,
title,
titleStyle,
titleTextStyle,
iconStyle,
iconColor,
iconSize,
bodyStyle,
renderTitle,
renderTitleExtra,
renderBody,
type = 'cell',
onAnimationEnd,
bodyPadding = true,
headerDivider = true,
bodyDivider,
lazyRender = true,
...restProps
} = _ref;
const TOKENS = Theme.useThemeTokens();
const CV = Theme.createVar(TOKENS, varCreator);
const STYLES = Theme.createStyle(CV, styleCreator, TOKENS);
bodyDivider = getDefaultValue(bodyDivider, type === 'cell');
const [collapse, onCollapse] = useControllableValue(restProps, {
defaultValuePropName: 'defaultCollapse',
valuePropName: 'collapse',
trigger: 'onCollapse',
defaultValue: false
});
const onAnimationEndPersistFn = usePersistFn(v => {
onAnimationEnd === null || onAnimationEnd === void 0 ? void 0 : onAnimationEnd(v);
});
/** 记录当前是否可见,在不断 onLayout 的时候可以有一个判断的依据 */
const Visible = useRef(collapse);
const BodyHeight = useRef(0);
const MountedRef = useRef(false);
const AnimatedValue = useRef(new Animated.Value(0)).current;
const toggleBody = useCallback((v, immediately) => {
const action = Animated.timing(AnimatedValue, {
toValue: v ? BodyHeight.current : 0,
duration: immediately ? 0 : CV.collapse_transition_duration,
useNativeDriver: false,
easing: v ? easing.easeOutCirc : easing.easeInCubic
});
action.start(_ref2 => {
let {
finished
} = _ref2;
if (finished) {
onAnimationEndPersistFn(v);
}
});
}, [AnimatedValue, onAnimationEndPersistFn, CV.collapse_transition_duration]); // 初始化好组件
useEffect(() => {
MountedRef.current = true;
}, []);
useEffect(() => {
// 同步当前的状态
Visible.current = collapse;
toggleBody(collapse, false);
}, [collapse, toggleBody]);
const onPressTitle = useCallback(() => {
onCollapse(!Visible.current);
}, [onCollapse]);
const onLayoutBody = useCallback(e => {
// 有点疑惑,折叠的过程中,高度在动态变化,通过 absolute 布局解决无法完全渲染
BodyHeight.current = e.nativeEvent.layout.height; // 当收齐的时候已知高度
toggleBody(Visible.current, Visible.current);
}, [toggleBody]);
const ArrowOutline = getArrowOutline(collapse ? 'up' : 'down');
const arrowJSX = /*#__PURE__*/React.createElement(ArrowOutline, {
style: iconStyle,
color: !isUndefined(iconColor) ? iconColor : CV.collapse_icon_color,
size: !isUndefined(iconSize) ? iconSize : CV.collapse_icon_size
});
const titleJSX = renderTitle ? renderTitle(collapse) : title;
const titleExtraJSX = renderTitleExtra ? renderTitleExtra(collapse, arrowJSX) : arrowJSX;
const bodyJSX = lazyRender && !MountedRef.current && !collapse ? null : renderBody ? renderBody() : children;
const ctxJSX = /*#__PURE__*/React.createElement(Animated.View, {
style: [STYLES.collapse, {
height: AnimatedValue
}]
}, /*#__PURE__*/React.createElement(View, {
collapsable: false,
style: STYLES.body,
onLayout: onLayoutBody
}, /*#__PURE__*/React.createElement(View, {
style: [bodyPadding ? STYLES.body_padding : undefined, bodyStyle]
}, bodyJSX), bodyDivider ? /*#__PURE__*/React.createElement(Divider, {
type: "light",
style: STYLES.divider
}) : null));
if (type === 'card') {
return /*#__PURE__*/React.createElement(Card, {
square: true,
title: titleJSX,
extra: titleExtraJSX,
headerDivider: headerDivider,
titleStyle: titleStyle,
titleTextStyle: titleTextStyle,
bodyPadding: false,
onPressHeader: onPressTitle
}, ctxJSX);
}
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Cell, {
title: titleJSX,
style: titleStyle,
titleTextStyle: titleTextStyle,
valueExtra: titleExtraJSX,
onPress: onPressTitle,
divider: headerDivider
}), ctxJSX);
};
export default /*#__PURE__*/memo(Collapse);
//# sourceMappingURL=index.js.map