@mirawision/reactive-hooks
Version:
A comprehensive collection of 50+ React hooks for state management, UI interactions, device APIs, async operations, drag & drop, audio/speech, and more. Full TypeScript support with SSR safety.
84 lines (83 loc) • 2.75 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.useScroll = useScroll;
const react_1 = require("react");
function getScrollPosition(target) {
if (typeof window === 'undefined') {
return { x: 0, y: 0 };
}
// Handle ref case
if (target && 'current' in target) {
const element = target.current;
if (!element)
return { x: 0, y: 0 };
return {
x: element.scrollLeft,
y: element.scrollTop,
};
}
// Handle window case
if (!target || target === window) {
return {
x: window.pageXOffset || document.documentElement.scrollLeft,
y: window.pageYOffset || document.documentElement.scrollTop,
};
}
// Handle element case
const element = target;
return {
x: element.scrollLeft,
y: element.scrollTop,
};
}
/**
* A hook that tracks scroll position of a target element or window.
* @param target Optional target element (defaults to window)
* @param throttleMs Optional throttle delay in milliseconds
* @returns Object containing current scroll position (x, y)
*/
function useScroll(target, throttleMs) {
const [position, setPosition] = (0, react_1.useState)(() => getScrollPosition(target));
(0, react_1.useEffect)(() => {
if (typeof window === 'undefined')
return;
let timeoutId = null;
let rafId = null;
const updatePosition = () => {
setPosition(getScrollPosition(target));
};
const handleScroll = () => {
if (throttleMs) {
// Cancel any pending updates
if (timeoutId)
clearTimeout(timeoutId);
if (rafId)
cancelAnimationFrame(rafId);
timeoutId = setTimeout(() => {
rafId = requestAnimationFrame(updatePosition);
}, throttleMs);
}
else {
updatePosition();
}
};
// Initial position
updatePosition();
// Add event listener to appropriate target
const scrollTarget = target && 'current' in target ? target.current : target || window;
if (scrollTarget) {
scrollTarget.addEventListener('scroll', handleScroll, { passive: true });
}
// Cleanup
return () => {
if (scrollTarget) {
scrollTarget.removeEventListener('scroll', handleScroll);
}
if (timeoutId)
clearTimeout(timeoutId);
if (rafId)
cancelAnimationFrame(rafId);
};
}, [target, throttleMs]);
return position;
}