summaryrefslogtreecommitdiff
path: root/apps/web/src/hooks
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2026-04-01 19:27:49 +0200
committerMaze Winther <mazewinther@gmail.com>2026-04-01 19:27:49 +0200
commitbd9ec023eefc4b5d26fa8b66c4338e97104f0f96 (patch)
tree08350eaa107b27f026eebdb65df54b1ca25521fd /apps/web/src/hooks
parentf4b9f40ab1ba1cedf208bba708f4331d36bb30cc (diff)
downloadopencut-bd9ec023eefc4b5d26fa8b66c4338e97104f0f96.tar.gz
refactor: split constants by domain and isolate timeline panel from core
Diffstat (limited to 'apps/web/src/hooks')
-rw-r--r--apps/web/src/hooks/timeline/element/use-element-interaction.ts27
-rw-r--r--apps/web/src/hooks/timeline/element/use-element-resize.ts4
-rw-r--r--apps/web/src/hooks/timeline/element/use-keyframe-drag.ts13
-rw-r--r--apps/web/src/hooks/timeline/use-bookmark-drag.ts7
-rw-r--r--apps/web/src/hooks/timeline/use-snap-indicator-position.ts5
-rw-r--r--apps/web/src/hooks/timeline/use-timeline-drag-drop.ts19
-rw-r--r--apps/web/src/hooks/timeline/use-timeline-playhead.ts10
-rw-r--r--apps/web/src/hooks/timeline/use-timeline-seek.ts4
-rw-r--r--apps/web/src/hooks/timeline/use-timeline-zoom.ts33
-rw-r--r--apps/web/src/hooks/use-paste-media.ts4
10 files changed, 72 insertions, 54 deletions
diff --git a/apps/web/src/hooks/timeline/element/use-element-interaction.ts b/apps/web/src/hooks/timeline/element/use-element-interaction.ts
index 3e0a6997..193379ed 100644
--- a/apps/web/src/hooks/timeline/element/use-element-interaction.ts
+++ b/apps/web/src/hooks/timeline/element/use-element-interaction.ts
@@ -10,12 +10,10 @@ import { useEditor } from "@/hooks/use-editor";
import { useShiftKey } from "@/hooks/use-shift-key";
import { useTimelineStore } from "@/stores/timeline-store";
import { useElementSelection } from "@/hooks/timeline/element/use-element-selection";
-import {
- DRAG_THRESHOLD_PX,
- TIMELINE_CONSTANTS,
-} from "@/constants/timeline-constants";
+import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/lib/timeline/scale";
+import { TIMELINE_DRAG_THRESHOLD_PX } from "@/components/editor/panels/timeline/interaction";
import { snapTimeToFrame } from "opencut-wasm";
-import { computeDropTarget } from "@/lib/timeline/drop-utils";
+import { computeDropTarget } from "@/components/editor/panels/timeline/drop-target";
import { getMouseTimeFromClientX } from "@/lib/timeline/drag-utils";
import { generateUUID } from "@/utils/id";
import { snapElementEdge, type SnapPoint } from "@/lib/timeline/snap-utils";
@@ -70,7 +68,7 @@ function getClickOffsetTime({
zoomLevel: number;
}): number {
const clickOffsetX = clientX - elementRect.left;
- return clickOffsetX / (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel);
+ return clickOffsetX / (BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel);
}
function getVerticalDragDirection({
@@ -136,7 +134,7 @@ function getDragDropTarget({
playheadTime: snappedTime,
isExternalDrop: false,
elementDuration,
- pixelsPerSecond: TIMELINE_CONSTANTS.PIXELS_PER_SECOND,
+ pixelsPerSecond: BASE_TIMELINE_PIXELS_PER_SECOND,
zoomLevel,
startTimeOverride: snappedTime,
excludeElementId: movingElement.id,
@@ -288,7 +286,10 @@ export function useElementInteraction({
if (isPendingDrag && pendingDragRef.current) {
const deltaX = Math.abs(clientX - pendingDragRef.current.startMouseX);
const deltaY = Math.abs(clientY - pendingDragRef.current.startMouseY);
- if (deltaX > DRAG_THRESHOLD_PX || deltaY > DRAG_THRESHOLD_PX) {
+ if (
+ deltaX > TIMELINE_DRAG_THRESHOLD_PX ||
+ deltaY > TIMELINE_DRAG_THRESHOLD_PX
+ ) {
const activeProject = editor.project.getActive();
if (!activeProject) return;
const scrollLeft = scrollContainer.scrollLeft;
@@ -416,7 +417,10 @@ export function useElementInteraction({
if (mouseDownLocationRef.current) {
const deltaX = Math.abs(clientX - mouseDownLocationRef.current.x);
const deltaY = Math.abs(clientY - mouseDownLocationRef.current.y);
- if (deltaX <= DRAG_THRESHOLD_PX && deltaY <= DRAG_THRESHOLD_PX) {
+ if (
+ deltaX <= TIMELINE_DRAG_THRESHOLD_PX &&
+ deltaY <= TIMELINE_DRAG_THRESHOLD_PX
+ ) {
mouseDownLocationRef.current = null;
endDrag();
onSnapPointChange?.(null);
@@ -596,7 +600,10 @@ export function useElementInteraction({
if (mouseDownLocationRef.current) {
const deltaX = Math.abs(event.clientX - mouseDownLocationRef.current.x);
const deltaY = Math.abs(event.clientY - mouseDownLocationRef.current.y);
- if (deltaX > DRAG_THRESHOLD_PX || deltaY > DRAG_THRESHOLD_PX) {
+ if (
+ deltaX > TIMELINE_DRAG_THRESHOLD_PX ||
+ deltaY > TIMELINE_DRAG_THRESHOLD_PX
+ ) {
mouseDownLocationRef.current = null;
return;
}
diff --git a/apps/web/src/hooks/timeline/element/use-element-resize.ts b/apps/web/src/hooks/timeline/element/use-element-resize.ts
index 26bd8ef9..890820d7 100644
--- a/apps/web/src/hooks/timeline/element/use-element-resize.ts
+++ b/apps/web/src/hooks/timeline/element/use-element-resize.ts
@@ -1,5 +1,5 @@
import { useState, useEffect, useRef, useCallback } from "react";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/lib/timeline/scale";
import { snapTimeToFrame } from "opencut-wasm";
import type { TimelineElement, TimelineTrack } from "@/lib/timeline";
import { useEditor } from "@/hooks/use-editor";
@@ -190,7 +190,7 @@ export function useTimelineElementResize({
const deltaX = clientX - resizing.startX;
let deltaTime =
- deltaX / (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel);
+ deltaX / (BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel);
let resizeSnapPoint: SnapPoint | null = null;
const projectFps = editor.project.getActive().settings.fps;
diff --git a/apps/web/src/hooks/timeline/element/use-keyframe-drag.ts b/apps/web/src/hooks/timeline/element/use-keyframe-drag.ts
index e0bf8084..bbe843f2 100644
--- a/apps/web/src/hooks/timeline/element/use-keyframe-drag.ts
+++ b/apps/web/src/hooks/timeline/element/use-keyframe-drag.ts
@@ -9,10 +9,8 @@ import { useEditor } from "@/hooks/use-editor";
import { useKeyframeSelection } from "./use-keyframe-selection";
import { snapTimeToFrame, getSnappedSeekTime } from "opencut-wasm";
import { timelineTimeToSnappedPixels } from "@/lib/timeline";
-import {
- DRAG_THRESHOLD_PX,
- TIMELINE_CONSTANTS,
-} from "@/constants/timeline-constants";
+import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/lib/timeline/scale";
+import { TIMELINE_DRAG_THRESHOLD_PX } from "@/components/editor/panels/timeline/interaction";
import { RetimeKeyframeCommand } from "@/lib/commands/timeline/element/keyframes/retime-keyframe";
import { BatchCommand } from "@/lib/commands";
import type { SelectedKeyframeRef } from "@/lib/animation/types";
@@ -64,7 +62,7 @@ export function useKeyframeDrag({
const activeProject = editor.project.getActive();
const fps = activeProject.settings.fps;
- const pixelsPerSecond = TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel;
+ const pixelsPerSecond = BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel;
const endDrag = useCallback(() => {
setDragState(initialDragState);
@@ -127,7 +125,7 @@ export function useKeyframeDrag({
const handleMouseMove = ({ clientX }: MouseEvent) => {
if (isPendingDrag && pendingDragRef.current) {
const deltaX = Math.abs(clientX - pendingDragRef.current.startMouseX);
- if (deltaX <= DRAG_THRESHOLD_PX) return;
+ if (deltaX <= TIMELINE_DRAG_THRESHOLD_PX) return;
const pending = pendingDragRef.current;
pendingDragRef.current = null;
@@ -248,7 +246,8 @@ export function useKeyframeDrag({
const wasDrag =
mouseDownXRef.current !== null &&
- Math.abs(event.clientX - mouseDownXRef.current) > DRAG_THRESHOLD_PX;
+ Math.abs(event.clientX - mouseDownXRef.current) >
+ TIMELINE_DRAG_THRESHOLD_PX;
mouseDownXRef.current = null;
if (wasDrag) return;
diff --git a/apps/web/src/hooks/timeline/use-bookmark-drag.ts b/apps/web/src/hooks/timeline/use-bookmark-drag.ts
index 4a1185bd..14d58d9a 100644
--- a/apps/web/src/hooks/timeline/use-bookmark-drag.ts
+++ b/apps/web/src/hooks/timeline/use-bookmark-drag.ts
@@ -7,7 +7,7 @@ import {
} from "react";
import { useEditor } from "@/hooks/use-editor";
import { useShiftKey } from "@/hooks/use-shift-key";
-import { DRAG_THRESHOLD_PX } from "@/constants/timeline-constants";
+import { TIMELINE_DRAG_THRESHOLD_PX } from "@/components/editor/panels/timeline/interaction";
import { snapTimeToFrame } from "opencut-wasm";
import { getMouseTimeFromClientX } from "@/lib/timeline/drag-utils";
import {
@@ -131,7 +131,10 @@ export function useBookmarkDrag({
const deltaX = Math.abs(event.clientX - startMouseX);
const deltaY = Math.abs(event.clientY - startMouseY);
- if (deltaX <= DRAG_THRESHOLD_PX && deltaY <= DRAG_THRESHOLD_PX) {
+ if (
+ deltaX <= TIMELINE_DRAG_THRESHOLD_PX &&
+ deltaY <= TIMELINE_DRAG_THRESHOLD_PX
+ ) {
return;
}
diff --git a/apps/web/src/hooks/timeline/use-snap-indicator-position.ts b/apps/web/src/hooks/timeline/use-snap-indicator-position.ts
index 3dc34b7f..b941dcb5 100644
--- a/apps/web/src/hooks/timeline/use-snap-indicator-position.ts
+++ b/apps/web/src/hooks/timeline/use-snap-indicator-position.ts
@@ -1,6 +1,6 @@
import { useEffect, useState } from "react";
import { timelineTimeToSnappedPixels } from "@/lib/timeline";
-import { TRACK_LABELS_WIDTH_PX } from "@/constants/timeline-constants";
+import { TIMELINE_TRACK_LABELS_COLUMN_WIDTH_PX } from "@/components/editor/panels/timeline/layout";
interface UseSnapIndicatorPositionParams {
snapPoint: { time: number } | null;
zoomLevel: number;
@@ -44,7 +44,8 @@ export function useSnapIndicatorPosition({
time: snapPoint?.time ?? 0,
zoomLevel,
});
- const leftPosition = TRACK_LABELS_WIDTH_PX + timelinePosition - scrollLeft;
+ const leftPosition =
+ TIMELINE_TRACK_LABELS_COLUMN_WIDTH_PX + timelinePosition - scrollLeft;
return {
leftPosition,
diff --git a/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts b/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
index ce6f1341..8e87510c 100644
--- a/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
+++ b/apps/web/src/hooks/timeline/use-timeline-drag-drop.ts
@@ -3,7 +3,8 @@ import { useEditor } from "@/hooks/use-editor";
import { processMediaAssets } from "@/lib/media/processing";
import { toast } from "sonner";
import { showMediaUploadToast } from "@/lib/media/upload-toast";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import { DEFAULT_NEW_ELEMENT_DURATION_SECONDS } from "@/lib/timeline/creation";
+import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/lib/timeline/scale";
import { snapTimeToFrame } from "opencut-wasm";
import {
buildTextElement,
@@ -14,7 +15,7 @@ import {
} from "@/lib/timeline/element-utils";
import { AddTrackCommand, InsertElementCommand } from "@/lib/commands/timeline";
import { BatchCommand } from "@/lib/commands";
-import { computeDropTarget } from "@/lib/timeline/drop-utils";
+import { computeDropTarget } from "@/components/editor/panels/timeline/drop-target";
import { getDragData, hasDragData } from "@/lib/drag-data";
import { isMainTrack } from "@/lib/timeline/placement";
import type { TrackType, DropTarget, ElementType } from "@/lib/timeline";
@@ -82,14 +83,14 @@ export function useTimelineDragDrop({
elementType === "sticker" ||
elementType === "effect"
) {
- return TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ return DEFAULT_NEW_ELEMENT_DURATION_SECONDS;
}
if (mediaId) {
const mediaAssets = editor.media.getAssets();
const media = mediaAssets.find((m) => m.id === mediaId);
- return media?.duration ?? TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ return media?.duration ?? DEFAULT_NEW_ELEMENT_DURATION_SECONDS;
}
- return TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ return DEFAULT_NEW_ELEMENT_DURATION_SECONDS;
},
[editor],
);
@@ -158,7 +159,7 @@ export function useTimelineDragDrop({
playheadTime: currentTime,
isExternalDrop: isExternal,
elementDuration: duration,
- pixelsPerSecond: TIMELINE_CONSTANTS.PIXELS_PER_SECOND,
+ pixelsPerSecond: BASE_TIMELINE_PIXELS_PER_SECOND,
zoomLevel,
targetElementTypes,
});
@@ -330,7 +331,7 @@ export function useTimelineDragDrop({
dragData.mediaType === "audio" ? "audio" : "video";
const duration =
- mediaAsset.duration ?? TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ mediaAsset.duration ?? DEFAULT_NEW_ELEMENT_DURATION_SECONDS;
const element = buildElementFromMedia({
mediaId: mediaAsset.id,
mediaType: mediaAsset.type,
@@ -445,7 +446,7 @@ export function useTimelineDragDrop({
const duration =
createdAsset.duration ??
- TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ DEFAULT_NEW_ELEMENT_DURATION_SECONDS;
const currentTracks = editor.timeline.getTracks();
const currentTime = editor.playback.getCurrentTime();
const onlyTrack = currentTracks[0];
@@ -467,7 +468,7 @@ export function useTimelineDragDrop({
playheadTime: currentTime,
isExternalDrop: true,
elementDuration: duration,
- pixelsPerSecond: TIMELINE_CONSTANTS.PIXELS_PER_SECOND,
+ pixelsPerSecond: BASE_TIMELINE_PIXELS_PER_SECOND,
zoomLevel,
});
diff --git a/apps/web/src/hooks/timeline/use-timeline-playhead.ts b/apps/web/src/hooks/timeline/use-timeline-playhead.ts
index d4cfcc06..fce84135 100644
--- a/apps/web/src/hooks/timeline/use-timeline-playhead.ts
+++ b/apps/web/src/hooks/timeline/use-timeline-playhead.ts
@@ -8,7 +8,7 @@ import {
getCenteredLineLeft,
timelineTimeToSnappedPixels,
} from "@/lib/timeline";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/lib/timeline/scale";
interface UseTimelinePlayheadProps {
zoomLevel: number;
@@ -67,7 +67,7 @@ export function useTimelinePlayhead({
const relativeMouseX = event.clientX - rulerRect.left;
const timelineContentWidth =
- duration * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel;
+ duration * BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel;
const clampedMouseX = Math.max(
0,
@@ -78,7 +78,7 @@ export function useTimelinePlayhead({
0,
Math.min(
duration,
- clampedMouseX / (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel),
+ clampedMouseX / (BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel),
),
);
@@ -161,7 +161,7 @@ export function useTimelinePlayhead({
getMouseClientX: () => lastMouseXRef.current,
rulerScrollRef,
tracksScrollRef,
- contentWidth: duration * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel,
+ contentWidth: duration * BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel,
});
useEffect(() => {
@@ -248,7 +248,7 @@ export function useTimelinePlayhead({
if (!rulerViewport || !tracksViewport) return;
const playheadPixels =
- time * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevelRef.current;
+ time * BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevelRef.current;
const viewportWidth = rulerViewport.clientWidth;
const scrollMinimum = 0;
const scrollMaximum = rulerViewport.scrollWidth - viewportWidth;
diff --git a/apps/web/src/hooks/timeline/use-timeline-seek.ts b/apps/web/src/hooks/timeline/use-timeline-seek.ts
index 2672062f..1690153e 100644
--- a/apps/web/src/hooks/timeline/use-timeline-seek.ts
+++ b/apps/web/src/hooks/timeline/use-timeline-seek.ts
@@ -1,6 +1,6 @@
import { useCallback, useRef } from "react";
import type { MutableRefObject, RefObject } from "react";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import { BASE_TIMELINE_PIXELS_PER_SECOND } from "@/lib/timeline/scale";
import { getSnappedSeekTime } from "opencut-wasm";
import { useEditor } from "../use-editor";
@@ -132,7 +132,7 @@ export function useTimelineSeek({
Math.min(
duration,
(mouseX + scrollLeft) /
- (TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel),
+ (BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel),
),
);
diff --git a/apps/web/src/hooks/timeline/use-timeline-zoom.ts b/apps/web/src/hooks/timeline/use-timeline-zoom.ts
index 64a0fb58..a1740384 100644
--- a/apps/web/src/hooks/timeline/use-timeline-zoom.ts
+++ b/apps/web/src/hooks/timeline/use-timeline-zoom.ts
@@ -7,7 +7,14 @@ import {
useRef,
useState,
} from "react";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import {
+ TIMELINE_ZOOM_ANCHOR_PLAYHEAD_THRESHOLD,
+} from "@/components/editor/panels/timeline/interaction";
+import {
+ TIMELINE_ZOOM_MAX,
+ TIMELINE_ZOOM_MIN,
+ BASE_TIMELINE_PIXELS_PER_SECOND,
+} from "@/lib/timeline/scale";
import { useEditor } from "@/hooks/use-editor";
import { zoomToSlider } from "@/lib/timeline/zoom-utils";
@@ -30,7 +37,7 @@ interface UseTimelineZoomReturn {
export function useTimelineZoom({
containerRef,
- minZoom = TIMELINE_CONSTANTS.ZOOM_MIN,
+ minZoom = TIMELINE_ZOOM_MIN,
initialZoom,
initialScrollLeft,
initialPlayheadTime,
@@ -49,7 +56,7 @@ export function useTimelineZoom({
hasInitializedRef.current = true;
return Math.max(
minZoom,
- Math.min(TIMELINE_CONSTANTS.ZOOM_MAX, initialZoom),
+ Math.min(TIMELINE_ZOOM_MAX, initialZoom),
);
}
return minZoom;
@@ -91,7 +98,7 @@ export function useTimelineZoom({
setZoomLevel((prev) => {
const nextZoom = Math.max(
minZoom,
- Math.min(TIMELINE_CONSTANTS.ZOOM_MAX, prev * zoomFactor),
+ Math.min(TIMELINE_ZOOM_MAX, prev * zoomFactor),
);
return nextZoom;
});
@@ -105,7 +112,7 @@ export function useTimelineZoom({
if (initialZoom !== undefined && !hasInitializedRef.current) {
hasInitializedRef.current = true;
setZoomLevel(
- Math.max(minZoom, Math.min(TIMELINE_CONSTANTS.ZOOM_MAX, initialZoom)),
+ Math.max(minZoom, Math.min(TIMELINE_ZOOM_MAX, initialZoom)),
);
return;
}
@@ -126,7 +133,7 @@ export function useTimelineZoom({
: zoomLevelOrUpdater;
const clampedZoom = Math.max(
minZoom,
- Math.min(TIMELINE_CONSTANTS.ZOOM_MAX, nextZoom),
+ Math.min(TIMELINE_ZOOM_MAX, nextZoom),
);
return clampedZoom;
});
@@ -153,12 +160,12 @@ export function useTimelineZoom({
});
const isCrossingThresholdUp =
previousSliderPercent <
- TIMELINE_CONSTANTS.ZOOM_ANCHOR_PLAYHEAD_THRESHOLD &&
- sliderPercent >= TIMELINE_CONSTANTS.ZOOM_ANCHOR_PLAYHEAD_THRESHOLD;
+ TIMELINE_ZOOM_ANCHOR_PLAYHEAD_THRESHOLD &&
+ sliderPercent >= TIMELINE_ZOOM_ANCHOR_PLAYHEAD_THRESHOLD;
const isCrossingThresholdDown =
previousSliderPercent >=
- TIMELINE_CONSTANTS.ZOOM_ANCHOR_PLAYHEAD_THRESHOLD &&
- sliderPercent < TIMELINE_CONSTANTS.ZOOM_ANCHOR_PLAYHEAD_THRESHOLD;
+ TIMELINE_ZOOM_ANCHOR_PLAYHEAD_THRESHOLD &&
+ sliderPercent < TIMELINE_ZOOM_ANCHOR_PLAYHEAD_THRESHOLD;
const syncScroll = (scrollLeft: number) => {
scrollElement.scrollLeft = scrollLeft;
@@ -178,11 +185,11 @@ export function useTimelineZoom({
isInPlayheadAnchorModeRef.current = true;
}
- if (sliderPercent >= TIMELINE_CONSTANTS.ZOOM_ANCHOR_PLAYHEAD_THRESHOLD) {
+ if (sliderPercent >= TIMELINE_ZOOM_ANCHOR_PLAYHEAD_THRESHOLD) {
const playheadPixelsBefore =
- playheadTime * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * previousZoom;
+ playheadTime * BASE_TIMELINE_PIXELS_PER_SECOND * previousZoom;
const playheadPixelsAfter =
- playheadTime * TIMELINE_CONSTANTS.PIXELS_PER_SECOND * zoomLevel;
+ playheadTime * BASE_TIMELINE_PIXELS_PER_SECOND * zoomLevel;
const viewportOffset = playheadPixelsBefore - currentScrollLeft;
const newScrollLeft = playheadPixelsAfter - viewportOffset;
diff --git a/apps/web/src/hooks/use-paste-media.ts b/apps/web/src/hooks/use-paste-media.ts
index 2c9c43ea..1cba34c0 100644
--- a/apps/web/src/hooks/use-paste-media.ts
+++ b/apps/web/src/hooks/use-paste-media.ts
@@ -7,7 +7,7 @@ import { buildElementFromMedia } from "@/lib/timeline/element-utils";
import { AddMediaAssetCommand } from "@/lib/commands/media";
import { InsertElementCommand } from "@/lib/commands/timeline";
import { BatchCommand } from "@/lib/commands";
-import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
+import { DEFAULT_NEW_ELEMENT_DURATION_SECONDS } from "@/lib/timeline/creation";
import { isTypableDOMElement } from "@/utils/browser";
import type { MediaType } from "@/lib/media/types";
@@ -74,7 +74,7 @@ export function usePasteMedia() {
);
const assetId = addMediaCmd.getAssetId();
const duration =
- asset.duration ?? TIMELINE_CONSTANTS.DEFAULT_ELEMENT_DURATION;
+ asset.duration ?? DEFAULT_NEW_ELEMENT_DURATION_SECONDS;
const trackType = asset.type === "audio" ? "audio" : "video";
const element = buildElementFromMedia({