"use client"; import { Plus } from "lucide-react"; import { type ReactNode, useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { AspectRatio } from "@/components/ui/aspect-ratio"; import { Button } from "@/components/ui/button"; import { Tooltip, TooltipContent, TooltipTrigger, } from "@/components/ui/tooltip"; import { useEditor } from "@/editor/use-editor"; import { clearDragData, setDragData } from "@/timeline/drag-data"; import type { TimelineDragData } from "@/timeline/drag"; import { cn } from "@/utils/ui"; import type { MediaTime } from "@/wasm"; export interface DraggableItemProps { name: string; preview: ReactNode; dragData: TimelineDragData; onDragStart?: ({ e }: { e: React.DragEvent }) => void; onAddToTimeline?: ({ currentTime }: { currentTime: MediaTime }) => void; aspectRatio?: number; className?: string; containerClassName?: string; shouldShowPlusOnDrag?: boolean; shouldShowLabel?: boolean; isRounded?: boolean; variant?: "card" | "compact"; isDraggable?: boolean; } export function DraggableItem({ name, preview, dragData, onDragStart, onAddToTimeline, aspectRatio = 16 / 9, className = "", containerClassName, shouldShowPlusOnDrag = true, shouldShowLabel = true, isRounded = true, variant = "card", isDraggable = true, }: DraggableItemProps) { const [isDragging, setIsDragging] = useState(false); const [dragPosition, setDragPosition] = useState({ x: 0, y: 0 }); const dragRef = useRef(null); const editor = useEditor(); const handleAddToTimeline = () => { onAddToTimeline?.({ currentTime: editor.playback.getCurrentTime() }); }; const emptyImg = new window.Image(); emptyImg.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs="; useEffect(() => { if (!isDragging) return; const handleDragOver = (e: DragEvent) => { setDragPosition({ x: e.clientX, y: e.clientY }); }; document.addEventListener("dragover", handleDragOver); return () => { document.removeEventListener("dragover", handleDragOver); }; }, [isDragging]); const handleDragStart = (e: React.DragEvent) => { e.dataTransfer.setDragImage(emptyImg, 0, 0); setDragData({ dataTransfer: e.dataTransfer, dragData }); e.dataTransfer.effectAllowed = "copy"; setDragPosition({ x: e.clientX, y: e.clientY }); setIsDragging(true); onDragStart?.({ e }); }; const handleDragEnd = () => { setIsDragging(false); clearDragData(); }; return ( <> {variant === "card" ? (
{preview} {!isDragging && ( )} {shouldShowLabel && ( {name} )}
) : (
)} {isDraggable && isDragging && typeof document !== "undefined" && createPortal(
{preview}
{shouldShowPlusOnDrag && ( )}
, document.body, )} ); } function PlusButton({ className, onClick, tooltipText, }: { className?: string; onClick?: () => void; tooltipText?: string; }) { const button = ( ); if (tooltipText) { return ( {button}

{tooltipText}

); } return button; }