mirror of https://github.com/buster-so/buster.git
observe text changes as well
This commit is contained in:
parent
5524f5fd4e
commit
cefe43e386
|
@ -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>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue