You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
139 lines
3.3 KiB
139 lines
3.3 KiB
import { MenuOutlined } from '@ant-design/icons';
|
|
import type { DragEndEvent } from '@dnd-kit/core';
|
|
import { DndContext } from '@dnd-kit/core';
|
|
import {
|
|
arrayMove,
|
|
SortableContext,
|
|
useSortable,
|
|
verticalListSortingStrategy,
|
|
} from '@dnd-kit/sortable';
|
|
import { CSS } from '@dnd-kit/utilities';
|
|
import { Table } from 'antd';
|
|
import type { ColumnsType } from 'antd/es/table';
|
|
import React, { useState } from 'react';
|
|
|
|
interface DataType {
|
|
key: string;
|
|
name: string;
|
|
age: number;
|
|
address: string;
|
|
}
|
|
|
|
const columns: ColumnsType<DataType> = [
|
|
{
|
|
key: 'sort',
|
|
},
|
|
{
|
|
title: 'Name',
|
|
dataIndex: 'name',
|
|
},
|
|
{
|
|
title: 'Age',
|
|
dataIndex: 'age',
|
|
},
|
|
{
|
|
title: 'Address',
|
|
dataIndex: 'address',
|
|
},
|
|
];
|
|
|
|
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
|
|
'data-row-key': string;
|
|
}
|
|
|
|
const Row = ({ children, ...props }: RowProps) => {
|
|
const {
|
|
attributes,
|
|
listeners,
|
|
setNodeRef,
|
|
setActivatorNodeRef,
|
|
transform,
|
|
transition,
|
|
isDragging,
|
|
} = useSortable({
|
|
id: props['data-row-key'],
|
|
});
|
|
|
|
const style: React.CSSProperties = {
|
|
...props.style,
|
|
transform: CSS.Transform.toString(transform && { ...transform, scaleY: 1 }),
|
|
transition,
|
|
...(isDragging ? { position: 'relative', zIndex: 9999 } : {}),
|
|
};
|
|
|
|
return (
|
|
<tr {...props} ref={setNodeRef} style={style} {...attributes}>
|
|
{React.Children.map(children, (child) => {
|
|
if ((child as React.ReactElement).key === 'sort') {
|
|
return React.cloneElement(child as React.ReactElement, {
|
|
children: (
|
|
<MenuOutlined
|
|
ref={setActivatorNodeRef}
|
|
style={{ touchAction: 'none', cursor: 'move' }}
|
|
{...listeners}
|
|
/>
|
|
),
|
|
});
|
|
}
|
|
return child;
|
|
})}
|
|
</tr>
|
|
);
|
|
};
|
|
|
|
const App: React.FC = () => {
|
|
const [dataSource, setDataSource] = useState([
|
|
{
|
|
key: '1',
|
|
name: 'John Brown',
|
|
age: 32,
|
|
address:
|
|
'Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text Long text',
|
|
},
|
|
{
|
|
key: '2',
|
|
name: 'Jim Green',
|
|
age: 42,
|
|
address: 'London No. 1 Lake Park',
|
|
},
|
|
{
|
|
key: '3',
|
|
name: 'Joe Black',
|
|
age: 32,
|
|
address: 'Sidney No. 1 Lake Park',
|
|
},
|
|
]);
|
|
|
|
const onDragEnd = ({ active, over }: DragEndEvent) => {
|
|
if (active.id !== over?.id) {
|
|
setDataSource((previous) => {
|
|
const activeIndex = previous.findIndex((i) => i.key === active.id);
|
|
const overIndex = previous.findIndex((i) => i.key === over?.id);
|
|
return arrayMove(previous, activeIndex, overIndex);
|
|
});
|
|
}
|
|
};
|
|
|
|
return (
|
|
<DndContext onDragEnd={onDragEnd}>
|
|
<SortableContext
|
|
// rowKey array
|
|
items={dataSource.map((i) => i.key)}
|
|
strategy={verticalListSortingStrategy}
|
|
>
|
|
<Table
|
|
components={{
|
|
body: {
|
|
row: Row,
|
|
},
|
|
}}
|
|
rowKey="key"
|
|
columns={columns}
|
|
dataSource={dataSource}
|
|
/>
|
|
</SortableContext>
|
|
</DndContext>
|
|
);
|
|
};
|
|
|
|
export default App;
|
|
|