Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ Then open `http://localhost:8000`.
| expandable.expandedRowRender | Function(recode, index, indent, expanded):ReactNode | | Content render to expanded row |
| expandable.forceRender | Boolean | false | Force render expanded row content before expansion. In virtual mode, only rows currently mounted by the virtual list are force-rendered; off-screen rows may still be unmounted |
| expandable.expandedRowClassName | `string` \| `(recode, index, indent) => string` | | get expanded row's className |
| expandable.columnTitle | ReactNode \| Function(originalNode) | | Customize expand column title |
| expandable.expandRowByClick | boolean | | Support expand by click row |
| expandable.expandIconColumnIndex | Number | 0 | The index of expandIcon which column will be inserted when expandIconAsCell is false |
| expandable.expandIcon | props => ReactNode | | Customize expand icon |
| expandable.expandIcon | props => ReactNode | | Deprecated. Use `components.ExpandIcon`; retained as a row-only fallback |
| expandable.indentSize | Number | 15 | indentSize for every level of data.i.children, better using with column.width specified |
| expandable.rowExpandable | (record) => boolean | | Config row support expandable |
| expandable.showExpandAll | Boolean | false | Show expand all icon in the expand column header when using `expandedRowRender` |
| expandable.onExpand | Function(expanded, record) | | function to call when click expand icon |
| expandable.onExpandAll | Function(expanded, records) | | function to call when click expand all icon |
| expandable.onExpandedRowsChange | Function(expandedRows) | | function to call when the expanded rows change |
| expandable.fixed | String \| Boolean | - | this expand icon will be fixed when table scroll horizontally: true or `left` or `right` and `expandIconColumnIndex` need to stay first or last |
| rowKey | string or Function(record, index):string | 'key' | If rowKey is string, `record[rowKey]` will be used as key. If rowKey is function, the return value of `rowKey(record, index)` will be use as key. |
Expand All @@ -105,6 +108,7 @@ Then open `http://localhost:8000`.
| emptyText | React.Node or Function | `No Data` | Display text when data is empty |
| columns | Object[] | | The columns config of table, see table below |
| components | Object | | Override table elements, see [#171](https://github.com/react-component/table/pull/171) for more details |
| components.ExpandIcon | `React.ComponentType<ExpandIconProps>` | | Customize both row and expand-all icons. Receives `type` (`row` or `all`), `expanded`, `expandable`, `onClick`, and `record` for rows only |
| sticky | boolean \| {offsetHeader?: number, offsetScroll?: number, getContainer?: () => Window \| HTMLElement } | false | stick header and scroll bar |
| summary | (data: readonly RecordType[]) => React.ReactNode | - | `summary` attribute in `table` component is used to define the summary row. |
| rowHoverable | boolean | true | Table hover interaction |
Expand Down
6 changes: 5 additions & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,15 @@ npm start
| expandable.expandedRowRender | Function(recode, index, indent, expanded):ReactNode | | 内容渲染到扩展行 |
| expandable.forceRender | Boolean | false | 在展开前强制渲染展开行内容。虚拟模式下,仅强制渲染虚拟列表当前挂载的行;屏幕外的行仍可能被卸载 |
| expandable.expandedRowClassName | `string` \| `(recode, index, indent) => string` | | 获取扩展行的 className |
| expandable.columnTitle | ReactNode \| Function(originalNode) | | 自定义展开列表头 |
| expandable.expandRowByClick | boolean | | 支持点击行展开 |
| expandable.expandIconColumnIndex | Number | 0 | ExpandIconAsCell 为 false 时将插入哪一列的 ExpandIcon 索引 |
| expandable.expandIcon | props => ReactNode | | 自定义展开图标 |
| expandable.expandIcon | props => ReactNode | | 已废弃。请使用 `components.ExpandIcon`;此配置仅作为行展开图标的后备方案保留 |
| expandable.indentSize | Number | 15 | 每一级 `data[i].children` 的缩进尺寸,建议配合指定的 `column.width` 使用 |
| expandable.rowExpandable | (record) => boolean | | 配置行支持可扩展 |
| expandable.showExpandAll | Boolean | false | 使用 `expandedRowRender` 时在展开列的表头中显示全部展开图标 |
| expandable.onExpand | Function(expanded, record) | | 单击展开图标时调用的函数 |
| expandable.onExpandAll | Function(expanded, records) | | 单击全部展开图标时调用的函数 |
| expandable.onExpandedRowsChange | Function(expandedRows) | | 扩展行更改时调用的函数 |
| expandable.fixed | String \| Boolean | - | 当表格水平滚动时,此展开图标将被修复: true 或 `left` 或 `right` 和 `expandIconColumnIndex` 需要保留在第一个或最后一个 |
| rowKey | string or Function(record, index):string | 'key' | 如果 rowKey 是字符串,则 `record[rowKey]` 将用作键。如果 rowKey 是函数,则 `rowKey(record, index)` 的返回值将用作 key。 |
Expand All @@ -105,6 +108,7 @@ npm start
| emptyText | React.Node or Function | `No Data` | 数据为空时显示文本 |
| columns | Object[] | | 表的列配置见下表 |
| components | Object | | 覆盖表元素,请参阅 [#171](https://github.com/react-component/table/pull/171) 了解更多详细信息 |
| components.ExpandIcon | `React.ComponentType<ExpandIconProps>` | | 自定义行展开和全部展开图标。接收 `type`(`row` 或 `all`)、`expanded`、`expandable`、`onClick`,仅行图标接收 `record` |
| sticky | boolean \| {offsetHeader?: number, offsetScroll?: number, getContainer?: () => Window \| HTMLElement } | false | 粘贴标题和滚动条 |
| summary | (data: readonly RecordType[]) => React.ReactNode | - | `table` 组件中的 `summary` 属性用于定义汇总行。 |
| rowHoverable | boolean | true | 表格 hover 交互 |
Expand Down
5 changes: 5 additions & 0 deletions assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -230,13 +230,18 @@
}

&-row-expand-icon {
box-sizing: inherit;
display: inline-block;
width: 16px;
height: 16px;
padding: 0;
color: #aaa;
font: inherit;
line-height: 16px;
text-align: center;
vertical-align: middle;
appearance: none;
background: transparent;
border: 1px solid currentColor;
cursor: pointer;

Expand Down
5 changes: 3 additions & 2 deletions src/Body/BodyRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import useRowInfo from '../hooks/useRowInfo';
import type { ColumnType, CustomizeComponent } from '../interface';
import ExpandedRow from './ExpandedRow';
import type { ExpandedRowProps } from './ExpandedRow';
import { computedExpandedClassName } from '../utils/expandUtil';
import { computedExpandedClassName, renderRowExpandIcon } from '../utils/expandUtil';
import type { TableProps } from '..';

export interface BodyRowProps<RecordType> {
Expand Down Expand Up @@ -54,6 +54,7 @@ export function getCellProps<RecordType>(
nestExpandable,
indentSize,
expandIcon,
ExpandIcon,
expanded,
hasNestChildren,
onTriggerExpand,
Expand All @@ -73,7 +74,7 @@ export function getCellProps<RecordType>(
style={{ paddingLeft: `${indentSize * indent}px` }}
className={`${prefixCls}-row-indent indent-level-${indent}`}
/>
{expandIcon({
{renderRowExpandIcon(ExpandIcon, expandIcon, {
prefixCls,
expanded,
expandable: hasNestChildren,
Expand Down
5 changes: 5 additions & 0 deletions src/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ const Table = <RecordType extends DefaultRecordType>(
mergedExpandIcon,
mergedChildrenColumnName,
onTriggerExpand,
expandAllInfo,
] = useExpand(props, mergedData, getRowKey);

// ====================== Column ======================
Expand All @@ -331,6 +332,8 @@ const Table = <RecordType extends DefaultRecordType>(
// https://github.com/ant-design/ant-design/issues/23894
onTriggerExpand,
expandIcon: mergedExpandIcon,
ExpandIcon: components?.ExpandIcon,
expandAllInfo,
expandIconColumnIndex: expandableConfig.expandIconColumnIndex,
direction,
scrollWidth: useInternalHooks && tailor && typeof scrollX === 'number' ? scrollX : null,
Expand Down Expand Up @@ -907,6 +910,7 @@ const Table = <RecordType extends DefaultRecordType>(
rowClassName,
expandedRowClassName: expandableConfig.expandedRowClassName,
expandIcon: mergedExpandIcon,
ExpandIcon: components?.ExpandIcon,
expandableType,
expandRowByClick: expandableConfig.expandRowByClick,
expandedRowRender: expandableConfig.expandedRowRender,
Expand Down Expand Up @@ -965,6 +969,7 @@ const Table = <RecordType extends DefaultRecordType>(
rowClassName,
expandableConfig.expandedRowClassName,
mergedExpandIcon,
components?.ExpandIcon,
expandableType,
expandableConfig.expandRowByClick,
expandableConfig.expandedRowRender,
Expand Down
2 changes: 2 additions & 0 deletions src/context/TableContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
Direction,
ExpandableConfig,
ExpandableType,
ExpandIconComponent,
ExpandedRowRender,
GetComponent,
GetComponentProps,
Expand Down Expand Up @@ -55,6 +56,7 @@ export interface TableContextProps<RecordType = any> {
expandedRowRender: ExpandedRowRender<RecordType>;
forceRender: boolean;
expandIcon: RenderExpandIcon<RecordType>;
ExpandIcon?: ExpandIconComponent<RecordType>;
onTriggerExpand: TriggerEventHandler<RecordType>;
expandIconColumnIndex: number;
allColumnsFixedLeft: boolean;
Expand Down
37 changes: 32 additions & 5 deletions src/hooks/useColumns/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ import type {
ColumnsType,
ColumnType,
Direction,
ExpandIconComponent,
ExpandIconProps,
FixedType,
GetRowKey,
Key,
RenderExpandIcon,
TriggerEventHandler,
} from '../../interface';
import { DefaultExpandIcon, renderRowExpandIcon } from '../../utils/expandUtil';
import { INTERNAL_COL_DEFINE } from '../../utils/legacyUtil';
import useWidthColumns from './useWidthColumns';

Expand Down Expand Up @@ -102,6 +105,8 @@ function useColumns<RecordType>(
getRowKey,
onTriggerExpand,
expandIcon,
ExpandIcon,
expandAllInfo,
rowExpandable,
expandIconColumnIndex,
expandedRowOffset = 0,
Expand All @@ -117,10 +122,12 @@ function useColumns<RecordType>(
children?: React.ReactNode;
expandable: boolean;
expandedKeys: Set<Key>;
columnTitle?: React.ReactNode;
columnTitle?: React.ReactNode | ((originalNode: React.ReactNode) => React.ReactNode);
getRowKey: GetRowKey<RecordType>;
onTriggerExpand: TriggerEventHandler<RecordType>;
expandIcon?: RenderExpandIcon<RecordType>;
expandIcon: RenderExpandIcon<RecordType>;
ExpandIcon?: ExpandIconComponent<RecordType>;
expandAllInfo?: Pick<ExpandIconProps<RecordType>, 'expanded' | 'expandable' | 'onClick'>;
rowExpandable?: (record: RecordType) => boolean;
expandIconColumnIndex?: number;
direction?: Direction;
Expand Down Expand Up @@ -190,13 +197,22 @@ function useColumns<RecordType>(
fixedColumn = prevColumn ? prevColumn.fixed : null;
}

const MergedExpandIcon = ExpandIcon || DefaultExpandIcon;
const expandAllNode = expandAllInfo ? (
<MergedExpandIcon type="all" prefixCls={prefixCls} {...expandAllInfo} />
) : undefined;
const mergedColumnTitle =
typeof columnTitle === 'function'
? columnTitle(expandAllNode)
: (columnTitle ?? expandAllNode);

// >>> Create expandable column
const expandColumn = {
[INTERNAL_COL_DEFINE]: {
className: `${prefixCls}-expand-icon-col`,
columnType: 'EXPAND_COLUMN',
},
title: columnTitle,
title: mergedColumnTitle,
fixed: fixedColumn,
className: `${prefixCls}-row-expand-icon-cell`,
width: columnWidth,
Expand All @@ -205,7 +221,7 @@ function useColumns<RecordType>(
const expanded = expandedKeys.has(rowKey);
const recordExpandable = rowExpandable ? rowExpandable(record) : true;

const icon = expandIcon({
const icon = renderRowExpandIcon(ExpandIcon, expandIcon, {
prefixCls,
expanded,
expandable: recordExpandable,
Expand Down Expand Up @@ -238,7 +254,18 @@ function useColumns<RecordType>(

return baseColumns.filter(col => col !== EXPAND_COLUMN);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [expandable, baseColumns, getRowKey, expandedKeys, expandIcon, direction, expandedRowOffset]);
}, [
expandable,
baseColumns,
getRowKey,
expandedKeys,
expandIcon,
ExpandIcon,
expandAllInfo,
columnTitle,
direction,
expandedRowOffset,
]);

// ========================= Transform ========================
const mergedColumns = React.useMemo(() => {
Expand Down
71 changes: 71 additions & 0 deletions src/hooks/useExpand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { INTERNAL_HOOKS } from '../constant';
import type {
ExpandableConfig,
ExpandableType,
ExpandIconProps,
GetRowKey,
Key,
RenderExpandIcon,
Expand All @@ -13,6 +14,11 @@ import type { TableProps } from '../Table';
import { findAllChildrenKeys, renderExpandIcon } from '../utils/expandUtil';
import { getExpandableProps } from '../utils/legacyUtil';

type ExpandAllInfo<RecordType> = Pick<
ExpandIconProps<RecordType>,
'expanded' | 'expandable' | 'onClick'
>;

export default function useExpand<RecordType>(
props: TableProps<RecordType>,
mergedData: readonly RecordType[],
Expand All @@ -24,6 +30,7 @@ export default function useExpand<RecordType>(
expandIcon: RenderExpandIcon<RecordType>,
childrenColumnName: string,
onTriggerExpand: TriggerEventHandler<RecordType>,
expandAllInfo: ExpandAllInfo<RecordType> | undefined,
] {
const expandableConfig = getExpandableProps(props);

Expand All @@ -34,8 +41,11 @@ export default function useExpand<RecordType>(
defaultExpandAllRows,
expandedRowRender,
onExpand,
onExpandAll,
onExpandedRowsChange,
childrenColumnName,
rowExpandable,
showExpandAll,
} = expandableConfig;

const mergedExpandIcon = expandIcon || renderExpandIcon;
Expand Down Expand Up @@ -81,6 +91,25 @@ export default function useExpand<RecordType>(
[expandedRowKeys, innerExpandedKeys],
);

const expandableRows = React.useMemo(() => {
if (!showExpandAll || expandableType !== 'row') {
return [];
}

return mergedData.reduce<{ key: Key; record: RecordType }[]>((rows, record, index) => {
if (!rowExpandable || rowExpandable(record)) {
rows.push({
key: getRowKey(record, index),
record,
});
}
return rows;
}, []);
}, [expandableType, getRowKey, mergedData, rowExpandable, showExpandAll]);

const allExpanded =
expandableRows.length > 0 && expandableRows.every(({ key }) => mergedExpandedKeys.has(key));

const onTriggerExpand: TriggerEventHandler<RecordType> = React.useCallback(
(record: RecordType) => {
const key = getRowKey(record, mergedData.indexOf(record));
Expand All @@ -105,6 +134,47 @@ export default function useExpand<RecordType>(
[getRowKey, mergedExpandedKeys, mergedData, onExpand, onExpandedRowsChange],
);

const onTriggerExpandAll: React.MouseEventHandler<HTMLElement> = React.useCallback(
event => {
event.stopPropagation();
if (!expandableRows.length) {
return;
}

const nextExpanded = !allExpanded;
const nextExpandedKeys = new Set(mergedExpandedKeys);

expandableRows.forEach(({ key }) => {
if (nextExpanded) {
nextExpandedKeys.add(key);
} else {
nextExpandedKeys.delete(key);
}
});

const keys = [...nextExpandedKeys];
setInnerExpandedKeys(keys);
onExpandAll?.(
nextExpanded,
expandableRows.map(({ record }) => record),
);
onExpandedRowsChange?.(keys);
},
[allExpanded, expandableRows, mergedExpandedKeys, onExpandAll, onExpandedRowsChange],
);

const expandAllInfo = React.useMemo<ExpandAllInfo<RecordType> | undefined>(
() =>
showExpandAll && expandableType === 'row'
? {
expanded: allExpanded,
expandable: expandableRows.length > 0,
onClick: onTriggerExpandAll,
}
: undefined,
[allExpanded, expandableRows.length, expandableType, onTriggerExpandAll, showExpandAll],
);

// Warning if use `expandedRowRender` and nest children in the same time
if (
process.env.NODE_ENV !== 'production' &&
Expand All @@ -123,5 +193,6 @@ export default function useExpand<RecordType>(
mergedExpandIcon,
mergedChildrenColumnName,
onTriggerExpand,
expandAllInfo,
];
}
2 changes: 2 additions & 0 deletions src/hooks/useRowInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export default function useRowInfo<RecordType>(
| 'expandedRowClassName'
| 'indentSize'
| 'expandIcon'
| 'ExpandIcon'
| 'expandedRowRender'
| 'forceRender'
| 'expandIconColumnIndex'
Expand Down Expand Up @@ -49,6 +50,7 @@ export default function useRowInfo<RecordType>(
'expandedRowClassName',
'indentSize',
'expandIcon',
'ExpandIcon',
'expandedRowRender',
'forceRender',
'expandIconColumnIndex',
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
ColumnType,
ColumnsType,
DefaultRecordType,
ExpandIconProps,
ExpandableConfig,
FixedType,
GetComponentProps,
Expand Down Expand Up @@ -37,6 +38,7 @@ export {
type ColumnType,
type ColumnsType,
type DefaultRecordType,
type ExpandIconProps,
type ExpandableConfig,
type FixedType,
type GetComponentProps,
Expand Down
Loading
Loading