UNPKG

@assistant-ui/react

Version:

Typescript/React library for AI Chat

68 lines (67 loc) 2.51 kB
"use client"; // src/primitives/thread/useThreadViewportAutoScroll.tsx import { useComposedRefs } from "@radix-ui/react-compose-refs"; import { useEffect, useRef } from "react"; import { useThreadRuntime } from "../../context/react/ThreadContext.mjs"; import { useOnResizeContent } from "../../utils/hooks/useOnResizeContent.mjs"; import { useOnScrollToBottom } from "../../utils/hooks/useOnScrollToBottom.mjs"; import { useManagedRef } from "../../utils/hooks/useManagedRef.mjs"; import { writableStore } from "../../context/ReadonlyStore.mjs"; import { useThreadViewportStore } from "../../context/react/ThreadViewportContext.mjs"; var useThreadViewportAutoScroll = ({ autoScroll = true }) => { const divRef = useRef(null); const threadViewportStore = useThreadViewportStore(); const lastScrollTop = useRef(0); const isScrollingToBottomRef = useRef(false); const scrollToBottom = (behavior) => { const div = divRef.current; if (!div || !autoScroll) return; isScrollingToBottomRef.current = true; div.scrollTo({ top: div.scrollHeight, behavior }); }; const handleScroll = () => { const div = divRef.current; if (!div) return; const isAtBottom = threadViewportStore.getState().isAtBottom; const newIsAtBottom = div.scrollHeight - div.scrollTop <= div.clientHeight + 1; if (!newIsAtBottom && lastScrollTop.current < div.scrollTop) { } else { if (newIsAtBottom) { isScrollingToBottomRef.current = false; } if (newIsAtBottom !== isAtBottom) { writableStore(threadViewportStore).setState({ isAtBottom: newIsAtBottom }); } } lastScrollTop.current = div.scrollTop; }; const resizeRef = useOnResizeContent(() => { if (isScrollingToBottomRef.current || threadViewportStore.getState().isAtBottom) { scrollToBottom("instant"); } handleScroll(); }); const scrollRef = useManagedRef((el) => { el.addEventListener("scroll", handleScroll); return () => { el.removeEventListener("scroll", handleScroll); }; }); useOnScrollToBottom(() => { scrollToBottom("auto"); }); const threadRuntime = useThreadRuntime(); useEffect(() => { return threadRuntime.unstable_on("run-start", () => scrollToBottom("auto")); }, [scrollToBottom, threadRuntime]); const autoScrollRef = useComposedRefs(resizeRef, scrollRef, divRef); return autoScrollRef; }; export { useThreadViewportAutoScroll }; //# sourceMappingURL=useThreadViewportAutoScroll.mjs.map