UNPKG

@fruits-chain/react-native-xiaoshu

Version:
199 lines (184 loc) 6.9 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 groupBy from 'lodash/groupBy'; import omit from 'lodash/omit'; import React, { useMemo, useEffect, memo, useRef, useCallback } from 'react'; import { View, Text, ScrollView } from 'react-native'; import Cell from '../cell/cell'; import { useControllableValue, usePersistFn, useSafeHeight } from '../hooks'; import useState from '../hooks/useStateUpdate'; import IconSuccessOutline from '../icon/success'; import Locale from '../locale'; import Popup from '../popup/popup'; import PopupHeader from '../popup/popup-header'; import Theme from '../theme'; import StepSelectorLine from './line'; import { varCreator, styleCreator } from './style'; function StepSelector(_ref) { let { title, safeAreaInsetTop, round = true, onPressClose, request, ...resetProps } = _ref; const safeHeight = useSafeHeight({ top: safeAreaInsetTop }); const locale = Locale.useLocale().StepSelector; const TOKENS = Theme.useThemeTokens(); const CV = Theme.createVar(TOKENS, varCreator); const STYLES = Theme.createStyle(CV, styleCreator); const requestPersistFn = usePersistFn(request); const ScrollViewRef = useRef(null); const [value, onChange] = useControllableValue(resetProps, { defaultValue: [] }); const [state, setState] = useState({ index: 0, selected: [], loading: false, responseData: [] }); const responseDataRef = useRef({}); const onPressRef = useRef(false); const fetchOption = useCallback(async (parentId, index) => { const c = responseDataRef.current[`${parentId}`]; if (c) { return c; } // 请求 const data = await requestPersistFn(parentId, index); responseDataRef.current[`${parentId}`] = data; return data; }, [requestPersistFn]); const optionScrollToTop = useCallback(() => { ScrollViewRef.current.scrollTo({ x: 0, y: 0, animated: false }); }, []); useEffect(() => { // 构建已选的数据 if (resetProps.visible) { setState({ loading: true }); const _value = [...value, null]; Promise.all(_value.map((_, index) => { return fetchOption(value[index - 1] || null, index); })).then(datas => { const isEnd = !datas[datas.length - 1].options.length; const __value = isEnd ? [...value] : _value; const selected = __value.map((v, index) => { const opts = datas[index].options; // eslint-disable-next-line max-nested-callbacks const vIndex = opts.findIndex(op => op.value === v); return opts[vIndex]; }); setState({ loading: false, index: __value.length - 1, responseData: datas, selected: selected }); if (datas[datas.length - 1].options.length) { optionScrollToTop(); } if (isEnd && onPressRef.current) { onPressRef.current = false; onChange(value, selected, true); } }); } }, [resetProps.visible, fetchOption, value, optionScrollToTop, onChange]); const { placeholder, options, groupOption } = useMemo(() => { const d = state.responseData[state.index] || { options: [], placeholder: '' }; const _groupOption = groupBy(d.options, item => item.index); return { placeholder: d.placeholder, options: d.options, groupOption: Object.keys(_groupOption).sort().map(key => { return _groupOption[key]; }) }; }, [state.index, state.responseData]); return /*#__PURE__*/React.createElement(Popup, _extends({}, omit(resetProps, ['value', 'defaultValue', 'onChange']), { position: "bottom", round: round, safeAreaInsetBottom: true }), /*#__PURE__*/React.createElement(View, { style: { height: safeHeight } }, /*#__PURE__*/React.createElement(PopupHeader, { title: title || locale.title, onClose: onPressClose }), state.selected.length > 1 && state.selected.map((item, index) => { return /*#__PURE__*/React.createElement(Cell, { key: `${item === null || item === void 0 ? void 0 : item.value}`, innerStyle: STYLES.selected_cell, title: (item === null || item === void 0 ? void 0 : item.label) || state.responseData[index].placeholder, titleExtra: /*#__PURE__*/React.createElement(StepSelectorLine, { index: index, total: state.selected.length, active: !!(item !== null && item !== void 0 && item.label) }), titleTextStyle: [STYLES.selected_cell_title_text, index === state.index && item !== null && item !== void 0 && item.label ? STYLES.option_text_active : null], isLink: true, disabled: state.loading, divider: index === state.selected.length - 1, onPress: () => { setState({ index }); optionScrollToTop(); } }); }), options.length && placeholder ? /*#__PURE__*/React.createElement(Cell, { titleTextStyle: STYLES.placeholder_text, title: placeholder, divider: false }) : null, /*#__PURE__*/React.createElement(ScrollView, { bounces: false, ref: ScrollViewRef }, groupOption.map(group => { return group.map((item, itemIndex) => { const selected = state.selected[state.index]; const isActive = item.value === (selected === null || selected === void 0 ? void 0 : selected.value); return /*#__PURE__*/React.createElement(Cell, { key: `${item.value}`, disabled: state.loading, titleExtra: /*#__PURE__*/React.createElement(Text, { style: STYLES.option_index_text }, itemIndex === 0 ? item.index : null), title: item.label, titleTextStyle: isActive ? STYLES.option_text_active : null, valueExtra: isActive ? /*#__PURE__*/React.createElement(IconSuccessOutline, { color: CV.step_selector_active_color }) : null, divider: false, onPress: () => { // 根据当前的 index 处理数据 const sliceEnd = state.index; const newValue = value.slice(0, sliceEnd); const option = newValue.map((v, index) => { const opts = state.responseData[index].options; // eslint-disable-next-line max-nested-callbacks const vIndex = opts.findIndex(op => op.value === v); return opts[vIndex]; }); onChange([...newValue, item.value], [...option, item]); onPressRef.current = true; } }); }); })))); } export default /*#__PURE__*/memo(StepSelector); //# sourceMappingURL=step-selector.js.map