UNPKG

8.58 kBJavaScriptView Raw
1import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
2import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
3import React from 'react';
4import KeyCode from "rc-util/es/KeyCode";
5import useMemo from "rc-util/es/hooks/useMemo";
6import Tree from 'rc-tree';
7import { SelectContext } from './Context';
8import useKeyValueMapping from './hooks/useKeyValueMapping';
9import useKeyValueMap from './hooks/useKeyValueMap';
10var HIDDEN_STYLE = {
11 width: 0,
12 height: 0,
13 display: 'flex',
14 overflow: 'hidden',
15 opacity: 0,
16 border: 0,
17 padding: 0,
18 margin: 0
19};
20
21var OptionList = function OptionList(props, ref) {
22 var prefixCls = props.prefixCls,
23 height = props.height,
24 itemHeight = props.itemHeight,
25 virtual = props.virtual,
26 options = props.options,
27 flattenOptions = props.flattenOptions,
28 multiple = props.multiple,
29 searchValue = props.searchValue,
30 onSelect = props.onSelect,
31 onToggleOpen = props.onToggleOpen,
32 open = props.open,
33 notFoundContent = props.notFoundContent;
34
35 var _React$useContext = React.useContext(SelectContext),
36 checkable = _React$useContext.checkable,
37 checkedKeys = _React$useContext.checkedKeys,
38 halfCheckedKeys = _React$useContext.halfCheckedKeys,
39 treeExpandedKeys = _React$useContext.treeExpandedKeys,
40 treeDefaultExpandAll = _React$useContext.treeDefaultExpandAll,
41 treeDefaultExpandedKeys = _React$useContext.treeDefaultExpandedKeys,
42 onTreeExpand = _React$useContext.onTreeExpand,
43 treeIcon = _React$useContext.treeIcon,
44 showTreeIcon = _React$useContext.showTreeIcon,
45 switcherIcon = _React$useContext.switcherIcon,
46 treeLine = _React$useContext.treeLine,
47 treeNodeFilterProp = _React$useContext.treeNodeFilterProp,
48 loadData = _React$useContext.loadData,
49 treeLoadedKeys = _React$useContext.treeLoadedKeys,
50 treeMotion = _React$useContext.treeMotion,
51 onTreeLoad = _React$useContext.onTreeLoad;
52
53 var treeRef = React.useRef();
54 var memoOptions = useMemo(function () {
55 return options;
56 }, [open, options], function (prev, next) {
57 return next[0] && prev[1] !== next[1];
58 });
59
60 var _useKeyValueMap = useKeyValueMap(flattenOptions),
61 _useKeyValueMap2 = _slicedToArray(_useKeyValueMap, 2),
62 cacheKeyMap = _useKeyValueMap2[0],
63 cacheValueMap = _useKeyValueMap2[1];
64
65 var _useKeyValueMapping = useKeyValueMapping(cacheKeyMap, cacheValueMap),
66 _useKeyValueMapping2 = _slicedToArray(_useKeyValueMapping, 2),
67 getEntityByKey = _useKeyValueMapping2[0],
68 getEntityByValue = _useKeyValueMapping2[1]; // ========================== Values ==========================
69
70
71 var valueKeys = React.useMemo(function () {
72 return checkedKeys.map(function (val) {
73 var entity = getEntityByValue(val);
74 return entity ? entity.key : null;
75 });
76 }, [checkedKeys]);
77 var mergedCheckedKeys = React.useMemo(function () {
78 if (!checkable) {
79 return null;
80 }
81
82 return {
83 checked: valueKeys,
84 halfChecked: halfCheckedKeys
85 };
86 }, [valueKeys, halfCheckedKeys, checkable]); // ========================== Scroll ==========================
87
88 React.useEffect(function () {
89 // Single mode should scroll to current key
90 if (open && !multiple && valueKeys.length) {
91 var _treeRef$current;
92
93 (_treeRef$current = treeRef.current) === null || _treeRef$current === void 0 ? void 0 : _treeRef$current.scrollTo({
94 key: valueKeys[0]
95 });
96 }
97 }, [open]); // ========================== Search ==========================
98
99 var lowerSearchValue = String(searchValue).toLowerCase();
100
101 var filterTreeNode = function filterTreeNode(treeNode) {
102 if (!lowerSearchValue) {
103 return false;
104 }
105
106 return String(treeNode[treeNodeFilterProp]).toLowerCase().includes(lowerSearchValue);
107 }; // =========================== Keys ===========================
108
109
110 var _React$useState = React.useState(treeDefaultExpandedKeys),
111 _React$useState2 = _slicedToArray(_React$useState, 2),
112 expandedKeys = _React$useState2[0],
113 setExpandedKeys = _React$useState2[1];
114
115 var _React$useState3 = React.useState(null),
116 _React$useState4 = _slicedToArray(_React$useState3, 2),
117 searchExpandedKeys = _React$useState4[0],
118 setSearchExpandedKeys = _React$useState4[1];
119
120 var mergedExpandedKeys = React.useMemo(function () {
121 if (treeExpandedKeys) {
122 return _toConsumableArray(treeExpandedKeys);
123 }
124
125 return searchValue ? searchExpandedKeys : expandedKeys;
126 }, [expandedKeys, searchExpandedKeys, lowerSearchValue, treeExpandedKeys]);
127 React.useEffect(function () {
128 if (searchValue) {
129 setSearchExpandedKeys(flattenOptions.map(function (o) {
130 return o.key;
131 }));
132 }
133 }, [searchValue]);
134
135 var onInternalExpand = function onInternalExpand(keys) {
136 setExpandedKeys(keys);
137 setSearchExpandedKeys(keys);
138
139 if (onTreeExpand) {
140 onTreeExpand(keys);
141 }
142 }; // ========================== Events ==========================
143
144
145 var onListMouseDown = function onListMouseDown(event) {
146 event.preventDefault();
147 };
148
149 var onInternalSelect = function onInternalSelect(_, _ref) {
150 var key = _ref.node.key;
151 var entity = getEntityByKey(key, checkable ? 'checkbox' : 'select');
152
153 if (entity !== null) {
154 onSelect(entity.data.value, {
155 selected: !checkedKeys.includes(entity.data.value)
156 });
157 }
158
159 if (!multiple) {
160 onToggleOpen(false);
161 }
162 }; // ========================= Keyboard =========================
163
164
165 var _React$useState5 = React.useState(null),
166 _React$useState6 = _slicedToArray(_React$useState5, 2),
167 activeKey = _React$useState6[0],
168 setActiveKey = _React$useState6[1];
169
170 var activeEntity = getEntityByKey(activeKey);
171 React.useImperativeHandle(ref, function () {
172 return {
173 onKeyDown: function onKeyDown(event) {
174 var _treeRef$current2;
175
176 var which = event.which;
177
178 switch (which) {
179 // >>> Arrow keys
180 case KeyCode.UP:
181 case KeyCode.DOWN:
182 case KeyCode.LEFT:
183 case KeyCode.RIGHT:
184 (_treeRef$current2 = treeRef.current) === null || _treeRef$current2 === void 0 ? void 0 : _treeRef$current2.onKeyDown(event);
185 break;
186 // >>> Select item
187
188 case KeyCode.ENTER:
189 {
190 if (activeEntity !== null) {
191 onInternalSelect(null, {
192 node: {
193 key: activeKey
194 },
195 selected: !checkedKeys.includes(activeEntity.data.value)
196 });
197 }
198
199 break;
200 }
201 // >>> Close
202
203 case KeyCode.ESC:
204 {
205 onToggleOpen(false);
206 }
207 }
208 },
209 onKeyUp: function onKeyUp() {}
210 };
211 }); // ========================== Render ==========================
212
213 if (memoOptions.length === 0) {
214 return React.createElement("div", {
215 role: "listbox",
216 className: "".concat(prefixCls, "-empty"),
217 onMouseDown: onListMouseDown
218 }, notFoundContent);
219 }
220
221 var treeProps = {};
222
223 if (treeLoadedKeys) {
224 treeProps.loadedKeys = treeLoadedKeys;
225 }
226
227 if (mergedExpandedKeys) {
228 treeProps.expandedKeys = mergedExpandedKeys;
229 }
230
231 return React.createElement("div", {
232 onMouseDown: onListMouseDown
233 }, activeEntity && open && React.createElement("span", {
234 style: HIDDEN_STYLE,
235 "aria-live": "assertive"
236 }, activeEntity.data.value), React.createElement(Tree, Object.assign({
237 ref: treeRef,
238 focusable: false,
239 prefixCls: "".concat(prefixCls, "-tree"),
240 treeData: memoOptions,
241 height: height,
242 itemHeight: itemHeight,
243 virtual: virtual,
244 multiple: multiple,
245 icon: treeIcon,
246 showIcon: showTreeIcon,
247 switcherIcon: switcherIcon,
248 showLine: treeLine,
249 loadData: searchValue ? null : loadData,
250 motion: treeMotion,
251 // We handle keys by out instead tree self
252 checkable: checkable,
253 checkStrictly: true,
254 checkedKeys: mergedCheckedKeys,
255 selectedKeys: !checkable ? valueKeys : [],
256 defaultExpandAll: treeDefaultExpandAll
257 }, treeProps, {
258 // Proxy event out
259 onActiveChange: setActiveKey,
260 onSelect: onInternalSelect,
261 onCheck: onInternalSelect,
262 onExpand: onInternalExpand,
263 onLoad: onTreeLoad,
264 filterTreeNode: filterTreeNode
265 })));
266};
267
268var RefOptionList = React.forwardRef(OptionList);
269RefOptionList.displayName = 'OptionList';
270export default RefOptionList;
\No newline at end of file