fix timeline zoom + selection box issues

This commit is contained in:
Maze Winther
2026-01-24 06:42:39 +01:00
parent 7de8e4172f
commit 33f453efc7
4 changed files with 10 additions and 11 deletions
-1
View File
@@ -281,7 +281,6 @@ use-timeline-snapping.ts
use-timeline-zoom.ts use-timeline-zoom.ts
export function useTimelineZoom({ export function useTimelineZoom({
containerRef, containerRef,
isInTimeline = false,
minZoom = TIMELINE_CONSTANTS.ZOOM_MIN, minZoom = TIMELINE_CONSTANTS.ZOOM_MIN,
}: UseTimelineZoomProps): UseTimelineZoomReturn }: UseTimelineZoomProps): UseTimelineZoomReturn
@@ -71,7 +71,6 @@ export function Timeline() {
const bookmarksScrollRef = useRef<HTMLDivElement>(null); const bookmarksScrollRef = useRef<HTMLDivElement>(null);
// state // state
const [isInTimeline, setIsInTimeline] = useState(false);
const [isResizing, setIsResizing] = useState(false); const [isResizing, setIsResizing] = useState(false);
const [currentSnapPoint, setCurrentSnapPoint] = useState<SnapPoint | null>( const [currentSnapPoint, setCurrentSnapPoint] = useState<SnapPoint | null>(
null, null,
@@ -98,7 +97,6 @@ export function Timeline() {
const { zoomLevel, setZoomLevel, handleWheel } = useTimelineZoom({ const { zoomLevel, setZoomLevel, handleWheel } = useTimelineZoom({
containerRef: timelineRef, containerRef: timelineRef,
isInTimeline,
minZoom: minZoomLevel, minZoom: minZoomLevel,
}); });
@@ -187,8 +185,6 @@ export function Timeline() {
} }
{...dragProps} {...dragProps}
aria-label="Timeline" aria-label="Timeline"
onMouseEnter={() => setIsInTimeline(true)}
onMouseLeave={() => setIsInTimeline(false)}
> >
<TimelineToolbar <TimelineToolbar
zoomLevel={zoomLevel} zoomLevel={zoomLevel}
@@ -400,6 +396,7 @@ export function Timeline() {
onResizeStateChange={handleResizeStateChange} onResizeStateChange={handleResizeStateChange}
onElementMouseDown={handleElementMouseDown} onElementMouseDown={handleElementMouseDown}
onElementClick={handleElementClick} onElementClick={handleElementClick}
onTrackMouseDown={handleSelectionMouseDown}
/> />
</div> </div>
</ContextMenuTrigger> </ContextMenuTrigger>
@@ -30,6 +30,7 @@ interface TimelineTrackContentProps {
element: TimelineElementType; element: TimelineElementType;
track: TimelineTrack; track: TimelineTrack;
}) => void; }) => void;
onTrackMouseDown?: (event: React.MouseEvent) => void;
} }
export function TimelineTrackContent({ export function TimelineTrackContent({
@@ -43,6 +44,7 @@ export function TimelineTrackContent({
onResizeStateChange, onResizeStateChange,
onElementMouseDown, onElementMouseDown,
onElementClick, onElementClick,
onTrackMouseDown,
}: TimelineTrackContentProps) { }: TimelineTrackContentProps) {
const editor = useEditor(); const editor = useEditor();
const { isElementSelected, clearElementSelection } = useElementSelection(); const { isElementSelected, clearElementSelection } = useElementSelection();
@@ -65,6 +67,9 @@ export function TimelineTrackContent({
<button <button
className={cn("size-full", hasSelectedElements && "bg-panel-accent/35")} className={cn("size-full", hasSelectedElements && "bg-panel-accent/35")}
onClick={clearElementSelection} onClick={clearElementSelection}
onMouseDown={(event) => {
onTrackMouseDown?.(event);
}}
type="button" type="button"
> >
<div className="relative h-full min-w-full"> <div className="relative h-full min-w-full">
@@ -9,7 +9,6 @@ import { TIMELINE_CONSTANTS } from "@/constants/timeline-constants";
interface UseTimelineZoomProps { interface UseTimelineZoomProps {
containerRef: RefObject<HTMLDivElement>; containerRef: RefObject<HTMLDivElement>;
isInTimeline?: boolean;
minZoom?: number; minZoom?: number;
} }
@@ -21,7 +20,6 @@ interface UseTimelineZoomReturn {
export function useTimelineZoom({ export function useTimelineZoom({
containerRef, containerRef,
isInTimeline = false,
minZoom = TIMELINE_CONSTANTS.ZOOM_MIN, minZoom = TIMELINE_CONSTANTS.ZOOM_MIN,
}: UseTimelineZoomProps): UseTimelineZoomReturn { }: UseTimelineZoomProps): UseTimelineZoomReturn {
const [zoomLevel, setZoomLevel] = useState(1); const [zoomLevel, setZoomLevel] = useState(1);
@@ -65,9 +63,9 @@ export function useTimelineZoom({
const isInContainer = containerRef.current?.contains( const isInContainer = containerRef.current?.contains(
event.target as Node, event.target as Node,
); );
const shouldPrevent = // only check isInContainer, not isInTimeline state - the state check
isInTimeline && isZoomKeyPressed && Boolean(isInContainer); // causes race conditions where the closure captures stale state
if (shouldPrevent) { if (isZoomKeyPressed && isInContainer) {
event.preventDefault(); event.preventDefault();
} }
}; };
@@ -80,7 +78,7 @@ export function useTimelineZoom({
return () => { return () => {
document.removeEventListener("wheel", preventZoom, { capture: true }); document.removeEventListener("wheel", preventZoom, { capture: true });
}; };
}, [isInTimeline, containerRef]); }, [containerRef]);
return { return {
zoomLevel, zoomLevel,