Files
nexus-hub/components/DraggablePanel.tsx
2025-03-22 17:15:35 +00:00

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,
widgetsId: event?.active?.data?.current?.widgetsId,
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;
};