1 | import _toArray from "@babel/runtime/helpers/esm/toArray";
|
2 | import _defineProperty from "@babel/runtime/helpers/esm/defineProperty";
|
3 | import _extends from "@babel/runtime/helpers/esm/extends";
|
4 | import _slicedToArray from "@babel/runtime/helpers/esm/slicedToArray";
|
5 | import _toConsumableArray from "@babel/runtime/helpers/esm/toConsumableArray";
|
6 | import _typeof from "@babel/runtime/helpers/esm/typeof";
|
7 | import * as React from 'react';
|
8 | import { useState, useCallback, useMemo } from 'react';
|
9 | import DownOutlined from "@ant-design/icons/es/icons/DownOutlined";
|
10 | import { convertDataToEntities } from "rc-tree/es/utils/treeUtil";
|
11 | import { conductCheck } from "rc-tree/es/utils/conductUtil";
|
12 | import { arrAdd, arrDel } from "rc-tree/es/util";
|
13 | import { INTERNAL_COL_DEFINE } from 'rc-table';
|
14 | import useMergedState from "rc-util/es/hooks/useMergedState";
|
15 | import Checkbox from '../../checkbox';
|
16 | import Dropdown from '../../dropdown';
|
17 | import Menu from '../../menu';
|
18 | import Radio from '../../radio';
|
19 | import devWarning from '../../_util/devWarning';
|
20 |
|
21 | export var SELECTION_ALL = 'SELECT_ALL';
|
22 | export var SELECTION_INVERT = 'SELECT_INVERT';
|
23 | export var SELECTION_NONE = 'SELECT_NONE';
|
24 |
|
25 | function getFixedType(column) {
|
26 | return column && column.fixed;
|
27 | }
|
28 |
|
29 | function flattenData(data, childrenColumnName) {
|
30 | var list = [];
|
31 | (data || []).forEach(function (record) {
|
32 | list.push(record);
|
33 |
|
34 | if (record && _typeof(record) === 'object' && childrenColumnName in record) {
|
35 | list = [].concat(_toConsumableArray(list), _toConsumableArray(flattenData(record[childrenColumnName], childrenColumnName)));
|
36 | }
|
37 | });
|
38 | return list;
|
39 | }
|
40 |
|
41 | export default function useSelection(rowSelection, config) {
|
42 | var _ref = rowSelection || {},
|
43 | preserveSelectedRowKeys = _ref.preserveSelectedRowKeys,
|
44 | selectedRowKeys = _ref.selectedRowKeys,
|
45 | defaultSelectedRowKeys = _ref.defaultSelectedRowKeys,
|
46 | getCheckboxProps = _ref.getCheckboxProps,
|
47 | onSelectionChange = _ref.onChange,
|
48 | onSelect = _ref.onSelect,
|
49 | onSelectAll = _ref.onSelectAll,
|
50 | onSelectInvert = _ref.onSelectInvert,
|
51 | onSelectNone = _ref.onSelectNone,
|
52 | onSelectMultiple = _ref.onSelectMultiple,
|
53 | selectionColWidth = _ref.columnWidth,
|
54 | selectionType = _ref.type,
|
55 | selections = _ref.selections,
|
56 | fixed = _ref.fixed,
|
57 | customizeRenderCell = _ref.renderCell,
|
58 | hideSelectAll = _ref.hideSelectAll,
|
59 | _ref$checkStrictly = _ref.checkStrictly,
|
60 | checkStrictly = _ref$checkStrictly === void 0 ? true : _ref$checkStrictly;
|
61 |
|
62 | var prefixCls = config.prefixCls,
|
63 | data = config.data,
|
64 | pageData = config.pageData,
|
65 | getRecordByKey = config.getRecordByKey,
|
66 | getRowKey = config.getRowKey,
|
67 | expandType = config.expandType,
|
68 | childrenColumnName = config.childrenColumnName,
|
69 | tableLocale = config.locale,
|
70 | expandIconColumnIndex = config.expandIconColumnIndex,
|
71 | getPopupContainer = config.getPopupContainer;
|
72 |
|
73 | var _useMergedState = useMergedState(selectedRowKeys || defaultSelectedRowKeys || [], {
|
74 | value: selectedRowKeys
|
75 | }),
|
76 | _useMergedState2 = _slicedToArray(_useMergedState, 2),
|
77 | mergedSelectedKeys = _useMergedState2[0],
|
78 | setMergedSelectedKeys = _useMergedState2[1];
|
79 |
|
80 |
|
81 | var preserveRecordsRef = React.useRef(new Map());
|
82 | var updatePreserveRecordsCache = useCallback(function (keys) {
|
83 | if (preserveSelectedRowKeys) {
|
84 | var newCache = new Map();
|
85 |
|
86 | keys.forEach(function (key) {
|
87 | var record = getRecordByKey(key);
|
88 |
|
89 | if (!record && preserveRecordsRef.current.has(key)) {
|
90 | record = preserveRecordsRef.current.get(key);
|
91 | }
|
92 |
|
93 | newCache.set(key, record);
|
94 | });
|
95 |
|
96 | preserveRecordsRef.current = newCache;
|
97 | }
|
98 | }, [getRecordByKey, preserveSelectedRowKeys]);
|
99 |
|
100 | React.useEffect(function () {
|
101 | updatePreserveRecordsCache(mergedSelectedKeys);
|
102 | }, [mergedSelectedKeys]);
|
103 |
|
104 | var _useMemo = useMemo(function () {
|
105 | return checkStrictly ? {
|
106 | keyEntities: null
|
107 | } : convertDataToEntities(data, {
|
108 | externalGetKey: getRowKey,
|
109 | childrenPropName: childrenColumnName
|
110 | });
|
111 | }, [data, getRowKey, checkStrictly, childrenColumnName]),
|
112 | keyEntities = _useMemo.keyEntities;
|
113 |
|
114 |
|
115 | var flattedData = useMemo(function () {
|
116 | return flattenData(pageData, childrenColumnName);
|
117 | }, [pageData, childrenColumnName]);
|
118 |
|
119 | var checkboxPropsMap = useMemo(function () {
|
120 | var map = new Map();
|
121 | flattedData.forEach(function (record, index) {
|
122 | var key = getRowKey(record, index);
|
123 | var checkboxProps = (getCheckboxProps ? getCheckboxProps(record) : null) || {};
|
124 | map.set(key, checkboxProps);
|
125 |
|
126 | if (process.env.NODE_ENV !== 'production' && ('checked' in checkboxProps || 'defaultChecked' in checkboxProps)) {
|
127 | devWarning(false, 'Table', 'Do not set `checked` or `defaultChecked` in `getCheckboxProps`. Please use `selectedRowKeys` instead.');
|
128 | }
|
129 | });
|
130 | return map;
|
131 | }, [flattedData, getRowKey, getCheckboxProps]);
|
132 | var isCheckboxDisabled = useCallback(function (r) {
|
133 | var _a;
|
134 |
|
135 | return !!((_a = checkboxPropsMap.get(getRowKey(r))) === null || _a === void 0 ? void 0 : _a.disabled);
|
136 | }, [checkboxPropsMap, getRowKey]);
|
137 |
|
138 | var _useMemo2 = useMemo(function () {
|
139 | if (checkStrictly) {
|
140 | return [mergedSelectedKeys || [], []];
|
141 | }
|
142 |
|
143 | var _conductCheck = conductCheck(mergedSelectedKeys, true, keyEntities, isCheckboxDisabled),
|
144 | checkedKeys = _conductCheck.checkedKeys,
|
145 | halfCheckedKeys = _conductCheck.halfCheckedKeys;
|
146 |
|
147 | return [checkedKeys || [], halfCheckedKeys];
|
148 | }, [mergedSelectedKeys, checkStrictly, keyEntities, isCheckboxDisabled]),
|
149 | _useMemo3 = _slicedToArray(_useMemo2, 2),
|
150 | derivedSelectedKeys = _useMemo3[0],
|
151 | derivedHalfSelectedKeys = _useMemo3[1];
|
152 |
|
153 | var derivedSelectedKeySet = useMemo(function () {
|
154 | var keys = selectionType === 'radio' ? derivedSelectedKeys.slice(0, 1) : derivedSelectedKeys;
|
155 | return new Set(keys);
|
156 | }, [derivedSelectedKeys, selectionType]);
|
157 | var derivedHalfSelectedKeySet = useMemo(function () {
|
158 | return selectionType === 'radio' ? new Set() : new Set(derivedHalfSelectedKeys);
|
159 | }, [derivedHalfSelectedKeys, selectionType]);
|
160 |
|
161 | var _useState = useState(null),
|
162 | _useState2 = _slicedToArray(_useState, 2),
|
163 | lastSelectedKey = _useState2[0],
|
164 | setLastSelectedKey = _useState2[1];
|
165 |
|
166 |
|
167 | React.useEffect(function () {
|
168 | if (!rowSelection) {
|
169 | setMergedSelectedKeys([]);
|
170 | }
|
171 | }, [!!rowSelection]);
|
172 | var setSelectedKeys = useCallback(function (keys) {
|
173 | var availableKeys;
|
174 | var records;
|
175 | updatePreserveRecordsCache(keys);
|
176 |
|
177 | if (preserveSelectedRowKeys) {
|
178 | availableKeys = keys;
|
179 | records = keys.map(function (key) {
|
180 | return preserveRecordsRef.current.get(key);
|
181 | });
|
182 | } else {
|
183 |
|
184 | availableKeys = [];
|
185 | records = [];
|
186 | keys.forEach(function (key) {
|
187 | var record = getRecordByKey(key);
|
188 |
|
189 | if (record !== undefined) {
|
190 | availableKeys.push(key);
|
191 | records.push(record);
|
192 | }
|
193 | });
|
194 | }
|
195 |
|
196 | setMergedSelectedKeys(availableKeys);
|
197 | onSelectionChange === null || onSelectionChange === void 0 ? void 0 : onSelectionChange(availableKeys, records);
|
198 | }, [setMergedSelectedKeys, getRecordByKey, onSelectionChange, preserveSelectedRowKeys]);
|
199 |
|
200 |
|
201 | var triggerSingleSelection = useCallback(function (key, selected, keys, event) {
|
202 | if (onSelect) {
|
203 | var rows = keys.map(function (k) {
|
204 | return getRecordByKey(k);
|
205 | });
|
206 | onSelect(getRecordByKey(key), selected, rows, event);
|
207 | }
|
208 |
|
209 | setSelectedKeys(keys);
|
210 | }, [onSelect, getRecordByKey, setSelectedKeys]);
|
211 | var mergedSelections = useMemo(function () {
|
212 | if (!selections || hideSelectAll) {
|
213 | return null;
|
214 | }
|
215 |
|
216 | var selectionList = selections === true ? [SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE] : selections;
|
217 | return selectionList.map(function (selection) {
|
218 | if (selection === SELECTION_ALL) {
|
219 | return {
|
220 | key: 'all',
|
221 | text: tableLocale.selectionAll,
|
222 | onSelect: function onSelect() {
|
223 | setSelectedKeys(data.map(function (record, index) {
|
224 | return getRowKey(record, index);
|
225 | }));
|
226 | }
|
227 | };
|
228 | }
|
229 |
|
230 | if (selection === SELECTION_INVERT) {
|
231 | return {
|
232 | key: 'invert',
|
233 | text: tableLocale.selectInvert,
|
234 | onSelect: function onSelect() {
|
235 | var keySet = new Set(derivedSelectedKeySet);
|
236 | pageData.forEach(function (record, index) {
|
237 | var key = getRowKey(record, index);
|
238 |
|
239 | if (keySet.has(key)) {
|
240 | keySet["delete"](key);
|
241 | } else {
|
242 | keySet.add(key);
|
243 | }
|
244 | });
|
245 | var keys = Array.from(keySet);
|
246 |
|
247 | if (onSelectInvert) {
|
248 | devWarning(false, 'Table', '`onSelectInvert` will be removed in future. Please use `onChange` instead.');
|
249 | onSelectInvert(keys);
|
250 | }
|
251 |
|
252 | setSelectedKeys(keys);
|
253 | }
|
254 | };
|
255 | }
|
256 |
|
257 | if (selection === SELECTION_NONE) {
|
258 | return {
|
259 | key: 'none',
|
260 | text: tableLocale.selectNone,
|
261 | onSelect: function onSelect() {
|
262 | onSelectNone === null || onSelectNone === void 0 ? void 0 : onSelectNone();
|
263 | setSelectedKeys([]);
|
264 | }
|
265 | };
|
266 | }
|
267 |
|
268 | return selection;
|
269 | });
|
270 | }, [selections, derivedSelectedKeySet, pageData, getRowKey, onSelectInvert, setSelectedKeys]);
|
271 |
|
272 | var transformColumns = useCallback(function (columns) {
|
273 | if (!rowSelection) {
|
274 | return columns;
|
275 | }
|
276 |
|
277 |
|
278 | var keySet = new Set(derivedSelectedKeySet);
|
279 |
|
280 | var recordKeys = flattedData.map(getRowKey).filter(function (key) {
|
281 | return !checkboxPropsMap.get(key).disabled;
|
282 | });
|
283 | var checkedCurrentAll = recordKeys.every(function (key) {
|
284 | return keySet.has(key);
|
285 | });
|
286 | var checkedCurrentSome = recordKeys.some(function (key) {
|
287 | return keySet.has(key);
|
288 | });
|
289 |
|
290 | var onSelectAllChange = function onSelectAllChange() {
|
291 | var changeKeys = [];
|
292 |
|
293 | if (checkedCurrentAll) {
|
294 | recordKeys.forEach(function (key) {
|
295 | keySet["delete"](key);
|
296 | changeKeys.push(key);
|
297 | });
|
298 | } else {
|
299 | recordKeys.forEach(function (key) {
|
300 | if (!keySet.has(key)) {
|
301 | keySet.add(key);
|
302 | changeKeys.push(key);
|
303 | }
|
304 | });
|
305 | }
|
306 |
|
307 | var keys = Array.from(keySet);
|
308 | onSelectAll === null || onSelectAll === void 0 ? void 0 : onSelectAll(!checkedCurrentAll, keys.map(function (k) {
|
309 | return getRecordByKey(k);
|
310 | }), changeKeys.map(function (k) {
|
311 | return getRecordByKey(k);
|
312 | }));
|
313 | setSelectedKeys(keys);
|
314 | };
|
315 |
|
316 |
|
317 |
|
318 | var title;
|
319 |
|
320 | if (selectionType !== 'radio') {
|
321 | var customizeSelections;
|
322 |
|
323 | if (mergedSelections) {
|
324 | var menu = React.createElement(Menu, {
|
325 | getPopupContainer: getPopupContainer
|
326 | }, mergedSelections.map(function (selection, index) {
|
327 | var key = selection.key,
|
328 | text = selection.text,
|
329 | onSelectionClick = selection.onSelect;
|
330 | return React.createElement(Menu.Item, {
|
331 | key: key || index,
|
332 | onClick: function onClick() {
|
333 | onSelectionClick === null || onSelectionClick === void 0 ? void 0 : onSelectionClick(recordKeys);
|
334 | }
|
335 | }, text);
|
336 | }));
|
337 | customizeSelections = React.createElement("div", {
|
338 | className: "".concat(prefixCls, "-selection-extra")
|
339 | }, React.createElement(Dropdown, {
|
340 | overlay: menu,
|
341 | getPopupContainer: getPopupContainer
|
342 | }, React.createElement("span", null, React.createElement(DownOutlined, null))));
|
343 | }
|
344 |
|
345 | var allDisabledData = flattedData.map(function (record, index) {
|
346 | var key = getRowKey(record, index);
|
347 | var checkboxProps = checkboxPropsMap.get(key) || {};
|
348 | return _extends({
|
349 | checked: keySet.has(key)
|
350 | }, checkboxProps);
|
351 | }).filter(function (_ref2) {
|
352 | var disabled = _ref2.disabled;
|
353 | return disabled;
|
354 | });
|
355 | var allDisabled = !!allDisabledData.length && allDisabledData.length === flattedData.length;
|
356 | var allDisabledAndChecked = allDisabled && allDisabledData.every(function (_ref3) {
|
357 | var checked = _ref3.checked;
|
358 | return checked;
|
359 | });
|
360 | var allDisabledSomeChecked = allDisabled && allDisabledData.some(function (_ref4) {
|
361 | var checked = _ref4.checked;
|
362 | return checked;
|
363 | });
|
364 | title = !hideSelectAll && React.createElement("div", {
|
365 | className: "".concat(prefixCls, "-selection")
|
366 | }, React.createElement(Checkbox, {
|
367 | checked: !allDisabled ? !!flattedData.length && checkedCurrentAll : allDisabledAndChecked,
|
368 | indeterminate: !allDisabled ? !checkedCurrentAll && checkedCurrentSome : !allDisabledAndChecked && allDisabledSomeChecked,
|
369 | onChange: onSelectAllChange,
|
370 | disabled: flattedData.length === 0 || allDisabled,
|
371 | skipGroup: true
|
372 | }), customizeSelections);
|
373 | }
|
374 |
|
375 |
|
376 | var renderCell;
|
377 |
|
378 | if (selectionType === 'radio') {
|
379 | renderCell = function renderCell(_, record, index) {
|
380 | var key = getRowKey(record, index);
|
381 | var checked = keySet.has(key);
|
382 | return {
|
383 | node: React.createElement(Radio, _extends({}, checkboxPropsMap.get(key), {
|
384 | checked: checked,
|
385 | onClick: function onClick(e) {
|
386 | return e.stopPropagation();
|
387 | },
|
388 | onChange: function onChange(event) {
|
389 | if (!keySet.has(key)) {
|
390 | triggerSingleSelection(key, true, [key], event.nativeEvent);
|
391 | }
|
392 | }
|
393 | })),
|
394 | checked: checked
|
395 | };
|
396 | };
|
397 | } else {
|
398 | renderCell = function renderCell(_, record, index) {
|
399 | var _a;
|
400 |
|
401 | var key = getRowKey(record, index);
|
402 | var checked = keySet.has(key);
|
403 | var indeterminate = derivedHalfSelectedKeySet.has(key);
|
404 | var checkboxProps = checkboxPropsMap.get(key);
|
405 | var mergedIndeterminate;
|
406 |
|
407 | if (expandType === 'nest') {
|
408 | mergedIndeterminate = indeterminate;
|
409 | devWarning(typeof (checkboxProps === null || checkboxProps === void 0 ? void 0 : checkboxProps.indeterminate) !== 'boolean', 'Table', 'set `indeterminate` using `rowSelection.getCheckboxProps` is not allowed with tree structured dataSource.');
|
410 | } else {
|
411 | mergedIndeterminate = (_a = checkboxProps === null || checkboxProps === void 0 ? void 0 : checkboxProps.indeterminate) !== null && _a !== void 0 ? _a : indeterminate;
|
412 | }
|
413 |
|
414 |
|
415 | return {
|
416 | node: React.createElement(Checkbox, _extends({}, checkboxProps, {
|
417 | indeterminate: mergedIndeterminate,
|
418 | checked: checked,
|
419 | skipGroup: true,
|
420 | onClick: function onClick(e) {
|
421 | return e.stopPropagation();
|
422 | },
|
423 | onChange: function onChange(_ref5) {
|
424 | var nativeEvent = _ref5.nativeEvent;
|
425 | var shiftKey = nativeEvent.shiftKey;
|
426 | var startIndex = -1;
|
427 | var endIndex = -1;
|
428 |
|
429 | if (shiftKey && checkStrictly) {
|
430 | var pointKeys = new Set([lastSelectedKey, key]);
|
431 | recordKeys.some(function (recordKey, recordIndex) {
|
432 | if (pointKeys.has(recordKey)) {
|
433 | if (startIndex === -1) {
|
434 | startIndex = recordIndex;
|
435 | } else {
|
436 | endIndex = recordIndex;
|
437 | return true;
|
438 | }
|
439 | }
|
440 |
|
441 | return false;
|
442 | });
|
443 | }
|
444 |
|
445 | if (endIndex !== -1 && startIndex !== endIndex && checkStrictly) {
|
446 |
|
447 | var rangeKeys = recordKeys.slice(startIndex, endIndex + 1);
|
448 | var changedKeys = [];
|
449 |
|
450 | if (checked) {
|
451 | rangeKeys.forEach(function (recordKey) {
|
452 | if (keySet.has(recordKey)) {
|
453 | changedKeys.push(recordKey);
|
454 | keySet["delete"](recordKey);
|
455 | }
|
456 | });
|
457 | } else {
|
458 | rangeKeys.forEach(function (recordKey) {
|
459 | if (!keySet.has(recordKey)) {
|
460 | changedKeys.push(recordKey);
|
461 | keySet.add(recordKey);
|
462 | }
|
463 | });
|
464 | }
|
465 |
|
466 | var keys = Array.from(keySet);
|
467 | onSelectMultiple === null || onSelectMultiple === void 0 ? void 0 : onSelectMultiple(!checked, keys.map(function (recordKey) {
|
468 | return getRecordByKey(recordKey);
|
469 | }), changedKeys.map(function (recordKey) {
|
470 | return getRecordByKey(recordKey);
|
471 | }));
|
472 | setSelectedKeys(keys);
|
473 | } else {
|
474 |
|
475 | var originCheckedKeys = derivedSelectedKeys;
|
476 |
|
477 | if (checkStrictly) {
|
478 | var checkedKeys = checked ? arrDel(originCheckedKeys, key) : arrAdd(originCheckedKeys, key);
|
479 | triggerSingleSelection(key, !checked, checkedKeys, nativeEvent);
|
480 | } else {
|
481 |
|
482 | var result = conductCheck([].concat(_toConsumableArray(originCheckedKeys), [key]), true, keyEntities, isCheckboxDisabled);
|
483 | var _checkedKeys = result.checkedKeys,
|
484 | halfCheckedKeys = result.halfCheckedKeys;
|
485 | var nextCheckedKeys = _checkedKeys;
|
486 |
|
487 | if (checked) {
|
488 | var tempKeySet = new Set(_checkedKeys);
|
489 | tempKeySet["delete"](key);
|
490 | nextCheckedKeys = conductCheck(Array.from(tempKeySet), {
|
491 | checked: false,
|
492 | halfCheckedKeys: halfCheckedKeys
|
493 | }, keyEntities, isCheckboxDisabled).checkedKeys;
|
494 | }
|
495 |
|
496 | triggerSingleSelection(key, !checked, nextCheckedKeys, nativeEvent);
|
497 | }
|
498 | }
|
499 |
|
500 | setLastSelectedKey(key);
|
501 | }
|
502 | })),
|
503 | checked: checked
|
504 | };
|
505 | };
|
506 | }
|
507 |
|
508 | var renderSelectionCell = function renderSelectionCell(_, record, index) {
|
509 | var _renderCell = renderCell(_, record, index),
|
510 | node = _renderCell.node,
|
511 | checked = _renderCell.checked;
|
512 |
|
513 | if (customizeRenderCell) {
|
514 | return customizeRenderCell(checked, record, index, node);
|
515 | }
|
516 |
|
517 | return node;
|
518 | };
|
519 |
|
520 |
|
521 | var selectionColumn = _defineProperty({
|
522 | width: selectionColWidth,
|
523 | className: "".concat(prefixCls, "-selection-column"),
|
524 | title: rowSelection.columnTitle || title,
|
525 | render: renderSelectionCell
|
526 | }, INTERNAL_COL_DEFINE, {
|
527 | className: "".concat(prefixCls, "-selection-col")
|
528 | });
|
529 |
|
530 | if (expandType === 'row' && columns.length && !expandIconColumnIndex) {
|
531 | var _columns = _toArray(columns),
|
532 | expandColumn = _columns[0],
|
533 | restColumns = _columns.slice(1);
|
534 |
|
535 | var selectionFixed = fixed || getFixedType(restColumns[0]);
|
536 |
|
537 | if (selectionFixed) {
|
538 | expandColumn.fixed = selectionFixed;
|
539 | }
|
540 |
|
541 | return [expandColumn, _extends(_extends({}, selectionColumn), {
|
542 | fixed: selectionFixed
|
543 | })].concat(_toConsumableArray(restColumns));
|
544 | }
|
545 |
|
546 | return [_extends(_extends({}, selectionColumn), {
|
547 | fixed: fixed || getFixedType(columns[0])
|
548 | })].concat(_toConsumableArray(columns));
|
549 | }, [getRowKey, flattedData, rowSelection, derivedSelectedKeys, derivedSelectedKeySet, derivedHalfSelectedKeySet, selectionColWidth, mergedSelections, expandType, lastSelectedKey, checkboxPropsMap, onSelectMultiple, triggerSingleSelection, isCheckboxDisabled]);
|
550 | return [transformColumns, derivedSelectedKeySet];
|
551 | } |
\ | No newline at end of file |