observe text changes as well

This commit is contained in:
Nate Kelley 2025-04-10 09:53:52 -06:00
parent 5524f5fd4e
commit cefe43e386
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
2 changed files with 93 additions and 18 deletions

View File

@ -300,3 +300,75 @@ export const ScrollAreaComponentWithAutoScroll: Story = {
);
}
};
export const RapidTextAppend: Story = {
render: () => {
const containerRef = useRef<HTMLDivElement>(null);
const [text, setText] = useState<string>('');
const [isRunning, setIsRunning] = useState(false);
const intervalRef = useRef<NodeJS.Timeout>();
const { isAutoScrollEnabled, enableAutoScroll, disableAutoScroll } = useAutoScroll(
containerRef,
{ observeDeepChanges: true }
);
const addWord = useCallback(() => {
const randomWord = faker.word.words(2);
setText((old) => old + ' ' + randomWord);
}, []);
const toggleRunning = useCallback(() => {
if (isRunning) {
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = undefined;
}
setIsRunning(false);
} else {
intervalRef.current = setInterval(addWord, 50);
setIsRunning(true);
enableAutoScroll();
}
}, [isRunning, addWord, enableAutoScroll]);
// Cleanup interval on unmount
useEffect(() => {
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
};
}, []);
return (
<div className="flex flex-col gap-4">
<div className="flex items-center gap-4">
<h3 className="text-lg font-semibold">Rapid Text Append</h3>
<div className="flex gap-2">
<button
onClick={toggleRunning}
className={`rounded px-3 py-1 text-sm text-white ${
isRunning ? 'bg-red-500 hover:bg-red-600' : 'bg-green-500 hover:bg-green-600'
}`}>
{isRunning ? 'Stop' : 'Start'} Adding Words
</button>
<button
onClick={isAutoScrollEnabled ? disableAutoScroll : enableAutoScroll}
className={`rounded px-3 py-1 text-sm text-white ${
isAutoScrollEnabled
? 'bg-blue-500 hover:bg-blue-600'
: 'bg-gray-500 hover:bg-gray-600'
}`}>
Auto-scroll {isAutoScrollEnabled ? 'ON' : 'OFF'}
</button>
</div>
</div>
<ScrollArea
viewportRef={containerRef}
className="h-[200px] w-[300px] rounded-lg border border-gray-200 p-4">
<div className="flex flex-wrap gap-1">{text}</div>
</ScrollArea>
</div>
);
}
};

View File

@ -13,6 +13,8 @@ interface UseAutoScrollOptions {
enabled?: boolean;
/** Whether to observe deep changes in the DOM tree */
observeDeepChanges?: boolean;
/** Specific node inside the container to observe for changes */
observeNode?: HTMLElement;
}
/**
@ -76,7 +78,8 @@ export const useAutoScroll = (
debounceDelay = 150,
scrollBehavior = 'smooth',
enabled = true,
observeDeepChanges = true
observeDeepChanges = true,
observeNode
} = options;
/** Current state of auto-scroll functionality */
@ -240,6 +243,22 @@ export const useAutoScroll = (
handleScrollThrottled();
}, [handleScrollThrottled, enabled]);
/**
* Enables auto-scroll functionality and immediately scrolls to bottom
*/
const enableAutoScroll = useCallback(() => {
if (!enabled) return;
setIsAutoScrollEnabled(true);
scrollToBottom();
}, [scrollToBottom, enabled]);
/**
* Disables auto-scroll functionality
*/
const disableAutoScroll = useCallback(() => {
setIsAutoScrollEnabled(false);
}, []);
// Handle content changes
useEffect(() => {
const container = containerRef.current;
@ -267,7 +286,7 @@ export const useAutoScroll = (
observer.observe(container, {
childList: true, // Only observe direct children changes
subtree: observeDeepChanges, // Don't observe deep changes
characterData: false, // Don't observe text changes,
characterData: observeDeepChanges, // Don't observe text changes,
attributes: false
});
@ -291,22 +310,6 @@ export const useAutoScroll = (
};
}, [containerRef, handleScroll, handleScrollThrottled, enabled]);
/**
* Enables auto-scroll functionality and immediately scrolls to bottom
*/
const enableAutoScroll = useCallback(() => {
if (!enabled) return;
setIsAutoScrollEnabled(true);
scrollToBottom();
}, [scrollToBottom, enabled]);
/**
* Disables auto-scroll functionality
*/
const disableAutoScroll = useCallback(() => {
setIsAutoScrollEnabled(false);
}, []);
return {
isAutoScrollEnabled,
scrollToBottom,