Skip to content

Commit

Permalink
Refactor table api and type (#223)
Browse files Browse the repository at this point in the history
  • Loading branch information
yazhouio authored May 27, 2024
1 parent caa0a23 commit 4259783
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 197 deletions.
5 changes: 5 additions & 0 deletions .changeset/real-carpets-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@kubed/components': patch
---

Refactor table api and type
31 changes: 9 additions & 22 deletions docs/docs/en/components/Table.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,12 @@ Customize column configuration by setting `column.meta`
```ts
interface ColumnMeta<TData extends RowData, TValue = unknown> {
description?: Record<string, any>; // icon ? tooltip props
filterOptions?: { key: string; label: React.ReactNode }[]; // filter options
// filterOptions?: { key: string; label: React.ReactNode }[]; // filter options
selectType?: 'single' | 'multiple'; // multiple selection type
sortable?: boolean; // whether it can be sorted
searchKey?: string; // custom search key
th?: Partial<BaseTable.TableCellProps>; // baseTable th props, priority is higher than getProps.th
td?: Partial<BaseTable.TableCellProps>; //baseTable td props, priority is higher than getProps.td
}
```

Expand Down Expand Up @@ -401,16 +403,6 @@ export const App = () => {
footer: (props) => props.column.id,
meta: {
sortable: true,
filterOptions: [
{
key: '0',
label: '0',
},
{
key: '1',
label: '1',
},
],
},
},
{
Expand All @@ -427,16 +419,6 @@ export const App = () => {
footer: (props) => props.column.id,
meta: {
searchKey: 'status1',
filterOptions: [
{
key: 'status-0',
label: 'status-0',
},
{
key: 'status-1',
label: 'status-1',
},
],
},
},
{
Expand Down Expand Up @@ -611,7 +593,12 @@ export const App = () => {
},
});
return <Table table={table} />;
return (
<>
<Table table={table} />
<pre>{JSON.stringify(state, null, 2)}</pre>
</>
);
};
```

Expand Down
31 changes: 9 additions & 22 deletions docs/docs/zh/components/Table.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,12 @@ interface StateHandler {
```ts
interface ColumnMeta<TData extends RowData, TValue = unknown> {
description?: Record<string, any>; // icon ? tooltip props
filterOptions?: { key: string; label: React.ReactNode }[]; // 过滤选项
// filterOptions?: { key: string; label: React.ReactNode }[]; // 过滤选项
selectType?: 'single' | 'multiple'; // 多选类型
sortable?: boolean; // 是否可排序
searchKey?: string; // 自定义搜索 key
th?: Partial<BaseTable.TableCellProps>; // baseTable th props,优先级高于 getProps.th
td?: Partial<BaseTable.TableCellProps>; //baseTable td props,优先级高于 getProps.td
}
```

Expand Down Expand Up @@ -400,16 +402,6 @@ export const App = () => {
footer: (props) => props.column.id,
meta: {
sortable: true,
filterOptions: [
{
key: '0',
label: '0',
},
{
key: '1',
label: '1',
},
],
},
},
{
Expand All @@ -426,16 +418,6 @@ export const App = () => {
footer: (props) => props.column.id,
meta: {
searchKey: 'status1',
filterOptions: [
{
key: 'status-0',
label: 'status-0',
},
{
key: 'status-1',
label: 'status-1',
},
],
},
},
{
Expand Down Expand Up @@ -610,7 +592,12 @@ export const App = () => {
},
});

return <Table table={table} />;
return (
<>
<Table table={table} />
<pre>{JSON.stringify(state, null, 2)}</pre>
</>
);
};
```

Expand Down
3 changes: 2 additions & 1 deletion packages/components/src/Table/DataTable/BaseTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import styled from 'styled-components';
import { LoadingOverlay } from '../../LoadingOverlay/LoadingOverlay';
import * as BaseTable from '../BaseTable';
import TableHead from './TableHead';
import { TableHead } from './TableHead';
import { getDefaultTrProps } from './utils';

interface BaseDataTableProps<T> {
Expand Down Expand Up @@ -57,6 +57,7 @@ export function BaseDataTable<T>({ table }: BaseDataTableProps<T>) {
<BaseTable.TableCell
key={cell.id}
{...(getTdProps && getTdProps(table, cell.getContext()))}
{...(cell.column.columnDef.meta?.td ?? {})}
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</BaseTable.TableCell>
Expand Down
71 changes: 18 additions & 53 deletions packages/components/src/Table/DataTable/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,35 @@
import * as React from 'react';
import type { Header, Row, RowData, Table, TableState } from '@tanstack/react-table';
import cx from 'classnames';
import type {
Table,
RowData,
Header,
TableState,
Row,
TableOptions as TableOptionsBase,
TableOptionsResolved,
} from '@tanstack/react-table';
import { Pagination } from './Pagination';
import * as React from 'react';
import * as BaseTable from '../BaseTable';
import { Toolbar } from './Toolbar';
import { BaseDataTable } from './BaseTable';

export interface TableEnableConfig {
enableToolbar?: boolean;
enablePagination?: boolean;
enableVisible?: boolean;
enableFilters?: boolean;
enableParamsToUrl?: boolean;
enableStateToStorage?: boolean;
enableSelection?: boolean;
enableSort?: boolean;
enableMultiSelection?: boolean;
enableInitParamsByUrl?: boolean;
}

export interface StorageStateOptions {
storage2State?: (storageKey: string) => Partial<TableState>;
state2Storage?: (storageKey: string, state: Partial<TableState>) => void;
}
export interface StateHandler {
handlerName?: string;
stateKeys: (keyof TableState)[] | '*';
callback?: (state: Partial<TableState>) => void;
}

export interface FeaturesHandlersOPtions {
_featuresHandlers?: StateHandler[];
_featuresInitState?: Partial<TableState>;
}

export interface DefaultOptionsResolved<TData> {
getDefaultOptionsResolved?: (options: TableOptionsResolved<TData>) => TableOptionsResolved<TData>;
}
import { Pagination } from './Pagination';
import { Toolbar } from './Toolbar';
import {
DataTableRootProps,
DefaultOptionsResolved,
FeaturesHandlersOptions,
StateHandler,
StorageStateOptions,
} from './interfaces';

declare module '@tanstack/react-table' {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface TableOptionsResolved<TData extends RowData>
extends StorageStateOptions,
FeaturesHandlersOPtions {
FeaturesHandlersOptions {
loading?: boolean;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface ColumnMeta<TData extends RowData, TValue = unknown> {
description?: Record<string, any>;
filterOptions?: { key: string; label: React.ReactNode }[];
// filterOptions?: { key: string; label: React.ReactNode }[];
selectType?: 'single' | 'multiple';
sortable?: boolean;
searchKey?: string;
th?: Omit<BaseTable.TableCellProps, 'ref'>;
td?: Omit<BaseTable.TableCellProps, 'ref'>;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
Expand All @@ -74,6 +43,9 @@ declare module '@tanstack/react-table' {
tableName: string;
refetch?: () => void;
storageStateKeys?: (keyof TableState)[] | '*';
_defaultConfig?: {
selectColumnId?: string;
};
manual?: boolean;
enable?: {
pagination?: boolean;
Expand Down Expand Up @@ -112,13 +84,6 @@ declare module '@tanstack/react-table' {
}
}

export interface TableInstance<T> extends Table<T> {}
export interface TableOptions<T> extends TableOptionsBase<T> {}
export interface DataTableRootProps<T> {
className?: string;
table: TableInstance<T>;
}

export function DataTable<T>({ className, table }: DataTableRootProps<T>) {
const { options: { meta: { enable: { pagination, toolbar } = {} } = {} } = {} } = table;
return (
Expand Down
68 changes: 44 additions & 24 deletions packages/components/src/Table/DataTable/TableHead.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,8 @@ import { BaseTable, Dropdown, Menu, MenuItem, MenuLabel, Popover } from '../../i
import { getDefaultThProps } from './utils';
import { useLocales } from '../../ConfigProvider/LocaleProvider/LocaleContext';

const TWrapper = styled.div`
display: inline-flex;
align-items: center;
gap: 4px;
const TWrapper = styled.div<{ center?: boolean }>`
${({ center }) => center && 'display: flex; align-items: center; justify-content: center;'}
.sort-indicator {
color: #79879c;
Expand Down Expand Up @@ -41,18 +39,21 @@ const DropdownWrapper = styled.span`
justify-content: center;
`;

export interface TableHeadProps<TData extends RowData> {
interface TableHeadProps<TData extends RowData> {
header: Header<TData, unknown>;
table: Table<TData>;
}

function TableHead<T>({ header, table }: PropsWithChildren<TableHeadProps<T>>) {
export type { TableHeadProps };

export function TableHead<T>({ header, table }: PropsWithChildren<TableHeadProps<T>>) {
const {
description,
// filterOptions = [],
searchKey: _searchKey,
selectType,
sortable: _sortable,
th = {},
} = header.column.columnDef.meta ?? {};

const { locales } = useLocales();
Expand All @@ -70,6 +71,17 @@ function TableHead<T>({ header, table }: PropsWithChildren<TableHeadProps<T>>) {

const searchKey = manualFiltering ? _searchKey ?? id : id;

const isCheckbox = selectType
? selectType === 'multiple'
: table.options.enableMultiRowSelection &&
id === table.options.meta._defaultConfig?.selectColumnId;

const isRadio = selectType
? selectType === 'single'
: table.options.enableRowSelection &&
!table.options.enableMultiRowSelection &&
id === table.options.meta._defaultConfig?.selectColumnId;

const suggestions = getFiltersProps?.(table)?.suggestions ?? [];
const filterOptions =
suggestions.find((suggestion) => suggestion.key === searchKey)?.options ?? [];
Expand Down Expand Up @@ -106,7 +118,20 @@ function TableHead<T>({ header, table }: PropsWithChildren<TableHeadProps<T>>) {
};

const handleFilter = (value: any) => {
header.column.setFilterValue(value);
if (searchKey === id) {
header.column.setFilterValue(value);
} else {
table.setColumnFilters((rows) => {
const index = rows.findIndex((row) => row.id === searchKey);
return [
...rows.slice(index, 1),
{
id: searchKey,
value,
},
];
});
}
};

const renderDropdown = () => {
Expand Down Expand Up @@ -162,7 +187,7 @@ function TableHead<T>({ header, table }: PropsWithChildren<TableHeadProps<T>>) {
);
}

if (header.column.id === '_selector' && selectType === 'single') return null;
if (isRadio) return null;
return flexRender(header.column.columnDef.header, header.getContext());
};

Expand All @@ -171,23 +196,18 @@ function TableHead<T>({ header, table }: PropsWithChildren<TableHeadProps<T>>) {
colSpan={header.colSpan}
{...(enableTh && getDefaultThProps(table))}
{...(getThProps && getThProps(table, header))}
{...th}
>
<div>
{header.isPlaceholder ? null : (
<>
<TWrapper>
{renderDropdown()}
{description && (
<Popover {...(description as Record<string, any>)}>
<Information />
</Popover>
)}
</TWrapper>
</>
)}
</div>
{header.isPlaceholder ? null : (
<TWrapper center={isCheckbox}>
{renderDropdown()}
{description && (
<Popover {...(description as Record<string, any>)}>
<Information />
</Popover>
)}
</TWrapper>
)}
</BaseTable.TableCell>
);
}

export default TableHead;
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
import {
ColumnFiltersState,
TableFeature,
TableOptionsResolved,
Updater,
functionalUpdate,
getFilteredRowModel,
shouldAutoRemoveFilter,
} from '@tanstack/react-table';
import { TableOptionsResolved, getFilteredRowModel } from '@tanstack/react-table';

import { TableFeature } from '../interfaces';

const getFilterOptions = <TData>(options: TableOptionsResolved<TData>) => {
const {
Expand Down
1 change: 1 addition & 0 deletions packages/components/src/Table/DataTable/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ export * from './hooks';
export * from './features/index';
export * from './TableHead';
export * from './utils';
export * from './interfaces';
Loading

0 comments on commit 4259783

Please sign in to comment.