| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253 |
- import {
- get,
- merge,
- isFunction,
- each,
- find,
- some,
- pull,
- isSet,
- filter,
- isMap,
- slice,
- isEqual,
- isUndefined
- } from 'lodash';
- import memoizeOne from 'memoize-one';
- import { ArrayElement } from '../utils/type';
- import { BaseCheckboxProps } from '../checkbox/checkboxFoundation';
- import BaseFoundation, { DefaultAdapter } from '../base/foundation';
- import { strings, numbers } from './constants';
- import { mergeQueries, flattenColumns, filterColumns } from './utils';
- import { pullAll, withOrderSort } from '../utils/array';
- export interface BaseColumnProps<RecordType> {
- align?: BaseAlign;
- children?: Array<BaseColumnProps<RecordType>>;
- className?: string;
- colSpan?: number;
- dataIndex?: string;
- defaultFilteredValue?: any[];
- defaultSortOrder?: BaseSortOrder;
- filterChildrenRecord?: boolean;
- filterDropdown?: any;
- filterDropdownProps?: Record<string, any>;
- filterDropdownVisible?: boolean;
- filterIcon?: any;
- filterMultiple?: boolean;
- filteredValue?: any[];
- filters?: BaseFilter[];
- fixed?: BaseFixed;
- key?: string | number;
- onCell?: BaseOnCell<RecordType>;
- onFilter?: BaseOnFilter<RecordType>;
- onFilterDropdownVisibleChange?: BaseOnFilterDropdownVisibleChange;
- onHeaderCell?: BaseOnHeaderCell<RecordType>;
- render?: (...args: any[]) => any;
- renderFilterDropdownItem?: (...args: any[]) => any;
- sortChildrenRecord?: boolean;
- sortOrder?: BaseSortOrder;
- sorter?: BaseSorter<RecordType>;
- title?: any;
- useFullRender?: boolean;
- width?: string | number;
- ellipsis?: BaseEllipsis
- }
- export interface TableAdapter<RecordType> extends DefaultAdapter {
- resetScrollY: () => void;
- setSelectedRowKeys: (selectedRowKeys: BaseRowKeyType[]) => void;
- setDisabledRowKeys: (disabledRowKeys: BaseRowKeyType[]) => void;
- setCurrentPage: (currentPage: number) => void;
- setPagination: (pagination: BasePagination) => void;
- setGroups: (groups: Map<string, RecordType[]>) => void;
- setDataSource: (dataSource: RecordType[]) => void;
- setExpandedRowKeys: (expandedRowKeys: BaseRowKeyType[]) => void;
- setQuery: (query?: BaseColumnProps<RecordType>) => void;
- setQueries: (queries: BaseColumnProps<RecordType>[]) => void;
- setFlattenData: (flattenData: RecordType[]) => void;
- setAllRowKeys: (allRowKeys: BaseRowKeyType[]) => void;
- setHoveredRowKey: (hoveredRowKey: BaseRowKeyType) => void;
- setCachedFilteredSortedDataSource: (filteredSortedDataSource: RecordType[]) => void;
- setCachedFilteredSortedRowKeys: (filteredSortedRowKeys: BaseRowKeyType[]) => void;
- getCurrentPage: () => number;
- getCurrentPageSize: () => number;
- getCachedFilteredSortedDataSource: () => RecordType[];
- getCachedFilteredSortedRowKeys: () => BaseRowKeyType[];
- getCachedFilteredSortedRowKeysSet: () => Set<BaseRowKeyType>;
- setAllDisabledRowKeys: (allDisabledRowKeys: BaseRowKeyType[]) => void;
- getAllDisabledRowKeys: () => BaseRowKeyType[];
- getAllDisabledRowKeysSet: () => Set<BaseRowKeyType>;
- notifyFilterDropdownVisibleChange: (visible: boolean, dataIndex: string) => void;
- notifyChange: (changeInfo: { pagination: BasePagination; filters: BaseChangeInfoFilter<RecordType>[]; sorter: BaseChangeInfoSorter<RecordType>; extra: any }) => void;
- notifyExpand: (expanded?: boolean, record?: BaseIncludeGroupRecord<RecordType>, mouseEvent?: any) => void;
- notifyExpandedRowsChange: (expandedRows: BaseIncludeGroupRecord<RecordType>[]) => void;
- notifySelect: (record?: BaseIncludeGroupRecord<RecordType>, selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], nativeEvent?: any) => void;
- notifySelectAll: (selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], changedRows?: BaseIncludeGroupRecord<RecordType>[], e?: any) => void;
- notifySelectInvert: (record?: RecordType[], selected?: boolean, selectedRows?: BaseIncludeGroupRecord<RecordType>[], nativeEvent?: any) => void;
- notifySelectionChange: (selectedRowKeys: BaseRowKeyType[], selectedRows: BaseIncludeGroupRecord<RecordType>[]) => void;
- isAnyColumnFixed: (columns?: BaseColumnProps<RecordType>[]) => boolean;
- useFixedHeader: () => boolean;
- setHeadWidths: (headWidths: Array<BaseHeadWidth>, index?: number) => void;
- getHeadWidths: (index?: number) => number[];
- getCellWidths: (flattenedColumns: BaseColumnProps<RecordType>[], flattenedWidths?: BaseHeadWidth[], ignoreScrollBarKey?: boolean) => number[];
- mergedRowExpandable: (record: RecordType) => boolean;
- isAnyColumnUseFullRender: (columns: BaseColumnProps<RecordType>[]) => boolean;
- getNormalizeColumns: () => (columns: BaseColumnProps<RecordType>[], children: any) => BaseColumnProps<RecordType>[];
- getHandleColumns: () => (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[];
- getMergePagination: () => (pagination: BasePagination) => BasePagination;
- setBodyHasScrollbar: (bodyHasScrollBar: boolean) => void;
- getTableLayout: () => 'fixed' | 'auto'
- }
- class TableFoundation<RecordType> extends BaseFoundation<TableAdapter<RecordType>> {
- memoizedWithFnsColumns: (
- queries: BaseColumnProps<RecordType>[],
- cachedColumns: BaseColumnProps<RecordType>[],
- rowSelectionUpdate: boolean,
- hideExpandedColumn: boolean,
- bodyHasScrollBar: boolean,
- ) => BaseColumnProps<RecordType>[];
- memoizedFilterColumns: (columns: BaseColumnProps<RecordType>[], ignoreKeys?: string[]) => BaseColumnProps<RecordType>[];
- memoizedFlattenFnsColumns: (columns: BaseColumnProps<RecordType>[], childrenColumnName?: string) => BaseColumnProps<RecordType>[];
- memoizedPagination: (pagination: BasePagination) => BasePagination;
- /**
- * update columns in place, and use default values as initial values if the sorting and filtering columns have no values
- */
- static initColumnsFilteredValueAndSorterOrder(columns: BaseColumnProps<unknown>[]) {
- columns.forEach(column => {
- TableFoundation.initFilteredValue(column);
- TableFoundation.initSorterOrder(column);
- });
- return columns;
- }
- /**
- * init filteredValue of filtering column, use defaultFilteredValue or [] when it is undefined
- */
- static initFilteredValue(column: BaseColumnProps<unknown>) {
- const { defaultFilteredValue, filteredValue } = column;
- // There may be cases where onFilter is empty, such as server-side filtering
- // Because filterValue affects the output of filters, it needs to be initialized here
- if (isUndefined(filteredValue)) {
- if (Array.isArray(defaultFilteredValue) && defaultFilteredValue.length) {
- column.filteredValue = defaultFilteredValue;
- } else {
- column.filteredValue = [];
- }
- }
- }
- /**
- * init sortOrder of sorting column, use defaultSortOrder or [] when it is undefined
- */
- static initSorterOrder(column: BaseColumnProps<unknown>) {
- const { defaultSortOrder, sortOrder, sorter } = column;
- if (sorter && isUndefined(sortOrder)) {
- if (!isUndefined(defaultSortOrder)) {
- column.sortOrder = defaultSortOrder;
- } else {
- column.sortOrder = false;
- }
- }
- }
- constructor(adapter: TableAdapter<RecordType>) {
- super({ ...adapter });
- /**
- * memoized function list
- */
- const handleColumns: (queries: BaseColumnProps<RecordType>[], cachedColumns: BaseColumnProps<RecordType>[]) => BaseColumnProps<RecordType>[] = this._adapter.getHandleColumns();
- const mergePagination: (pagination: BasePagination) => BasePagination = this._adapter.getMergePagination();
- this.memoizedWithFnsColumns = memoizeOne(handleColumns, isEqual);
- this.memoizedFilterColumns = memoizeOne(filterColumns);
- this.memoizedFlattenFnsColumns = memoizeOne(flattenColumns);
- this.memoizedPagination = memoizeOne(mergePagination, isEqual);
- }
- init() {
- const dataSource = [...this.getProp('dataSource')];
- const { queries } = this._adapter.getStates();
- const filteredSortedDataSource = this.getFilteredSortedDataSource(dataSource, queries);
- const allDataDisabledRowKeys = this.getAllDisabledRowKeys(filteredSortedDataSource);
- const pageData = this.getCurrentPageData(filteredSortedDataSource);
- this.setAdapterPageData(pageData);
- this.initExpandedRowKeys(pageData);
- this.initSelectedRowKeys(pageData);
- // cache dataSource after mount, and then calculate it on demand
- this.setCachedFilteredSortedDataSource(filteredSortedDataSource);
- this.setAllDisabledRowKeys(allDataDisabledRowKeys);
- }
- initExpandedRowKeys({ groups }: { groups?: Map<string, RecordType[]> } = {}) {
- const {
- defaultExpandAllRows,
- defaultExpandedRowKeys = [],
- expandedRowKeys: propExpandedRowKeys = [],
- dataSource = [],
- expandAllRows,
- defaultExpandAllGroupRows,
- expandAllGroupRows,
- } = this.getProps();
- const expandedRowKeys: BaseRowKeyType[] = [];
- if (defaultExpandAllRows || expandAllRows) {
- this._addNoDuplicatedItemsToArr(
- expandedRowKeys,
- this.getAllRowKeys(dataSource),
- groups && isMap(groups) && groups.size ? Array.from(groups.keys()) : []
- );
- } else if (defaultExpandAllGroupRows || expandAllGroupRows) {
- this._addNoDuplicatedItemsToArr(
- expandedRowKeys,
- propExpandedRowKeys,
- groups && isMap(groups) && groups.size ? Array.from(groups.keys()) : []
- );
- } else if (Array.isArray(defaultExpandedRowKeys) && defaultExpandedRowKeys.length) {
- this._addNoDuplicatedItemsToArr(expandedRowKeys, defaultExpandedRowKeys);
- } else if (Array.isArray(propExpandedRowKeys) && propExpandedRowKeys.length) {
- this._addNoDuplicatedItemsToArr(expandedRowKeys, propExpandedRowKeys);
- }
- this._adapter.setExpandedRowKeys(expandedRowKeys);
- }
- initSelectedRowKeys({ disabledRowKeys }: { disabledRowKeys?: BaseRowKeyType[] }) {
- const rowSelection = this.getProp('rowSelection');
- const rowKeys: BaseRowKeyType[] = [];
- if (rowSelection) {
- const selectedRowKeys = get(rowSelection, 'selectedRowKeys');
- const defaultSelectedRowKeys = get(rowSelection, 'defaultSelectedRowKeys');
- if (Array.isArray(selectedRowKeys)) {
- this._addNoDuplicatedItemsToArr(rowKeys, selectedRowKeys);
- } else if (Array.isArray(defaultSelectedRowKeys)) {
- this._addNoDuplicatedItemsToArr(rowKeys, defaultSelectedRowKeys);
- }
- if (Array.isArray(disabledRowKeys) && disabledRowKeys.length) {
- pull(rowKeys, ...disabledRowKeys);
- }
- this._adapter.setSelectedRowKeys(rowKeys);
- }
- }
- /**
- * Get filtered and sorted data
- * @param {Object[]} dataSource
- * @param {Object[]} queries
- * @returns {Object[]} sortedDataSource
- */
- getFilteredSortedDataSource(dataSource: RecordType[], queries: BaseColumnProps<RecordType>[]) {
- const filteredDataSource = this.filterDataSource(dataSource, queries.filter(
- query => {
- const currentFilteredValue = query.filteredValue ? query.filteredValue : query.defaultFilteredValue;
- return (
- isFunction(query.onFilter) &&
- Array.isArray(currentFilteredValue) &&
- currentFilteredValue.length
- );
- }
- ));
- const sortedDataSource = this.sortDataSource(filteredDataSource, queries.filter(query => query && isFunction(query.sorter)));
- return sortedDataSource;
- }
- /**
- * get current page data
- *
- * @param {Array} dataSource
- * @param {object} pagination
- * @param {object} queries
- * @returns {{dataSource: RecordType[], groups: Map<string, Set<string>>, pagination: object, disabledRowKeys: string[], queries: BaseColumnProps[], allRowKeys: string[]}}
- */
- getCurrentPageData(dataSource?: RecordType[], pagination?: BasePagination, queries?: BaseColumnProps<RecordType>[]) {
- const filteredSortedDataSource = this._adapter.getCachedFilteredSortedDataSource();
- dataSource = dataSource == null ? [...filteredSortedDataSource] : dataSource;
- pagination =
- pagination == null ? this.getState('pagination') && { ...this.getState('pagination') } : pagination;
- queries = queries == null ? [...this.getState('queries')] : queries;
- let groups;
- if (this.getProp('groupBy') != null) {
- const { groups: groupedGroups, dataSource: groupedData } = this.groupDataSource(dataSource);
- dataSource = groupedData;
- groups = groupedGroups;
- }
- pagination = this.normalizePagination(pagination, dataSource);
- dataSource = this.limitPageDataSource(dataSource, pagination);
- const disabledRowKeys = this.getAllDisabledRowKeys(dataSource);
- const allRowKeys = this.getAllRowKeys(dataSource);
- const pageData: BasePageData<RecordType> = {
- dataSource,
- groups,
- pagination,
- disabledRowKeys,
- allRowKeys,
- queries,
- };
- return pageData;
- }
- /**
- * group dataSource, return grouped row keys
- *
- * @param {*[]} dataSource
- * @param {Function|string} groupBy
- */
- groupDataSource(dataSource: RecordType[], groupBy?: BaseGroupBy<RecordType>) {
- groupBy = groupBy == null ? this.getProp('groupBy') : groupBy;
- const groups = new Map();
- const newDataSource = [];
- if (groupBy != null) {
- each(dataSource, (record, index) => {
- const groupKey = typeof groupBy === 'function' ? groupBy(record) : get(record, groupBy);
- if (groupKey != null && groupKey !== '') {
- const recordKey = this.getRecordKey(record);
- let group = groups.get(groupKey);
- if (!isSet(group)) {
- group = new Set([recordKey]);
- groups.set(groupKey, group);
- } else {
- group.add(recordKey);
- }
- }
- });
- }
- if (groups && groups.size) {
- groups.forEach((set, key) => {
- if (isSet(set)) {
- set.forEach(realKey => {
- newDataSource.push(this._getRecord(realKey));
- });
- }
- });
- } else {
- newDataSource.push(...dataSource);
- }
- return { groups, dataSource: newDataSource };
- }
- /**
- * sort data
- *
- * @param {Array} dataSource
- * @param {Array} sorters
- * @returns {Array}
- */
- sortDataSource(dataSource: RecordType[], sorters: BaseSorterInfo<RecordType>[]) {
- each(sorters, sorterObj => {
- // const sorterObj = last(sorters) || {};
- const { sorter, sortOrder, defaultSortOrder, sortChildrenRecord } = sorterObj;
- const currentSortOrder = this.isSortOrderValid(sortOrder) ? sortOrder : defaultSortOrder;
- if (isFunction(sorter) && (currentSortOrder && strings.SORT_DIRECTIONS.includes(currentSortOrder))) {
- if (sortChildrenRecord) {
- const childrenRecordName = this.getProp('childrenRecordName');
- dataSource =
- dataSource &&
- dataSource.map(record => {
- const children = this._getRecordChildren(record);
- if (Array.isArray(children) && children.length) {
- return {
- ...record,
- [childrenRecordName]: this.sortDataSource(children, [sorterObj]),
- };
- }
- return record;
- });
- }
- dataSource.sort(withOrderSort(sorter, currentSortOrder));
- return false;
- }
- return undefined;
- });
- return dataSource;
- }
- /**
- * set page number
- */
- setPage = (currentPage: number, currentPageSize: number) => {
- currentPage = currentPage || this._adapter.getCurrentPage();
- const currentPagination = this.getState('pagination');
- const { dataSource, pagination, disabledRowKeys, allRowKeys } = this.getCurrentPageData(null, {
- ...currentPagination,
- currentPage,
- pageSize: currentPageSize,
- });
- if (!this._pagerIsControlled() && currentPage > 0) {
- this._adapter.setDisabledRowKeys(disabledRowKeys);
- this._adapter.setAllRowKeys(allRowKeys);
- this._adapter.setPagination(pagination);
- this._adapter.setDataSource(dataSource);
- }
- this._notifyChange(pagination);
- };
- /**
- * filter data source
- *
- * @param {*[]} dataSource
- * @param {*[]} filters
- * @returns {*[]}
- */
- filterDataSource(dataSource: RecordType[], filters: BaseChangeInfoFilter<RecordType>[]) {
- let filteredData: Map<string, RecordType> | null = null;
- let hasValidFilters = false;
- const childrenRecordName = this.getProp('childrenRecordName');
- each(filters, filterObj => {
- const { onFilter, filteredValue, filterChildrenRecord, defaultFilteredValue } = filterObj;
- const currentFilteredValue = Array.isArray(filteredValue) ? filteredValue : defaultFilteredValue;
- if (typeof onFilter === 'function' && Array.isArray(currentFilteredValue) && currentFilteredValue.length) {
- hasValidFilters = true;
- if (filteredData === null) {
- filteredData = new Map();
- } else {
- dataSource = Array.from(filteredData && filteredData.values());
- filteredData = new Map();
- }
- each(dataSource, record => {
- each(currentFilteredValue, value => {
- const childrenRecords = get(record, childrenRecordName);
- const recordKey = this.getRecordKey(record);
- let filteredChildren;
- if (Array.isArray(childrenRecords) && childrenRecords.length && filterChildrenRecord) {
- filteredChildren = this.filterDataSource(childrenRecords, [filterObj]);
- }
- if (Array.isArray(filteredChildren) && filteredChildren.length) {
- if (recordKey != null) {
- const children = get(filteredData.get(recordKey), childrenRecordName, []);
- filteredData.set(recordKey, {
- ...record,
- [childrenRecordName]: filteredChildren.reduce(
- (arr, cur) => {
- if (
- arr.find((item: any) => this.getRecordKey(item) === this.getRecordKey(cur)) ==
- null
- ) {
- arr.push(cur);
- }
- return arr;
- },
- // @ts-ignore
- [...children]
- ),
- });
- }
- } else if (onFilter(value, record)) {
- filteredData.set(recordKey, record);
- }
- });
- });
- }
- });
- if (hasValidFilters) {
- dataSource = Array.from(filteredData && filteredData.values());
- }
- return dataSource;
- }
- limitPageDataSource(dataSource: RecordType[], pagination: BasePagination) {
- dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
- pagination = pagination == null ? this.getState('pagination') : pagination;
- let pageData = dataSource;
- const pageNo = get(pagination, 'currentPage');
- if (this.getProp('pagination') !== false && pageNo && dataSource && pagination && !this._pagerIsControlled()) {
- const { pageSize = numbers.DEFAULT_PAGE_SIZE } = pagination;
- const start = (pageNo - 1) * pageSize;
- const end = pageNo * pageSize;
- pageData = slice(dataSource, start, end);
- }
- return pageData;
- }
- normalizePagination(pagination: BasePagination, dataSource: RecordType[]) {
- pagination = pagination == null ? this._getPagination() : pagination;
- dataSource = dataSource == null ? this._getDataSource() : dataSource;
- const propPagination = this.getProp('pagination');
- if (pagination) {
- pagination = typeof pagination === 'object' ? { ...pagination } : {};
- pagination = merge(
- {
- total: (dataSource && dataSource.length) || 0,
- pageSize: numbers.DEFAULT_PAGE_SIZE,
- currentPage: get(propPagination, 'defaultCurrentPage', 1),
- position: strings.PAGINATION_POSITIONS[0],
- },
- pagination
- );
- if (!this._pagerIsControlled()) {
- const total = get(propPagination, 'total', dataSource.length);
- const { currentPage, pageSize } = pagination;
- const realTotalPage = Math.ceil(total / pageSize);
- pagination.total = total;
- if (currentPage > realTotalPage) {
- pagination.currentPage = 1;
- }
- }
- }
- return pagination;
- }
- setAdapterPageData(pageData: BasePageData<RecordType> = {}) {
- const { pagination, dataSource, disabledRowKeys, allRowKeys, groups } = pageData;
- this._adapter.setDisabledRowKeys(disabledRowKeys);
- this._adapter.setAllRowKeys(allRowKeys);
- this._adapter.setPagination(pagination);
- this._adapter.setGroups(groups);
- this._adapter.setDataSource(dataSource);
- }
- /**
- * Cache related data when initializing or updating the calculated dataSource
- * @param {*} filteredSortedDataSource
- */
- setCachedFilteredSortedDataSource = (filteredSortedDataSource: RecordType[]) => {
- this._adapter.setCachedFilteredSortedDataSource(filteredSortedDataSource);
- const filteredSortedRowKeys = this.getAllRowKeys(filteredSortedDataSource);
- this._adapter.setCachedFilteredSortedRowKeys(filteredSortedRowKeys);
- };
- destroy() { }
- setAllDisabledRowKeys(disabledRowKeys) {
- this._adapter.setAllDisabledRowKeys(disabledRowKeys);
- }
- handleClick(e: any) { }
- handleMouseEnter(e: any) { }
- handleMouseLeave(e: any) { }
- stopPropagation(e: any) {
- this._adapter.stopPropagation(e);
- }
- /**
- * Add non-repeating elements to the array itself
- */
- _addNoDuplicatedItemsToArr(srcArr: any[] = [], ...objArrs: any[][]) {
- for (const objArr of objArrs) {
- if (Array.isArray(objArr)) {
- for (const item of objArr) {
- if (!srcArr.includes(item)) {
- srcArr.push(item);
- }
- }
- }
- }
- return srcArr;
- }
- _notifyChange(pagination: BasePagination, filters?: BaseChangeInfoFilter<RecordType>[], sorter?: BaseChangeInfoSorter<RecordType>, extra?: RecordType) {
- pagination = pagination == null ? this._getPagination() : pagination;
- filters = filters == null ? this._getAllFilters() : filters;
- sorter = sorter == null ? this._getAllSorters()[0] as BaseChangeInfoSorter<RecordType> : sorter;
- if (get(this.getProp('scroll'), 'scrollToFirstRowOnChange')) {
- this._adapter.resetScrollY();
- }
- this._adapter.notifyChange({
- pagination: { ...pagination },
- filters: [...filters],
- sorter,
- extra: { ...extra },
- });
- }
- _rowExpansionIsControlled() {
- return Array.isArray(this.getProp('expandedRowKeys'));
- }
- _pagerIsControlled() {
- return get(this.getProp('pagination'), 'currentPage') != null;
- }
- _selectionIsControlled() {
- return Array.isArray(get(this.getProp('rowSelection'), 'selectedRowKeys'));
- }
- /**
- * Determine whether the column sorting is controlled
- * Controlled: the column passed the sortOrder prop
- * @param {String} dataIndex
- * @returns {Boolean}
- */
- _sorterIsControlled(dataIndex: string) {
- // The basis for judgment should be props columns instead of cachedColumns fix#1141
- const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
- return Boolean(query && query.sortOrder != null);
- }
- /**
- * Determine whether the column is filtered and controlled
- * Controlled: the column passed the filteredValue prop
- * @param {String} dataIndex
- * @returns {Boolean}
- */
- _filterIsControlled(dataIndex: string) {
- const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
- return Boolean(query && Array.isArray(query.filteredValue));
- }
- _filterShowIsControlled(dataIndex?: string) {
- const query = dataIndex && this.getQuery(dataIndex, this.getState('flattenColumns'));
- return Boolean(query && (query.filterDropdownVisible === true || query.filterDropdownVisible === false));
- }
- _getSelectedRowKeys() {
- const rowSelection = this.getState('rowSelection');
- const selectedRowKeys = get(rowSelection, 'selectedRowKeys', []);
- return [...selectedRowKeys];
- }
- _getSelectedRowKeysSet() {
- const rowSelection = this.getState('rowSelection');
- const selectedRowKeysSet = get(rowSelection, 'selectedRowKeysSet', new Set());
- return selectedRowKeysSet;
- }
- _getDataSource() {
- return this.getProp('dataSource') || [];
- }
- _getRecord(realKey: string | number) {
- return find(
- this.getProp('dataSource'),
- record => realKey != null && realKey !== '' && this.getRecordKey(record) === realKey
- );
- }
- _getRecordChildren(record: RecordType) {
- return get(record, this.getProp('childrenRecordName'));
- }
- _getPagination() {
- return this.getState('pagination') || {};
- }
- /**
- * Filters are considered valid if filteredValue exists
- */
- _getAllFilters(queries?: BaseColumnProps<RecordType>[]) {
- queries = queries || this.getState('queries');
- const filters: BaseChangeInfoFilter<RecordType>[] = [];
- each(queries, query => {
- if (
- Array.isArray(query.filteredValue) &&
- (query.filteredValue.length || this._filterIsControlled(query.dataIndex))
- ) {
- filters.push(query);
- }
- });
- return filters;
- }
- _getAllSorters(queries?: BaseColumnProps<RecordType>[]): BaseColumnProps<RecordType>[] {
- queries = queries || this.getState('queries');
- return filter(queries, query => query.sorter && query.sortOrder) as BaseColumnProps<RecordType>[];
- }
- _filterQueries(targetQuery: BaseColumnProps<RecordType>, queries: BaseColumnProps<RecordType>[], keys = ['dataIndex']) {
- queries = queries == null ? this.getState('queries') : queries;
- const filteredQueries: BaseColumnProps<RecordType>[] = [];
- const filteredIndexes: number[] = [];
- each(queries, (itQuery, index) => {
- const flag = some(keys, k => k && targetQuery[k] != null && targetQuery[k] === itQuery[k]);
- if (flag) {
- filteredQueries.push(itQuery);
- filteredIndexes.push(index);
- }
- });
- return { filteredQueries, filteredIndexes };
- }
- _mergeToQueries(query: BaseColumnProps<RecordType>, queries: BaseColumnProps<RecordType>[], keys = ['dataIndex']) {
- queries = queries == null ? this.getState('queries') : queries;
- queries = [...queries];
- query = { ...query };
- const { filteredQueries, filteredIndexes } = this._filterQueries(query, queries, keys);
- each(filteredQueries, (curQuery, idx) => {
- // assign(curQuery, query);
- queries[filteredIndexes[idx]] = { ...query };
- });
- return queries;
- }
- /**
- * get record real key
- * @param {RecordType} record
- * @returns {string}
- */
- getRecordKey(record: RecordType): string {
- if (!record) {
- return undefined;
- }
- const rowKey = this.getProp('rowKey');
- return typeof rowKey === 'function' ? rowKey(record) : get(record, rowKey);
- }
- isEmpty(dataSource: RecordType[]) {
- dataSource = dataSource == null ? this.getProp('dataSource') : dataSource;
- return !(Array.isArray(dataSource) && dataSource.length > 0);
- }
- handleSelectRow(realKey: BaseRowKeyType, selected: boolean, e: any) {
- this.stopPropagation(e);
- if (typeof selected === 'boolean' && realKey != null) {
- const selectedRowKeys = this._getSelectedRowKeys();
- let foundIdx = -1;
- const selectedRow = this.getSelectedRows(null, [realKey])[0];
- let selectedRows: BaseIncludeGroupRecord<RecordType>[];
- if ((foundIdx = selectedRowKeys.indexOf(realKey)) > -1 && selected === false) {
- selectedRowKeys.splice(foundIdx, 1);
- selectedRows = this.getSelectedRows(null, selectedRowKeys);
- if (!this._selectionIsControlled()) {
- this._adapter.setSelectedRowKeys(selectedRowKeys);
- }
- this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
- this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
- } else if (selectedRowKeys.indexOf(realKey) === -1 && selected === true) {
- selectedRowKeys.push(realKey);
- selectedRows = this.getSelectedRows(null, selectedRowKeys);
- if (!this._selectionIsControlled()) {
- this._adapter.setSelectedRowKeys(selectedRowKeys);
- }
- this._adapter.notifySelect(selectedRow, selected, selectedRows, e);
- this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
- }
- }
- }
- /**
- * select all rows
- * @param {*} selected The future state of the select all button
- * @param {*} e
- */
- handleSelectAllRow(selected: boolean, e: any) {
- this.stopPropagation(e);
- if (typeof selected === 'boolean') {
- const curSelectedRowKeys = this._getSelectedRowKeys();
- let selectedRowKeys = [...curSelectedRowKeys];
- const selectedRowKeysSet = this._getSelectedRowKeysSet();
- let allRowKeys = [...this._adapter.getCachedFilteredSortedRowKeys()];
- const disabledRowKeys = this._adapter.getAllDisabledRowKeys();
- const disabledRowKeysSet = this._adapter.getAllDisabledRowKeysSet();
- let changedRowKeys;
- // Select all, if not disabled && not in selectedRowKeys
- if (selected) {
- for (const key of allRowKeys) {
- if (!disabledRowKeysSet.has(key) && !selectedRowKeysSet.has(key)) {
- selectedRowKeys.push(key);
- }
- }
- allRowKeys = pullAll(allRowKeys, [...disabledRowKeys, ...curSelectedRowKeys]);
- changedRowKeys = [...allRowKeys];
- } else {
- selectedRowKeys = pullAll(selectedRowKeys, allRowKeys);
- changedRowKeys = [...curSelectedRowKeys];
- }
- const changedRows = this.getSelectedRows(null, changedRowKeys || []);
- const selectedRows = this.getSelectedRows(null, selectedRowKeys || []);
- if (!this._selectionIsControlled()) {
- this._adapter.setSelectedRowKeys(selectedRowKeys);
- }
- this._adapter.notifySelectAll(selected, selectedRows, changedRows, e);
- this._adapter.notifySelectionChange(selectedRowKeys, selectedRows);
- }
- }
- /**
- * row keys => rows
- * @param {*} dataSource
- * @param {*} selectedRowKeys
- * @param {*} selectedRowKeysSet Recursive optimization
- */
- getSelectedRows(dataSource: RecordType[], selectedRowKeys: BaseRowKeyType[], selectedRowKeysSet?: Set<BaseRowKeyType>): BaseIncludeGroupRecord<RecordType>[] {
- dataSource = dataSource == null ? this._getDataSource() : dataSource;
- selectedRowKeys = selectedRowKeys == null ? this._getSelectedRowKeys() : selectedRowKeys;
- if (!isSet(selectedRowKeysSet)) {
- selectedRowKeysSet = new Set(selectedRowKeys);
- }
- const childrenRecordName = this.getProp('childrenRecordName');
- const selectedRows: BaseIncludeGroupRecord<RecordType>[] = [];
- if (
- isSet(selectedRowKeysSet) &&
- selectedRowKeysSet.size &&
- Array.isArray(dataSource) &&
- dataSource.length
- ) {
- // Time complexity optimization, replace the includes operation of array with has of set
- selectedRows.push(...dataSource.filter(data => selectedRowKeysSet.has(this.getRecordKey(data))));
- if (selectedRows.length < selectedRowKeys.length) {
- for (const item of dataSource) {
- const children = get(item, childrenRecordName);
- if (Array.isArray(children) && children.length) {
- const rows = this.getSelectedRows(children, selectedRowKeys, selectedRowKeysSet);
- selectedRows.push(...rows);
- }
- }
- }
- }
- return selectedRows;
- }
- getAllDisabledRowKeys(dataSource?: RecordType[], getCheckboxProps?: GetCheckboxProps<RecordType>): BaseRowKeyType[] {
- dataSource = dataSource == null ? this._getDataSource() : dataSource;
- getCheckboxProps =
- getCheckboxProps == null ? get(this.getProp('rowSelection'), 'getCheckboxProps') : getCheckboxProps;
- const childrenRecordName = this.getProp('childrenRecordName');
- const disabledRowKeys: BaseRowKeyType[] = [];
- if (Array.isArray(dataSource) && dataSource.length && typeof getCheckboxProps === 'function') {
- for (const record of dataSource) {
- const props = getCheckboxProps(record);
- if (props && props.disabled) {
- disabledRowKeys.push(this.getRecordKey(record));
- }
- const children = get(record, childrenRecordName);
- if (Array.isArray(children) && children.length) {
- const keys: BaseRowKeyType[] = this.getAllDisabledRowKeys(children, getCheckboxProps);
- disabledRowKeys.push(...keys);
- }
- }
- }
- return disabledRowKeys;
- }
- getAllRowKeys(dataSource: RecordType[]): BaseRowKeyType[] {
- dataSource = dataSource == null ? this._getDataSource() : dataSource;
- const childrenRecordName = this.getProp('childrenRecordName');
- const allRowKeys = [];
- if (Array.isArray(dataSource) && dataSource.length) {
- for (const record of dataSource) {
- const childrenRowKeys = [];
- const children = get(record, childrenRecordName);
- if (Array.isArray(children) && children.length) {
- childrenRowKeys.push(...this.getAllRowKeys(children));
- }
- allRowKeys.push(this.getRecordKey(record), ...childrenRowKeys);
- }
- }
- return allRowKeys;
- }
- /**
- * Check if the selected item is in allRowKeysSet
- * @param {Array} selectedRowKeys
- * @param {Set} allRowKeysSet
- */
- hasRowSelected(selectedRowKeys: BaseRowKeyType[], allRowKeysSet: Set<BaseRowKeyType>) {
- return Boolean(Array.isArray(selectedRowKeys) &&
- selectedRowKeys.length &&
- isSet(allRowKeysSet) &&
- allRowKeysSet.size &&
- selectedRowKeys.filter(key => allRowKeysSet.has(key)).length);
- }
- /**
- * expand processing function
- * @param {Boolean} expanded
- * @param {String} realKey
- * @param {Event} domEvent
- */
- handleRowExpanded(expanded: boolean, realKey: string, domEvent: any) {
- this.stopPropagation(domEvent);
- const expandedRowKeys = [...this.getState('expandedRowKeys')];
- const index = expandedRowKeys.indexOf(realKey);
- const keyIsValid = typeof realKey === 'string' || typeof realKey === 'number';
- if (keyIsValid && expanded && index === -1) {
- expandedRowKeys.push(realKey);
- } else if (keyIsValid && !expanded && index > -1) {
- expandedRowKeys.splice(index, 1);
- }
- if (!this._rowExpansionIsControlled()) {
- this._adapter.setExpandedRowKeys(expandedRowKeys);
- }
- const expandedRows = this.getSelectedRows(null, expandedRowKeys);
- let expandedRow = this.getSelectedRows(null, [realKey])[0];
- // groups record processing
- const groups = this._getGroups();
- if (groups) {
- // Construct group expandRow
- if (groups.has(realKey)) {
- expandedRow = { groupKey: realKey };
- }
- // If expandedRowKeys includes groupKey, add to expandedRows
- for (let i = 0, len = expandedRowKeys.length; i < len; i++) {
- if (groups.has(realKey)) {
- expandedRows.push({ groupKey: expandedRowKeys[i] });
- }
- }
- }
- this._adapter.notifyExpand(expanded, expandedRow, domEvent);
- this._adapter.notifyExpandedRowsChange(expandedRows);
- }
- /**
- * get state.groups
- * @returns {Map|Null}
- */
- _getGroups() {
- const groupBy = this._adapter.getProp('groupBy');
- if (groupBy !== null) {
- const groups = this._adapter.getState('groups');
- return groups;
- }
- return null;
- }
- /**
- * Determine whether you have selected all except for disabled
- * @param {Set} selectedRowKeysSet
- * @param {Set} disabledRowKeysSet
- * @param {Array} allKeys keys after sorted and filtered
- */
- allIsSelected(selectedRowKeysSet: Set<BaseRowKeyType>, disabledRowKeysSet: Set<BaseRowKeyType>, allKeys: BaseRowKeyType[]) {
- const filteredAllKeys = filter(allKeys, key => key != null && !disabledRowKeysSet.has(key));
- if (filteredAllKeys && filteredAllKeys.length) {
- for (const key of filteredAllKeys) {
- if (key != null && !selectedRowKeysSet.has(key)) {
- return false;
- }
- }
- return true;
- } else {
- const isAllSelected = allKeys.length && allKeys.every(rowKey => selectedRowKeysSet.has(rowKey));
- return isAllSelected || false;
- }
- }
- /**
- * This function is not used yet
- * @param {*} selectedRowKeys
- * @param {*} allKeys
- */
- allIsNotSelected(selectedRowKeys: BaseRowKeyType[], allKeys: BaseRowKeyType[]) {
- for (const key of allKeys) {
- if (key != null && Array.isArray(selectedRowKeys) && selectedRowKeys.includes(key)) {
- return true;
- }
- }
- return false;
- }
- formatPaginationInfo(pagination: BasePagination = {}, defaultPageText = '') {
- let info = '';
- const formatPageText = get(this.getProp('pagination'), 'formatPageText');
- const { total, pageSize, currentPage } = pagination;
- const currentStart = Math.min((currentPage - 1) * pageSize + 1, total);
- const currentEnd = Math.min(currentPage * pageSize, total);
- if (formatPageText || (formatPageText !== false && defaultPageText && total > 0)) {
- info =
- typeof formatPageText === 'function' ?
- formatPageText({ currentStart, currentEnd, total }) :
- defaultPageText
- .replace('${currentStart}', currentStart as any)
- .replace('${currentEnd}', currentEnd as any)
- .replace('${total}', total as any);
- }
- return info;
- }
- toggleShowFilter(dataIndex: string, visible: boolean) {
- let filterObj: BaseColumnProps<RecordType> = this.getQuery(dataIndex);
- const filterDropdownVisible = visible;
- filterObj = { ...filterObj, filterDropdownVisible };
- if (!this._filterShowIsControlled()) {
- // this._adapter.setQuery({
- // ...filterObj,
- // filterDropdownVisible,
- // });
- }
- this._adapter.notifyFilterDropdownVisibleChange(filterDropdownVisible, dataIndex);
- }
- /**
- * Called when the filter changes
- * @param {*} dataIndex
- * @param {*} data
- */
- handleFilterSelect(dataIndex: string, data: { filteredValue?: string[] } = {}) {
- let query: BaseColumnProps<RecordType> = this.getQuery(dataIndex);
- let queries = [...this._adapter.getState('queries')];
- const { filteredValue } = data;
- query = {
- ...query,
- filteredValue,
- };
- queries = mergeQueries(query, queries);
- const mergedQueries = this._mergeToQueries(query, null);
- const filters = this._getAllFilters(mergedQueries);
- if (!this._filterIsControlled(dataIndex)) {
- this._adapter.setQueries(queries);
- this.handleClickFilterOrSorter(queries);
- }
- this._notifyChange(null, filters);
- }
- /**
- * Click the sort button to call
- * @param {*} column
- * @param {*} e
- */
- handleSort(column: { dataIndex?: string; sortOrder?: BaseSortOrder } = {}, e: any) {
- this.stopPropagation(e);
- const { dataIndex } = column;
- let queries = this.getState('queries');
- let curQuery = null;
- queries = [...queries];
- each(queries, (query, idx, arr) => {
- if (query.sorter) {
- const sorterObj = { ...query };
- const stateSortOrder = get(sorterObj, 'sortOrder');
- const defaultSortOrder = get(sorterObj, 'defaultSortOrder', false);
- let querySortOrder = this.isSortOrderValid(stateSortOrder) ? stateSortOrder : defaultSortOrder;
- if (dataIndex && dataIndex === sorterObj.dataIndex) {
- if (querySortOrder === strings.SORT_DIRECTIONS[0]) {
- querySortOrder = strings.SORT_DIRECTIONS[1];
- } else if (querySortOrder === strings.SORT_DIRECTIONS[1]) {
- querySortOrder = false;
- } else {
- querySortOrder = strings.SORT_DIRECTIONS[0];
- }
- } else {
- // This results in the current click only supports single column sorting
- querySortOrder = false;
- }
- arr[idx] = { ...sorterObj, sortOrder: querySortOrder };
- if (dataIndex === sorterObj.dataIndex) {
- curQuery = arr[idx];
- }
- }
- });
- if (!this._sorterIsControlled(dataIndex)) {
- this._adapter.setQueries(queries);
- this.handleClickFilterOrSorter(queries);
- }
- // notify sort event
- this._notifyChange(null, null, curQuery, null);
- }
- /**
- * Recalculate the cached data after clicking filter or sorter
- * @param {*} queries
- */
- handleClickFilterOrSorter(queries: BaseColumnProps<RecordType>[]) {
- const dataSource = [...this.getProp('dataSource')];
- const sortedDataSource = this.getFilteredSortedDataSource(dataSource, queries);
- const allDataDisabledRowKeys = this.getAllDisabledRowKeys(sortedDataSource);
- this.setCachedFilteredSortedDataSource(sortedDataSource);
- this.setAllDisabledRowKeys(allDataDisabledRowKeys);
- const pageData = this.getCurrentPageData(sortedDataSource);
- this.setAdapterPageData(pageData);
- }
- getQuery(dataIndex: string, queries?: BaseColumnProps<RecordType>[]) {
- queries = queries || this.getState('queries');
- if (dataIndex != null) {
- return find(queries, query => query.dataIndex === dataIndex);
- }
- return undefined;
- }
- getCellWidths(flattenedColumns: BaseColumnProps<RecordType>[], flattenedWidths?: BaseHeadWidth[], ignoreScrollBarKey?: boolean) {
- return this._adapter.getCellWidths(flattenedColumns, flattenedWidths, ignoreScrollBarKey);
- }
- setHeadWidths(headWidths: Array<BaseHeadWidth>, index?: number) {
- return this._adapter.setHeadWidths(headWidths, index);
- }
- getHeadWidths(index: number) {
- return this._adapter.getHeadWidths(index);
- }
- mergedRowExpandable(record: RecordType) {
- return this._adapter.mergedRowExpandable(record);
- }
- setBodyHasScrollbar(bodyHasScrollbar: boolean) {
- this._adapter.setBodyHasScrollbar(bodyHasScrollbar);
- }
- isSortOrderValid = (sortOrder: BaseSortOrder) => strings.SORT_DIRECTIONS.includes(sortOrder as any) || sortOrder === false;
- }
- export type BaseRowKeyType = string | number;
- export interface BasePagination {
- total?: number;
- currentPage?: number;
- pageSize?: number;
- position?: ArrayElement<typeof strings.PAGINATION_POSITIONS>;
- defaultCurrentPage?: number;
- formatPageText?: any
- }
- export interface BaseHeadWidth {
- width: number;
- key: string
- }
- export interface BasePageData<RecordType> {
- dataSource?: RecordType[];
- groups?: Map<string, RecordType[]>;
- pagination?: BasePagination;
- disabledRowKeys?: BaseRowKeyType[];
- allRowKeys?: BaseRowKeyType[];
- queries?: BaseColumnProps<RecordType>[]
- }
- export type GetCheckboxProps<RecordType> = (record?: RecordType) => BaseCheckboxProps;
- export type BaseGroupBy<RecordType> = string | number | BaseGroupByFn<RecordType>;
- export type BaseGroupByFn<RecordType> = (record?: RecordType) => string | number;
- export interface BaseSorterInfo<RecordType> {
- [x: string]: any;
- dataIndex?: string;
- sortOrder?: BaseSortOrder;
- sorter?: BaseSorter<RecordType>
- }
- export type BaseSortOrder = boolean | ArrayElement<typeof strings.SORT_DIRECTIONS>;
- export type BaseSorter<RecordType> = boolean | ((a?: RecordType, b?: RecordType, sortOrder?: 'ascend' | 'descend') => number);
- export interface BaseChangeInfoFilter<RecordType> {
- dataIndex?: string;
- value?: any;
- text?: any;
- filters?: BaseFilter[];
- onFilter?: (filteredValue?: any, record?: RecordType) => boolean;
- filteredValue?: any[];
- defaultFilteredValue?: any[];
- children?: BaseFilter[];
- filterChildrenRecord?: boolean
- }
- export interface BaseFilter {
- value?: any;
- text?: any;
- children?: BaseFilter[]
- }
- export type BaseFixed = ArrayElement<typeof strings.FIXED_SET>;
- export type BaseAlign = ArrayElement<typeof strings.ALIGNS>;
- export type BaseOnCell<RecordType> = (record?: RecordType, rowIndex?: number) => BaseOnCellReturnObject;
- export interface BaseOnCellReturnObject {
- [x: string]: any;
- style?: Record<string, any>;
- className?: string;
- onClick?: (e: any) => void
- }
- export type BaseOnFilter<RecordType> = (filteredValue?: any, record?: RecordType) => boolean;
- export type BaseOnFilterDropdownVisibleChange = (visible?: boolean) => void;
- export type BaseOnHeaderCell<RecordType> = (record?: RecordType, columnIndex?: number) => BaseOnHeaderCellReturnObject;
- export interface BaseOnHeaderCellReturnObject {
- [x: string]: any;
- style?: Record<string, any>;
- className?: string;
- onClick?: (e: any) => void
- }
- export interface BaseChangeInfoSorter<RecordType> {
- [x: string]: any;
- dataIndex: string;
- sortOrder: BaseSortOrder;
- sorter: BaseSorter<RecordType>
- }
- export type BaseIncludeGroupRecord<RecordType> = RecordType | { groupKey: string };
- export type BaseEllipsis = boolean | { showTitle: boolean };
- export default TableFoundation;
|