useSelection.js 23 KB

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