UNPKG

bonree-cascader

Version:

cascade select ui component for react

333 lines (270 loc) 12.9 kB
"use strict"; var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard"); var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = Column; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var React = _interopRequireWildcard(require("react")); var _classnames = _interopRequireDefault(require("classnames")); var _rcVirtualList = _interopRequireDefault(require("rc-virtual-list")); var _Cascader = require("../Cascader"); var _util = require("../util"); var _context = _interopRequireDefault(require("../context")); var _Checkbox = _interopRequireDefault(require("./Checkbox")); var _commonUtil = require("bonree-select/lib/utils/commonUtil"); function Column(_ref) { var _classNames4; var prefixCls = _ref.prefixCls, index = _ref.index, multiple = _ref.multiple, options = _ref.options, openKey = _ref.openKey, onSelect = _ref.onSelect, onOpen = _ref.onOpen, onToggleOpen = _ref.onToggleOpen, checkedSet = _ref.checkedSet, halfCheckedSet = _ref.halfCheckedSet, openFinalValue = _ref.openFinalValue, searchValue = _ref.searchValue, height = _ref.height, itemHeight = _ref.itemHeight, values = _ref.values, onSelectAll = _ref.onSelectAll, autoEllipsis = _ref.autoEllipsis, Tooltip = _ref.tooltip; var menuPrefixCls = "".concat(prefixCls, "-menu"); var menuItemPrefixCls = "".concat(prefixCls, "-menu-item"); var uuidRef = React.useRef((0, _commonUtil.getUUID)()); var _React$useContext = React.useContext(_context.default), changeOnSelect = _React$useContext.changeOnSelect, expandTrigger = _React$useContext.expandTrigger, expandIcon = _React$useContext.expandIcon, loadingIcon = _React$useContext.loadingIcon, dropdownMenuColumnStyle = _React$useContext.dropdownMenuColumnStyle, requestFailureIcon = _React$useContext.requestFailureIcon, requestFailureText = _React$useContext.requestFailureText, refreshText = _React$useContext.refreshText, empty = _React$useContext.empty, virtual = _React$useContext.virtual, treeCheckStrictly = _React$useContext.treeCheckStrictly; var hoverOpen = expandTrigger === 'hover'; // ========================= Overflow ========================= // 记录每个选项内容是否溢出,key 为 option.value var _React$useState = React.useState({}), _React$useState2 = (0, _slicedToArray2.default)(_React$useState, 2), overflowMap = _React$useState2[0], setOverflowMap = _React$useState2[1]; // 虚拟滚动模式下,跟踪当前可见的选项 var _React$useState3 = React.useState([]), _React$useState4 = (0, _slicedToArray2.default)(_React$useState3, 2), visibleOptions = _React$useState4[0], setVisibleOptions = _React$useState4[1]; // 虚拟滚动模式下仅检测当前可见的选项,非虚拟模式检测所有选项 var itemsToCheck = virtual ? visibleOptions : options; // 通过 ref 追踪 options 变化,用于在虚拟模式下检测数据源切换并重置 overflowMap var prevOptionsRef = React.useRef(options); React.useLayoutEffect(function () { if (!autoEllipsis || !Tooltip) return; // 检测 options 是否发生变化(如切换级联列) var optionsChanged = prevOptionsRef.current !== options; prevOptionsRef.current = options; var newEntries = {}; itemsToCheck.forEach(function (option) { if (option.value === _util.ALL_KEY) return; var contentId = "cascader-content-".concat(option.value, "-").concat(uuidRef.current); var el = document.getElementById(contentId); if (el) { newEntries[option.value] = (0, _commonUtil.judgeOverflowing)(el); } }); // 非虚拟模式或 options 变化时直接替换;虚拟模式下增量合并,保留已检测过的结果 if (!virtual || optionsChanged) { setOverflowMap(newEntries); } else { setOverflowMap(function (prev) { return (0, _objectSpread2.default)((0, _objectSpread2.default)({}, prev), newEntries); }); } }, [itemsToCheck, options, autoEllipsis, Tooltip, virtual]); // 全选按钮状态 var getCheckStatus = function getCheckStatus() { var status = 'none'; if (values.size === 0) { return status; } var optValues = options.filter(function (item) { return item.value !== _util.ALL_KEY && !item.disabled; }).map(function (item) { return item.value; }); if (optValues.some(function (k) { return values.has(k); })) { status = 'part'; } if (optValues.every(function (k) { return values.has(k); })) { status = 'all'; } return status; }; var handleSelectAll = function handleSelectAll(value) { var newValues = options.filter(function (v) { return v.value !== undefined && !v.disabled; }).filter(function (v) { return v.value !== _util.ALL_KEY; }).map(function (item) { return item.value; }); if (newValues && newValues.length) { onSelectAll(newValues, { selected: getCheckStatus() !== 'all', triggerValue: value }); } }; var handleScroll = function handleScroll() { document.querySelectorAll(".".concat(prefixCls, "-menu-item-content-tooltip")).forEach(function (node) { if (node) { node.style.display = 'none'; } }); }; // ============================ Render ============================ var renderOption = function renderOption(option) { var _classNames2; var disabled = option.disabled, value = option.value, node = option.node; // 处理"全部"选项 if (value === _util.ALL_KEY) { return /*#__PURE__*/React.createElement("li", { key: value, className: (0, _classnames.default)(menuItemPrefixCls, "".concat(menuItemPrefixCls, "-all"), (0, _defineProperty2.default)({}, "".concat(menuItemPrefixCls, "-disabled"), disabled)), onClick: function onClick() { return !treeCheckStrictly && !disabled && handleSelectAll(value); } }, multiple && /*#__PURE__*/React.createElement(_Checkbox.default, { prefixCls: "".concat(prefixCls, "-checkbox"), checked: getCheckStatus() === 'all', halfChecked: getCheckStatus() === 'part', disabled: disabled, onClick: function onClick(e) { e.stopPropagation(); if (!disabled) { handleSelectAll(value); } } }), /*#__PURE__*/React.createElement("div", { className: "".concat(menuItemPrefixCls, "-content") }, option.title)); } var isMergedLeaf = (0, _util.isLeaf)(option); // const isLoading = loadingKeys.includes(value); // 加载中 var isLoading = value === (0, _util.connectValue)([openFinalValue, _Cascader.LOAD_STATUS.LOADING]) || value === _Cascader.LOAD_STATUS.LOADING; if (isLoading) { return /*#__PURE__*/React.createElement("li", { key: value, className: (0, _classnames.default)(menuItemPrefixCls, "".concat(menuItemPrefixCls, "-loading")), style: dropdownMenuColumnStyle }, loadingIcon); } // 加载数据失败 var isLoadFailed = value === (0, _util.connectValue)([openFinalValue, _Cascader.LOAD_STATUS.FAILED]) || value === _Cascader.LOAD_STATUS.FAILED; if (isLoadFailed) { return /*#__PURE__*/React.createElement("li", { key: value, className: (0, _classnames.default)(menuItemPrefixCls, "".concat(menuItemPrefixCls, "-failed")), style: dropdownMenuColumnStyle }, /*#__PURE__*/React.createElement("div", { className: "".concat(menuItemPrefixCls, "-failed-content") }, requestFailureIcon, requestFailureText, /*#__PURE__*/React.createElement("span", { className: "".concat(menuItemPrefixCls, "-failed-content-refresh"), onClick: function onClick() { onOpen(index, openFinalValue); } }, refreshText))); } // 无数据 var isNoData = value === (0, _util.connectValue)([openFinalValue, _Cascader.LOAD_STATUS.EMPTY]) || value === _Cascader.LOAD_STATUS.EMPTY; if (isNoData) { return /*#__PURE__*/React.createElement("li", { key: value, className: (0, _classnames.default)(menuItemPrefixCls, "".concat(menuItemPrefixCls, "-empty")), style: dropdownMenuColumnStyle }, empty); } // >>>>> checked var checked = checkedSet.has(value); // >>>>> Open var triggerOpenPath = function triggerOpenPath() { // if (!disabled && hoverOpen) { if (!disabled && (!hoverOpen || !isMergedLeaf)) { onOpen(index, value); } }; // >>>>> Selection var triggerSelect = function triggerSelect() { if (!disabled && (isMergedLeaf || changeOnSelect || multiple)) { onSelect(value, isMergedLeaf); } }; // >>>>> Title var title; if (typeof (node === null || node === void 0 ? void 0 : node.title) === 'string' || typeof (node === null || node === void 0 ? void 0 : node.title) === 'number') { title = String(node.title); } else if (typeof option.title === 'string' || typeof (option === null || option === void 0 ? void 0 : option.title) === 'number') { title = String(option.title); } // >>>>> Ellipsis & Tooltip var ellipsisConfig = autoEllipsis === true ? {} : autoEllipsis; var contentId = "cascader-content-".concat(value, "-").concat(uuidRef.current); var isOverflowing = overflowMap[value] || false; // >>>>> Render return /*#__PURE__*/React.createElement("li", { key: value, className: (0, _classnames.default)(menuItemPrefixCls, (_classNames2 = {}, (0, _defineProperty2.default)(_classNames2, "".concat(menuItemPrefixCls, "-expand"), !isMergedLeaf), (0, _defineProperty2.default)(_classNames2, "".concat(menuItemPrefixCls, "-active"), openKey === value), (0, _defineProperty2.default)(_classNames2, "".concat(menuItemPrefixCls, "-disabled"), disabled), _classNames2)), style: dropdownMenuColumnStyle, role: "menuitemcheckbox", "aria-checked": checked, "data-value": value, onClick: function onClick() { triggerOpenPath(); if (!treeCheckStrictly && (!multiple || isMergedLeaf)) { triggerSelect(); } }, onDoubleClick: function onDoubleClick() { if (changeOnSelect) { onToggleOpen(false); } }, onMouseEnter: function onMouseEnter() { if (!disabled && hoverOpen) { onOpen(index, value); } } }, multiple && value !== _util.DATA_EMPTY && !isLoading && /*#__PURE__*/React.createElement(_Checkbox.default, { prefixCls: "".concat(prefixCls, "-checkbox"), checked: checked, halfChecked: halfCheckedSet.has(value), disabled: disabled, onClick: function onClick(e) { e.stopPropagation(); triggerSelect(); } }), /*#__PURE__*/React.createElement(!disabled && ellipsisConfig && isOverflowing && title && Tooltip ? Tooltip : React.Fragment, !disabled && ellipsisConfig && isOverflowing && title && Tooltip ? (0, _objectSpread2.default)({ title: title, overlayClassName: "".concat(prefixCls, "-menu-item-content-tooltip"), destroyTooltipOnHide: true }, ellipsisConfig) : null, /*#__PURE__*/React.createElement("div", { id: contentId, className: (0, _classnames.default)("".concat(menuItemPrefixCls, "-content"), (0, _defineProperty2.default)({}, "".concat(menuItemPrefixCls, "-content-overflowing"), isOverflowing)) }, option.title)), expandIcon && !isMergedLeaf && /*#__PURE__*/React.createElement("div", { className: "".concat(menuItemPrefixCls, "-expand-icon") }, expandIcon)); }; return /*#__PURE__*/React.createElement("ul", { className: (0, _classnames.default)(menuPrefixCls, (_classNames4 = {}, (0, _defineProperty2.default)(_classNames4, "".concat(menuPrefixCls, "-virtual"), virtual), (0, _defineProperty2.default)(_classNames4, "".concat(menuPrefixCls, "-searchValue"), !!searchValue), _classNames4)), role: "menu", onScroll: virtual ? undefined : handleScroll }, virtual ? /*#__PURE__*/React.createElement(_rcVirtualList.default, { data: options, height: height, itemHeight: itemHeight, itemKey: "value", fullHeight: false, onVisibleChange: function onVisibleChange(visibleList) { setVisibleOptions(visibleList); }, onScroll: handleScroll }, renderOption) : options.map(renderOption)); }