UNPKG

@nutui/nutui-react

Version:

京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序

398 lines (397 loc) 17.7 kB
import { _ as _async_to_generator } from "@swc/helpers/_/_async_to_generator"; import { _ as _define_property } from "@swc/helpers/_/_define_property"; import { _ as _object_spread } from "@swc/helpers/_/_object_spread"; import { _ as _object_spread_props } from "@swc/helpers/_/_object_spread_props"; import { _ as _sliced_to_array } from "@swc/helpers/_/_sliced_to_array"; import { _ as _ts_generator } from "@swc/helpers/_/_ts_generator"; import React, { forwardRef, isValidElement, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"; import { Check, Loading } from "@nutui/icons-react"; import classNames from "classnames"; import Tabs from "../tabs"; import Popup from "../popup"; import { normalizeListOptions, normalizeOptions } from "./utils"; import { ComponentDefaults } from "../../utils/typings"; import { mergeProps } from "../../utils/merge-props"; import { usePropsValue } from "../../hooks/use-props-value"; import { isEmpty } from "../../utils/is-empty"; import { getRefValue, useRefState } from "../../hooks/use-ref-state"; import { useConfig } from "../configprovider"; var defaultProps = _object_spread_props(_object_spread({}, ComponentDefaults), { activeColor: '', activeIcon: 'checklist', popup: true, options: [], optionKey: {}, format: {}, closeable: false, closeIconPosition: 'top-right', closeIcon: 'close', lazy: false, onClose: function() {}, onChange: function() {}, onPathChange: function() {} }); export var Cascader = /*#__PURE__*/ forwardRef(function(props, ref) { var classPrefix = 'nut-cascader'; var classPane = "".concat(classPrefix, "-pane"); var _mergeProps = mergeProps(defaultProps, props), activeColor = _mergeProps.activeColor, activeIcon = _mergeProps.activeIcon, popup = _mergeProps.popup, _mergeProps_popupProps = _mergeProps.popupProps, popupProps = _mergeProps_popupProps === void 0 ? {} : _mergeProps_popupProps, outerVisible = _mergeProps.visible, outerOptions = _mergeProps.options, outerValue = _mergeProps.value, outerDefaultValue = _mergeProps.defaultValue, optionKey = _mergeProps.optionKey, format = _mergeProps.format, closeable = _mergeProps.closeable, closeIconPosition = _mergeProps.closeIconPosition, closeIcon = _mergeProps.closeIcon, lazy = _mergeProps.lazy, onLoad = _mergeProps.onLoad; var locale = useConfig().locale; var _useState = _sliced_to_array(useState(0), 2), tabActiveIndex = _useState[0], setTabActiveIndex = _useState[1]; var _useRefState = _sliced_to_array(useRefState(outerOptions), 2), optionsRef = _useRefState[0], setInnerOptions = _useRefState[1]; var innerOptions = getRefValue(optionsRef); var _useState1 = _sliced_to_array(useState({}), 2), loading = _useState1[0], setLoading = _useState1[1]; var _usePropsValue = _sliced_to_array(usePropsValue({ value: outerValue, defaultValue: outerDefaultValue, finalValue: [], onChange: function(value) { var _props_onChange, _props_onPathChange; (_props_onChange = props.onChange) === null || _props_onChange === void 0 ? void 0 : _props_onChange.call(props, value, pathNodes.current); (_props_onPathChange = props.onPathChange) === null || _props_onPathChange === void 0 ? void 0 : _props_onPathChange.call(props, value, pathNodes.current); } }), 2), value = _usePropsValue[0], setValue = _usePropsValue[1]; var _useState2 = _sliced_to_array(useState(value), 2), innerValue = _useState2[0], setInnerValue = _useState2[1]; var options = useMemo(function() { if (!isEmpty(format)) { return normalizeListOptions(innerOptions, format); } if (!isEmpty(optionKey)) { return normalizeOptions(innerOptions, optionKey); } return innerOptions; }, [ innerOptions, optionKey, format, innerValue ]); var pathNodes = useRef([]); var levels = useMemo(function() { var next = []; var end = false; var currentOptions = options; var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined; try { var _loop = function() { var _step_value = _sliced_to_array(_step.value, 2), index = _step_value[0], val = _step_value[1]; var opt = currentOptions === null || currentOptions === void 0 ? void 0 : currentOptions.find(function(o) { return o.value === val; }); next.push({ selected: val, selectedText: opt === null || opt === void 0 ? void 0 : opt.text, pane: currentOptions }); pathNodes.current[index] = opt; if (opt === null || opt === void 0 ? void 0 : opt.children) { currentOptions = opt.children; } else { end = true; return "break"; } }; for(var _iterator = innerValue.entries()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){ var _ret = _loop(); if (_ret === "break") break; } } catch (err) { _didIteratorError = true; _iteratorError = err; } finally{ try { if (!_iteratorNormalCompletion && _iterator.return != null) { _iterator.return(); } } finally{ if (_didIteratorError) { throw _iteratorError; } } } if (!end) { next.push({ selected: null, pane: currentOptions }); } return next; }, [ innerValue, options, innerOptions ]); var _usePropsValue1 = _sliced_to_array(usePropsValue({ value: outerVisible, defaultValue: undefined, onChange: function(value) { if (value === false) { var _props_onClose; (_props_onClose = props.onClose) === null || _props_onClose === void 0 ? void 0 : _props_onClose.call(props); } } }), 2), visible = _usePropsValue1[0], setVisible = _usePropsValue1[1]; var actions = { open: function() { setVisible(true); }, close: function() { setVisible(false); } }; useImperativeHandle(ref, function() { return actions; }); useEffect(function() { if (!visible) { setInnerValue(value); } }, [ visible, value ]); useEffect(function() { setInnerOptions(outerOptions); }, [ outerOptions ]); useEffect(function() { setTabActiveIndex(levels.length - 1); }, [ innerValue, innerOptions, outerOptions ]); useEffect(function() { var max = levels.length - 1; if (tabActiveIndex > max) { setTabActiveIndex(max); } }, [ tabActiveIndex, levels, innerOptions, outerOptions ]); useEffect(function() { var load = /*#__PURE__*/ function() { var _ref = _async_to_generator(function() { var parent, error; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: parent = { children: [] }; _state.label = 1; case 1: _state.trys.push([ 1, 3, , 4 ]); return [ 4, innerValue.reduce(/*#__PURE__*/ function() { var _ref = _async_to_generator(function(promise, val, key) { var pane, parent, node; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: return [ 4, onLoad({ value: val }, key) ]; case 1: pane = _state.sent(); return [ 4, promise ]; case 2: parent = _state.sent(); parent.children = pane; if (key === innerValue.length - 1) { return [ 2, Promise.resolve(parent) ]; } if (pane) { node = pane.find(function(p) { return p.value === val; }); return [ 2, Promise.resolve(node) ]; } return [ 2 ]; } }); }); return function(promise, val, key) { return _ref.apply(this, arguments); }; }(), Promise.resolve(parent)) ]; case 2: _state.sent(); // 如果需要处理最终结果,可以在这里使用 last setInnerOptions(parent.children); return [ 3, 4 ]; case 3: error = _state.sent(); console.error('Error loading data:', error); return [ 3, 4 ]; case 4: return [ 2 ]; } }); }); return function load() { return _ref.apply(this, arguments); }; }(); if (lazy) load(); }, [ lazy ]); var chooseItem = /*#__PURE__*/ function() { var _ref = _async_to_generator(function(pane, levelIndex) { var nextValue, nextPathNodes, _props_onPathChange, asyncOptions; return _ts_generator(this, function(_state) { switch(_state.label){ case 0: if (pane.disabled) return [ 2 ]; nextValue = innerValue.slice(0, levelIndex); nextPathNodes = pathNodes.current.slice(0, levelIndex); if (pane.value) { ; setLoading(!!onLoad && _define_property({}, levelIndex, pane.value)); nextValue[levelIndex] = pane.value; nextPathNodes[levelIndex] = pane; pathNodes.current = nextPathNodes; props === null || props === void 0 ? void 0 : (_props_onPathChange = props.onPathChange) === null || _props_onPathChange === void 0 ? void 0 : _props_onPathChange.call(props, nextValue, pathNodes.current); } if (!onLoad) return [ 3, 3 ]; if (!!pane.leaf) return [ 3, 2 ]; return [ 4, onLoad(pane, levelIndex) ]; case 1: asyncOptions = _state.sent(); // 修改 options 触发渲染逻辑 if (asyncOptions) pane.children = asyncOptions; return [ 3, 3 ]; case 2: setVisible(false); setValue(nextValue); _state.label = 3; case 3: if (!pane.children && !onLoad) { setVisible(false); setValue(nextValue); } setInnerValue(nextValue); setLoading({}); return [ 2 ]; } }); }); return function chooseItem(pane, levelIndex) { return _ref.apply(this, arguments); }; }(); var renderCascaderItem = function(item, levelIndex) { var _item_pane; return (_item_pane = item.pane) === null || _item_pane === void 0 ? void 0 : _item_pane.map(function(pane, index) { var active = item.selected === pane.value; var classes = classNames({ active: active, disabled: pane.disabled }, 'nut-cascader-item'); var showLoadingIcon = loading[levelIndex] === pane.value; return /*#__PURE__*/ React.createElement("div", { className: classes, style: { color: active ? activeColor : '' }, key: pane.value, onClick: function() { chooseItem(pane, levelIndex); } }, /*#__PURE__*/ React.createElement("div", { className: "nut-cascader-item-title" }, pane.text), showLoadingIcon && /*#__PURE__*/ React.createElement(Loading, { color: "#969799", className: "nut-cascader-item-icon-loading" }), active && /*#__PURE__*/ (isValidElement(activeIcon) ? activeIcon : /*#__PURE__*/ React.createElement(Check, { className: "".concat(classPrefix, "-icon-check") }))); }); }; var renderTab = function() { return /*#__PURE__*/ React.createElement("div", { className: classNames(classPrefix, props.className), style: props.style }, /*#__PURE__*/ React.createElement(Tabs, { value: tabActiveIndex, onChange: function(index) { var _props_onTabsChange; (_props_onTabsChange = props.onTabsChange) === null || _props_onTabsChange === void 0 ? void 0 : _props_onTabsChange.call(props, Number(index)); setTabActiveIndex(Number(index)); } }, levels.map(function(pane, index) { return /*#__PURE__*/ React.createElement(Tabs.TabPane, { title: pane.selectedText || locale.select, key: index }, /*#__PURE__*/ React.createElement("div", { className: classPane }, renderCascaderItem(pane, index))); }))); }; return popup ? /*#__PURE__*/ React.createElement(Popup, _object_spread_props(_object_spread({}, popupProps), { visible: visible, position: "bottom", round: true, closeIcon: closeIcon, closeable: closeable, closeIconPosition: closeIconPosition, title: props.title, left: props.left, onOverlayClick: function() { return setVisible(false); }, onCloseIconClick: function() { return setVisible(false); } }), renderTab()) : renderTab(); }); Cascader.displayName = 'NutCascader';