mirror of
https://github.com/muerwre/vault-frontend.git
synced 2025-04-24 12:26:40 +07:00
48 lines
1.2 KiB
TypeScript
48 lines
1.2 KiB
TypeScript
import { useEffect, useMemo } from 'react';
|
|
|
|
import { throttle } from 'throttle-debounce';
|
|
|
|
import { useWindowSize } from './useWindowSize';
|
|
|
|
interface Options {
|
|
active?: boolean;
|
|
threshold?: number;
|
|
}
|
|
|
|
export const useScrollEnd = (
|
|
item: Element | Element[] | undefined | null,
|
|
callback?: () => void,
|
|
{ active = true, threshold = 1.5 }: Options = {},
|
|
) => {
|
|
const debouncedCallback = useMemo(
|
|
() => callback && throttle(1000, callback),
|
|
[callback],
|
|
);
|
|
|
|
const { innerHeight } = useWindowSize();
|
|
|
|
useEffect(() => {
|
|
if (!item || !active || !debouncedCallback) return;
|
|
|
|
const items = Array.isArray(item) ? item : [item];
|
|
const positions = items.map((it) => {
|
|
const { top, height } = it.getBoundingClientRect();
|
|
return top + window.scrollY + height;
|
|
});
|
|
|
|
const eventHandler = () => {
|
|
if (
|
|
!positions.some(
|
|
(it) => it < window.scrollY + window.innerHeight * threshold,
|
|
)
|
|
)
|
|
return;
|
|
|
|
debouncedCallback();
|
|
};
|
|
|
|
window.addEventListener('scroll', eventHandler);
|
|
|
|
return () => window.removeEventListener('scroll', eventHandler);
|
|
}, [item, active, innerHeight, debouncedCallback, threshold]);
|
|
};
|