@nutui/nutui-react
Version:
京东风格的轻量级移动端 React 组件库,支持一套代码生成 H5 和小程序
398 lines (397 loc) • 17.7 kB
JavaScript
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';