Skip to content

Commit

Permalink
feat: add support for ReadonlyArray in table
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaoxiangmoe committed Jan 27, 2021
1 parent 15a9947 commit 52418d0
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 76 deletions.
2 changes: 1 addition & 1 deletion components/table/ColumnGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { ColumnProps } from './Column';
export interface ColumnGroupProps<RecordType> extends Omit<ColumnType<RecordType>, 'children'> {
children:
| React.ReactElement<ColumnProps<RecordType>>
| React.ReactElement<ColumnProps<RecordType>>[];
| readonly React.ReactElement<ColumnProps<RecordType>>[];
}

/* istanbul ignore next */
Expand Down
25 changes: 15 additions & 10 deletions components/table/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,11 @@ interface ChangeEventInfo<RecordType> {
pageSize?: number;
total?: number;
};
filters: Record<string, (Key | boolean)[] | null>;
sorter: SorterResult<RecordType> | SorterResult<RecordType>[];
filters: Record<string, readonly (Key | boolean)[] | null>;
sorter: SorterResult<RecordType> | readonly SorterResult<RecordType>[];

filterStates: FilterState<RecordType>[];
sorterStates: SortState<RecordType>[];
filterStates: readonly FilterState<RecordType>[];
sorterStates: readonly SortState<RecordType>[];

resetPagination: Function;
}
Expand All @@ -84,8 +84,8 @@ export interface TableProps<RecordType>

onChange?: (
pagination: TablePaginationConfig,
filters: Record<string, (Key | boolean)[] | null>,
sorter: SorterResult<RecordType> | SorterResult<RecordType>[],
filters: Record<string, readonly (Key | boolean)[] | null>,
sorter: SorterResult<RecordType> | readonly SorterResult<RecordType>[],
extra: TableCurrentDataSource<RecordType>,
) => void;
rowSelection?: TableRowSelection<RecordType>;
Expand All @@ -94,7 +94,7 @@ export interface TableProps<RecordType>
scroll?: RcTableProps<RecordType>['scroll'] & {
scrollToFirstRowOnChange?: boolean;
};
sortDirections?: SortOrder[];
sortDirections?: readonly SortOrder[];
showSorterTooltip?: boolean;
}

Expand Down Expand Up @@ -152,7 +152,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
);
const mergedSize = customizeSize || size;
const tableLocale = { ...contextLocale.Table, ...locale } as TableLocale;
const rawData: RecordType[] = dataSource || EMPTY_LIST;
const rawData: readonly RecordType[] = dataSource || EMPTY_LIST;

const { getPrefixCls } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('table', customizePrefixCls);
Expand Down Expand Up @@ -236,7 +236,12 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
}
};

/** Controlled state in `columns` is not a good idea that makes too many code (1000+ line?) to read state out and then put it back to title render. Move these code into `hooks` but still too complex. We should provides Table props like `sorter` & `filter` to handle control in next big version. */
/**
* Controlled state in `columns` is not a good idea that makes too many code (1000+ line?) to
* read state out and then put it back to title render. Move these code into `hooks` but still
* too complex. We should provides Table props like `sorter` & `filter` to handle control in next
* big version.
*/

// ============================ Sorter =============================
const onSorterChange = (
Expand Down Expand Up @@ -327,7 +332,7 @@ function Table<RecordType extends object = any>(props: TableProps<RecordType>) {
changeEventInfo.resetPagination = resetPagination;

// ============================= Data =============================
const pageData = React.useMemo<RecordType[]>(() => {
const pageData = React.useMemo<readonly RecordType[]>(() => {
if (pagination === false || !mergedPagination.pageSize) {
return mergedData;
}
Expand Down
10 changes: 5 additions & 5 deletions components/table/hooks/useFilter/FilterDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { ConfigContext } from '../../../config-provider/context';

const { SubMenu, Item: MenuItem } = Menu;

function hasSubMenu(filters: ColumnFilterItem[]) {
function hasSubMenu(filters: readonly ColumnFilterItem[]) {
return filters.some(({ children }) => children);
}

Expand All @@ -34,9 +34,9 @@ function renderFilterItems({
filterMultiple,
locale,
}: {
filters: ColumnFilterItem[];
filters: readonly ColumnFilterItem[];
prefixCls: string;
filteredKeys: Key[];
filteredKeys: readonly Key[];
filterMultiple: boolean;
locale: TableLocale;
}) {
Expand Down Expand Up @@ -139,7 +139,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
const propFilteredKeys = filterState && filterState.filteredKeys;
const [getFilteredKeysSync, setFilteredKeysSync] = useSyncState(propFilteredKeys || []);

const onSelectKeys = ({ selectedKeys }: { selectedKeys?: Key[] }) => {
const onSelectKeys = ({ selectedKeys }: { selectedKeys?: readonly Key[] }) => {
setFilteredKeysSync(selectedKeys!);
};

Expand All @@ -166,7 +166,7 @@ function FilterDropdown<RecordType>(props: FilterDropdownProps<RecordType>) {
);

// ======================= Submit ========================
const internalTriggerFilter = (keys: Key[] | undefined | null) => {
const internalTriggerFilter = (keys: readonly Key[] | undefined | null) => {
const mergedKeys = keys && keys.length ? keys : null;
if (mergedKeys === null && (!filterState || !filterState.filteredKeys)) {
return null;
Expand Down
26 changes: 13 additions & 13 deletions components/table/hooks/useFilter/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import FilterDropdown from './FilterDropdown';
export interface FilterState<RecordType> {
column: ColumnType<RecordType>;
key: Key;
filteredKeys?: Key[] | null;
filteredKeys?: readonly Key[] | null;
forceFiltered?: boolean;
}

function collectFilterStates<RecordType>(
columns: ColumnsType<RecordType>,
init: boolean,
pos?: string,
): FilterState<RecordType>[] {
): readonly FilterState<RecordType>[] {
let filterStates: FilterState<RecordType>[] = [];

(columns || []).forEach((column, index) => {
Expand Down Expand Up @@ -64,7 +64,7 @@ function injectFilter<RecordType>(
prefixCls: string,
dropdownPrefixCls: string,
columns: ColumnsType<RecordType>,
filterStates: FilterState<RecordType>[],
filterStates: readonly FilterState<RecordType>[],
triggerFilter: (filterState: FilterState<RecordType>) => void,
getPopupContainer: GetPopupContainer | undefined,
locale: TableLocale,
Expand Down Expand Up @@ -120,7 +120,7 @@ function injectFilter<RecordType>(
});
}

function flattenKeys(filters?: ColumnFilterItem[]) {
function flattenKeys(filters?: readonly ColumnFilterItem[]) {
let keys: (string | number | boolean)[] = [];
(filters || []).forEach(({ value, children }) => {
keys.push(value);
Expand All @@ -131,8 +131,8 @@ function flattenKeys(filters?: ColumnFilterItem[]) {
return keys;
}

function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[]) {
const currentFilters: Record<string, (Key | boolean)[] | null> = {};
function generateFilterInfo<RecordType>(filterStates: readonly FilterState<RecordType>[]) {
const currentFilters: Record<string, readonly (Key | boolean)[] | null> = {};

filterStates.forEach(({ key, filteredKeys, column }) => {
const { filters, filterDropdown } = column;
Expand All @@ -150,8 +150,8 @@ function generateFilterInfo<RecordType>(filterStates: FilterState<RecordType>[])
}

export function getFilterData<RecordType>(
data: RecordType[],
filterStates: FilterState<RecordType>[],
data: readonly RecordType[],
filterStates: readonly FilterState<RecordType>[],
) {
return filterStates.reduce((currentData, filterState) => {
const {
Expand All @@ -178,8 +178,8 @@ interface FilterConfig<RecordType> {
mergedColumns: ColumnsType<RecordType>;
locale: TableLocale;
onFilterChange: (
filters: Record<string, (Key | boolean)[] | null>,
filterStates: FilterState<RecordType>[],
filters: Record<string, readonly (Key | boolean)[] | null>,
filterStates: readonly FilterState<RecordType>[],
) => void;
getPopupContainer?: GetPopupContainer;
}
Expand All @@ -193,10 +193,10 @@ function useFilter<RecordType>({
locale: tableLocale,
}: FilterConfig<RecordType>): [
TransformColumns<RecordType>,
FilterState<RecordType>[],
() => Record<string, (Key | boolean)[] | null>,
readonly FilterState<RecordType>[],
() => Record<string, readonly (Key | boolean)[] | null>,
] {
const [filterStates, setFilterStates] = React.useState<FilterState<RecordType>[]>(
const [filterStates, setFilterStates] = React.useState<readonly FilterState<RecordType>[]>(
collectFilterStates(mergedColumns, true),
);

Expand Down
6 changes: 3 additions & 3 deletions components/table/hooks/useLazyKVMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ import * as React from 'react';
import { Key, GetRowKey } from '../interface';

interface MapCache<RecordType> {
data?: RecordType[];
data?: readonly RecordType[];
childrenColumnName?: string;
kvMap?: Map<Key, RecordType>;
getRowKey?: Function;
}

export default function useLazyKVMap<RecordType>(
data: RecordType[],
data: readonly RecordType[],
childrenColumnName: string,
getRowKey: GetRowKey<RecordType>,
) {
Expand All @@ -25,7 +25,7 @@ export default function useLazyKVMap<RecordType>(
const kvMap = new Map<Key, RecordType>();

/* eslint-disable no-inner-declarations */
function dig(records: RecordType[]) {
function dig(records: readonly RecordType[]) {
records.forEach((record, index) => {
const rowKey = getRowKey(record, index);
kvMap.set(rowKey, record);
Expand Down
2 changes: 1 addition & 1 deletion components/table/hooks/usePagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ export default function usePagination(
total: number,
pagination: TablePaginationConfig | false | undefined,
onChange: (current: number, pageSize: number) => void,
): [TablePaginationConfig, () => void] {
): readonly [TablePaginationConfig, () => void] {
const { total: paginationTotal = 0, ...paginationObj } =
pagination && typeof pagination === 'object' ? pagination : {};

Expand Down
14 changes: 7 additions & 7 deletions components/table/hooks/useSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ function getFixedType<RecordType>(column: ColumnsType<RecordType>[number]): Fixe

interface UseSelectionConfig<RecordType> {
prefixCls: string;
pageData: RecordType[];
data: RecordType[];
pageData: readonly RecordType[];
data: readonly RecordType[];
getRowKey: GetRowKey<RecordType>;
getRecordByKey: (key: Key) => RecordType;
expandType: ExpandType;
Expand All @@ -54,9 +54,9 @@ export type INTERNAL_SELECTION_ITEM =
| typeof SELECTION_NONE;

function flattenData<RecordType>(
data: RecordType[] | undefined,
data: readonly RecordType[] | undefined,
childrenColumnName: string,
): RecordType[] {
): readonly RecordType[] {
let list: RecordType[] = [];
(data || []).forEach(record => {
list.push(record);
Expand All @@ -75,7 +75,7 @@ function flattenData<RecordType>(
export default function useSelection<RecordType>(
rowSelection: TableRowSelection<RecordType> | undefined,
config: UseSelectionConfig<RecordType>,
): [TransformColumns<RecordType>, Set<Key>] {
): readonly [TransformColumns<RecordType>, Set<Key>] {
const {
preserveSelectedRowKeys,
selectedRowKeys,
Expand Down Expand Up @@ -165,7 +165,7 @@ export default function useSelection<RecordType>(
return [mergedSelectedKeys || [], []];
}
const { checkedKeys, halfCheckedKeys } = conductCheck(
mergedSelectedKeys,
mergedSelectedKeys as React.Key[],
true,
keyEntities as any,
isCheckboxDisabled as any,
Expand Down Expand Up @@ -257,7 +257,7 @@ export default function useSelection<RecordType>(
return null;
}

const selectionList: INTERNAL_SELECTION_ITEM[] =
const selectionList: readonly INTERNAL_SELECTION_ITEM[] =
selections === true ? [SELECTION_ALL, SELECTION_INVERT, SELECTION_NONE] : selections;

return selectionList.map((selection: INTERNAL_SELECTION_ITEM) => {
Expand Down
27 changes: 14 additions & 13 deletions components/table/hooks/useSorter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function getSortFunction<RecordType>(
return false;
}

function nextSortDirection(sortDirections: SortOrder[], current: SortOrder | null) {
function nextSortDirection(sortDirections: readonly SortOrder[], current: SortOrder | null) {
if (!current) {
return sortDirections[0];
}
Expand Down Expand Up @@ -104,9 +104,9 @@ function collectSortStates<RecordType>(
function injectSorter<RecordType>(
prefixCls: string,
columns: ColumnsType<RecordType>,
sorterSates: SortState<RecordType>[],
sorterSates: readonly SortState<RecordType>[],
triggerSorter: (sorterSates: SortState<RecordType>) => void,
defaultSortDirections: SortOrder[],
defaultSortDirections: readonly SortOrder[],
tableLocale?: TableLocale,
tableShowSorterTooltip?: boolean,
pos?: string,
Expand All @@ -116,7 +116,8 @@ function injectSorter<RecordType>(
let newColumn: ColumnsType<RecordType>[number] = column;

if (newColumn.sorter) {
const sortDirections: SortOrder[] = newColumn.sortDirections || defaultSortDirections;
const sortDirections: readonly SortOrder[] =
newColumn.sortDirections || defaultSortDirections;
const showSorterTooltip =
newColumn.showSorterTooltip === undefined
? tableShowSorterTooltip
Expand Down Expand Up @@ -223,8 +224,8 @@ function stateToInfo<RecordType>(sorterStates: SortState<RecordType>) {
}

function generateSorterInfo<RecordType>(
sorterStates: SortState<RecordType>[],
): SorterResult<RecordType> | SorterResult<RecordType>[] {
sorterStates: readonly SortState<RecordType>[],
): SorterResult<RecordType> | readonly SorterResult<RecordType>[] {
const list = sorterStates.filter(({ sortOrder }) => sortOrder).map(stateToInfo);

// =========== Legacy compatible support ===========
Expand All @@ -244,10 +245,10 @@ function generateSorterInfo<RecordType>(
}

export function getSortData<RecordType>(
data: RecordType[],
sortStates: SortState<RecordType>[],
data: readonly RecordType[],
sortStates: readonly SortState<RecordType>[],
childrenColumnName: string,
): RecordType[] {
): readonly RecordType[] {
const innerSorterStates = sortStates
.slice()
.sort((a, b) => (b.multiplePriority as number) - (a.multiplePriority as number));
Expand Down Expand Up @@ -301,10 +302,10 @@ interface SorterConfig<RecordType> {
prefixCls: string;
mergedColumns: ColumnsType<RecordType>;
onSorterChange: (
sorterResult: SorterResult<RecordType> | SorterResult<RecordType>[],
sorterResult: SorterResult<RecordType> | readonly SorterResult<RecordType>[],
sortStates: SortState<RecordType>[],
) => void;
sortDirections: SortOrder[];
sortDirections: readonly SortOrder[];
tableLocale?: TableLocale;
showSorterTooltip?: boolean;
}
Expand All @@ -318,9 +319,9 @@ export default function useFilterSorter<RecordType>({
showSorterTooltip,
}: SorterConfig<RecordType>): [
TransformColumns<RecordType>,
SortState<RecordType>[],
readonly SortState<RecordType>[],
ColumnTitleProps<RecordType>,
() => SorterResult<RecordType> | SorterResult<RecordType>[],
() => SorterResult<RecordType> | readonly SorterResult<RecordType>[],
] {
const [sortStates, setSortStates] = React.useState<SortState<RecordType>[]>(
collectSortStates(mergedColumns, true),
Expand Down
2 changes: 1 addition & 1 deletion components/table/hooks/useTitleColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function fillTitle<RecordType>(

export default function useTitleColumns<RecordType>(
columnTitleProps: ColumnTitleProps<RecordType>,
): [TransformColumns<RecordType>] {
): readonly [TransformColumns<RecordType>] {
const filledColumns = React.useCallback(
(columns: ColumnsType<RecordType>) => fillTitle(columns, columnTitleProps),
[columnTitleProps],
Expand Down

0 comments on commit 52418d0

Please sign in to comment.