Files
klz-cables.com/.pnpm-store/v10/files/f4/bb2db38181ead536d50656a86faa46817bfc8a2f9043a6b57d1ff0512d029d80f7aeef7e9df1c035303ce3c1768c4e2023c5b38a4c10950bd06bfccb955899
Marc Mintel 5397309103
Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
fix(products): fix breadcrumbs and product filtering (backport from main)
2026-02-24 16:04:21 +01:00

82 lines
3.9 KiB
Plaintext

import React, { useCallback, useEffect, useReducer, useRef, } from 'react';
import { ScrollInfoContext } from '../ScrollInfoProvider/context.js';
const reducer = (state, payload) => {
const { timestamp, animationRef, } = payload;
animationRef.current = null;
const { x: prevScrollX, y: prevScrollY, xDirection: prevXDirection, yDirection: prevYDirection, eventsFired: prevEventsFired, hasScrolled: prevHasScrolled, } = state;
// Set currentScroll to zero on mount for cross-browser compatibility --
// Some browsers populate the cached window.pageOffset at different points of the component lifecycle.
// Chrome mounts with cached window.pageOffset coordinates even before firing the respective cached scroll event.
// Neither Safari and FireFox populate these coordinates until this cached scroll (natively triggered by the browser).
// The presence of a timestamp indicates that the caller of this method was not componentDidMount,
// but rather a true scroll event via requestAnimationFrame. Keep at zero otherwise.
const hasScrolled = prevHasScrolled || Boolean(timestamp);
const currentScrollX = hasScrolled ? window.pageXOffset : 0;
const currentScrollY = hasScrolled ? window.pageYOffset : 0;
// Only increment the eventsFired state after the first true scroll event.
const eventsFired = hasScrolled ? prevEventsFired + 1 : prevEventsFired;
const xDifference = currentScrollX - prevScrollX;
const yDifference = currentScrollY - prevScrollY;
const xPercentage = (currentScrollX / (document.body.scrollWidth - window.innerWidth)) * 100;
const yPercentage = (currentScrollY / (document.body.scrollHeight - window.innerHeight)) * 100;
const totalPercentage = (xPercentage + yPercentage) / 2;
const xDirection = xDifference > 0 ? 'right' : xDifference < 0 ? 'left' : prevXDirection; // eslint-disable-line no-nested-ternary
const yDirection = yDifference > 0 ? 'down' : yDifference < 0 ? 'up' : prevYDirection; // eslint-disable-line no-nested-ternary
return {
x: currentScrollX,
y: currentScrollY,
xDifference,
yDifference,
xDirection,
yDirection,
xPercentage,
yPercentage,
totalPercentage,
eventsFired,
hasScrolled,
};
};
export const ScrollInfoProvider = (props) => {
const { children, } = props;
const animationRef = useRef(null);
const [state, dispatch] = useReducer(reducer, {
x: 0,
y: 0,
xDifference: 0,
yDifference: 0,
xDirection: undefined,
yDirection: undefined,
xPercentage: 0,
yPercentage: 0,
totalPercentage: 0,
eventsFired: 0,
hasScrolled: false,
});
const requestAnimation = useCallback((e) => {
if (animationRef.current) {
cancelAnimationFrame(animationRef.current);
}
animationRef.current = requestAnimationFrame((timestamp) => {
dispatch({
e,
timestamp,
animationRef,
});
});
}, []);
useEffect(() => {
window.addEventListener('scroll', requestAnimation);
return () => {
window.removeEventListener('scroll', requestAnimation);
};
}, [requestAnimation]);
// use this effect to test rAF debounce by requesting animation every 1ms, for a total 120ms
// count the number of times 'requestAnimation' callback is fired compared to the reducer
// results: ~23 requests will be made, ~17 requests will be canceled, so only ~8 will truly dispatch
// useEffect(() => {
// const firstID = setInterval(requestAnimation, 1);
// setInterval(() => clearInterval(firstID), 120);
// }, [requestAnimation]);
return (React.createElement(ScrollInfoContext.Provider, { value: Object.assign({}, state) }, children && children));
};
//# sourceMappingURL=index.js.map