Skip to content
Merged
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 src/Table.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ import FixedHolder from './FixedHolder';
import type { SummaryProps } from './Footer/Summary';
import Summary from './Footer/Summary';
import StickyContext from './context/StickyContext';
import { EXPAND_COLUMN } from './constant';

// Used for conditions cache
const EMPTY_DATA = [];
Expand Down Expand Up @@ -106,7 +107,8 @@ const MemoTableContent = React.memo<MemoTableContentProps>(
},
);

export interface TableProps<RecordType = unknown> extends LegacyExpandableProps<RecordType> {
export interface TableProps<RecordType = unknown>
extends Omit<LegacyExpandableProps<RecordType>, 'showExpandColumn'> {
prefixCls?: string;
className?: string;
style?: React.CSSProperties;
Expand Down Expand Up @@ -849,6 +851,8 @@ function Table<RecordType extends DefaultRecordType>(props: TableProps<RecordTyp
);
}

Table.EXPAND_COLUMN = EXPAND_COLUMN;

Table.Column = Column;

Table.ColumnGroup = ColumnGroup;
Expand Down
1 change: 1 addition & 0 deletions src/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const EXPAND_COLUMN = {} as const;
47 changes: 38 additions & 9 deletions src/hooks/useColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
ColumnGroupType,
} from '../interface';
import { INTERNAL_COL_DEFINE } from '../utils/legacyUtil';
import { EXPAND_COLUMN } from '../constant';

export function convertChildrenToColumns<RecordType>(
children: React.ReactNode,
Expand Down Expand Up @@ -144,11 +145,41 @@ function useColumns<RecordType>(
[columns, children],
);

// Add expand column
// ========================== Expand ==========================
const withExpandColumns = React.useMemo<ColumnsType<RecordType>>(() => {
if (expandable) {
const expandColIndex = expandIconColumnIndex || 0;
const prevColumn = baseColumns[expandColIndex];
let cloneColumns = baseColumns.slice();

// >>> Warning if use `expandIconColumnIndex`
if (process.env.NODE_ENV !== 'production' && expandIconColumnIndex >= 0) {
warning(
false,
'`expandIconColumnIndex` is deprecated. Please use `Table.EXPAND_COLUMN` in `columns` instead.',
);
}

// >>> Insert expand column if not exist
if (!cloneColumns.includes(EXPAND_COLUMN)) {
const expandColIndex = expandIconColumnIndex || 0;
if (expandColIndex >= 0) {
cloneColumns.splice(expandColIndex, 0, EXPAND_COLUMN);
}
}

// >>> Deduplicate additional expand column
if (
process.env.NODE_ENV !== 'production' &&
cloneColumns.filter(c => c === EXPAND_COLUMN).length > 1
) {
warning(false, 'There exist more than one `EXPAND_COLUMN` in `columns`.');
}
const expandColumnIndex = cloneColumns.indexOf(EXPAND_COLUMN);
cloneColumns = cloneColumns.filter(
(column, index) => column !== EXPAND_COLUMN || index === expandColumnIndex,
);

// >>> Check if expand column need to fixed
const prevColumn = baseColumns[expandColumnIndex];

let fixedColumn: FixedType | null;
if ((fixed === 'left' || fixed) && !expandIconColumnIndex) {
Expand All @@ -159,6 +190,7 @@ function useColumns<RecordType>(
fixedColumn = prevColumn ? prevColumn.fixed : null;
}

// >>> Create expandable column
const expandColumn = {
[INTERNAL_COL_DEFINE]: {
className: `${prefixCls}-expand-icon-col`,
Expand Down Expand Up @@ -187,16 +219,12 @@ function useColumns<RecordType>(
},
};

// Insert expand column in the target position
const cloneColumns = baseColumns.slice();
if (expandColIndex >= 0) {
cloneColumns.splice(expandColIndex, 0, expandColumn);
}
return cloneColumns;
return cloneColumns.map(col => (col === EXPAND_COLUMN ? expandColumn : col));
}
return baseColumns;
}, [expandable, baseColumns, getRowKey, expandedKeys, expandIcon, direction]);

// ========================= Transform ========================
const mergedColumns = React.useMemo(() => {
let finalColumns = withExpandColumns;
if (transformColumns) {
Expand All @@ -214,6 +242,7 @@ function useColumns<RecordType>(
return finalColumns;
}, [transformColumns, withExpandColumns, direction]);

// ========================== Flatten =========================
const flattenColumns = React.useMemo(() => {
if (direction === 'rtl') {
return revertForRtl(flatColumns(mergedColumns));
Expand Down
2 changes: 2 additions & 0 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,9 @@ export interface ExpandableConfig<RecordType> {
onExpandedRowsChange?: (expandedKeys: readonly Key[]) => void;
defaultExpandAllRows?: boolean;
indentSize?: number;
/** @deprecated Please use `EXPAND_COLUMN` in `columns` directly */
expandIconColumnIndex?: number;
showExpandColumn?: boolean;
expandedRowClassName?: RowClassName<RecordType>;
childrenColumnName?: string;
rowExpandable?: (record: RecordType) => boolean;
Expand Down
46 changes: 27 additions & 19 deletions src/utils/legacyUtil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,32 +9,40 @@ export function getExpandableProps<RecordType>(
},
): ExpandableConfig<RecordType> {
const { expandable, ...legacyExpandableConfig } = props;
let config: ExpandableConfig<RecordType>;

if ('expandable' in props) {
return {
config = {
...legacyExpandableConfig,
...expandable,
};
} else {
if (
process.env.NODE_ENV !== 'production' &&
[
'indentSize',
'expandedRowKeys',
'defaultExpandedRowKeys',
'defaultExpandAllRows',
'expandedRowRender',
'expandRowByClick',
'expandIcon',
'onExpand',
'onExpandedRowsChange',
'expandedRowClassName',
'expandIconColumnIndex',
'showExpandColumn',
].some(prop => prop in props)
) {
warning(false, 'expanded related props have been moved into `expandable`.');
}

config = legacyExpandableConfig;
}

if (
process.env.NODE_ENV !== 'production' &&
[
'indentSize',
'expandedRowKeys',
'defaultExpandedRowKeys',
'defaultExpandAllRows',
'expandedRowRender',
'expandRowByClick',
'expandIcon',
'onExpand',
'onExpandedRowsChange',
'expandedRowClassName',
'expandIconColumnIndex',
].some(prop => prop in props)
) {
warning(false, 'expanded related props have been moved into `expandable`.');
if (config.showExpandColumn === false) {
config.expandIconColumnIndex = -1;
}

return legacyExpandableConfig;
return config;
}
110 changes: 87 additions & 23 deletions tests/ExpandRow.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,31 +200,95 @@ describe('Table.Expand', () => {
expect(wrapper2.find('.rc-table-has-fix-right').length).toBe(0);
});

it('renders expand icon to the specify column', () => {
const wrapper = mount(
createTable({
expandable: {
expandedRowRender,
expandIconColumnIndex: 1,
},
}),
);
expect(
wrapper.find('tbody tr td').at(1).hasClass('rc-table-row-expand-icon-cell'),
).toBeTruthy();
describe('config expand column index', () => {
it('renders expand icon to the specify column', () => {
resetWarned();
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

const wrapper = mount(
createTable({
expandable: {
expandedRowRender,
expandIconColumnIndex: 1,
},
}),
);
expect(
wrapper.find('tbody tr td').at(1).hasClass('rc-table-row-expand-icon-cell'),
).toBeTruthy();

expect(errorSpy).toHaveBeenCalledWith(
'Warning: `expandIconColumnIndex` is deprecated. Please use `Table.EXPAND_COLUMN` in `columns` instead.',
);
errorSpy.mockRestore();
});

it('order with EXPAND_COLUMN', () => {
const wrapper = mount(
createTable({
columns: [...sampleColumns, Table.EXPAND_COLUMN],
expandable: {
expandedRowRender,
},
}),
);

expect(
wrapper.find('tbody tr td').at(2).hasClass('rc-table-row-expand-icon-cell'),
).toBeTruthy();
});

it('de-duplicate of EXPAND_COLUMN', () => {
resetWarned();
const errorSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

const wrapper = mount(
createTable({
columns: [Table.EXPAND_COLUMN, ...sampleColumns, Table.EXPAND_COLUMN],
expandable: {
expandedRowRender,
},
}),
);

expect(
wrapper.find('tbody tr td').at(0).hasClass('rc-table-row-expand-icon-cell'),
).toBeTruthy();
expect(wrapper.find('tbody tr').first().find('td')).toHaveLength(3);

expect(errorSpy).toHaveBeenCalledWith(
'Warning: There exist more than one `EXPAND_COLUMN` in `columns`.',
);

errorSpy.mockRestore();
});
});

// https://github.com/ant-design/ant-design/issues/24129
it('should not render expand icon column when expandIconColumnIndex is negative', () => {
const wrapper = mount(
createTable({
expandable: {
expandedRowRender,
expandIconColumnIndex: -1,
},
}),
);
expect(wrapper.find('.rc-table-row-expand-icon-cell').length).toBe(0);
describe('hide expandColumn', () => {
// https://github.com/ant-design/ant-design/issues/24129
it('should not render expand icon column when expandIconColumnIndex is negative', () => {
const wrapper = mount(
createTable({
expandable: {
expandedRowRender,
expandIconColumnIndex: -1,
},
}),
);
expect(wrapper.find('.rc-table-row-expand-icon-cell').length).toBe(0);
});

it('showExpandColumn = false', () => {
const wrapper = mount(
createTable({
expandable: {
expandedRowRender,
showExpandColumn: false,
},
}),
);
expect(wrapper.find('.rc-table-row-expand-icon-cell').length).toBe(0);
});
});

it('renders a custom icon', () => {
Expand Down
3 changes: 3 additions & 0 deletions tests/Table.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,9 @@ describe('Table.Basic', () => {
const wrapper = mount(createTable());
wrapper.find('tbody td').first().simulate('mouseEnter');
expect(wrapper.exists('.rc-table-cell-row-hover')).toBeTruthy();

wrapper.find('tbody td').first().simulate('mouseLeave');
expect(wrapper.exists('.rc-table-cell-row-hover')).toBeFalsy();
});

it('skip when config should cell update', () => {
Expand Down