react-fa-picker
Version:
A reusable React Icon Picker component, bundled with its own Tailwind CSS build.
61 lines (53 loc) • 1.61 kB
text/typescript
import { useEffect } from "react";
type OnReachEnd = () => void;
/**
* Watches a ShadCN <ScrollArea> (via its root ref) and calls `onReachEnd`
* once you scroll past `threshold` (default 90%) of its inner viewport,
* debounced by `debounceMs` (default 200ms).
*/
export function useScrollAreaEnd(
rootRef: React.RefObject<HTMLElement | null>,
onReachEnd: OnReachEnd,
threshold = 0.9,
debounceMs = 200,
) {
useEffect(() => {
const root = rootRef.current;
if (!root) return;
// find the Radix viewport inside the ShadCN ScrollArea
const viewport = root.querySelector<HTMLElement>(
"[data-radix-scroll-area-viewport]",
);
if (!viewport) return;
let ticking = false;
let timer: number | null = null;
const handleScroll = () => {
const { scrollTop, scrollHeight, clientHeight } = viewport;
if (scrollTop + clientHeight >= scrollHeight * threshold) {
// clear any pending call
if (timer !== null) {
clearTimeout(timer);
}
// schedule the reach-end callback
timer = window.setTimeout(() => {
onReachEnd();
timer = null;
}, debounceMs);
}
ticking = false;
};
const onScroll = () => {
if (!ticking) {
window.requestAnimationFrame(handleScroll);
ticking = true;
}
};
viewport.addEventListener("scroll", onScroll);
return () => {
viewport.removeEventListener("scroll", onScroll);
if (timer !== null) {
clearTimeout(timer);
}
};
}, [rootRef, onReachEnd, threshold, debounceMs]);
}