diff options
| author | Maze Winther <mazewinther@gmail.com> | 2026-03-27 00:55:15 +0100 |
|---|---|---|
| committer | Maze Winther <mazewinther@gmail.com> | 2026-03-29 15:56:48 +0200 |
| commit | 4d127a038bf768eded68aae3cfa5c1b12241bdac (patch) | |
| tree | 16bbb801caf6770546cff4fdb37b6408ec9ead98 /apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts | |
| parent | 82817cb50cb0487350573d6129130aec705f924b (diff) | |
| download | opencut-4d127a038bf768eded68aae3cfa5c1b12241bdac.tar.gz | |
chore: normalize line endings
Diffstat (limited to 'apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts')
| -rw-r--r-- | apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts | 84 |
1 files changed, 42 insertions, 42 deletions
diff --git a/apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts b/apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts index 50833f14..0b1cf92a 100644 --- a/apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts +++ b/apps/web/src/hooks/timeline/use-initial-scroll-bottom.ts @@ -1,42 +1,42 @@ -import { type RefObject, useLayoutEffect, useRef } from "react"; - -interface UseInitialScrollBottomProps { - tracksScrollRef: RefObject<HTMLDivElement | null>; - trackLabelsScrollRef: RefObject<HTMLDivElement | null>; - onAfterScroll?: () => void; - /** Defers the scroll until there is at least one track to measure against. */ - isReady: boolean; -} - -/** - * Scrolls the timeline tracks viewport to the bottom once on mount. - * useLayoutEffect runs synchronously after React commits the DOM but before - * the browser paints, so the initial scroll position is never visible. - */ -export function useInitialScrollBottom({ - tracksScrollRef, - trackLabelsScrollRef, - onAfterScroll, - isReady, -}: UseInitialScrollBottomProps): void { - const hasScrolledRef = useRef(false); - - useLayoutEffect(() => { - if (!isReady || hasScrolledRef.current) return; - - const viewport = tracksScrollRef.current; - if (!viewport) return; - - const maxScrollTop = viewport.scrollHeight - viewport.clientHeight; - if (maxScrollTop <= 0) return; - - viewport.scrollTop = maxScrollTop; - - if (trackLabelsScrollRef.current) { - trackLabelsScrollRef.current.scrollTop = maxScrollTop; - } - - onAfterScroll?.(); - hasScrolledRef.current = true; - }, [isReady, tracksScrollRef, trackLabelsScrollRef, onAfterScroll]); -} +import { type RefObject, useLayoutEffect, useRef } from "react";
+
+interface UseInitialScrollBottomProps {
+ tracksScrollRef: RefObject<HTMLDivElement | null>;
+ trackLabelsScrollRef: RefObject<HTMLDivElement | null>;
+ onAfterScroll?: () => void;
+ /** Defers the scroll until there is at least one track to measure against. */
+ isReady: boolean;
+}
+
+/**
+ * Scrolls the timeline tracks viewport to the bottom once on mount.
+ * useLayoutEffect runs synchronously after React commits the DOM but before
+ * the browser paints, so the initial scroll position is never visible.
+ */
+export function useInitialScrollBottom({
+ tracksScrollRef,
+ trackLabelsScrollRef,
+ onAfterScroll,
+ isReady,
+}: UseInitialScrollBottomProps): void {
+ const hasScrolledRef = useRef(false);
+
+ useLayoutEffect(() => {
+ if (!isReady || hasScrolledRef.current) return;
+
+ const viewport = tracksScrollRef.current;
+ if (!viewport) return;
+
+ const maxScrollTop = viewport.scrollHeight - viewport.clientHeight;
+ if (maxScrollTop <= 0) return;
+
+ viewport.scrollTop = maxScrollTop;
+
+ if (trackLabelsScrollRef.current) {
+ trackLabelsScrollRef.current.scrollTop = maxScrollTop;
+ }
+
+ onAfterScroll?.();
+ hasScrolledRef.current = true;
+ }, [isReady, tracksScrollRef, trackLabelsScrollRef, onAfterScroll]);
+}
|
