From 46db6f476ab475396b005ffcd63be45de2d64b47 Mon Sep 17 00:00:00 2001 From: zombiej Date: Sat, 25 Apr 2020 22:25:41 +0800 Subject: [PATCH 1/6] support data type --- src/Body/BodyRow.tsx | 8 ++++--- src/Footer/index.tsx | 51 ++++++++++++++++++++++++++++++++++++++++---- src/Table.tsx | 4 +++- src/interface.ts | 4 ++++ 4 files changed, 59 insertions(+), 8 deletions(-) diff --git a/src/Body/BodyRow.tsx b/src/Body/BodyRow.tsx index ba2b3615b..4c642228d 100644 --- a/src/Body/BodyRow.tsx +++ b/src/Body/BodyRow.tsx @@ -43,6 +43,7 @@ function BodyRow(props: BodyRowP rowKey, getRowKey, rowExpandable, + expandedKeys, onRow, indent = 0, rowComponent: RowComponent, @@ -68,7 +69,7 @@ function BodyRow(props: BodyRowP } = React.useContext(BodyContext); const [expandRended, setExpandRended] = React.useState(false); - const expanded = props.expandedKeys.has(props.recordKey); + const expanded = expandedKeys && expandedKeys.has(props.recordKey); React.useEffect(() => { if (expanded) { @@ -76,7 +77,7 @@ function BodyRow(props: BodyRowP } }, [expanded]); - // Move to Body to enhance performance + // TODO: Move to Body to enhance performance const fixedInfoList = flattenColumns.map((column, colIndex) => getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction), ); @@ -84,7 +85,8 @@ function BodyRow(props: BodyRowP const rowSupportExpand = expandableType === 'row' && (!rowExpandable || rowExpandable(record)); // Only when row is not expandable and `children` exist in record const nestExpandable = expandableType === 'nest'; - const hasNestChildren = childrenColumnName in record && record[childrenColumnName]; + const hasNestChildren = + childrenColumnName && childrenColumnName in record && record[childrenColumnName]; const mergedExpandable = rowSupportExpand || nestExpandable; // =========================== onRow =========================== diff --git a/src/Footer/index.tsx b/src/Footer/index.tsx index 22a9b6451..595f35934 100644 --- a/src/Footer/index.tsx +++ b/src/Footer/index.tsx @@ -1,11 +1,54 @@ import * as React from 'react'; +import { SummaryFooter, SummaryFooterArray, StickyOffsets } from '../interface'; +import Cell from '../Cell'; +import BodyContext from '../context/BodyContext'; +import TableContext from '../context/TableContext'; +import { getCellFixedInfo } from '../utils/fixUtil'; -export interface FooterProps { - children: React.ReactNode; +export interface FooterProps { + stickyOffsets: StickyOffsets; + children: SummaryFooter; } -function Footer({ children }: FooterProps) { - return {children}; +function Footer({ stickyOffsets, children }: FooterProps) { + let footer: React.ReactNode; + + const { flattenColumns } = React.useContext(BodyContext); + const { direction } = React.useContext(TableContext); + + if (React.isValidElement(children)) { + footer = children; + } else if (Array.isArray(children)) { + // Move to Body to enhance performance + const fixedInfoList = flattenColumns.map((column, colIndex) => + getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction), + ); + + footer = (children as SummaryFooterArray).map((row, index) => { + return ( + + {row.map((cell, cellIndex) => { + const fixedInfo = fixedInfoList[cellIndex]; + + return ( + cell} + {...fixedInfo} + /> + ); + })} + + ); + }); + } + + return {footer}; } export default Footer; diff --git a/src/Table.tsx b/src/Table.tsx index e59c267eb..128f42aca 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -517,7 +517,9 @@ function Table(props: TableProps width)} columns={flattenColumns} /> ); - const footerTable = summary &&
{summary(mergedData)}
; + const footerTable = summary && ( +
{summary(mergedData)}
+ ); const customizeScrollBody = getComponent(['body']) as CustomizeScrollBody; if ( diff --git a/src/interface.ts b/src/interface.ts index 7d6b31277..3d16e6cd8 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -32,6 +32,10 @@ export type RowClassName = ( indent: number, ) => string; +export type SummaryFooterArray = CellType[][]; + +export type SummaryFooter = React.ReactNode | SummaryFooterArray; + // =================== Column =================== export interface CellType { key?: Key; From 4c7ebdb9831800bf32b9651ced389f7e72c5a1fd Mon Sep 17 00:00:00 2001 From: zombiej Date: Sat, 25 Apr 2020 22:38:44 +0800 Subject: [PATCH 2/6] update test case --- src/Footer/index.tsx | 3 +- tests/Table.spec.js | 46 ++++++++++++++++++++------ tests/__snapshots__/Table.spec.js.snap | 19 +++++++++++ 3 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/Footer/index.tsx b/src/Footer/index.tsx index 595f35934..66aed662c 100644 --- a/src/Footer/index.tsx +++ b/src/Footer/index.tsx @@ -14,7 +14,7 @@ function Footer({ stickyOffsets, children }: FooterProps let footer: React.ReactNode; const { flattenColumns } = React.useContext(BodyContext); - const { direction } = React.useContext(TableContext); + const { prefixCls, direction } = React.useContext(TableContext); if (React.isValidElement(children)) { footer = children; @@ -34,6 +34,7 @@ function Footer({ stickyOffsets, children }: FooterProps { ).toEqual('footer'); }); - it('render summary correctly', () => { - const wrapper = mount( - createTable({ - summary: () => ( - - Good - - ), - }), - ); + describe('summary', () => { + it('render correctly', () => { + const wrapper = mount( + createTable({ + summary: () => ( + + Good + + ), + }), + ); + + expect(wrapper.find('tfoot').text()).toEqual('Good'); + }); - expect(wrapper.find('tfoot').text()).toEqual('Good'); + it('support data type', () => { + const wrapper = mount( + [ + [ + { children: 'Light', props: { colSpan: 2 } }, + { children: 'Hidden', props: { colSpan: 0 } }, + { children: 'Bamboo' }, + ], + ]} + />, + ); + + expect(wrapper.find('tfoot').render()).toMatchSnapshot(); + }); }); it('renders with id correctly', () => { diff --git a/tests/__snapshots__/Table.spec.js.snap b/tests/__snapshots__/Table.spec.js.snap index 34bcaa619..69eb7b716 100644 --- a/tests/__snapshots__/Table.spec.js.snap +++ b/tests/__snapshots__/Table.spec.js.snap @@ -663,6 +663,25 @@ exports[`Table.Basic renders rowSpan correctly 1`] = ` `; +exports[`Table.Basic summary support data type 1`] = ` + + + + + + +`; + exports[`Table.Basic syntactic sugar 1`] = `
Date: Sun, 26 Apr 2020 10:21:40 +0800 Subject: [PATCH 3/6] use jsx --- assets/index.less | 6 +++++ examples/fixedColumns.tsx | 14 ++++++++++ src/Body/BodyRow.tsx | 19 ++------------ src/Footer/Cell.tsx | 42 ++++++++++++++++++++++++++++++ src/Footer/index.tsx | 50 +++--------------------------------- src/Table.tsx | 13 +++++++--- src/context/TableContext.tsx | 4 +++ src/index.ts | 3 ++- src/interface.ts | 4 --- tests/Table.spec.js | 15 ++++++----- 10 files changed, 91 insertions(+), 79 deletions(-) create mode 100644 src/Footer/Cell.tsx diff --git a/assets/index.less b/assets/index.less index 3115f72a3..510ec4f1a 100644 --- a/assets/index.less +++ b/assets/index.less @@ -281,4 +281,10 @@ border-top: 0; padding: @cell-padding; } + + tfoot { + td { + background: #fff; + } + } } diff --git a/examples/fixedColumns.tsx b/examples/fixedColumns.tsx index 88f86989c..4b8340e7e 100644 --- a/examples/fixedColumns.tsx +++ b/examples/fixedColumns.tsx @@ -63,6 +63,20 @@ const Demo = () => ( expandedRowRender={({ b, c }) => b || c} scroll={{ x: 1200 }} data={data} + summary={() => ( + <> +
+ + + Summary + + + Content + + Right + + + )} /> ); diff --git a/src/Body/BodyRow.tsx b/src/Body/BodyRow.tsx index 4c642228d..412172393 100644 --- a/src/Body/BodyRow.tsx +++ b/src/Body/BodyRow.tsx @@ -4,15 +4,7 @@ import Cell from '../Cell'; import TableContext from '../context/TableContext'; import BodyContext from '../context/BodyContext'; import { getColumnsKey } from '../utils/valueUtil'; -import { - ColumnType, - StickyOffsets, - CustomizeComponent, - GetComponentProps, - Key, - GetRowKey, -} from '../interface'; -import { getCellFixedInfo } from '../utils/fixUtil'; +import { ColumnType, CustomizeComponent, GetComponentProps, Key, GetRowKey } from '../interface'; import ExpandedRow from './ExpandedRow'; export interface BodyRowProps { @@ -20,7 +12,6 @@ export interface BodyRowProps { index: number; className?: string; style?: React.CSSProperties; - stickyOffsets: StickyOffsets; recordKey: Key; expandedKeys: Set; rowComponent: CustomizeComponent; @@ -37,7 +28,6 @@ function BodyRow(props: BodyRowP const { className, style, - stickyOffsets, record, index, rowKey, @@ -50,7 +40,7 @@ function BodyRow(props: BodyRowP cellComponent, childrenColumnName, } = props; - const { prefixCls, direction } = React.useContext(TableContext); + const { prefixCls, fixedInfoList } = React.useContext(TableContext); const { fixHeader, fixColumn, @@ -77,11 +67,6 @@ function BodyRow(props: BodyRowP } }, [expanded]); - // TODO: Move to Body to enhance performance - const fixedInfoList = flattenColumns.map((column, colIndex) => - getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction), - ); - const rowSupportExpand = expandableType === 'row' && (!rowExpandable || rowExpandable(record)); // Only when row is not expandable and `children` exist in record const nestExpandable = expandableType === 'nest'; diff --git a/src/Footer/Cell.tsx b/src/Footer/Cell.tsx new file mode 100644 index 000000000..f85dd55e6 --- /dev/null +++ b/src/Footer/Cell.tsx @@ -0,0 +1,42 @@ +import * as React from 'react'; +import Cell from '../Cell'; +import TableContext from '../context/TableContext'; + +export interface SummaryCellProps { + className?: string; + children?: React.ReactNode; + index: number; + colSpan?: number; + rowSpan?: number; +} + +export default function SummaryCell({ + className, + index, + children, + colSpan, + rowSpan, +}: SummaryCellProps) { + const { prefixCls, fixedInfoList } = React.useContext(TableContext); + + const fixedInfo = fixedInfoList[index]; + + return ( + ({ + children, + props: { + colSpan, + rowSpan, + }, + })} + {...fixedInfo} + /> + ); +} diff --git a/src/Footer/index.tsx b/src/Footer/index.tsx index 66aed662c..15dba4a4d 100644 --- a/src/Footer/index.tsx +++ b/src/Footer/index.tsx @@ -1,55 +1,13 @@ import * as React from 'react'; -import { SummaryFooter, SummaryFooterArray, StickyOffsets } from '../interface'; -import Cell from '../Cell'; -import BodyContext from '../context/BodyContext'; import TableContext from '../context/TableContext'; -import { getCellFixedInfo } from '../utils/fixUtil'; export interface FooterProps { - stickyOffsets: StickyOffsets; - children: SummaryFooter; + children: React.ReactNode; } -function Footer({ stickyOffsets, children }: FooterProps) { - let footer: React.ReactNode; - - const { flattenColumns } = React.useContext(BodyContext); - const { prefixCls, direction } = React.useContext(TableContext); - - if (React.isValidElement(children)) { - footer = children; - } else if (Array.isArray(children)) { - // Move to Body to enhance performance - const fixedInfoList = flattenColumns.map((column, colIndex) => - getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction), - ); - - footer = (children as SummaryFooterArray).map((row, index) => { - return ( - - {row.map((cell, cellIndex) => { - const fixedInfo = fixedInfoList[cellIndex]; - - return ( - cell} - {...fixedInfo} - /> - ); - })} - - ); - }); - } - - return {footer}; +function Footer({ children }: FooterProps) { + const { prefixCls } = React.useContext(TableContext); + return {children}; } export default Footer; diff --git a/src/Table.tsx b/src/Table.tsx index 128f42aca..c90409af3 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -32,6 +32,7 @@ import ResizeObserver from 'rc-resize-observer'; import getScrollBarSize from 'rc-util/lib/getScrollBarSize'; import ColumnGroup from './sugar/ColumnGroup'; import Column from './sugar/Column'; +import SummaryCell from './Footer/Cell'; import FixedHeader from './Header/FixedHeader'; import Header from './Header/Header'; import { @@ -66,6 +67,7 @@ import { getExpandableProps, getDataAndAriaProps } from './utils/legacyUtil'; import Panel from './Panel'; import Footer from './Footer'; import { findAllChildrenKeys, renderExpandIcon } from './utils/expandUtil'; +import { getCellFixedInfo } from './utils/fixUtil'; // Used for conditions cache const EMPTY_DATA = []; @@ -517,9 +519,7 @@ function Table(props: TableProps width)} columns={flattenColumns} /> ); - const footerTable = summary && ( -
{summary(mergedData)}
- ); + const footerTable = summary &&
{summary(mergedData)}
; const customizeScrollBody = getComponent(['body']) as CustomizeScrollBody; if ( @@ -663,8 +663,11 @@ function Table(props: TableProps + getCellFixedInfo(colIndex, colIndex, flattenColumns, stickyOffsets, direction), + ), }), - [prefixCls, getComponent, scrollbarSize, direction], + [prefixCls, getComponent, scrollbarSize, direction, flattenColumns, stickyOffsets, direction], ); const BodyContextValue = React.useMemo( @@ -719,6 +722,8 @@ Table.Column = Column; Table.ColumnGroup = ColumnGroup; +Table.SummaryCell = SummaryCell; + Table.defaultProps = { rowKey: 'key', prefixCls: 'rc-table', diff --git a/src/context/TableContext.tsx b/src/context/TableContext.tsx index e089f4e98..cf9a9ee7a 100644 --- a/src/context/TableContext.tsx +++ b/src/context/TableContext.tsx @@ -1,14 +1,18 @@ import * as React from 'react'; import { GetComponent } from '../interface'; +import { FixedInfo } from '../utils/fixUtil'; export interface TableContextProps { // Table context prefixCls: string; + getComponent: GetComponent; scrollbarSize: number; direction: 'ltr' | 'rtl'; + + fixedInfoList: FixedInfo[]; } const TableContext = React.createContext(null); diff --git a/src/index.ts b/src/index.ts index 5a87a23e8..444cac9ab 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,8 +1,9 @@ import Table from './Table'; +import SummaryCell from './Footer/Cell'; import Column from './sugar/Column'; import ColumnGroup from './sugar/ColumnGroup'; import { INTERNAL_COL_DEFINE } from './utils/legacyUtil'; -export { Column, ColumnGroup, INTERNAL_COL_DEFINE }; +export { SummaryCell, Column, ColumnGroup, INTERNAL_COL_DEFINE }; export default Table; diff --git a/src/interface.ts b/src/interface.ts index 3d16e6cd8..7d6b31277 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -32,10 +32,6 @@ export type RowClassName = ( indent: number, ) => string; -export type SummaryFooterArray = CellType[][]; - -export type SummaryFooter = React.ReactNode | SummaryFooterArray; - // =================== Column =================== export interface CellType { key?: Key; diff --git a/tests/Table.spec.js b/tests/Table.spec.js index d7a68de4b..62c671511 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -168,13 +168,14 @@ describe('Table.Basic', () => { { dataIndex: 'c', width: 30 }, ]} data={[{ key: 1, a: 2, b: 3, c: 4 }]} - summary={() => [ - [ - { children: 'Light', props: { colSpan: 2 } }, - { children: 'Hidden', props: { colSpan: 0 } }, - { children: 'Bamboo' }, - ], - ]} + summary={() => ( +
+ + Light + + Bamboo + + )} />, ); From a9e3a56603d8c22229a2514aff9bfe33a240d441 Mon Sep 17 00:00:00 2001 From: zombiej Date: Sun, 26 Apr 2020 10:22:47 +0800 Subject: [PATCH 4/6] clean up props --- src/Body/index.tsx | 6 +----- src/Table.tsx | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Body/index.tsx b/src/Body/index.tsx index 96cf62994..140b438c9 100644 --- a/src/Body/index.tsx +++ b/src/Body/index.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import ResizeObserver from 'rc-resize-observer'; import BodyRow from './BodyRow'; import TableContext from '../context/TableContext'; -import { GetRowKey, StickyOffsets, Key, GetComponentProps } from '../interface'; +import { GetRowKey, Key, GetComponentProps } from '../interface'; import ExpandedRow from './ExpandedRow'; import BodyContext from '../context/BodyContext'; import { getColumnsKey } from '../utils/valueUtil'; @@ -12,7 +12,6 @@ export interface BodyProps { data: RecordType[]; getRowKey: GetRowKey; measureColumnWidth: boolean; - stickyOffsets: StickyOffsets; expandedKeys: Set; onRow: GetComponentProps; rowExpandable: (record: RecordType) => boolean; @@ -24,7 +23,6 @@ function Body({ data, getRowKey, measureColumnWidth, - stickyOffsets, expandedKeys, onRow, rowExpandable, @@ -56,7 +54,6 @@ function Body({ index={index} rowComponent={trComponent} cellComponent={tdComponent} - stickyOffsets={stickyOffsets} expandedKeys={expandedKeys} onRow={onRow} getRowKey={getRowKey} @@ -112,7 +109,6 @@ function Body({ prefixCls, onRow, measureColumnWidth, - stickyOffsets, expandedKeys, getRowKey, getComponent, diff --git a/src/Table.tsx b/src/Table.tsx index c90409af3..7c68e61c8 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -505,7 +505,6 @@ function Table(props: TableProps Date: Sun, 26 Apr 2020 10:26:48 +0800 Subject: [PATCH 5/6] patch summary className --- tests/__snapshots__/Table.spec.js.snap | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/__snapshots__/Table.spec.js.snap b/tests/__snapshots__/Table.spec.js.snap index 69eb7b716..a1e6c12d7 100644 --- a/tests/__snapshots__/Table.spec.js.snap +++ b/tests/__snapshots__/Table.spec.js.snap @@ -664,7 +664,9 @@ exports[`Table.Basic renders rowSpan correctly 1`] = ` `; exports[`Table.Basic summary support data type 1`] = ` - + - - + + + Summary - - + + Content - - Right - + + Right + )} /> diff --git a/src/Footer/Row.tsx b/src/Footer/Row.tsx new file mode 100644 index 000000000..e86a8b46e --- /dev/null +++ b/src/Footer/Row.tsx @@ -0,0 +1,11 @@ +import * as React from 'react'; + +export interface FooterRowProps { + children?: React.ReactNode; + className?: string; + style?: React.CSSProperties; +} + +export default function FooterRow(props: FooterRowProps) { + return ; +} diff --git a/src/Footer/index.tsx b/src/Footer/index.tsx index 15dba4a4d..732ae5a0c 100644 --- a/src/Footer/index.tsx +++ b/src/Footer/index.tsx @@ -1,5 +1,7 @@ import * as React from 'react'; import TableContext from '../context/TableContext'; +import Cell from './Cell'; +import Row from './Row'; export interface FooterProps { children: React.ReactNode; @@ -11,3 +13,8 @@ function Footer({ children }: FooterProps) { } export default Footer; + +export const FooterComponents = { + Cell, + Row, +}; diff --git a/src/Table.tsx b/src/Table.tsx index 7c68e61c8..b0cb746aa 100644 --- a/src/Table.tsx +++ b/src/Table.tsx @@ -32,7 +32,6 @@ import ResizeObserver from 'rc-resize-observer'; import getScrollBarSize from 'rc-util/lib/getScrollBarSize'; import ColumnGroup from './sugar/ColumnGroup'; import Column from './sugar/Column'; -import SummaryCell from './Footer/Cell'; import FixedHeader from './Header/FixedHeader'; import Header from './Header/Header'; import { @@ -65,7 +64,7 @@ import useStickyOffsets from './hooks/useStickyOffsets'; import ColGroup from './ColGroup'; import { getExpandableProps, getDataAndAriaProps } from './utils/legacyUtil'; import Panel from './Panel'; -import Footer from './Footer'; +import Footer, { FooterComponents } from './Footer'; import { findAllChildrenKeys, renderExpandIcon } from './utils/expandUtil'; import { getCellFixedInfo } from './utils/fixUtil'; @@ -721,7 +720,7 @@ Table.Column = Column; Table.ColumnGroup = ColumnGroup; -Table.SummaryCell = SummaryCell; +Table.Summary = FooterComponents; Table.defaultProps = { rowKey: 'key', diff --git a/src/index.ts b/src/index.ts index 444cac9ab..f094e67c4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,9 @@ import Table from './Table'; -import SummaryCell from './Footer/Cell'; +import { FooterComponents as Summary } from './Footer'; import Column from './sugar/Column'; import ColumnGroup from './sugar/ColumnGroup'; import { INTERNAL_COL_DEFINE } from './utils/legacyUtil'; -export { SummaryCell, Column, ColumnGroup, INTERNAL_COL_DEFINE }; +export { Summary, Column, ColumnGroup, INTERNAL_COL_DEFINE }; export default Table; diff --git a/tests/Table.spec.js b/tests/Table.spec.js index 62c671511..8d9633e64 100644 --- a/tests/Table.spec.js +++ b/tests/Table.spec.js @@ -169,12 +169,12 @@ describe('Table.Basic', () => { ]} data={[{ key: 1, a: 2, b: 3, c: 4 }]} summary={() => ( - - + + Light - - Bamboo - + + Bamboo + )} />, );
+ Light + + Bamboo +
Date: Sun, 26 Apr 2020 23:05:40 +0800 Subject: [PATCH 6/6] Add Summary Components --- examples/fixedColumns.tsx | 16 ++++++++-------- src/Footer/Row.tsx | 11 +++++++++++ src/Footer/index.tsx | 7 +++++++ src/Table.tsx | 5 ++--- src/index.ts | 4 ++-- tests/Table.spec.js | 10 +++++----- 6 files changed, 35 insertions(+), 18 deletions(-) create mode 100644 src/Footer/Row.tsx diff --git a/examples/fixedColumns.tsx b/examples/fixedColumns.tsx index 4b8340e7e..d16faa21b 100644 --- a/examples/fixedColumns.tsx +++ b/examples/fixedColumns.tsx @@ -65,16 +65,16 @@ const Demo = () => ( data={data} summary={() => ( <> -