@fruits-chain/react-native-xiaoshu
Version:
React Native UI library
183 lines (172 loc) • 5.75 kB
JavaScript
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