UNPKG

@fruits-chain/react-native-xiaoshu

Version:
183 lines (172 loc) 5.75 kB
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } import React, { useCallback, memo } from 'react'; import { TouchableWithoutFeedback, View, ScrollView, useWindowDimensions } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import Portal from '../portal'; import Popup from '../popup/popup'; import Cell from '../cell'; import IconSuccessOutline from '../icon/success'; import useState from '../hooks/useStateUpdate'; import { useUpdateEffect } from '../hooks'; import { getDefaultValue } from '../helpers'; import { useDropdownConfig } from './context'; import DropdownText from './text'; const POPUP_STYLE = { backgroundColor: 'transparent' }; const DropdownItem = _ref => { let { titleStyle, titleTextStyle, lazyRender, options = [], value, defaultValue, onChange, duration, zIndex, closeOnPressOutside, ...restProps } = _ref; const insets = useSafeAreaInsets(); const { height: windowHeight } = useWindowDimensions(); const config = useDropdownConfig(); const [state, setState] = useState({ active: false, ctxMaxHeight: 0, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions ctxStyle: {}, // eslint-disable-next-line @typescript-eslint/consistent-type-assertions shadeStyle: {}, position: 'bottom', value: getDefaultValue(value, defaultValue) }); // 修正数据 lazyRender = getDefaultValue(lazyRender, config.lazyRender); duration = getDefaultValue(duration, config.duration); zIndex = getDefaultValue(zIndex, config.zIndex); closeOnPressOutside = getDefaultValue(closeOnPressOutside, config.closeOnPressOutside); // 同步值 useUpdateEffect(() => { setState({ value }); }, [value]); const onPressText = useCallback(() => { // 计算 Menu 的 Top 和元素高度 // eslint-disable-next-line max-params config.MenuRef.current.measure((x, y, width, height, pageX, pageY) => { const topHeight = pageY - insets.top; const bottomHeight = windowHeight - pageY - height - insets.bottom; if (topHeight >= bottomHeight) { // 内容在上半部分 setState({ active: true, position: 'bottom', ctxStyle: { top: 0, height: pageY }, shadeStyle: { top: pageY, bottom: 0 } }); } else { // 内容在下半部分 setState({ active: true, position: 'top', ctxStyle: { top: pageY + height, bottom: 0 }, shadeStyle: { top: 0, height: pageY + height } }); } }); }, [config.MenuRef, insets.bottom, insets.top, windowHeight]); const onPressShade = useCallback(() => { setState({ active: false }); }, []); /** 弹出层可以的最大高度 */ const onLayoutPlace = useCallback(e => { setState({ ctxMaxHeight: e.nativeEvent.layout.height }); }, []); const genOnPressCell = o => () => { setState({ value: o.value, active: false }); onChange === null || onChange === void 0 ? void 0 : onChange(o.value); }; const shadeStyles = [{ position: 'absolute', left: 0, right: 0, zIndex // backgroundColor: '#f30', // to test ui }, state.shadeStyle]; const boxStyles = [{ position: 'absolute', left: 0, right: 0, zIndex, overflow: 'hidden' // backgroundColor: '#000', // to test ui }, state.ctxStyle]; const text = (options.filter(op => op.value === state.value)[0] || {}).label; const isContextTop = state.position === 'bottom'; const placeholderJSX = /*#__PURE__*/React.createElement(TouchableWithoutFeedback, { onPress: onPressShade }, /*#__PURE__*/React.createElement(View, { style: { height: insets.top } })); return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(DropdownText, _extends({}, restProps, { style: titleStyle, textStyle: titleTextStyle, title: text, active: state.active, onPress: onPressText })), /*#__PURE__*/React.createElement(Portal, null, state.active ? /*#__PURE__*/React.createElement(TouchableWithoutFeedback, { onPress: closeOnPressOutside ? onPressShade : undefined }, /*#__PURE__*/React.createElement(View, { style: shadeStyles })) : null, /*#__PURE__*/React.createElement(View, { style: boxStyles, pointerEvents: "box-none", onLayout: onLayoutPlace }, /*#__PURE__*/React.createElement(Popup, { visible: state.active, style: POPUP_STYLE, lazyRender: lazyRender, position: state.position, duration: duration, onPressOverlay: onPressShade }, /*#__PURE__*/React.createElement(View, { style: { maxHeight: state.ctxMaxHeight } }, isContextTop ? placeholderJSX : null, /*#__PURE__*/React.createElement(ScrollView, { bounces: false }, options.map(opt => { return /*#__PURE__*/React.createElement(Cell, { key: opt.value, title: opt.label, valueExtra: opt.value === value ? /*#__PURE__*/React.createElement(IconSuccessOutline, { size: 16, color: config.activeColor }) : null, onPress: genOnPressCell(opt) }); })), !isContextTop ? placeholderJSX : null))))); }; export default /*#__PURE__*/memo(DropdownItem); //# sourceMappingURL=item.js.map