foundation.ts 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206
  1. /* eslint-disable prefer-destructuring */
  2. /* eslint-disable max-depth */
  3. /* eslint-disable max-nested-callbacks */
  4. /* eslint-disable max-len */
  5. /* eslint-disable no-param-reassign */
  6. /* eslint-disable eqeqeq */
  7. /* eslint-disable @typescript-eslint/no-empty-function */
  8. import {
  9. get,
  10. merge,
  11. isFunction,
  12. each,
  13. find,
  14. some,
  15. pull,
  16. isSet,
  17. filter,
  18. isMap,
  19. slice,
  20. isEqual
  21. } from 'lodash-es';
  22. import memoizeOne from 'memoize-one';
  23. import { ArrayElement } from '../utils/type';
  24. import { BaseCheckboxProps } from '../checkbox/checkboxFoundation';
  25. import BaseFoundation, { DefaultAdapter } from '../base/foundation';
  26. import { strings, numbers } from './constants';
  27. import { mergeQueries, flattenColumns, filterColumns } from './utils';
  28. import { pullAll, withOrderSort } from '../utils/array';
  29. export interface BaseColumnProps<RecordType> {
  30. align?: BaseAlign;
  31. children?: Array<BaseColumnProps<RecordType>>;
  32. className?: string;
  33. colSpan?: number;
  34. dataIndex?: string;
  35. defaultSortOrder?: BaseSortOrder;
  36. filterChildrenRecord?: boolean;
  37. filterDropdown?: any;
  38. filterDropdownProps?: Record<string, any>;
  39. filterDropdownVisible?: boolean;
  40. filterIcon?: any;
  41. filterMultiple?: boolean;
  42. filteredValue?: any[];
  43. filters?: BaseFilter[];
  44. fixed?: BaseFixed;
  45. key?: string | number;
  46. onCell?: BaseOnCell<RecordType>;
  47. onFilter?: BaseOnFilter<RecordType>;
  48. onFilterDropdownVisibleChange?: BaseOnFilterDropdownVisibleChange;
  49. onHeaderCell?: BaseOnHeaderCell<RecordType>;
  50. render?: (...args: any[]) => any;
  51. renderFilterDropdownItem?: (...args: any[]) => any;
  52. sortChildrenRecord?: boolean;
  53. sortOrder?: BaseSortOrder;
  54. sorter?: BaseSorter<RecordType>;
  55. title?: any;
  56. useFullRender?: boolean;
  57. width?: string | number;
  58. }
  59. export interface TableAdapter<RecordType> extends DefaultAdapter {
  60. resetScrollY: () => void;
  61. setSelectedRowKeys: (selectedRowKeys: BaseRowKeyType[]) => void;
  62. setDisabledRowKeys: (disabledRowKeys: BaseRowKeyType[]) => void;
  63. setCurrentPage: (currentPage: number) => void;
  64. setPagination: (pagination: BasePagination) => void;
  65. setGroups: (groups: Map<string, RecordType[]>) => void;
  66. setDataSource: (dataSource: RecordType[]) => void;
  67. setExpandedRowKeys: (expandedRowKeys: BaseRowKeyType[]) => void;
  68. setQuery: (query?: BaseColumnProps<RecordType>) => void;
  69. setQueries: (queries: BaseColumnProps<RecordType>[]) => void;
  70. setFlattenData: (flattenData: RecordType[]) => void;
  71. setAllRowKeys: (allRowKeys: BaseRowKeyType[]) => void;
  72. setHoveredRowKey: (hoveredRowKey: BaseRowKeyType) => void;
  73. setCachedFilteredSortedDataSource: (filteredSortedDataSource: RecordType[]) => void;
  74. setCachedFilteredSortedRowKeys: (filteredSortedRowKeys: BaseRowKeyType[]) => void;
  75. getCurrentPage: () => number;
  76. getCurrentPageSize: () => number;
  77. getCachedFilteredSortedDataSource: () => RecordType[];
  78. getCachedFilteredSortedRowKeys: () => BaseRowKeyType[];
  79. getCachedFilteredSortedRowKeysSet: () => Set<BaseRowKeyType>;
  80. notifyFilterDropdownVisibleChange: (visible: boolean, dataIndex: string) => void;
  81. notifyChange: (changeInfo: { pagination: BasePagination; filters: BaseChangeInfoFilter<RecordType>[]; sorter: BaseChangeInfoSorter<RecordType>; extra: any }) => void;
  82. notifyExpand: (expanded?: boolean, record?: BaseIncludeGroupRecord<RecordType>, mouseEvent?: any) => void;
  83. notifyExpandedRowsChange: (expandedRows: BaseIncludeGroupRecord<RecordType>[]) => void;
  84. notifySelect: (record?: BaseIncludeGroupRecord<RecordType>, selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], nativeEvent?: any) => void;
  85. notifySelectAll: (selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], changedRows?: BaseIncludeGroupRecord<RecordType>[], e?: any) => void;
  86. notifySelectInvert: (record?: RecordType[], selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], nativeEvent?: any) => void;
  87. notifySelectionChange: (selectedRowKeys: BaseRowKeyType[], selectedRows: BaseIncludeGroupRecord<RecordType>[]) => void;
  88. isAnyColumnFixed: (columns?: BaseColumnProps<RecordType>[]) => boolean;
  89. useFixedHeader: () => boolean;
  90. setHeadWidths: (headWidths: Array<BaseHeadWidth>, index?: number) => void;
  91. getHeadWidths: (index?: number) => number[];
  92. getCellWidths: (flattenedColumns: BaseColumnProps<RecordType>[], flattenedWidths?: BaseHeadWidth[], ignoreScrollBarKey?: boolean) => number[];
  93. mergedRowExpandable: (record: RecordType) => boolean;
  94. isAnyColumnUseFullRender: (columns: BaseColumnProps<RecordType>[]) => boolean;
  95. getNormalizeColumns: () => (columns: BaseColumnProps<RecordType>[], children: any) => BaseColumnProps<RecordType>[];
  96. getHandleColumns: () => (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[];
  97. getMergePagination: () => (pagination: BasePagination) => BasePagination;
  98. setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void;
  99. }
  100. class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType>> {
  101. memoizedWithFnsColumns: (
  102. queries: BaseColumnProps<RecordType>[],
  103. cachedColumns: BaseColumnProps<RecordType>[],
  104. rowSelectionUpdate: boolean,
  105. hideExpandedColumn: boolean,
  106. bodyHasScrollBar: boolean,
  107. ) => BaseColumnProps<RecordType>[];
  108. memoizedFilterColumns: (columns: BaseColumnProps<RecordType>[], ignoreKeys?: string[]) => BaseColumnProps<RecordType>[];
  109. memoizedFlattenFnsColumns: (columns: BaseColumnProps<RecordType>[], childrenColumnName?: string) => BaseColumnProps<RecordType>[];
  110. memoizedPagination: (pagination: BasePagination) => BasePagination;
  111. constructor(adapter: TableAdapter<RecordType>) {
  112. super({ ...adapter });
  113. /**
  114. * memoized function list
  115. */
  116. const handleColumns: (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[] = this._adapter.getHandleColumns();
  117. const mergePagination: (pagination: BasePagination) => BasePagination = this._adapter.getMergePagination();
  118. this.memoizedWithFnsColumns = memoizeOne(handleColumns, isEqual);
  119. this.memoizedFilterColumns = memoizeOne(filterColumns);
  120. this.memoizedFlattenFnsColumns = memoizeOne(flattenColumns);
  121. this.memoizedPagination = memoizeOne(mergePagination, isEqual);
  122. }
  123. init() {
  124. const dataSource = [...this.getProp('dataSource')];
  125. const { queries } = this._adapter.getStates();
  126. const filteredSortedDataSource = this.getFilteredSortedDataSource(dataSource, queries);
  127. const pageData = this.getCurrentPageData(filteredSortedDataSource);
  128. this.setAdapterPageData(pageData);
  129. this.initExpandedRowKeys(pageData);
  130. this.initSelectedRowKeys(pageData);
  131. // cache dataSource after mount, and then calculate it on demand
  132. this.setCachedFilteredSortedDataSource(filteredSortedDataSource);
  133. }
  134. initExpandedRowKeys({ groups }: { groups?: Map<string, RecordType[]> } = {}) {
  135. const {
  136. defaultExpandAllRows,
  137. defaultExpandedRowKeys = [],
  138. expandedRowKeys: propExpandedRowKeys = [],
  139. dataSource = [],
  140. expandAllRows,
  141. defaultExpandAllGroupRows,
  142. expandAllGroupRows,
  143. } = this.getProps();
  144. const expandedRowKeys: BaseRowKeyType[] = [];
  145. if (defaultExpandAllRows || expandAllRows) {
  146. this._addNoDuplicatedItemsToArr(
  147. expandedRowKeys,
  148. this.getAllRowKeys(dataSource),
  149. groups && isMap(groups) && groups.size ? Array.from(groups.keys()) : []
  150. );
  151. } else if (defaultExpandAllGroupRows || expandAllGroupRows) {
  152. this._addNoDuplicatedItemsToArr(
  153. expandedRowKeys,
  154. groups && isMap(groups) && groups.size ? Array.from(groups.keys()) : []
  155. );
  156. } else if (Array.isArray(defaultExpandedRowKeys) && defaultExpandedRowKeys.length) {
  157. this._addNoDuplicatedItemsToArr(expandedRowKeys, defaultExpandedRowKeys);
  158. } else if (Array.isArray(propExpandedRowKeys) && propExpandedRowKeys.length) {
  159. this._addNoDuplicatedItemsToArr(expandedRowKeys, propExpandedRowKeys);
  160. }
  161. this._adapter.setExpandedRowKeys(expandedRowKeys);
  162. }
  163. initSelectedRowKeys({ disabledRowKeys }: { disabledRowKeys?: BaseRowKeyType[] }) {
  164. const rowSelection = this.getProp('rowSelection');
  165. const rowKeys: BaseRowKeyType[] = [];
  166. if (rowSelection) {
  167. const selectedRowKeys = get(rowSelection, 'selectedRowKeys');
  168. const defaultSelectedRowKeys = get(rowSelection, 'defaultSelectedRowKeys');
  169. if (Array.isArray(selectedRowKeys)) {
  170. this._addNoDuplicatedItemsToArr(rowKeys, selectedRowKeys);
  171. } else if (Array.isArray(defaultSelectedRowKeys)) {
  172. this._addNoDuplicatedItemsToArr(rowKeys, defaultSelectedRowKeys);
  173. }
  174. if (Array.isArray(disabledRowKeys) && disabledRowKeys.length) {
  175. pull(rowKeys, ...disabledRowKeys);
  176. }
  177. this._adapter.setSelectedRowKeys(rowKeys);
  178. }
  179. }
  180. /**
  181. * Get filtered and sorted data
  182. * @param {Object[]} dataSource
  183. * @param {Object[]} queries
  184. * @returns {Object[]} sortedDataSource
  185. */
  186. getFilteredSortedDataSource(dataSource: RecordType[], queries: BaseColumnProps<RecordType>[]) {
  187. const filteredDataSource = this.filterDataSource(dataSource, queries.filter(
  188. query => (
  189. isFunction(query.onFilter) &&
  190. Array.isArray(query.filters) &&
  191. query.filters.length &&
  192. Array.isArray(query.filteredValue) &&
  193. query.filteredValue.length
  194. )
  195. ));
  196. const sortedDataSource = this.sortDataSource(filteredDataSource, queries.filter(query => query && isFunction(query.sorter)));
  197. return sortedDataSource;
  198. }
  199. /**
  200. * get current page data
  201. *
  202. * @param {Array} dataSource
  203. * @param {object} pagination
  204. * @param {object} queries
  205. * @returns {{dataSource: RecordType[], groups: Map<string, Set<string>>, pagination: object, disabledRowKeys: string[], queries: BaseColumnProps[], allRowKeys: string[]}}
  206. */
  207. getCurrentPageData(dataSource?: RecordType[], pagination?: BasePagination, queries?: BaseColumnProps<RecordType>[]) {
  208. const filteredSortedDataSource = this._adapter.getCachedFilteredSortedDataSource();
  209. dataSource = dataSource == null ? [...filteredSortedDataSource] : dataSource;
  210. pagination =
  211. pagination == null ? this.getState('pagination') && { ...this.getState('pagination') } : pagination;
  212. queries = queries == null ? [...this.getState('queries')] : queries;
  213. let groups;
  214. if (this.getProp('groupBy') != null) {
  215. const { groups: groupedGroups, dataSource: groupedData } = this.groupDataSource(dataSource);
  216. dataSource = groupedData;
  217. groups = groupedGroups;
  218. }
  219. pagination = this.normalizePagination(pagination, dataSource);
  220. dataSource = this.limitPageDataSource(dataSource, pagination);
  221. const disabledRowKeys = this.getAllDisabledRowKeys(dataSource);
  222. const allRowKeys = this.getAllRowKeys(dataSource);
  223. const pageData: BasePageData<RecordType> = {
  224. dataSource,
  225. groups,
  226. pagination,
  227. disabledRowKeys,
  228. allRowKeys,
  229. queries,
  230. };
  231. return pageData;
  232. }
  233. /**
  234. * group dataSource, return grouped row keys
  235. *
  236. * @param {*[]} dataSource
  237. * @param {Function|string} groupBy
  238. */
  239. groupDataSource(dataSource: RecordType[], groupBy?: BaseGroupBy<RecordType>) {
  240. groupBy = groupBy == null ? this.getProp('groupBy') : groupBy;
  241. const groups = new Map();
  242. const newDataSource = [];
  243. if (groupBy != null) {
  244. each(dataSource, (record, index) => {
  245. const groupKey = typeof groupBy === 'function' ? groupBy(record) : get(record, groupBy);
  246. if (groupKey != null && groupKey !== '') {
  247. const recordKey = this.getRecordKey(record);
  248. let group = groups.get(groupKey);
  249. if (!isSet(group)) {
  250. group = new Set([recordKey]);
  251. groups.set(groupKey, group);
  252. } else {
  253. group.add(recordKey);
  254. }
  255. }
  256. });
  257. }
  258. if (groups && groups.size) {
  259. groups.forEach((set, key) => {
  260. if (isSet(set)) {
  261. set.forEach(realKey => {
  262. newDataSource.push(this._getRecord(realKey));
  263. });
  264. }
  265. });
  266. } else {
  267. newDataSource.push(...dataSource);
  268. }
  269. return { groups, dataSource: newDataSource };
  270. }
  271. /**
  272. * sort data
  273. *
  274. * @param {Array} dataSource
  275. * @param {Array} sorters
  276. * @returns {Array}
  277. */
  278. sortDataSource(dataSource: RecordType[], sorters: BaseSorterInfo<RecordType>[]) {
  279. each(sorters, sorterObj => {
  280. // const sorterObj = last(sorters) || {};
  281. const { sorter, sortOrder, defaultSortOrder, sortChildrenRecord } = sorterObj;
  282. const currentSortOrder = this.isSortOrderValid(sortOrder) ? sortOrder : defaultSortOrder;
  283. if (isFunction(sorter) && (currentSortOrder && strings.SORT_DIRECTIONS.includes(currentSortOrder))) {
  284. if (sortChildrenRecord) {
  285. const childrenRecordName = this.getProp('childrenRecordName');
  286. dataSource =
  287. dataSource &&
  288. dataSource.map(record => {
  289. const children = this._getRecordChildren(record);
  290. if (Array.isArray(children) && children.length) {
  291. return {
  292. ...record,
  293. [childrenRecordName]: this.sortDataSource(children, [sorterObj]),
  294. };
  295. }
  296. return record;
  297. });
  298. }
  299. dataSource.sort(withOrderSort(sorter, currentSortOrder));
  300. return false;
  301. }
  302. return undefined;
  303. });
  304. return dataSource;
  305. }
  306. /**
  307. * set page number
  308. */
  309. setPage = (currentPage: number, currentPageSize: number) => {
  310. currentPage = currentPage || this._adapter.getCurrentPage();
  311. const currentPagination = this.getState('pagination');
  312. const { dataSource, pagination, disabledRowKeys, allRowKeys } = this.getCurrentPageData(null, {
  313. ...currentPagination,
  314. currentPage,
  315. pageSize: currentPageSize,
  316. });
  317. if (!this._pagerIsControlled() && currentPage > 0) {
  318. this._adapter.setDisabledRowKeys(disabledRowKeys);
  319. this._adapter.setAllRowKeys(allRowKeys);
  320. this._adapter.setPagination(pagination);
  321. this._adapter.setDataSource(dataSource);
  322. }
  323. this._notifyChange(pagination);
  324. };
  325. /**
  326. * filter data source
  327. *
  328. * @param {*[]} dataSource
  329. * @param {*[]} filters
  330. * @returns {*[]}
  331. */
  332. filterDataSource(dataSource: RecordType[], filters: BaseChangeInfoFilter<RecordType>[]) {
  333. let filteredData: Map<string, RecordType> | null = null;
  334. let hasValidFilters = false;
  335. const childrenRecordName = this.getProp('childrenRecordName');
  336. each(filters, filterObj => {
  337. const { onFilter, filteredValue, filterChildrenRecord } = filterObj;
  338. if (typeof onFilter === 'function' && Array.isArray(filteredValue) && filteredValue.length) {
  339. hasValidFilters = true;
  340. if (filteredData === null) {
  341. filteredData = new Map();
  342. } else {
  343. dataSource = Array.from(filteredData && filteredData.values());
  344. filteredData = new Map();
  345. }
  346. each(filteredValue, value => {
  347. each(dataSource, record => {
  348. const childrenRecords = get(record, childrenRecordName);
  349. const recordKey = this.getRecordKey(record);
  350. let filteredChildren;
  351. if (Array.isArray(childrenRecords) && childrenRecords.length && filterChildrenRecord) {
  352. filteredChildren = this.filterDataSource(childrenRecords, [filterObj]);
  353. }
  354. if (Array.isArray(filteredChildren) && filteredChildren.length) {
  355. if (recordKey != null) {
  356. const children = get(filteredData.get(recordKey), childrenRecordName, []);
  357. filteredData.set(recordKey, {
  358. ...record,
  359. [childrenRecordName]: filteredChildren.reduce(
  360. (arr, cur) => {
  361. if (
  362. arr.find((item: any) => this.getRecordKey(item) === this.getRecordKey(cur)) ==
  363. null
  364. ) {
  365. arr.push(cur);
  366. }
  367. return arr;
  368. },
  369. [...children]
  370. ),
  371. });
  372. }
  373. } else if (onFilter(value, record)) {
  374. filteredData.set(recordKey, record);
  375. }
  376. });
  377. });
  378. }
  379. });
  380. if (hasValidFilters) {
  381. dataSource = Array.from(filteredData && filteredData.values());
  382. }
  383. return dataSource;
  384. }
  385. limitPageDataSource(dataSource: RecordType[], pagination: BasePagination) {
  386. dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
  387. pagination = pagination == null ? this.getState('pagination') : pagination;
  388. let pageData = dataSource;
  389. const pageNo = get(pagination, 'currentPage');
  390. if (this.getProp('pagination') !== false && pageNo && dataSource && pagination && !this._pagerIsControlled()) {
  391. const { pageSize = numbers.DEFAULT_PAGE_SIZE } = pagination;
  392. const start = (pageNo - 1) * pageSize;
  393. const end = pageNo * pageSize;
  394. pageData = slice(dataSource, start, end);
  395. }
  396. return pageData;
  397. }
  398. normalizePagination(pagination: BasePagination, dataSource: RecordType[]) {
  399. pagination = pagination == null ? this._getPagination() : pagination;
  400. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  401. const propPagination = this.getProp('pagination');
  402. if (pagination) {
  403. pagination = typeof pagination === 'object' ? { ...pagination } : {};
  404. pagination = merge(
  405. {
  406. total: (dataSource && dataSource.length) || 0,
  407. pageSize: numbers.DEFAULT_PAGE_SIZE,
  408. currentPage: get(propPagination, 'defaultCurrentPage', 1),
  409. position: strings.PAGINATION_POSITIONS[0],
  410. },
  411. pagination
  412. );
  413. if (!this._pagerIsControlled()) {
  414. const total = get(propPagination, 'total', dataSource.length);
  415. const pageSize = get(propPagination, 'pageSize', pagination.pageSize);
  416. const { currentPage } = pagination;
  417. const realTotalPage = Math.ceil(total / pageSize);
  418. pagination.total = total;
  419. if (currentPage > realTotalPage) {
  420. pagination.currentPage = 1;
  421. }
  422. }
  423. }
  424. return pagination;
  425. }
  426. setAdapterPageData(pageData: BasePageData<RecordType> = {}) {
  427. const { pagination, dataSource, disabledRowKeys, allRowKeys, groups } = pageData;
  428. this._adapter.setDisabledRowKeys(disabledRowKeys);
  429. this._adapter.setAllRowKeys(allRowKeys);
  430. this._adapter.setPagination(pagination);
  431. this._adapter.setGroups(groups);
  432. this._adapter.setDataSource(dataSource);
  433. }
  434. /**
  435. * Cache related data when initializing or updating the calculated dataSource
  436. * @param {*} filteredSortedDataSource
  437. */
  438. setCachedFilteredSortedDataSource = (filteredSortedDataSource: RecordType[]) => {
  439. this._adapter.setCachedFilteredSortedDataSource(filteredSortedDataSource);
  440. const filteredSortedRowKeys = this.getAllRowKeys(filteredSortedDataSource);
  441. this._adapter.setCachedFilteredSortedRowKeys(filteredSortedRowKeys);
  442. };
  443. destroy() { }
  444. handleClick(e: any) { }
  445. handleMouseEnter(e: any) { }
  446. handleMouseLeave(e: any) { }
  447. stopPropagation(e: any) {
  448. if (e && typeof e === 'object') {
  449. if (typeof e.stopPropagation === 'function') {
  450. e.stopPropagation();
  451. }
  452. if (e.nativeEvent && typeof e.nativeEvent.stopPropagation === 'function') {
  453. e.nativeEvent.stopPropagation();
  454. } else if (typeof e.stopImmediatePropagation === 'function') {
  455. e.stopImmediatePropagation();
  456. }
  457. }
  458. }
  459. /**
  460. * Add non-repeating elements to the array itself
  461. * @param {Array} srcArr
  462. * @param {Object} objArrs
  463. */
  464. _addNoDuplicatedItemsToArr(srcArr: any[] = [], ...objArrs: any[]) {
  465. for (const objArr of objArrs) {
  466. if (Array.isArray(objArr)) {
  467. for (const item of objArr) {
  468. if (!srcArr.includes(item)) {
  469. srcArr.push(item);
  470. }
  471. }
  472. }
  473. }
  474. return srcArr;
  475. }
  476. _notifyChange(pagination: BasePagination, filters?: BaseChangeInfoFilter<RecordType>[], sorter?: BaseChangeInfoSorter<RecordType>, extra?: RecordType) {
  477. pagination = pagination == null ? this._getPagination() : pagination;
  478. filters = filters == null ? this._getAllFilters() : filters;
  479. sorter = sorter == null ? this._getAllSorters()[0] as BaseChangeInfoSorter<RecordType> : sorter;
  480. if (get(this.getProp('scroll'), 'scrollToFirstRowOnChange')) {
  481. this._adapter.resetScrollY();
  482. }
  483. this._adapter.notifyChange({
  484. pagination: { ...pagination },
  485. filters: [...filters],
  486. sorter,
  487. extra: { ...extra },
  488. });
  489. }
  490. _rowExpansionIsControlled() {
  491. return Array.isArray(this.getProp('expandedRowKeys'));
  492. }
  493. _pagerIsControlled() {
  494. return get(this.getProp('pagination'), 'currentPage') != null;
  495. }
  496. _selectionIsControlled() {
  497. return Array.isArray(get(this.getProp('rowSelection'), 'selectedRowKeys'));
  498. }
  499. /**
  500. * Determine whether the column sorting is controlled
  501. * Controlled: the column passed the sortOrder prop
  502. * @param {String} dataIndex
  503. * @returns {Boolean}
  504. */
  505. _sorterIsControlled(dataIndex: string) {
  506. // The basis for judgment should be props columns instead of cachedColumns fix#1141
  507. const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
  508. return Boolean(query && query.sortOrder != null);
  509. }
  510. /**
  511. * Determine whether the column is filtered and controlled
  512. * Controlled: the column passed the filteredValue prop
  513. * @param {String} dataIndex
  514. * @returns {Boolean}
  515. */
  516. _filterIsControlled(dataIndex: string) {
  517. const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
  518. return Boolean(query && Array.isArray(query.filteredValue));
  519. }
  520. _filterShowIsControlled(dataIndex?: string) {
  521. const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
  522. return Boolean(query && (query.filterDropdownVisible === true || query.filterDropdownVisible === false));
  523. }
  524. _getSelectedRowKeys() {
  525. const rowSelection = this.getState('rowSelection');
  526. const selectedRowKeys = get(rowSelection, 'selectedRowKeys', []);
  527. return [...selectedRowKeys];
  528. }
  529. _getSelectedRowKeysSet() {
  530. const rowSelection = this.getState('rowSelection');
  531. const selectedRowKeysSet = get(rowSelection, 'selectedRowKeysSet', new Set());
  532. return selectedRowKeysSet;
  533. }
  534. _getDataSource() {
  535. return this.getProp('dataSource') || [];
  536. }
  537. _getRecord(realKey: string | number) {
  538. return find(
  539. this.getProp('dataSource'),
  540. record => realKey != null && realKey !== '' && this.getRecordKey(record) === realKey
  541. );
  542. }
  543. _getRecordChildren(record: RecordType) {
  544. return get(record, this.getProp('childrenRecordName'));
  545. }
  546. _getPagination() {
  547. return this.getState('pagination') || {};
  548. }
  549. _getAllFilters(queries?: BaseColumnProps<RecordType>[]) {
  550. queries = queries || this.getState('queries');
  551. const filters: BaseChangeInfoFilter<RecordType>[] = [];
  552. each(queries, query => {
  553. if (
  554. Array.isArray(query.filteredValue) &&
  555. (query.filteredValue.length || this._filterIsControlled(query.dataIndex))
  556. ) {
  557. filters.push(query);
  558. }
  559. });
  560. return filters;
  561. }
  562. _getAllSorters(queries?: BaseColumnProps<RecordType>[]): BaseColumnProps<RecordType>[] {
  563. queries = queries || this.getState('queries');
  564. return filter(queries, query => query.sorter && query.sortOrder) as BaseColumnProps<RecordType>[];
  565. }
  566. _filterQueries(targetQuery: BaseColumnProps<RecordType>, queries: BaseColumnProps<RecordType>[], keys = ['dataIndex']) {
  567. queries = queries == null ? this.getState('queries') : queries;
  568. const filteredQueries: BaseColumnProps<RecordType>[] = [];
  569. const filteredIndexes: number[] = [];
  570. each(queries, (itQuery, index) => {
  571. const flag = some(keys, k => k && targetQuery[k] != null && targetQuery[k] === itQuery[k]);
  572. if (flag) {
  573. filteredQueries.push(itQuery);
  574. filteredIndexes.push(index);
  575. }
  576. });
  577. return { filteredQueries, filteredIndexes };
  578. }
  579. _mergeToQueries(query: BaseColumnProps<RecordType>, queries: BaseColumnProps<RecordType>[], keys = ['dataIndex']) {
  580. queries = queries == null ? this.getState('queries') : queries;
  581. queries = [...queries];
  582. query = { ...query };
  583. const { filteredQueries, filteredIndexes } = this._filterQueries(query, queries, keys);
  584. each(filteredQueries, (curQuery, idx) => {
  585. // assign(curQuery, query);
  586. queries[filteredIndexes[idx]] = { ...query };
  587. });
  588. return queries;
  589. }
  590. /**
  591. * get record real key
  592. * @param {RecordType} record
  593. * @returns {string}
  594. */
  595. getRecordKey(record: RecordType): string {
  596. if (!record) {
  597. return undefined;
  598. }
  599. const rowKey = this.getProp('rowKey');
  600. return typeof rowKey === 'function' ? rowKey(record) : get(record, rowKey);
  601. }
  602. isEmpty(dataSource: RecordType[]) {
  603. dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
  604. return !(Array.isArray(dataSource) && dataSource.length > 0);
  605. }
  606. handleSelectRow(realKey: BaseRowKeyType, selected: boolean, e: any) {
  607. this.stopPropagation(e);
  608. if (typeof selected === 'boolean' && realKey != null) {
  609. const selectedRowKeys = this._getSelectedRowKeys();
  610. let foundIdx = -1;
  611. const selectedRow = this.getSelectedRows(null, [realKey])[0];
  612. let selectedRows: BaseIncludeGroupRecord<RecordType>[];
  613. if ((foundIdx = selectedRowKeys.indexOf(realKey)) > -1 && selected === false) {
  614. selectedRowKeys.splice(foundIdx, 1);
  615. selectedRows = this.getSelectedRows(null, selectedRowKeys);
  616. if (!this._selectionIsControlled()) {
  617. this._adapter.setSelectedRowKeys(selectedRowKeys);
  618. }
  619. this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
  620. this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
  621. } else if (selectedRowKeys.indexOf(realKey) === -1 && selected === true) {
  622. selectedRowKeys.push(realKey);
  623. selectedRows = this.getSelectedRows(null, selectedRowKeys);
  624. if (!this._selectionIsControlled()) {
  625. this._adapter.setSelectedRowKeys(selectedRowKeys);
  626. }
  627. this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
  628. this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
  629. }
  630. }
  631. }
  632. /**
  633. * select all rows
  634. * @param {*} selected The future state of the select all button
  635. * @param {*} e
  636. */
  637. handleSelectAllRow(selected: boolean, e: any) {
  638. this.stopPropagation(e);
  639. if (typeof selected === 'boolean') {
  640. const curSelectedRowKeys = this._getSelectedRowKeys();
  641. let selectedRowKeys = [...curSelectedRowKeys];
  642. const selectedRowKeysSet = this._getSelectedRowKeysSet();
  643. let allRowKeys = [...this._adapter.getCachedFilteredSortedRowKeys()];
  644. const disabledRowKeys = this.getAllDisabledRowKeys();
  645. const disabledRowKeysSet = new Set(disabledRowKeys);
  646. let changedRowKeys;
  647. // Select all, if not disabled && not in selectedRowKeys
  648. if (selected) {
  649. for (const key of allRowKeys) {
  650. if (!disabledRowKeysSet.has(key) && !selectedRowKeysSet.has(key)) {
  651. selectedRowKeys.push(key);
  652. }
  653. }
  654. allRowKeys = pullAll(allRowKeys, [...disabledRowKeys, ...curSelectedRowKeys]);
  655. changedRowKeys = [...allRowKeys];
  656. } else {
  657. selectedRowKeys = pullAll(selectedRowKeys, allRowKeys);
  658. changedRowKeys = [...curSelectedRowKeys];
  659. }
  660. const changedRows = this.getSelectedRows(null, changedRowKeys || []);
  661. const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
  662. if (!this._selectionIsControlled()) {
  663. this._adapter.setSelectedRowKeys(selectedRowKeys);
  664. }
  665. this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
  666. this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
  667. }
  668. }
  669. /**
  670. * row keys => rows
  671. * @param {*} dataSource
  672. * @param {*} selectedRowKeys
  673. * @param {*} selectedRowKeysSet Recursive optimization
  674. */
  675. getSelectedRows(dataSource: RecordType[], selectedRowKeys: BaseRowKeyType[], selectedRowKeysSet?: Set<BaseRowKeyType>): BaseIncludeGroupRecord<RecordType>[] {
  676. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  677. selectedRowKeys = selectedRowKeys == null ? this._getSelectedRowKeys() : selectedRowKeys;
  678. if (!isSet(selectedRowKeysSet)) {
  679. selectedRowKeysSet = new Set(selectedRowKeys);
  680. }
  681. const childrenRecordName = this.getProp('childrenRecordName');
  682. const selectedRows: BaseIncludeGroupRecord<RecordType>[] = [];
  683. if (
  684. isSet(selectedRowKeysSet) &&
  685. selectedRowKeysSet.size &&
  686. Array.isArray(dataSource) &&
  687. dataSource.length
  688. ) {
  689. // Time complexity optimization, replace the includes operation of array with has of set
  690. selectedRows.push(...dataSource.filter(data => selectedRowKeysSet.has(this.getRecordKey(data))));
  691. if (selectedRows.length < selectedRowKeys.length) {
  692. for (const item of dataSource) {
  693. const children = get(item, childrenRecordName);
  694. if (Array.isArray(children) && children.length) {
  695. const rows = this.getSelectedRows(children, selectedRowKeys, selectedRowKeysSet);
  696. selectedRows.push(...rows);
  697. }
  698. }
  699. }
  700. }
  701. return selectedRows;
  702. }
  703. getAllDisabledRowKeys(dataSource?: RecordType[], getCheckboxProps?: GetCheckboxProps<RecordType>): BaseRowKeyType[] {
  704. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  705. getCheckboxProps =
  706. getCheckboxProps == null ? get(this.getProp('rowSelection'), 'getCheckboxProps') : getCheckboxProps;
  707. const childrenRecordName = this.getProp('childrenRecordName');
  708. const disabledRowKeys: BaseRowKeyType[] = [];
  709. if (Array.isArray(dataSource) && dataSource.length && typeof getCheckboxProps === 'function') {
  710. for (const record of dataSource) {
  711. const props = getCheckboxProps(record);
  712. if (props && props.disabled) {
  713. disabledRowKeys.push(this.getRecordKey(record));
  714. }
  715. const children = get(record, childrenRecordName);
  716. if (Array.isArray(children) && children.length) {
  717. const keys: BaseRowKeyType[] = this.getAllDisabledRowKeys(children, getCheckboxProps);
  718. disabledRowKeys.push(...keys);
  719. }
  720. }
  721. }
  722. return disabledRowKeys;
  723. }
  724. getAllRowKeys(dataSource: RecordType[]): BaseRowKeyType[] {
  725. dataSource = dataSource == null ? this._getDataSource() : dataSource;
  726. const childrenRecordName = this.getProp('childrenRecordName');
  727. const allRowKeys = [];
  728. if (Array.isArray(dataSource) && dataSource.length) {
  729. for (const record of dataSource) {
  730. const childrenRowKeys = [];
  731. const children = get(record, childrenRecordName);
  732. if (Array.isArray(children) && children.length) {
  733. childrenRowKeys.push(...this.getAllRowKeys(children));
  734. }
  735. allRowKeys.push(this.getRecordKey(record), ...childrenRowKeys);
  736. }
  737. }
  738. return allRowKeys;
  739. }
  740. /**
  741. * Check if the selected item is in allRowKeysSet
  742. * @param {Array} selectedRowKeys
  743. * @param {Set} allRowKeysSet
  744. */
  745. hasRowSelected(selectedRowKeys: BaseRowKeyType[], allRowKeysSet: Set<BaseRowKeyType>) {
  746. return Boolean(Array.isArray(selectedRowKeys) &&
  747. selectedRowKeys.length &&
  748. isSet(allRowKeysSet) &&
  749. allRowKeysSet.size &&
  750. selectedRowKeys.filter(key => allRowKeysSet.has(key)).length);
  751. }
  752. /**
  753. * expand processing function
  754. * @param {Boolean} expanded
  755. * @param {String} realKey
  756. * @param {Event} domEvent
  757. */
  758. handleRowExpanded(expanded: boolean, realKey: string, domEvent: any) {
  759. this.stopPropagation(domEvent);
  760. const expandedRowKeys = [...this.getState('expandedRowKeys')];
  761. const index = expandedRowKeys.indexOf(realKey);
  762. const keyIsValid = typeof realKey === 'string' || typeof realKey === 'number';
  763. if (keyIsValid && expanded && index === -1) {
  764. expandedRowKeys.push(realKey);
  765. } else if (keyIsValid && !expanded && index > -1) {
  766. expandedRowKeys.splice(index, 1);
  767. }
  768. if (!this._rowExpansionIsControlled()) {
  769. this._adapter.setExpandedRowKeys(expandedRowKeys);
  770. }
  771. const expandedRows = this.getSelectedRows(null, expandedRowKeys);
  772. let expandedRow = this.getSelectedRows(null, [realKey])[0];
  773. // groups record processing
  774. const groups = this._getGroups();
  775. if (groups) {
  776. // Construct group expandRow
  777. if (groups.has(realKey)) {
  778. expandedRow = { groupKey: realKey };
  779. }
  780. // If expandedRowKeys includes groupKey, add to expandedRows
  781. for (let i = 0, len = expandedRowKeys.length; i < len; i++) {
  782. if (groups.has(realKey)) {
  783. expandedRows.push({ groupKey: expandedRowKeys[i] });
  784. }
  785. }
  786. }
  787. this._adapter.notifyExpand(expanded, expandedRow, domEvent);
  788. this._adapter.notifyExpandedRowsChange(expandedRows);
  789. }
  790. /**
  791. * get state.groups
  792. * @returns {Map|Null}
  793. */
  794. _getGroups() {
  795. const groupBy = this._adapter.getProp('groupBy');
  796. if (groupBy !== null) {
  797. const groups = this._adapter.getState('groups');
  798. return groups;
  799. }
  800. return null;
  801. }
  802. /**
  803. * Determine whether you have selected all except for disabled
  804. * @param {Set} selectedRowKeysSet
  805. * @param {Set} disabledRowKeysSet
  806. * @param {Array} allKeys keys after sorted and filtered
  807. */
  808. allIsSelected(selectedRowKeysSet: Set<BaseRowKeyType>, disabledRowKeysSet: Set<BaseRowKeyType>, allKeys: BaseRowKeyType[]) {
  809. const filteredAllKeys = filter(allKeys, key => key != null && !disabledRowKeysSet.has(key));
  810. if (filteredAllKeys && filteredAllKeys.length) {
  811. for (const key of filteredAllKeys) {
  812. if (key != null && !selectedRowKeysSet.has(key)) {
  813. return false;
  814. }
  815. }
  816. return true;
  817. } else {
  818. return false;
  819. }
  820. }
  821. /**
  822. * This function is not used yet
  823. * @param {*} selectedRowKeys
  824. * @param {*} allKeys
  825. */
  826. allIsNotSelected(selectedRowKeys: BaseRowKeyType[], allKeys: BaseRowKeyType[]) {
  827. for (const key of allKeys) {
  828. if (key != null && Array.isArray(selectedRowKeys) && selectedRowKeys.includes(key)) {
  829. return true;
  830. }
  831. }
  832. return false;
  833. }
  834. formatPaginationInfo(pagination: BasePagination = {}, defaultPageText = '') {
  835. let info = '';
  836. const formatPageText = get(this.getProp('pagination'), 'formatPageText');
  837. const { total, pageSize, currentPage } = pagination;
  838. const currentStart = Math.min((currentPage - 1) * pageSize + 1, total);
  839. const currentEnd = Math.min(currentPage * pageSize, total);
  840. if (formatPageText || (formatPageText !== false && defaultPageText && total > 0)) {
  841. info =
  842. typeof formatPageText === 'function' ?
  843. formatPageText({ currentStart, currentEnd, total }) :
  844. defaultPageText
  845. .replace('${currentStart}', currentStart as any)
  846. .replace('${currentEnd}', currentEnd as any)
  847. .replace('${total}', total as any);
  848. }
  849. return info;
  850. }
  851. toggleShowFilter(dataIndex: string, visible: boolean) {
  852. let filterObj: BaseColumnProps<RecordType> = this.getQuery(dataIndex);
  853. const filterDropdownVisible = visible;
  854. // eslint-disable-next-line @typescript-eslint/no-unused-vars
  855. filterObj = { ...filterObj, filterDropdownVisible };
  856. if (!this._filterShowIsControlled()) {
  857. // this._adapter.setQuery({
  858. // ...filterObj,
  859. // filterDropdownVisible,
  860. // });
  861. }
  862. this._adapter.notifyFilterDropdownVisibleChange(filterDropdownVisible, dataIndex);
  863. }
  864. /**
  865. * Called when the filter changes
  866. * @param {*} dataIndex
  867. * @param {*} data
  868. */
  869. handleFilterSelect(dataIndex: string, data: { filteredValue?: string[] } = {}) {
  870. let query: BaseColumnProps<RecordType> = this.getQuery(dataIndex);
  871. let queries = [...this._adapter.getState('queries')];
  872. const { filteredValue } = data;
  873. query = {
  874. ...query,
  875. filteredValue,
  876. };
  877. queries = mergeQueries(query, queries);
  878. const mergedQueries = this._mergeToQueries(query, null);
  879. const filters = this._getAllFilters(mergedQueries);
  880. if (!this._filterIsControlled(dataIndex)) {
  881. this._adapter.setQueries(queries);
  882. this.handleClickFilterOrSorter(queries);
  883. }
  884. this._notifyChange(null, filters);
  885. }
  886. /**
  887. * Click the sort button to call
  888. * @param {*} column
  889. * @param {*} e
  890. */
  891. handleSort(column: { dataIndex?: string; sortOrder?: BaseSortOrder } = {}, e: any) {
  892. this.stopPropagation(e);
  893. const { dataIndex } = column;
  894. let queries = this.getState('queries');
  895. let curQuery = null;
  896. queries = [...queries];
  897. each(queries, (query, idx, arr) => {
  898. if (query.sorter) {
  899. const sorterObj = { ...query };
  900. const stateSortOrder = get(sorterObj, 'sortOrder');
  901. const defaultSortOrder = get(sorterObj, 'defaultSortOrder', false);
  902. let querySortOrder = this.isSortOrderValid(stateSortOrder) ? stateSortOrder : defaultSortOrder;
  903. if (dataIndex && dataIndex === sorterObj.dataIndex) {
  904. if (querySortOrder === strings.SORT_DIRECTIONS[0]) {
  905. querySortOrder = strings.SORT_DIRECTIONS[1];
  906. } else if (querySortOrder === strings.SORT_DIRECTIONS[1]) {
  907. querySortOrder = false;
  908. } else {
  909. querySortOrder = strings.SORT_DIRECTIONS[0];
  910. }
  911. } else {
  912. // This results in the current click only supports single column sorting
  913. querySortOrder = false;
  914. }
  915. arr[idx] = { ...sorterObj, sortOrder: querySortOrder };
  916. if (dataIndex === sorterObj.dataIndex) {
  917. curQuery = arr[idx];
  918. }
  919. }
  920. });
  921. if (!this._sorterIsControlled(dataIndex)) {
  922. this._adapter.setQueries(queries);
  923. this.handleClickFilterOrSorter(queries);
  924. }
  925. // notify sort event
  926. this._notifyChange(null, null, curQuery, null);
  927. }
  928. /**
  929. * Recalculate the cached data after clicking filter or sorter
  930. * @param {*} queries
  931. */
  932. handleClickFilterOrSorter(queries: BaseColumnProps<RecordType>[]) {
  933. const dataSource = [...this.getProp('dataSource')];
  934. const sortedDataSource = this.getFilteredSortedDataSource(dataSource, queries);
  935. this.setCachedFilteredSortedDataSource(sortedDataSource);
  936. const pageData = this.getCurrentPageData(sortedDataSource);
  937. this.setAdapterPageData(pageData);
  938. }
  939. getQuery(dataIndex: string, queries?: BaseColumnProps<RecordType>[]) {
  940. queries = queries || this.getState('queries');
  941. if (dataIndex != null) {
  942. return find(queries, query => query.dataIndex === dataIndex);
  943. }
  944. return undefined;
  945. }
  946. getCellWidths(flattenedColumns: BaseColumnProps<RecordType>[], flattenedWidths?: BaseHeadWidth[], ignoreScrollBarKey?: boolean) {
  947. return this._adapter.getCellWidths(flattenedColumns, flattenedWidths, ignoreScrollBarKey);
  948. }
  949. setHeadWidths(headWidths: Array<BaseHeadWidth>, index?: number) {
  950. return this._adapter.setHeadWidths(headWidths, index);
  951. }
  952. getHeadWidths(index: number) {
  953. return this._adapter.getHeadWidths(index);
  954. }
  955. mergedRowExpandable(record: RecordType) {
  956. return this._adapter.mergedRowExpandable(record);
  957. }
  958. setBodyHasScrollbar(bodyHasScrollbar: boolean) {
  959. this._adapter.setBodyHasScrollbar(bodyHasScrollbar);
  960. }
  961. isSortOrderValid = (sortOrder: BaseSortOrder) => strings.SORT_DIRECTIONS.includes(sortOrder as any) || sortOrder === false;
  962. }
  963. export type BaseRowKeyType = string | number;
  964. export interface BasePagination {
  965. total?: number;
  966. currentPage?: number;
  967. pageSize?: number;
  968. position?: ArrayElement<typeof strings.PAGINATION_POSITIONS>;
  969. defaultCurrentPage?: number;
  970. formatPageText?: any;
  971. }
  972. export interface BaseHeadWidth {
  973. width: number;
  974. key: string;
  975. }
  976. export interface BasePageData<RecordType> {
  977. dataSource?: RecordType[];
  978. groups?: Map<string, RecordType[]>;
  979. pagination?: BasePagination;
  980. disabledRowKeys?: BaseRowKeyType[];
  981. allRowKeys?: BaseRowKeyType[];
  982. queries?: BaseColumnProps<RecordType>[];
  983. }
  984. export type GetCheckboxProps<RecordType> = (record?: RecordType) => BaseCheckboxProps;
  985. export type BaseGroupBy<RecordType> = string | number | BaseGroupByFn<RecordType>;
  986. export type BaseGroupByFn<RecordType> = (record?: RecordType) => string | number;
  987. export interface BaseSorterInfo<RecordType> {
  988. [x: string]: any;
  989. dataIndex?: string;
  990. sortOrder?: BaseSortOrder;
  991. sorter?: BaseSorter<RecordType>;
  992. }
  993. export type BaseSortOrder = boolean | ArrayElement<typeof strings.SORT_DIRECTIONS>;
  994. export type BaseSorter<RecordType> = boolean | ((a?: RecordType, b?: RecordType) => number);
  995. export interface BaseChangeInfoFilter<RecordType> {
  996. dataIndex?: string;
  997. value?: any;
  998. text?: any;
  999. filters?: BaseFilter[];
  1000. onFilter?: (filteredValue?: any, record?: RecordType) => boolean;
  1001. filteredValue?: any[];
  1002. children?: BaseFilter[];
  1003. filterChildrenRecord?: boolean;
  1004. }
  1005. export interface BaseFilter {
  1006. value?: any;
  1007. text?: any;
  1008. children?: BaseFilter[];
  1009. }
  1010. export type BaseFixed = ArrayElement<typeof strings.FIXED_SET>;
  1011. export type BaseAlign = ArrayElement<typeof strings.ALIGNS>;
  1012. export type BaseOnCell<RecordType> = (record?: RecordType, rowIndex?: number) => BaseOnCellReturnObject;
  1013. export interface BaseOnCellReturnObject {
  1014. [x: string]: any;
  1015. style?: Record<string, any>;
  1016. className?: string;
  1017. onClick?: (e: any) => void;
  1018. }
  1019. export type BaseOnFilter<RecordType> = (filteredValue?: any, record?: RecordType) => boolean;
  1020. export type BaseOnFilterDropdownVisibleChange = (visible?: boolean) => void;
  1021. export type BaseOnHeaderCell<RecordType> = (record?: RecordType, columnIndex?: number) => BaseOnHeaderCellReturnObject;
  1022. export interface BaseOnHeaderCellReturnObject {
  1023. [x: string]: any;
  1024. style?: Record<string, any>;
  1025. className?: string;
  1026. onClick?: (e: any) => void;
  1027. }
  1028. export interface BaseChangeInfoSorter<RecordType> {
  1029. [x: string]: any;
  1030. dataIndex: string;
  1031. sortOrder: BaseSortOrder;
  1032. sorter: BaseSorter<RecordType>;
  1033. }
  1034. export type BaseIncludeGroupRecord<RecordType> = RecordType | { groupKey: string };
  1035. export default TableFoundation;