2022-11-09 12:28:04 +08:00
|
|
|
import { UploadOutlined } from '@ant-design/icons';
|
2023-02-13 10:29:12 +08:00
|
|
|
import type { DragEndEvent } from '@dnd-kit/core';
|
2023-02-21 11:13:00 +08:00
|
|
|
import { DndContext, PointerSensor, useSensor } from '@dnd-kit/core';
|
2023-02-13 10:29:12 +08:00
|
|
|
import {
|
|
|
|
arrayMove,
|
|
|
|
SortableContext,
|
|
|
|
useSortable,
|
|
|
|
verticalListSortingStrategy,
|
|
|
|
} from '@dnd-kit/sortable';
|
|
|
|
import { CSS } from '@dnd-kit/utilities';
|
2023-07-28 16:17:43 +08:00
|
|
|
import React, { useState } from 'react';
|
2023-02-13 10:29:12 +08:00
|
|
|
import { Button, Upload } from 'antd';
|
2022-11-09 12:28:04 +08:00
|
|
|
import type { UploadFile, UploadProps } from 'antd/es/upload/interface';
|
|
|
|
|
2023-02-13 10:49:44 +08:00
|
|
|
interface DraggableUploadListItemProps {
|
2022-11-09 12:28:04 +08:00
|
|
|
originNode: React.ReactElement<any, string | React.JSXElementConstructor<any>>;
|
2023-02-13 10:29:12 +08:00
|
|
|
file: UploadFile<any>;
|
2022-11-09 12:28:04 +08:00
|
|
|
}
|
|
|
|
|
2023-02-13 10:49:44 +08:00
|
|
|
const DraggableUploadListItem = ({ originNode, file }: DraggableUploadListItemProps) => {
|
2023-02-13 10:29:12 +08:00
|
|
|
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
|
|
|
|
id: file.uid,
|
2022-11-09 12:28:04 +08:00
|
|
|
});
|
2023-02-13 10:29:12 +08:00
|
|
|
|
|
|
|
const style: React.CSSProperties = {
|
|
|
|
transform: CSS.Transform.toString(transform),
|
|
|
|
transition,
|
|
|
|
cursor: 'move',
|
|
|
|
};
|
|
|
|
|
2022-11-09 12:28:04 +08:00
|
|
|
return (
|
2023-07-20 19:27:11 +08:00
|
|
|
<div
|
|
|
|
ref={setNodeRef}
|
|
|
|
style={style}
|
|
|
|
// prevent preview event when drag end
|
|
|
|
className={isDragging ? 'is-dragging' : ''}
|
|
|
|
{...attributes}
|
|
|
|
{...listeners}
|
|
|
|
>
|
2023-02-13 10:29:12 +08:00
|
|
|
{/* hide error tooltip when dragging */}
|
|
|
|
{file.status === 'error' && isDragging ? originNode.props.children : originNode}
|
2022-11-09 12:28:04 +08:00
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
const App: React.FC = () => {
|
|
|
|
const [fileList, setFileList] = useState<UploadFile[]>([
|
|
|
|
{
|
|
|
|
uid: '-1',
|
|
|
|
name: 'image1.png',
|
|
|
|
status: 'done',
|
|
|
|
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
uid: '-2',
|
|
|
|
name: 'image2.png',
|
|
|
|
status: 'done',
|
|
|
|
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
uid: '-3',
|
|
|
|
name: 'image3.png',
|
|
|
|
status: 'done',
|
|
|
|
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
uid: '-4',
|
|
|
|
name: 'image4.png',
|
|
|
|
status: 'done',
|
|
|
|
url: 'https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png',
|
|
|
|
},
|
|
|
|
{
|
|
|
|
uid: '-5',
|
|
|
|
name: 'image.png',
|
|
|
|
status: 'error',
|
|
|
|
},
|
|
|
|
]);
|
|
|
|
|
2023-02-21 11:13:00 +08:00
|
|
|
const sensor = useSensor(PointerSensor, {
|
|
|
|
activationConstraint: { distance: 10 },
|
|
|
|
});
|
|
|
|
|
2023-02-13 10:29:12 +08:00
|
|
|
const onDragEnd = ({ active, over }: DragEndEvent) => {
|
|
|
|
if (active.id !== over?.id) {
|
|
|
|
setFileList((prev) => {
|
|
|
|
const activeIndex = prev.findIndex((i) => i.uid === active.id);
|
|
|
|
const overIndex = prev.findIndex((i) => i.uid === over?.id);
|
|
|
|
return arrayMove(prev, activeIndex, overIndex);
|
2023-02-07 10:13:29 +08:00
|
|
|
});
|
2023-02-13 10:29:12 +08:00
|
|
|
}
|
|
|
|
};
|
2022-11-09 12:28:04 +08:00
|
|
|
|
|
|
|
const onChange: UploadProps['onChange'] = ({ fileList: newFileList }) => {
|
|
|
|
setFileList(newFileList);
|
|
|
|
};
|
|
|
|
|
|
|
|
return (
|
2023-02-21 11:13:00 +08:00
|
|
|
<DndContext sensors={[sensor]} onDragEnd={onDragEnd}>
|
2023-02-13 10:29:12 +08:00
|
|
|
<SortableContext items={fileList.map((i) => i.uid)} strategy={verticalListSortingStrategy}>
|
|
|
|
<Upload
|
2023-09-15 13:48:23 +08:00
|
|
|
action="https://run.mocky.io/v3/435e224c-44fb-4773-9faf-380c5e6a2188"
|
2023-02-13 10:29:12 +08:00
|
|
|
fileList={fileList}
|
|
|
|
onChange={onChange}
|
|
|
|
itemRender={(originNode, file) => (
|
2023-02-13 10:49:44 +08:00
|
|
|
<DraggableUploadListItem originNode={originNode} file={file} />
|
2023-02-13 10:29:12 +08:00
|
|
|
)}
|
|
|
|
>
|
|
|
|
<Button icon={<UploadOutlined />}>Click to Upload</Button>
|
|
|
|
</Upload>
|
|
|
|
</SortableContext>
|
|
|
|
</DndContext>
|
2022-11-09 12:28:04 +08:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
export default App;
|