Skip to content

Commit

Permalink
feat: add table component (#356)
Browse files Browse the repository at this point in the history
* feat: add table component

* fix: fix code review on table

* fix: fix ts lint

---------

Co-authored-by: jialan <jialan@dtstack.com>
  • Loading branch information
JackWang032 and jialan committed Jun 20, 2023
1 parent be7aacb commit 0553e28
Show file tree
Hide file tree
Showing 6 changed files with 224 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export { default as Resize } from './resize';
export { default as SlidePane } from './slidePane';
export { default as SpreadSheet } from './spreadSheet';
export { default as StatusTag } from './statusTag';
export { default as Table } from './table';
export { default as useWindowSwitchListener } from './switchWindow';
export { default as useCookieListener } from './cookies';
export { default as useList } from './useList';
40 changes: 40 additions & 0 deletions src/table/__tests__/table.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import Table from '../index';
import { fireEvent, render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { act } from 'react-dom/test-utils';

const columns = [
{
dataIndex: 'name',
title: 'Name',
tooltip: { title: 'This is Name!', mouseEnterDelay: 0, mouseLeaveDelay: 0 },
},
{ dataIndex: 'address', title: 'Address' },
];

const dataSource = [
{ id: 1, name: 'ZhangSan', age: 17, address: 'New York No. 1 Lake Park' },
{ id: 2, name: 'LiSi', age: 17, address: 'Bei Jing No. 1 Lake Park' },
{ id: 3, name: 'WangWu', age: 17, address: 'Zhe Jiang No. 1 Lake Park' },
];

describe('test Table', () => {
test('should support tooltip column attribute', async () => {
jest.useFakeTimers();
const { container } = render(
<Table rowKey="id" columns={columns} dataSource={dataSource} />
);
const iconNode = container.querySelector('.dtc-table__tooltip');
expect(iconNode).toBeInTheDocument();

act(() => {
fireEvent.mouseEnter(iconNode!);
jest.runAllTimers();
});

expect(
container.parentElement?.querySelector('.ant-tooltip:not(.ant-tooltip-hidden)')
).toBeInTheDocument();
});
});
30 changes: 30 additions & 0 deletions src/table/demos/basic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import { Table } from 'dt-react-component';
import { ColumnType } from '..';

interface DataType {
id: number;
name: string;
age: number;
address: string;
}

const columns: ColumnType<DataType>[] = [
{ dataIndex: 'name', title: 'Name', tooltip: 'This is Name!' },
{
dataIndex: 'age',
title: 'Age',
tooltip: { icon: <span></span>, title: 'This is Age!', color: 'pink' },
},
{ dataIndex: 'address', title: 'Address' },
];

const dataSource = [
{ id: 1, name: 'ZhangSan', age: 17, address: 'New York No. 1 Lake Park' },
{ id: 2, name: 'LiSi', age: 17, address: 'Bei Jing No. 1 Lake Park' },
{ id: 3, name: 'WangWu', age: 17, address: 'Zhe Jiang No. 1 Lake Park' },
];

export default () => {
return <Table rowKey="id" columns={columns} dataSource={dataSource} />;
};
30 changes: 30 additions & 0 deletions src/table/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
title: Table 表格
group: 组件
toc: content
demo:
cols: 1
---

# Table 表格

## 何时使用

继承并完全兼容`antd``Table`,可以直接替换,并扩充了其他功能

## 示例

<code src="./demos/basic.tsx" description="为标题头添加tooltip">基础使用</code>

## API

### Table

完全继承自`antd``Table`组件,参考[Table](https://4x.ant.design/components/table-cn/#API)

### ColumnType

除继承自`Table`组件的 ColumnType 外,还额外扩充以下属性
| 参数 | 说明 | 类型 | 默认值 |
| ----------- | ---------------------------------------- | ----------------- | ------ |
| tooltip | 配置表格 title 提示信息 | `React.ReactNode` \| <a href="https://4x.ant.design/components/tooltip-cn/#API" target="_blank">TooltipProps & { icon: React.ReactNode }</a> | - |
8 changes: 8 additions & 0 deletions src/table/index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.dtc-table {
&__tooltip {
margin-left: 4px;
font-size: 16px;
color: #B1B4C5;
cursor: help;
}
}
115 changes: 115 additions & 0 deletions src/table/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React, { forwardRef, useMemo } from 'react';
import { Table as InternalTable, Tooltip } from 'antd';
import type { LabelTooltipType, WrapperTooltipProps } from 'antd/lib/form/FormItemLabel';
import type { ColumnType as PrimitiveColumnType, TableProps } from 'antd/lib/table';
import { QuestionCircleOutlined } from '@ant-design/icons';
import classNames from 'classnames';
import './index.scss';

const {
SELECTION_COLUMN,
EXPAND_COLUMN,
SELECTION_ALL,
SELECTION_INVERT,
SELECTION_NONE,
Column,
ColumnGroup,
} = InternalTable;

export interface ColumnType<R = any> extends PrimitiveColumnType<R> {
tooltip?: LabelTooltipType;
}

export interface ITableProps<R = any> extends TableProps<R> {
columns?: ColumnType<R>[];
}

export type RefTable = <R extends object = any>(
props: React.PropsWithChildren<TableProps<R>> & { ref?: React.Ref<HTMLDivElement | unknown> }
) => React.ReactElement;

function toTooltipProps(tooltip: LabelTooltipType): WrapperTooltipProps | null {
if (!tooltip) {
return null;
}

if (typeof tooltip === 'object' && !React.isValidElement(tooltip)) {
return tooltip as WrapperTooltipProps;
}

return {
title: tooltip,
};
}

function convertColumns(columns?: ColumnType[]): PrimitiveColumnType<any>[] {
if (!columns?.length) return [];
return columns.map((col) => {
const { tooltip, title } = col;

const tooltipProps = toTooltipProps(tooltip);
let tooltipNode: React.ReactNode | null = null;
if (tooltipProps) {
const { icon = <QuestionCircleOutlined />, ...restTooltipProps } = tooltipProps;
tooltipNode = (
<Tooltip {...restTooltipProps}>
{React.cloneElement(icon, {
className: `dtc-table__tooltip ${icon.props?.className || ''}`,
})}
</Tooltip>
);
}

const titleNode = (
<>
{title}
{tooltipNode}
</>
);

return {
...col,
title: titleNode,
};
});
}

function Table<R extends Record<any, any> = any>(
props: ITableProps<R>,
ref: React.Ref<HTMLDivElement>
) {
const { columns, className, ...reset } = props;
const cols = useMemo(() => convertColumns(columns), [columns]);

return (
<InternalTable<R>
{...reset}
className={classNames(['dtc-table', className])}
columns={cols}
ref={ref}
/>
);
}

const ForwardTable = forwardRef(Table) as unknown as RefTable & {
SELECTION_COLUMN: typeof SELECTION_COLUMN;
EXPAND_COLUMN: typeof EXPAND_COLUMN;
SELECTION_ALL: typeof SELECTION_ALL;
SELECTION_INVERT: typeof SELECTION_INVERT;
SELECTION_NONE: typeof SELECTION_NONE;
Column: typeof Column;
ColumnGroup: typeof ColumnGroup;
// use InternalTable.Summary because of typescript bug(TS2742)
Summary: typeof InternalTable.Summary;
};

ForwardTable.SELECTION_COLUMN = SELECTION_COLUMN;
ForwardTable.EXPAND_COLUMN = EXPAND_COLUMN;
ForwardTable.SELECTION_ALL = SELECTION_ALL;
ForwardTable.SELECTION_INVERT = SELECTION_INVERT;
ForwardTable.SELECTION_NONE = SELECTION_NONE;
ForwardTable.Column = Column;
ForwardTable.ColumnGroup = ColumnGroup;
ForwardTable.Summary = InternalTable.Summary;

export default ForwardTable;

0 comments on commit 0553e28

Please sign in to comment.