2022-06-01 14:24:24 +02:00
|
|
|
import { useEffect, useState } from 'react';
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get index of first and last displayed item in current window scroll offset.
|
|
|
|
* This is done to optimize performance for large lists.
|
|
|
|
*
|
|
|
|
* @param rowHeight height of single item in pixels
|
|
|
|
* @param scrollOffset how many items above and below to render -- TODO: calculate from window height
|
|
|
|
* @param dampening cause less re-renders -- only after jumping this x of elements, "staircase" effect
|
|
|
|
* @returns [firstIndex, lastIndex]
|
|
|
|
*/
|
|
|
|
export const useVirtualizedRange = (
|
|
|
|
rowHeight: number,
|
|
|
|
scrollOffset = 40,
|
2023-06-15 14:11:04 +02:00
|
|
|
dampening = 5,
|
2023-10-02 14:25:46 +02:00
|
|
|
parentElement?: HTMLElement | null,
|
2022-06-01 14:24:24 +02:00
|
|
|
) => {
|
2023-06-15 14:11:04 +02:00
|
|
|
const parent = parentElement ? parentElement : window;
|
|
|
|
|
2022-06-01 14:24:24 +02:00
|
|
|
const [scrollIndex, setScrollIndex] = useState(
|
2023-06-15 14:11:04 +02:00
|
|
|
Math.floor(
|
|
|
|
(parent instanceof HTMLElement
|
|
|
|
? parent.scrollTop
|
2023-10-02 14:25:46 +02:00
|
|
|
: parent.pageYOffset) / rowHeight,
|
|
|
|
),
|
2022-06-01 14:24:24 +02:00
|
|
|
);
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
const handleScroll = () => {
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
setScrollIndex(
|
2023-06-15 14:11:04 +02:00
|
|
|
Math.floor(
|
|
|
|
(parent instanceof HTMLElement
|
|
|
|
? parent.scrollTop
|
|
|
|
: parent.pageYOffset) /
|
2023-10-02 14:25:46 +02:00
|
|
|
(rowHeight * dampening),
|
|
|
|
) * dampening,
|
2022-06-01 14:24:24 +02:00
|
|
|
);
|
|
|
|
});
|
|
|
|
};
|
2023-06-21 15:37:04 +02:00
|
|
|
handleScroll();
|
2023-06-15 14:11:04 +02:00
|
|
|
parent.addEventListener('scroll', handleScroll, { passive: true });
|
2022-06-01 14:24:24 +02:00
|
|
|
|
|
|
|
return () => {
|
2023-06-15 14:11:04 +02:00
|
|
|
parent.removeEventListener('scroll', handleScroll);
|
2022-06-01 14:24:24 +02:00
|
|
|
};
|
2023-06-15 14:11:04 +02:00
|
|
|
}, [rowHeight, dampening, parent]);
|
2022-06-01 14:24:24 +02:00
|
|
|
|
|
|
|
return [scrollIndex - scrollOffset, scrollIndex + scrollOffset] as const;
|
|
|
|
};
|