import { useDroppable } from "@dnd-kit/core" import { useRef, useState } from "react" import { Transition } from "@/features/transitions/types/transitions" import { cn } from "@/lib/utils" import { TimelineClip } from "../../types/timeline" interface TransitionDropZoneProps { leftClip: TimelineClip rightClip: TimelineClip trackId: string timeScale: number onDrop: (transition: Transition) => void disabled?: boolean className?: string } /** * Зона для drag & drop переходов между клипами */ export function TransitionDropZone({ leftClip, rightClip, trackId, timeScale, _onDrop, disabled = false, className, }: TransitionDropZoneProps) { const [isHovered, setIsHovered] = useState(false) const dropZoneRef = useRef(null) // Вычисляем позицию и размер зоны const leftEnd = leftClip.startTime + leftClip.duration const rightStart = rightClip.startTime const gap = rightStart - leftEnd // Позиция зоны - середина между клипами const position = leftEnd + gap / 2 const left = position * timeScale // Настраиваем drop zone с @dnd-kit const { isOver, setNodeRef } = useDroppable({ id: `transition-drop-${leftClip.id}-${rightClip.id}`, disabled, data: { type: "transition-drop", leftClipId: leftClip.id, rightClipId: rightClip.id, trackId, }, }) // Drop обрабатывается через DndContext в родительском компоненте // Если клипы не соседние, не показываем зону if (Math.abs(gap) > 0.01) { return null } return (
{ setNodeRef(el) if (dropZoneRef.current !== el) { dropZoneRef.current = el } }} className={cn("absolute top-0 bottom-0 z-10", "transition-all duration-200", isOver && "scale-110", className)} style={{ left: left - 15, // Центрируем зону width: 30, // Ширина зоны }} onMouseEnter={() => setIsHovered(true)} onMouseLeave={() => setIsHovered(false)} > {/* Визуальный индикатор */}
{/* Центральная линия */}
{/* Иконка при наведении */} {(isOver || isHovered) && (
+
)}
{/* Подсказка при наведении */} {isOver && (
Отпустите для добавления перехода
)}
) }