import { useDraggable, useDroppable } from "@dnd-kit/react";
import { pointerIntersection } from "@dnd-kit/collision";
import { GripVertical } from "lucide-react";
import type { CSSProperties, ReactNode } from "react";
function chartSlotPosition(index: number, columns: number): CSSProperties {
return { gridRow: Math.floor(index / columns) + 1, gridColumn: index % columns + 1 };
}
export function ChartDropSlot({ index, columns, occupied }: { index: number; columns: number; occupied: boolean }) {
const { ref, isDropTarget } = useDroppable({ id: `slot:${index}`, type: "slot", accept: "chart", data: { slot: index }, collisionDetector: pointerIntersection });
return
{!occupied ?
位置 {index + 1}拖动图表到这里
: null}
;
}
/** The chart stays under the same grid parent when its CSS position changes. */
export function ManagedChartSlot({ id, title, index, columns, located, helpId, register, children }: {
id: string;
title: string;
index: number;
columns: number;
located: boolean;
helpId: string;
register: (id: string, element: HTMLElement | null) => void;
children: ReactNode;
}) {
const { ref, handleRef, isDragSource } = useDraggable({ id, type: "chart", data: { title } });
return { ref(node); register(id, node); }} tabIndex={-1}
data-managed-chart={id} data-chart-title={title} data-slot-index={index} data-chart-located={located} data-chart-dragging={isDragSource}
aria-label={`图表窗口 ${title}`} style={chartSlotPosition(index, columns)}
className="group/chart-slot relative z-0 flex min-h-0 min-w-0 flex-col rounded-xl outline-hidden">
{children}
;
}