framer-motion
Version:
A simple and powerful React animation library
59 lines (56 loc) • 2.13 kB
JavaScript
import { useConstant } from '../../utils/use-constant.mjs';
import { createScrollUpdater, createScrollMotionValues } from './utils.mjs';
import { addDomEvent } from '../../events/use-dom-event.mjs';
import { useIsomorphicLayoutEffect } from '../../utils/use-isomorphic-effect.mjs';
import { invariant } from 'hey-listen';
var getElementScrollOffsets = function (element) { return function () {
return {
xOffset: element.scrollLeft,
yOffset: element.scrollTop,
xMaxOffset: element.scrollWidth - element.offsetWidth,
yMaxOffset: element.scrollHeight - element.offsetHeight,
};
}; };
/**
* Returns MotionValues that update when the provided element scrolls:
*
* - `scrollX` — Horizontal scroll distance in pixels.
* - `scrollY` — Vertical scroll distance in pixels.
* - `scrollXProgress` — Horizontal scroll progress between `0` and `1`.
* - `scrollYProgress` — Vertical scroll progress between `0` and `1`.
*
* This element must be set to `overflow: scroll` on either or both axes to report scroll offset.
*
* ```jsx
* export const MyComponent = () => {
* const ref = useRef()
* const { scrollYProgress } = useElementScroll(ref)
*
* return (
* <div ref={ref}>
* <motion.div style={{ scaleX: scrollYProgress }} />
* </div>
* )
* }
* ```
*
* @public
*/
function useElementScroll(ref) {
var values = useConstant(createScrollMotionValues);
useIsomorphicLayoutEffect(function () {
var element = ref.current;
invariant(!!element, "ref provided to useScroll must be passed into a HTML element.");
if (!element)
return;
var updateScrollValues = createScrollUpdater(values, getElementScrollOffsets(element));
var scrollListener = addDomEvent(element, "scroll", updateScrollValues, { passive: true });
var resizeListener = addDomEvent(element, "resize", updateScrollValues);
return function () {
scrollListener && scrollListener();
resizeListener && resizeListener();
};
}, []);
return values;
}
export { useElementScroll };