@mantine/hooks
Version:
A collection of 50+ hooks for state and UI management
76 lines (75 loc) • 3.7 kB
JavaScript
"use client";
const require_use_isomorphic_effect = require("../use-isomorphic-effect/use-isomorphic-effect.cjs");
const require_use_window_scroll = require("../use-window-scroll/use-window-scroll.cjs");
const require_use_scroll_direction = require("../use-scroll-direction/use-scroll-direction.cjs");
let react = require("react");
//#region packages/@mantine/hooks/src/use-headroom/use-headroom.ts
const isFixed = (current, fixedAt) => current <= fixedAt;
const isPinnedOrReleased = (current, fixedAt, isCurrentlyPinnedRef, isScrollingUp, onPin, onRelease) => {
const isInFixedPosition = isFixed(current, fixedAt);
if (isInFixedPosition && !isCurrentlyPinnedRef.current) {
isCurrentlyPinnedRef.current = true;
onPin?.();
} else if (!isInFixedPosition && isScrollingUp && !isCurrentlyPinnedRef.current) {
isCurrentlyPinnedRef.current = true;
onPin?.();
} else if (!isInFixedPosition && !isScrollingUp && isCurrentlyPinnedRef.current) {
isCurrentlyPinnedRef.current = false;
onRelease?.();
}
};
function useHeadroom({ fixedAt = 0, scrollDistance = 100, onPin, onFix, onRelease } = {}) {
const isCurrentlyPinnedRef = (0, react.useRef)(false);
const isScrollingUp = require_use_scroll_direction.useScrollDirection() === "up";
const [{ y: scrollPosition }] = require_use_window_scroll.useWindowScroll();
const onPinEvent = (0, react.useEffectEvent)(() => onPin?.());
const onReleaseEvent = (0, react.useEffectEvent)(() => onRelease?.());
const onFixEvent = (0, react.useEffectEvent)(() => onFix?.());
require_use_isomorphic_effect.useIsomorphicEffect(() => {
isPinnedOrReleased(scrollPosition, fixedAt, isCurrentlyPinnedRef, isScrollingUp, onPinEvent, onReleaseEvent);
}, [
scrollPosition,
fixedAt,
isScrollingUp
]);
require_use_isomorphic_effect.useIsomorphicEffect(() => {
if (isFixed(scrollPosition, fixedAt)) onFixEvent();
}, [scrollPosition, fixedAt]);
const currentlyFixed = isFixed(scrollPosition, fixedAt);
const prevIsFixedRef = (0, react.useRef)(currentlyFixed);
const directionChangeScrollYRef = (0, react.useRef)(scrollPosition);
const progressAtDirectionChangeRef = (0, react.useRef)(currentlyFixed ? 1 : 0);
const prevIsScrollingUpRef = (0, react.useRef)(isScrollingUp);
if (prevIsFixedRef.current !== currentlyFixed) {
prevIsFixedRef.current = currentlyFixed;
if (!currentlyFixed) {
directionChangeScrollYRef.current = fixedAt;
progressAtDirectionChangeRef.current = 1;
} else {
directionChangeScrollYRef.current = scrollPosition;
progressAtDirectionChangeRef.current = 1;
}
prevIsScrollingUpRef.current = isScrollingUp;
}
if (!currentlyFixed && prevIsScrollingUpRef.current !== isScrollingUp) {
const transitionDelta = Math.abs(scrollPosition - directionChangeScrollYRef.current);
const transitionProgress = prevIsScrollingUpRef.current ? Math.min(progressAtDirectionChangeRef.current + transitionDelta / scrollDistance, 1) : Math.max(progressAtDirectionChangeRef.current - transitionDelta / scrollDistance, 0);
prevIsScrollingUpRef.current = isScrollingUp;
directionChangeScrollYRef.current = scrollPosition;
progressAtDirectionChangeRef.current = transitionProgress;
}
let scrollProgress;
if (currentlyFixed) scrollProgress = 1;
else {
const scrollDelta = Math.abs(scrollPosition - directionChangeScrollYRef.current);
if (isScrollingUp) scrollProgress = Math.min(progressAtDirectionChangeRef.current + scrollDelta / scrollDistance, 1);
else scrollProgress = Math.max(progressAtDirectionChangeRef.current - scrollDelta / scrollDistance, 0);
}
return {
pinned: scrollProgress > 0,
scrollProgress
};
}
//#endregion
exports.useHeadroom = useHeadroom;
//# sourceMappingURL=use-headroom.cjs.map