@scrolia/react
Version:
A headless scrollbar component
109 lines (107 loc) • 3.21 kB
JavaScript
import { useScrollCore } from "../contexts/scrollcore.mjs";
import { tryPlugin } from "../functions/plugin.mjs";
import * as React from "react";
const handleScrollFn = ({ axis, disabled, page, plugins, contentRef, hvTrack, hvThumb, total, view, viewOffset, scrollbarOffset, setScrollbarOffset }) => {
if (page) if (axis === "x") viewOffset.current = window.scrollX;
else viewOffset.current = window.scrollY;
else if (contentRef.current) if (axis === "x") viewOffset.current = contentRef.current.scrollLeft;
else viewOffset.current = contentRef.current.scrollTop;
const scrollbarOffsetNext = viewOffset.current / total.current * view.current;
let result;
for (const plugin of plugins) {
if (!plugin.onScroll) continue;
result = tryPlugin(plugin, plugin.onScroll, {
axis,
isDisabled: disabled,
isPage: page,
isDefined: hvTrack && hvThumb,
total: total.current,
view: view.current,
viewOffset: viewOffset.current,
scrollbarOffsetPrev: scrollbarOffset,
scrollbarOffsetNext: result?.scrollbarOffset ?? scrollbarOffsetNext
}) ?? result;
}
let offset;
if (result?.scrollbarOffset) offset = result.scrollbarOffset;
else offset = scrollbarOffsetNext;
setScrollbarOffset(offset);
};
/** Hook for handling scroll events. */
const useScrollHandler = () => {
const { options: { disabled, page, plugins }, contentRef, x, y } = useScrollCore();
React.useEffect(() => {
const handleScroll = () => {
x.hvTrack && x.hvThumb && handleScrollFn({
axis: "x",
disabled,
page,
plugins,
contentRef,
hvTrack: x.hvTrack,
hvThumb: x.hvThumb,
total: x.total,
view: x.view,
viewOffset: x.viewOffset,
scrollbarOffset: x.scrollbarOffset,
setScrollbarOffset: x.setScrollbarOffset
});
};
if (page) window.addEventListener("scroll", handleScroll);
else if (contentRef.current) contentRef.current.addEventListener("scroll", handleScroll);
return () => {
if (page) window.removeEventListener("scroll", handleScroll);
else if (contentRef.current) contentRef.current.removeEventListener("scroll", handleScroll);
};
}, [
disabled,
page,
plugins,
contentRef,
x.hvTrack,
x.hvThumb,
x.total,
x.view,
x.viewOffset,
x.scrollbarOffset,
x.setScrollbarOffset
]);
React.useEffect(() => {
const handleScroll = () => {
y.hvTrack && y.hvThumb && handleScrollFn({
axis: "y",
disabled,
page,
plugins,
contentRef,
hvTrack: y.hvTrack,
hvThumb: y.hvThumb,
total: y.total,
view: y.view,
viewOffset: y.viewOffset,
scrollbarOffset: y.scrollbarOffset,
setScrollbarOffset: y.setScrollbarOffset
});
};
if (page) window.addEventListener("scroll", handleScroll);
else if (contentRef.current) contentRef.current.addEventListener("scroll", handleScroll);
return () => {
if (page) window.removeEventListener("scroll", handleScroll);
else if (contentRef.current) contentRef.current.removeEventListener("scroll", handleScroll);
};
}, [
disabled,
page,
plugins,
contentRef,
y.hvTrack,
y.hvThumb,
y.total,
y.view,
y.viewOffset,
y.scrollbarOffset,
y.setScrollbarOffset
]);
};
export { useScrollHandler };
//# sourceMappingURL=scroll.mjs.map