70 lines
2.5 KiB
TypeScript
70 lines
2.5 KiB
TypeScript
"use client";
|
|
import classnames from "classnames";
|
|
import { DndContext } from "@dnd-kit/core";
|
|
import { Droppable } from "./Droppable";
|
|
import PreviewStore from "@/stores/previewStore";
|
|
import ComponentStore from '@/stores/componentStore';
|
|
import Preview from "./Draggable/Preview";
|
|
import { useObserver } from "mobx-react-lite";
|
|
import { nearestMultiple } from "./Draggable/utils";
|
|
import { ReactElement } from "react";
|
|
|
|
export default function DraggablePanel(props: DraggablePanelType) {
|
|
const { draggable, wdith = "full", height = "full", children } = props;
|
|
|
|
const draggablePanelClass = classnames(
|
|
`relative h-${height} w-${wdith}`,
|
|
{
|
|
"h-full": height === "full" || height === "100%",
|
|
"w-full": wdith === "full" || wdith === "100%",
|
|
"base-200": draggable, // 当 active 为 true 时添加
|
|
"base-100": !draggable, // 当 disabled 为 true 时添加
|
|
},
|
|
);
|
|
return useObserver(() => (
|
|
<DndContext
|
|
onDragMove={(event) => {
|
|
const node = event?.activatorEvent?.target?.parentNode;
|
|
const rect = node.getBoundingClientRect();
|
|
const { width, height } = rect;
|
|
const x = nearestMultiple(node.offsetLeft + event.delta.x);
|
|
const y = nearestMultiple(node.offsetTop + event.delta.y);
|
|
PreviewStore.changePreviewX(x);
|
|
PreviewStore.changePreviewY(y);
|
|
PreviewStore.changePreviewWidth(nearestMultiple(width));
|
|
PreviewStore.changePreviewHeight(nearestMultiple(height));
|
|
}}
|
|
onDragEnd={(event) => {
|
|
const node = event?.activatorEvent?.target?.parentNode;
|
|
const rect = node.getBoundingClientRect();
|
|
const { width, height } = rect;
|
|
const x = nearestMultiple(node.offsetLeft + event.delta.x);
|
|
const y = nearestMultiple(node.offsetTop + event.delta.y);
|
|
PreviewStore.clearPreview();
|
|
ComponentStore.changeComponent({
|
|
id: event?.active?.data?.current?.id,
|
|
component: event?.active?.data?.current?.component,
|
|
x,
|
|
y,
|
|
width: nearestMultiple(width),
|
|
height: nearestMultiple(height),
|
|
});
|
|
}}>
|
|
<Droppable>
|
|
<div className={draggablePanelClass}>
|
|
<Preview x={PreviewStore.x} y={PreviewStore.y} width={PreviewStore.width} height={PreviewStore.height} />
|
|
{children}
|
|
</div>
|
|
</Droppable>
|
|
</DndContext>
|
|
));
|
|
}
|
|
|
|
export type DraggablePanelType = {
|
|
draggable: boolean;
|
|
wdith?: number | string;
|
|
height?: number | string;
|
|
children: any;
|
|
// grid: boolean;
|
|
};
|