From bd9ec023eefc4b5d26fa8b66c4338e97104f0f96 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Wed, 1 Apr 2026 19:27:49 +0200 Subject: refactor: split constants by domain and isolate timeline panel from core --- apps/web/src/lib/timeline/drop-utils.ts | 257 -------------------------------- 1 file changed, 257 deletions(-) delete mode 100644 apps/web/src/lib/timeline/drop-utils.ts (limited to 'apps/web/src/lib/timeline/drop-utils.ts') diff --git a/apps/web/src/lib/timeline/drop-utils.ts b/apps/web/src/lib/timeline/drop-utils.ts deleted file mode 100644 index 161d2714..00000000 --- a/apps/web/src/lib/timeline/drop-utils.ts +++ /dev/null @@ -1,257 +0,0 @@ -import type { - TimelineTrack, - TimelineElement, -} from "@/lib/timeline"; -import { TRACK_CONFIG, TRACK_GAP } from "@/constants/timeline-constants"; -import type { ComputeDropTargetParams, DropTarget } from "@/lib/timeline"; -import { resolveTrackPlacement } from "@/lib/timeline/placement"; - -function findElementAtPosition({ - mouseX, - tracks, - trackIndex, - targetElementTypes, - pixelsPerSecond, - zoomLevel, -}: { - mouseX: number; - tracks: TimelineTrack[]; - trackIndex: number; - targetElementTypes: string[]; - pixelsPerSecond: number; - zoomLevel: number; -}): { elementId: string; trackId: string } | null { - const time = mouseX / (pixelsPerSecond * zoomLevel); - const track = tracks[trackIndex]; - if (!track || !("elements" in track)) return null; - - const hit = track.elements.find( - (element: TimelineElement) => - targetElementTypes.includes(element.type) && - element.startTime <= time && - time < element.startTime + element.duration, - ); - if (!hit) return null; - return { elementId: hit.id, trackId: track.id }; -} - -function getTrackAtY({ - mouseY, - tracks, - verticalDragDirection, -}: { - mouseY: number; - tracks: TimelineTrack[]; - verticalDragDirection?: "up" | "down" | null; -}): { trackIndex: number; relativeY: number } | null { - let cumulativeHeight = 0; - - for (let i = 0; i < tracks.length; i++) { - const trackHeight = TRACK_CONFIG[tracks[i].type].height; - const trackTop = cumulativeHeight; - const trackBottom = trackTop + trackHeight; - - if (mouseY >= trackTop && mouseY < trackBottom) { - return { - trackIndex: i, - relativeY: mouseY - trackTop, - }; - } - - if (i < tracks.length - 1 && verticalDragDirection) { - const gapTop = trackBottom; - const gapBottom = gapTop + TRACK_GAP; - if (mouseY >= gapTop && mouseY < gapBottom) { - const isDraggingUp = verticalDragDirection === "up"; - return { - trackIndex: isDraggingUp ? i : i + 1, - relativeY: isDraggingUp ? trackHeight - 1 : 0, - }; - } - } - - cumulativeHeight += trackHeight + TRACK_GAP; - } - - return null; -} - -const EMPTY_TARGET_ELEMENT = null; - -function fallbackNewTrackDropTarget({ - xPosition, -}: { - xPosition: number; -}): DropTarget { - return { - trackIndex: 0, - isNewTrack: true, - insertPosition: null, - xPosition, - targetElement: EMPTY_TARGET_ELEMENT, - }; -} - -export function computeDropTarget({ - elementType, - mouseX, - mouseY, - tracks, - playheadTime, - isExternalDrop, - elementDuration, - pixelsPerSecond, - zoomLevel, - verticalDragDirection, - startTimeOverride, - excludeElementId, - targetElementTypes, -}: ComputeDropTargetParams): DropTarget { - const xPosition = - typeof startTimeOverride === "number" - ? startTimeOverride - : isExternalDrop - ? playheadTime - : Math.max(0, mouseX / (pixelsPerSecond * zoomLevel)); - - if (tracks.length === 0) { - const placementResult = resolveTrackPlacement({ - tracks, - elementType, - timeSpans: [{ startTime: xPosition, duration: elementDuration, excludeElementId }], - strategy: { - type: "preferIndex", - trackIndex: 0, - hoverDirection: "below", - createNewTrackOnly: true, - }, - }); - const emptyTimelineResult = - placementResult?.kind === "newTrack" ? placementResult : null; - if (!emptyTimelineResult) { - return fallbackNewTrackDropTarget({ xPosition }); - } - - return { - trackIndex: emptyTimelineResult.insertIndex, - isNewTrack: true, - insertPosition: emptyTimelineResult.insertPosition, - xPosition, - targetElement: EMPTY_TARGET_ELEMENT, - }; - } - - const trackAtMouse = getTrackAtY({ mouseY, tracks, verticalDragDirection }); - - if (!trackAtMouse) { - const isAboveAllTracks = mouseY < 0; - - const placementResult = resolveTrackPlacement({ - tracks, - elementType, - timeSpans: [{ startTime: xPosition, duration: elementDuration, excludeElementId }], - strategy: { - type: "preferIndex", - trackIndex: isAboveAllTracks ? 0 : tracks.length - 1, - hoverDirection: isAboveAllTracks ? "above" : "below", - createNewTrackOnly: true, - }, - }); - const outOfBoundsResult = - placementResult?.kind === "newTrack" ? placementResult : null; - if (!outOfBoundsResult) { - return fallbackNewTrackDropTarget({ xPosition }); - } - - return { - trackIndex: outOfBoundsResult.insertIndex, - isNewTrack: true, - insertPosition: outOfBoundsResult.insertPosition, - xPosition, - targetElement: EMPTY_TARGET_ELEMENT, - }; - } - - const { trackIndex, relativeY } = trackAtMouse; - const track = tracks[trackIndex]; - - if ( - targetElementTypes && - targetElementTypes.length > 0 - ) { - const targetElement = findElementAtPosition({ - mouseX, - tracks, - trackIndex, - targetElementTypes, - pixelsPerSecond, - zoomLevel, - }); - if (targetElement) { - return { - trackIndex, - isNewTrack: false, - insertPosition: null, - xPosition, - targetElement, - }; - } - } - - const trackHeight = TRACK_CONFIG[track.type].height; - const placementResult = resolveTrackPlacement({ - tracks, - elementType, - timeSpans: [{ startTime: xPosition, duration: elementDuration, excludeElementId }], - strategy: { - type: "preferIndex", - trackIndex, - hoverDirection: relativeY < trackHeight / 2 ? "above" : "below", - verticalDragDirection, - }, - }); - if (!placementResult) { - return fallbackNewTrackDropTarget({ xPosition }); - } - - if (placementResult.kind === "existingTrack") { - const adjustedXPosition = - placementResult.adjustedStartTime ?? xPosition; - - return { - trackIndex: placementResult.trackIndex, - isNewTrack: false, - insertPosition: null, - xPosition: adjustedXPosition, - targetElement: EMPTY_TARGET_ELEMENT, - }; - } - - return { - trackIndex: placementResult.insertIndex, - isNewTrack: true, - insertPosition: placementResult.insertPosition, - xPosition, - targetElement: EMPTY_TARGET_ELEMENT, - }; -} - -export function getDropLineY({ - dropTarget, - tracks, -}: { - dropTarget: DropTarget; - tracks: TimelineTrack[]; -}): number { - const safeTrackIndex = Math.min( - Math.max(dropTarget.trackIndex, 0), - tracks.length, - ); - let y = 0; - - for (let i = 0; i < safeTrackIndex; i++) { - y += TRACK_CONFIG[tracks[i].type].height + TRACK_GAP; - } - - return y; -} -- cgit v1.3.1