@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
48 lines • 1.91 kB
JavaScript
import { useCallback, useEffect, useRef, useState } from 'react';
/**
* Follow a streaming transcript only while the reader is already at the bottom. Reading back
* through history during a stream is the case this exists for: an unconditional scroll-to-bottom
* yanks the viewport away mid-sentence on every token.
*/
export function useStickToBottom({ contentKey, threshold = 32, }) {
const containerRef = useRef(null);
const [isAtBottom, setIsAtBottom] = useState(true);
const measure = useCallback(() => {
const element = containerRef.current;
if (!element) {
return;
}
const distance = element.scrollHeight - element.scrollTop - element.clientHeight;
setIsAtBottom(distance <= threshold);
}, [threshold]);
const scrollToBottom = useCallback(() => {
const element = containerRef.current;
if (!element) {
return;
}
element.scrollTop = element.scrollHeight;
setIsAtBottom(true);
}, []);
const setContainer = useCallback((element) => {
containerRef.current = element;
if (element) {
measure();
}
}, [measure]);
// Re-pin as content arrives. Guarded on `isAtBottom` so a reader who scrolled up keeps their
// position for the rest of the stream, and re-pins the moment they scroll back down.
// biome-ignore lint/correctness/useExhaustiveDependencies: `contentKey` IS the content dependency
useEffect(() => {
if (isAtBottom) {
scrollToBottom();
}
}, [contentKey, isAtBottom, scrollToBottom]);
const getContainerProps = useCallback(() => ({ ref: setContainer, onScroll: measure }), [setContainer, measure]);
return {
isAtBottom,
showJumpToLatest: !isAtBottom,
scrollToBottom,
getContainerProps,
};
}
//# sourceMappingURL=use-stick-to-bottom.js.map