import { useCallback, useRef, useState } from "react" import { cn } from "@/lib/utils" interface TransitionHandlesProps { transitionId: string duration: number position: number pixelsPerSecond: number timelineScale: number minDuration: number maxDuration: number onDurationChange: (id: string, duration: number) => void onPositionChange: (id: string, position: number) => void isLocked?: boolean } /** * Handles для изменения длительности и позиции перехода */ export function TransitionHandles({ transitionId, duration, position, pixelsPerSecond, timelineScale, minDuration, maxDuration, onDurationChange, onPositionChange, isLocked = false, }: TransitionHandlesProps) { const [isDragging, setIsDragging] = useState<"start" | "end" | null>(null) const dragStartRef = useRef<{ x: number; duration: number; position: number }>() // Обработчик начала перетаскивания const handleMouseDown = useCallback( (e: React.MouseEvent, handle: "start" | "end") => { if (isLocked) return e.preventDefault() e.stopPropagation() setIsDragging(handle) dragStartRef.current = { x: e.clientX, duration, position, } // Добавляем глобальные обработчики document.addEventListener("mousemove", handleMouseMove) document.addEventListener("mouseup", handleMouseUp) }, [duration, position, isLocked], ) // Обработчик перемещения мыши const handleMouseMove = useCallback( (e: MouseEvent) => { if (!isDragging || !dragStartRef.current) return const deltaX = e.clientX - dragStartRef.current.x const deltaTime = deltaX / (pixelsPerSecond * timelineScale) if (isDragging === "start") { // Изменяем позицию и длительность const newPosition = Math.max(0, dragStartRef.current.position + deltaTime) const newDuration = Math.max(minDuration, Math.min(maxDuration, dragStartRef.current.duration - deltaTime)) onPositionChange(transitionId, newPosition) onDurationChange(transitionId, newDuration) } else if (isDragging === "end") { // Изменяем только длительность const newDuration = Math.max(minDuration, Math.min(maxDuration, dragStartRef.current.duration + deltaTime)) onDurationChange(transitionId, newDuration) } }, [ isDragging, transitionId, pixelsPerSecond, timelineScale, minDuration, maxDuration, onDurationChange, onPositionChange, ], ) // Обработчик отпускания мыши const handleMouseUp = useCallback(() => { setIsDragging(null) dragStartRef.current = undefined // Удаляем глобальные обработчики document.removeEventListener("mousemove", handleMouseMove) document.removeEventListener("mouseup", handleMouseUp) }, [handleMouseMove]) return ( <> {/* Левый handle (начало) */}