UNPKG

@fruits-chain/react-native-xiaoshu

Version:
201 lines (199 loc) 6.86 kB
"use strict"; import { SuccessOutline } from '@fruits-chain/icons-react-native'; import groupBy from 'lodash/groupBy'; import isNil from 'lodash/isNil'; 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.js"; import { useControllableValue, usePersistFn, useSafeHeight } from "../hooks/index.js"; import useState from "../hooks/useStateUpdate.js"; import Loading from "../loading/index.js"; import Locale from "../locale/index.js"; import Popup from "../popup/popup.js"; import PopupHeader from "../popup/popup-header.js"; import Theme from "../theme/index.js"; import StepSelectorLine from "./line.js"; import { varCreator, styleCreator } from "./style.js"; import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; const defaultLoading = /*#__PURE__*/_jsx(Loading, { vertical: true }); function StepSelector({ theme, title, safeAreaInsetTop, round = true, onPressClose, request, loading = defaultLoading, ...resetProps }) { const safeHeight = useSafeHeight({ top: safeAreaInsetTop }); const locale = Locale.useLocale().StepSelector; const [CV, STYLES] = Theme.useStyle({ varCreator, styleCreator, theme }); 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], 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]; }).filter(v => !isNil(v)); 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__*/_jsx(Popup, { ...omit(resetProps, ['value', 'defaultValue', 'onChange']), position: "bottom", round: round, safeAreaInsetBottom: true, children: /*#__PURE__*/_jsxs(View, { style: { height: safeHeight }, children: [/*#__PURE__*/_jsx(PopupHeader, { title: title ?? locale.title, onClose: onPressClose }), state.selected.map((item, index) => { return /*#__PURE__*/_jsx(Cell, { innerStyle: STYLES.selected_cell, title: item?.label || state.responseData[index].placeholder, titleExtra: /*#__PURE__*/_jsx(StepSelectorLine, { index: index, total: state.selected.length, active: !!item?.label }), titleTextStyle: [STYLES.selected_cell_title_text, index === state.index && item?.label ? STYLES.option_text_active : null], isLink: true, disabled: state.loading, divider: index === state.selected.length - 1, onPress: () => { setState({ index }); optionScrollToTop(); } }, `${item?.value}`); }), options.length && placeholder ? /*#__PURE__*/_jsx(Cell, { titleTextStyle: STYLES.placeholder_text, title: placeholder, divider: false }) : null, state.loading && value.length === 0 ? loading : null, /*#__PURE__*/_jsx(ScrollView, { bounces: false, ref: ScrollViewRef, children: groupOption.map(group => { return group.map((item, itemIndex) => { const selected = state.selected[state.index]; const isActive = item.value === selected?.value; return /*#__PURE__*/_jsx(Cell, { disabled: state.loading, titleExtra: /*#__PURE__*/_jsx(Text, { style: STYLES.option_index_text, children: itemIndex === 0 ? item.index : null }), title: item.label, titleTextStyle: isActive ? STYLES.option_text_active : null, valueExtra: isActive ? /*#__PURE__*/_jsx(SuccessOutline, { 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; } }, `${item.value}`); }); }) })] }) }); } export default /*#__PURE__*/memo(StepSelector); //# sourceMappingURL=step-selector.js.map