Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: columnResizable #1106

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ React.render(<Table columns={columns} data={data} />, mountNode);
| fixed | String \| Boolean | | this column will be fixed when table scroll horizontally: true or 'left' or 'right' |
| align | String | | specify how cell content is aligned |
| ellipsis | Boolean | | specify whether cell content be ellipsized |
| resizable | Boolean | | column resize |
| rowScope | 'row' \| 'rowgroup' | | Set scope attribute for all cells in this column |
| onCell | Function(record, index) | | Set custom props per each cell. |
| onHeaderCell | Function(record) | | Set custom props per each header cell. |
Expand Down
33 changes: 33 additions & 0 deletions assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,42 @@
}
}

&-column-resizing {
cursor: col-resize;
}

&-cell {
background: #f4f4f4;

&-resize-handle {
position: absolute;
top: 0;
inset-inline-end: 0;
width: 4px;
height: 100%;
cursor: col-resize;
z-index: 1;
background: red;
}

&-resize-line {
position: absolute;
width: 4px;
background: red;
height: 100%;
top: 0;
transform: translateX(-50%);
z-index: 2;
}

&-fix-left &-resize-handle {
right: 0
}

&-fix-right &-resize-handle {
left: 0
}

&-fix-left,
&-fix-right {
z-index: 2;
Expand Down
183 changes: 97 additions & 86 deletions docs/examples/column-resize.tsx
Original file line number Diff line number Diff line change
@@ -1,95 +1,106 @@
import React from 'react';
import { Resizable } from 'react-resizable';
import Table from 'rc-table';
import React, { useState } from 'react';
import Table, { INTERNAL_HOOKS } from 'rc-table';
import type { ColumnType } from 'rc-table';
import '../../assets/index.less';
import 'react-resizable/css/styles.css';
import type { ColumnType } from '@/interface';

const ResizableTitle = props => {
const { onResize, width, ...restProps } = props;
const data = [
{ a: '123', b: 'xxxxxxxx xxxxxxxx', d: 3, key: '1' },
{ a: 'cdd', b: 'edd12221 edd12221', d: 3, key: '2' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '3' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '4' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '5' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '6' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '7' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '8' },
{ a: '133', c: 'edd12221 edd12221', d: 2, key: '9' },
];

if (!width) {
return <th {...restProps} />;
}
const Demo = () => {
const [widthMap, setWidthMap] = useState<Map<React.Key, number>>(new Map());

const columns1 = [
{ title: 'title1', dataIndex: 'aaa', key: 'aaa', width: 100 },
{ title: 'title2', dataIndex: 'bbb', key: 'bbb', width: 100 },
].map(i => ({
...i,
resizable: true,
width: widthMap.get(i.key ?? i.dataIndex) ?? i.width,
})) as ColumnType<any>[];

const columns2 = [
{ title: 'title1', dataIndex: 'a', key: 'a', fixed: 'left' },
{ title: 'title2', dataIndex: 'b', key: 'b', fixed: 'left' },
{ title: 'title3', dataIndex: 'c', key: 'c' },
{ title: 'title4', dataIndex: 'b', key: 'd' },
{ title: 'title5', dataIndex: 'b', key: 'e' },
{ title: 'title6', dataIndex: 'b', key: 'f' },
{ title: 'title7', dataIndex: 'b', key: 'g' },
{ title: 'title8', dataIndex: 'b', key: 'h' },
{ title: 'title9', dataIndex: 'b', key: 'i' },
{ title: 'title10', dataIndex: 'b', key: 'j' },
{ title: 'title11', dataIndex: 'b', key: 'k', fixed: 'right' },
{ title: 'title12', dataIndex: 'b', key: 'l', fixed: 'right' },
].map(i => ({
...i,
resizable: true,
width: widthMap.get(i.key ?? i.dataIndex) ?? 150,
})) as ColumnType<any>[];

return (
<Resizable width={width} height={0} onResize={onResize}>
<th {...restProps} />
</Resizable>
<div>
table width: 800px {'columns=[{width: 100, width: 100}]'} 情况
<Table
style={{ width: 800 }}
scroll={{ y: 300, x: columns1.reduce((t, c) => t + (c.width as number), 0) }}
columns={columns1}
data={data}
onColumnResizeComplete={({ columnWidths }) => {
setWidthMap(prev => {
const result = new Map(prev);
columnWidths.forEach(i => {
result.set(i.columnKey, i.width);
});
return result;
});
}}
internalHooks={INTERNAL_HOOKS}
getContainerWidth={(ele, width) => {
// Minus border
const borderWidth = getComputedStyle(
ele.querySelector('.rc-table-body'),
).borderInlineStartWidth;
const mergedWidth = width - parseInt(borderWidth, 10);
return mergedWidth;
}}
/>
<br />
大多数情况
<Table
style={{ width: 800 }}
scroll={{ y: 300, x: columns2.reduce((t, c) => t + (c.width as number), 0) }}
columns={columns2}
data={data}
onColumnResizeComplete={({ columnWidths }) => {
setWidthMap(prev => {
const result = new Map(prev);
columnWidths.forEach(i => {
result.set(i.columnKey, i.width);
});
return result;
});
}}
internalHooks={INTERNAL_HOOKS}
getContainerWidth={(ele, width) => {
// Minus border
const borderWidth = getComputedStyle(
ele.querySelector('.rc-table-body'),
).borderInlineStartWidth;
const mergedWidth = width - parseInt(borderWidth, 10);
return mergedWidth;
}}
/>
</div>
);
};

interface RecordType {
a: string;
b?: string;
c?: string;
d?: number;
key: string;
}

interface DemoState {
columns: ColumnType<RecordType>[];
}

class Demo extends React.Component<{}, DemoState> {
state: DemoState = {
columns: [
{ title: 'title1', dataIndex: 'a', key: 'a', width: 100 },
{ title: 'title2', dataIndex: 'b', key: 'b', width: 100 },
{ title: 'title3', dataIndex: 'c', key: 'c', width: 200 },
{
title: 'Operations',
dataIndex: '',
key: 'd',
render() {
return <a href="#">Operations</a>;
},
},
],
};

components = {
header: {
cell: ResizableTitle,
},
};

data = [
{ a: '123', key: '1' },
{ a: 'cdd', b: 'edd', key: '2' },
{ a: '1333', c: 'eee', d: 2, key: '3' },
];

handleResize =
index =>
(e, { size }) => {
this.setState(({ columns }) => {
const nextColumns = [...columns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return { columns: nextColumns };
});
};

render() {
const columns = this.state.columns.map((col, index) => ({
...col,
onHeaderCell: (column: ColumnType<RecordType>) =>
({
width: column.width,
onResize: this.handleResize(index),
}) as any,
}));

return (
<div>
<h2>Integrate with react-resizable</h2>
<Table components={this.components} columns={columns} data={this.data} />
</div>
);
}
}

export default Demo;
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,6 @@
"react-dnd": "^2.5.4",
"react-dnd-html5-backend": "^2.5.4",
"react-dom": "^16.0.0",
"react-resizable": "^3.0.5",
"react-virtualized": "^9.12.0",
"react-window": "^1.8.5",
"regenerator-runtime": "^0.14.0",
Expand Down
6 changes: 3 additions & 3 deletions src/Body/MeasureCell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@ import ResizeObserver from 'rc-resize-observer';

export interface MeasureCellProps {
columnKey: React.Key;
onColumnResize: (key: React.Key, width: number) => void;
onColumnWidthChange: (key: React.Key, width: number) => void;
}

export default function MeasureCell({ columnKey, onColumnResize }: MeasureCellProps) {
export default function MeasureCell({ columnKey, onColumnWidthChange }: MeasureCellProps) {
const cellRef = React.useRef<HTMLTableCellElement>();

React.useEffect(() => {
if (cellRef.current) {
onColumnResize(columnKey, cellRef.current.offsetWidth);
onColumnWidthChange(columnKey, cellRef.current.offsetWidth);
}
}, []);

Expand Down
16 changes: 12 additions & 4 deletions src/Body/MeasureRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@ import MeasureCell from './MeasureCell';

export interface MeasureCellProps {
prefixCls: string;
onColumnResize: (key: React.Key, width: number) => void;
onColumnWidthChange: (key: React.Key, width: number) => void;
columnsKey: React.Key[];
}

export default function MeasureRow({ prefixCls, columnsKey, onColumnResize }: MeasureCellProps) {
export default function MeasureRow({
prefixCls,
columnsKey,
onColumnWidthChange,
}: MeasureCellProps) {
return (
<tr
aria-hidden="true"
Expand All @@ -18,12 +22,16 @@ export default function MeasureRow({ prefixCls, columnsKey, onColumnResize }: Me
<ResizeObserver.Collection
onBatchResize={infoList => {
infoList.forEach(({ data: columnKey, size }) => {
onColumnResize(columnKey, size.offsetWidth);
onColumnWidthChange(columnKey, size.offsetWidth);
});
}}
>
{columnsKey.map(columnKey => (
<MeasureCell key={columnKey} columnKey={columnKey} onColumnResize={onColumnResize} />
<MeasureCell
key={columnKey}
columnKey={columnKey}
onColumnWidthChange={onColumnWidthChange}
/>
))}
</ResizeObserver.Collection>
</tr>
Expand Down
6 changes: 3 additions & 3 deletions src/Body/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function Body<RecordType>(props: BodyProps<RecordType>) {
const {
prefixCls,
getComponent,
onColumnResize,
onColumnWidthChange,
flattenColumns,
getRowKey,
expandedKeys,
Expand All @@ -34,7 +34,7 @@ function Body<RecordType>(props: BodyProps<RecordType>) {
} = useContext(TableContext, [
'prefixCls',
'getComponent',
'onColumnResize',
'onColumnWidthChange',
'flattenColumns',
'getRowKey',
'expandedKeys',
Expand Down Expand Up @@ -104,7 +104,7 @@ function Body<RecordType>(props: BodyProps<RecordType>) {
<MeasureRow
prefixCls={prefixCls}
columnsKey={columnsKey}
onColumnResize={onColumnResize}
onColumnWidthChange={onColumnWidthChange}
/>
)}

Expand Down
38 changes: 38 additions & 0 deletions src/Header/HeaderCell.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import type { CellProps } from '../Cell';
import Cell from '../Cell';
import useCellResize from './useCellResize';

interface HeaderCellProps<RecordType> extends CellProps<RecordType> {
isFixLeft: boolean;
isFixRight: boolean;
columnKey?: React.Key;
resizable?: boolean;
minWidth?: number;
}

function HeaderCell<RecordType>({
isFixLeft,
isFixRight,
columnKey,
resizable,
minWidth,
...cellProps
}: HeaderCellProps<RecordType>) {
const { prefixCls } = cellProps;

const cellPrefixCls = `${prefixCls}-cell`;

const resizeHandleNode = useCellResize(
columnKey,
isFixLeft,
isFixRight,
cellPrefixCls,
resizable,
minWidth,
);

return <Cell {...cellProps} appendNode={resizeHandleNode} />;
}

export default HeaderCell;
Loading