You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

272 lines
8.4 KiB

import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
import React from 'react';
import KeyCode from "rc-util/es/KeyCode";
import useMemo from "rc-util/es/hooks/useMemo";
import Tree from 'rc-tree';
import { SelectContext } from './Context';
import useKeyValueMapping from './hooks/useKeyValueMapping';
import useKeyValueMap from './hooks/useKeyValueMap';
var HIDDEN_STYLE = {
width: 0,
height: 0,
display: 'flex',
overflow: 'hidden',
opacity: 0,
border: 0,
padding: 0,
margin: 0
};
var OptionList = function OptionList(props, ref) {
var prefixCls = props.prefixCls,
height = props.height,
itemHeight = props.itemHeight,
virtual = props.virtual,
options = props.options,
flattenOptions = props.flattenOptions,
multiple = props.multiple,
searchValue = props.searchValue,
onSelect = props.onSelect,
onToggleOpen = props.onToggleOpen,
open = props.open,
notFoundContent = props.notFoundContent,
onMouseEnter = props.onMouseEnter;
var _React$useContext = React.useContext(SelectContext),
checkable = _React$useContext.checkable,
checkedKeys = _React$useContext.checkedKeys,
halfCheckedKeys = _React$useContext.halfCheckedKeys,
treeExpandedKeys = _React$useContext.treeExpandedKeys,
treeDefaultExpandAll = _React$useContext.treeDefaultExpandAll,
treeDefaultExpandedKeys = _React$useContext.treeDefaultExpandedKeys,
onTreeExpand = _React$useContext.onTreeExpand,
treeIcon = _React$useContext.treeIcon,
showTreeIcon = _React$useContext.showTreeIcon,
switcherIcon = _React$useContext.switcherIcon,
treeLine = _React$useContext.treeLine,
treeNodeFilterProp = _React$useContext.treeNodeFilterProp,
loadData = _React$useContext.loadData,
treeLoadedKeys = _React$useContext.treeLoadedKeys,
treeMotion = _React$useContext.treeMotion,
onTreeLoad = _React$useContext.onTreeLoad;
var treeRef = React.useRef();
var memoOptions = useMemo(function () {
return options;
}, [open, options], function (prev, next) {
return next[0] && prev[1] !== next[1];
});
var _useKeyValueMap = useKeyValueMap(flattenOptions),
_useKeyValueMap2 = _slicedToArray(_useKeyValueMap, 2),
cacheKeyMap = _useKeyValueMap2[0],
cacheValueMap = _useKeyValueMap2[1];
var _useKeyValueMapping = useKeyValueMapping(cacheKeyMap, cacheValueMap),
_useKeyValueMapping2 = _slicedToArray(_useKeyValueMapping, 2),
getEntityByKey = _useKeyValueMapping2[0],
getEntityByValue = _useKeyValueMapping2[1]; // ========================== Values ==========================
var valueKeys = React.useMemo(function () {
return checkedKeys.map(function (val) {
var entity = getEntityByValue(val);
return entity ? entity.key : null;
});
}, [checkedKeys]);
var mergedCheckedKeys = React.useMemo(function () {
if (!checkable) {
return null;
}
return {
checked: valueKeys,
halfChecked: halfCheckedKeys
};
}, [valueKeys, halfCheckedKeys, checkable]); // ========================== Scroll ==========================
React.useEffect(function () {
// Single mode should scroll to current key
if (open && !multiple && valueKeys.length) {
var _treeRef$current;
(_treeRef$current = treeRef.current) === null || _treeRef$current === void 0 ? void 0 : _treeRef$current.scrollTo({
key: valueKeys[0]
});
}
}, [open]); // ========================== Search ==========================
var lowerSearchValue = String(searchValue).toLowerCase();
var filterTreeNode = function filterTreeNode(treeNode) {
if (!lowerSearchValue) {
return false;
}
return String(treeNode[treeNodeFilterProp]).toLowerCase().includes(lowerSearchValue);
}; // =========================== Keys ===========================
var _React$useState = React.useState(treeDefaultExpandedKeys),
_React$useState2 = _slicedToArray(_React$useState, 2),
expandedKeys = _React$useState2[0],
setExpandedKeys = _React$useState2[1];
var _React$useState3 = React.useState(null),
_React$useState4 = _slicedToArray(_React$useState3, 2),
searchExpandedKeys = _React$useState4[0],
setSearchExpandedKeys = _React$useState4[1];
var mergedExpandedKeys = React.useMemo(function () {
if (treeExpandedKeys) {
return _toConsumableArray(treeExpandedKeys);
}
return searchValue ? searchExpandedKeys : expandedKeys;
}, [expandedKeys, searchExpandedKeys, lowerSearchValue, treeExpandedKeys]);
React.useEffect(function () {
if (searchValue) {
setSearchExpandedKeys(flattenOptions.map(function (o) {
return o.key;
}));
}
}, [searchValue]);
var onInternalExpand = function onInternalExpand(keys) {
setExpandedKeys(keys);
setSearchExpandedKeys(keys);
if (onTreeExpand) {
onTreeExpand(keys);
}
}; // ========================== Events ==========================
var onListMouseDown = function onListMouseDown(event) {
event.preventDefault();
};
var onInternalSelect = function onInternalSelect(_, _ref) {
var key = _ref.node.key;
var entity = getEntityByKey(key, checkable ? 'checkbox' : 'select');
if (entity !== null) {
onSelect(entity.data.value, {
selected: !checkedKeys.includes(entity.data.value)
});
}
if (!multiple) {
onToggleOpen(false);
}
}; // ========================= Keyboard =========================
var _React$useState5 = React.useState(null),
_React$useState6 = _slicedToArray(_React$useState5, 2),
activeKey = _React$useState6[0],
setActiveKey = _React$useState6[1];
var activeEntity = getEntityByKey(activeKey);
React.useImperativeHandle(ref, function () {
return {
onKeyDown: function onKeyDown(event) {
var _treeRef$current2;
var which = event.which;
switch (which) {
// >>> Arrow keys
case KeyCode.UP:
case KeyCode.DOWN:
case KeyCode.LEFT:
case KeyCode.RIGHT:
(_treeRef$current2 = treeRef.current) === null || _treeRef$current2 === void 0 ? void 0 : _treeRef$current2.onKeyDown(event);
break;
// >>> Select item
case KeyCode.ENTER:
{
if (activeEntity !== null) {
onInternalSelect(null, {
node: {
key: activeKey
},
selected: !checkedKeys.includes(activeEntity.data.value)
});
}
break;
}
// >>> Close
case KeyCode.ESC:
{
onToggleOpen(false);
}
}
},
onKeyUp: function onKeyUp() {}
};
}); // ========================== Render ==========================
if (memoOptions.length === 0) {
return React.createElement("div", {
role: "listbox",
className: "".concat(prefixCls, "-empty"),
onMouseDown: onListMouseDown
}, notFoundContent);
}
var treeProps = {};
if (treeLoadedKeys) {
treeProps.loadedKeys = treeLoadedKeys;
}
if (mergedExpandedKeys) {
treeProps.expandedKeys = mergedExpandedKeys;
}
return React.createElement("div", {
onMouseDown: onListMouseDown,
onMouseEnter: onMouseEnter
}, activeEntity && open && React.createElement("span", {
style: HIDDEN_STYLE,
"aria-live": "assertive"
}, activeEntity.data.value), React.createElement(Tree, Object.assign({
ref: treeRef,
focusable: false,
prefixCls: "".concat(prefixCls, "-tree"),
treeData: memoOptions,
height: height,
itemHeight: itemHeight,
virtual: virtual,
multiple: multiple,
icon: treeIcon,
showIcon: showTreeIcon,
switcherIcon: switcherIcon,
showLine: treeLine,
loadData: searchValue ? null : loadData,
motion: treeMotion,
// We handle keys by out instead tree self
checkable: checkable,
checkStrictly: true,
checkedKeys: mergedCheckedKeys,
selectedKeys: !checkable ? valueKeys : [],
defaultExpandAll: treeDefaultExpandAll
}, treeProps, {
// Proxy event out
onActiveChange: setActiveKey,
onSelect: onInternalSelect,
onCheck: onInternalSelect,
onExpand: onInternalExpand,
onLoad: onTreeLoad,
filterTreeNode: filterTreeNode
})));
};
var RefOptionList = React.forwardRef(OptionList);
RefOptionList.displayName = 'OptionList';
export default RefOptionList;