diff --git a/apps/web/src/hooks/use-timeline-element-resize.ts b/apps/web/src/hooks/use-timeline-element-resize.ts index 3afa637b..e7d46dff 100644 --- a/apps/web/src/hooks/use-timeline-element-resize.ts +++ b/apps/web/src/hooks/use-timeline-element-resize.ts @@ -133,8 +133,10 @@ export function useTimelineElementResize({ if (canExtendElementDuration()) { // Text/Image: extend element to the left by moving startTime and increasing duration const extensionAmount = Math.abs(calculated); - const newStartTime = element.startTime - extensionAmount; - const newDuration = element.duration + extensionAmount; + const maxExtension = element.startTime; + const actualExtension = Math.min(extensionAmount, maxExtension); + const newStartTime = element.startTime - actualExtension; + const newDuration = element.duration + actualExtension; // Keep trimStart at 0 and extend the element updateElementTrim( diff --git a/apps/web/src/stores/timeline-store.ts b/apps/web/src/stores/timeline-store.ts index 6f9dfbd6..9e3f56d6 100644 --- a/apps/web/src/stores/timeline-store.ts +++ b/apps/web/src/stores/timeline-store.ts @@ -754,13 +754,16 @@ export const useTimelineStore = create((set, get) => { pushHistory = true ) => { if (pushHistory) get().pushHistory(); + const clampedStartTime = Math.max(0, startTime); updateTracksAndSave( get()._tracks.map((track) => track.id === trackId ? { ...track, elements: track.elements.map((element) => - element.id === elementId ? { ...element, startTime } : element + element.id === elementId + ? { ...element, startTime: clampedStartTime } + : element ), } : track @@ -799,8 +802,7 @@ export const useTimelineStore = create((set, get) => { const updatedElements = currentTrack.elements.map((currentElement) => { if (currentElement.id === elementId && currentTrack.id === trackId) { - // Update the moved element - return { ...currentElement, startTime: newStartTime }; + return { ...currentElement, startTime: Math.max(0, newStartTime) }; } // Only apply ripple effects if we should process this track