import React, { useState } from "react";
import styled from "styled-components";
import {
DragDropContext,
Draggable,
DraggableProvided,
DraggableRubric,
DraggableStateSnapshot,
DragStart,
DragUpdate,
Droppable,
DropResult,
ResponderProvided,
} from "react-beautiful-dnd";
import "./styles.css";
interface IItem {
id: string;
label: string;
}
export const DndForm: React.FC = () => {
const COLLECTION: IItem[] = [
{ id: "1", label: "Apple" },
{ id: "2", label: "Banana" },
{ id: "3", label: "orange" },
];
const [items, setItems] = useState<IItem[]>(COLLECTION);
const [enabled, setEnabled] = React.useState(false);
React.useEffect(() => {
const animation = requestAnimationFrame(() => setEnabled(true));
return () => {
cancelAnimationFrame(animation);
setEnabled(false);
};
}, []);
const onDragStart = (start: DragStart, provided: ResponderProvided) => {
console.log("onDragStart", start, provided);
};
const onDragUpdate = (update: DragUpdate, provided: ResponderProvided) => {
console.log("onDragUpdate", update, provided);
};
const onDragEnd = (result: DropResult, provided: ResponderProvided) => {
console.log("onDragEnd", result, provided);
};
const getRenderItem =
(items: IItem[]) =>
(
provided: DraggableProvided,
snapshot: DraggableStateSnapshot,
rubric: DraggableRubric
) => {
const item = items[rubric.source.index];
return (
<React.Fragment>
<li
{...provided.draggableProps}
{...provided.dragHandleProps}
ref={provided.innerRef}
style={provided.draggableProps.style}
className={snapshot.isDragging ? "dragging" : ""}
>
{item.label}
</li>
</React.Fragment>
);
};
return (
<DragDropContext
onDragStart={onDragStart}
onDragUpdate={onDragUpdate}
onDragEnd={onDragEnd}
>
{enabled && (
<Wrapper>
<Droppable
droppableId="tools"
renderClone={getRenderItem(COLLECTION)}
isDropDisabled
>
{(provided, snapshot) => {
return (
<LeftWapper
ref={provided.innerRef}
{...provided.droppableProps}
>
<ul ref={provided.innerRef} className="shop">
{items.map((item: IItem, index: number) => {
const shouldRenderClone =
item.id === snapshot.draggingFromThisWith;
return (
<React.Fragment key={item.id}>
{shouldRenderClone ? (
<li className="react-beatiful-dnd-copy">
{item.label}
</li>
) : (
<Draggable draggableId={item.id} index={index}>
{(provided, snapshot) => (
<React.Fragment>
<li
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps}
className={
snapshot.isDragging ? "dragging" : ""
}
>
{item.label}
</li>
</React.Fragment>
)}
</Draggable>
)}
</React.Fragment>
);
})}
</ul>
</LeftWapper>
);
}}
</Droppable>
<Droppable droppableId="form">
{(provided, snapshot) => {
return (
<MiddleWrapper
ref={provided.innerRef}
{...provided.droppableProps}
></MiddleWrapper>
);
}}
</Droppable>
<RightWrapper></RightWrapper>
</Wrapper>
)}
</DragDropContext>
);
};
const Wrapper = styled.div`
position: absolute;
width: 100%;
height: 100%;
background-color: #6dc1e6;
display: flex;
justify-content: space-between;
`;
const LeftWapper = styled.div`
width: 350px;
height: 100%;
background-color: aquamarine;
flex-shrink: 0;
`;
const MiddleWrapper = styled.div`
min-width: 500px;
flex-grow: 10;
`;
const RightWrapper = styled.div`
width: 300px;
height: 100%;
background-color: #e8d4ba;
`;
/* 不重要 */
ul,
li {
margin: 0;
padding: 0;
list-style: none;
}
/* 重要 copy后的拖动元素样式 */
.react-beatiful-dnd-copy ~ li {
transform: none !important;
}
/* 拖动时的样式 */
.dragging {
background: yellow;
text-align: center;
font-family: sans-serif;
}
/* 拖动时复制停留在原来空间的样式 */
.react-beatiful-dnd-copy {
background: lightblue;
}
.react-beatiful-dnd-copy ~ [data-rbd-placeholder-context-id] {
display: none !important;
}
/* 不重要 */
.shop {
padding: 10px;
border: 1px solid #aaa;
}