react-scroll-tracker
Version:
A React hook for tracking scroll depth with TypeScript support and SSR compatibility
79 lines (78 loc) • 3.46 kB
JavaScript
;
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
Object.defineProperty(exports, "__esModule", { value: true });
var react_1 = require("react");
var utils_1 = require("./utils");
var useScrollTracker = function (trackScrollDepths, callback) {
var _a = (0, react_1.useState)({
scrollDepths: trackScrollDepths,
scrollY: 0
}), state = _a[0], setState = _a[1];
var scrollDepths = state.scrollDepths, scrollY = state.scrollY;
(0, react_1.useEffect)(function () {
if (typeof window === 'undefined' || window.pageYOffset === 0) {
return;
}
setState(function (oldState) { return (__assign(__assign({}, oldState), { scrollY: window.pageYOffset })); });
}, []);
(0, react_1.useEffect)(function () {
if (typeof window === 'undefined') {
return;
}
var endScrollTracker = function () {
return window.removeEventListener('scroll', handleScroll);
};
var handleScroll = function () {
var scrollPercent = (0, utils_1.getScrollPercent)(document);
if (!scrollDepths) {
return setState(function (oldState) { return (__assign(__assign({}, oldState), { scrollY: scrollPercent })); });
}
var sortedScrollDepths = __spreadArray([], scrollDepths, true).sort(function (a, b) { return a - b; });
var reachedDepths = sortedScrollDepths.filter(function (depth) { return scrollPercent >= depth; });
var remainingDepths = sortedScrollDepths.filter(function (depth) { return scrollPercent < depth; });
if (reachedDepths.length > 0) {
if (remainingDepths.length === 0) {
endScrollTracker();
}
if (callback) {
reachedDepths.forEach(function (depth, i) {
// Remaining = unreached depths + reached depths not yet processed
var stillRemaining = __spreadArray(__spreadArray([], reachedDepths.slice(i + 1), true), remainingDepths, true);
callback({
scrollY: depth,
scrollPercent: scrollPercent,
remainingDepths: stillRemaining,
});
});
}
setState({
scrollY: reachedDepths[reachedDepths.length - 1],
scrollDepths: remainingDepths,
});
}
};
window.addEventListener('scroll', handleScroll);
return endScrollTracker;
}, [scrollDepths, callback]);
return { scrollY: scrollY };
};
exports.default = useScrollTracker;