"use client"; import "@/app/globals.css"; import _ from "lodash"; import { useDraggable } from "@dnd-kit/core"; import { useEffect, useRef, useState } from "react"; import { nearestMultiple } from "./utils"; import PreviewStore from "@/stores/previewStore"; import { useWidgets } from "@/hooks/useWidgets"; export default function Draggable(props: DraggablePropsType) { const targetRef = useRef(null); const timerRef = useRef(null); const [size, setSize] = useState({ width: 16, height: 16 }); const { id, widgetsId, data, x, y, width:_width, height:_height } = props; const [width, setWidth] = useState(_width); const [height, setHeight] = useState(_height); const {widgets, widgetsLibrary} = useWidgets(); const { attributes, listeners, setNodeRef, transform } = useDraggable({ id, data: props }); const style = transform ? { transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`, opacity: 0.6, } : {}; useEffect(() => { const element = targetRef.current; if (!element) return; const observer = new ResizeObserver( _.throttle((entries: any) => { for (const entry of entries) { const { width, height } = entry.contentRect; setSize({ width: nearestMultiple(width), height: nearestMultiple(height), }); const x = nearestMultiple(element.offsetLeft); const y = nearestMultiple(element.offsetTop); PreviewStore.changePreviewX(x); PreviewStore.changePreviewY(y); PreviewStore.changePreviewWidth(nearestMultiple(width)); PreviewStore.changePreviewHeight(nearestMultiple(height)); if (timerRef.current) { clearTimeout(timerRef.current); } timerRef.current = setTimeout(() => { setWidth(nearestMultiple(width)); setHeight(nearestMultiple(height)); PreviewStore.clearPreview(); }, 500); } }, 300), ); observer.observe(element); return () => { observer.disconnect(); }; }, []); const className = transform ? "shadow-xl absolute w-min min-w-[128px] min-h-[128px]" : "absolute w-min resize overflow-hidden min-w-[128px] min-h-[128px]"; return (
{ setNodeRef(el); // DnD 的 ref (targetRef as React.MutableRefObject).current = el; }} style={{ top: y, left: x, width: width, height: height, ...style, }} {...attributes}> {widgetsLibrary[widgetsId] && widgetsLibrary[widgetsId](data ?? {})}
); } export type DraggablePropsType = { id: string; widgetsId: string; data?: Record; x: number; y: number; width: number; height: number; };