foundation.ts 46 KB

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