@shopgate/engage
Version:
Shopgate's ENGAGE library.
33 lines • 4.29 kB
JavaScript
var _excluded=["scrollIn","scrollOut","scrolled"],_excluded2=["scrollIn","scrollOut","scrolled"];function _objectWithoutProperties(source,excluded){if(source==null)return{};var target=_objectWithoutPropertiesLoose(source,excluded);var key,i;if(Object.getOwnPropertySymbols){var sourceSymbolKeys=Object.getOwnPropertySymbols(source);for(i=0;i<sourceSymbolKeys.length;i++){key=sourceSymbolKeys[i];if(excluded.indexOf(key)>=0)continue;if(!Object.prototype.propertyIsEnumerable.call(source,key))continue;target[key]=source[key];}}return target;}function _objectWithoutPropertiesLoose(source,excluded){if(source==null)return{};var target={};var sourceKeys=Object.keys(source);var key,i;for(i=0;i<sourceKeys.length;i++){key=sourceKeys[i];if(excluded.indexOf(key)>=0)continue;target[key]=source[key];}return target;}import{useEffect,useRef,useCallback}from'react';import{viewScroll$}from'@shopgate/engage/core/streams';/**
* @typedef {Object} ViewScrollEvent
* @property {Event} event The original scroll event object
* @property {number} scrollTop Current vertical scroll position
* @property {number} previousScrollTop Previous scrollTop value
* @property {boolean} scrollDown True if scrolling down
* @property {boolean} scrollUp True if scrolling up
* @property {'up' | 'down' | null} direction Scroll direction
*/ /**
* @callback ScrollCallback
* @param {ViewScrollEvent} event
* @returns {void}
*/ /**
* A scroll hook that detects scroll direction changes (up/down) and
* triggers the appropriate callbacks. Commonly used to show/hide
* UI elements based on scroll behavior.
*
* @param {Object} params The hook parameters
* @param {boolean} params.enabled Whether the hook is active
* @param {number} [params.offset=100] ScrollTop threshold for down scroll triggers. When set,
* onScrollDown will first be triggered when the scroll position is greater than this value.
* @param {boolean} [params.onlyFireOnDirectionChange=true]
* If true, callbacks fire only once per direction change
* @param {ScrollCallback} [params.onScrollUp] Triggered on scroll up
* @param {ScrollCallback} [params.onScrollDown] Triggered on scroll down past offset
*/export default function useScrollDirectionChange(_ref){var enabled=_ref.enabled,_ref$offset=_ref.offset,offset=_ref$offset===void 0?100:_ref$offset,_ref$onlyFireOnDirect=_ref.onlyFireOnDirectionChange,onlyFireOnDirectionChange=_ref$onlyFireOnDirect===void 0?true:_ref$onlyFireOnDirect,onScrollUp=_ref.onScrollUp,onScrollDown=_ref.onScrollDown;var lastDirectionRef=useRef(null);var downTriggeredRef=useRef(false);var upTriggeredRef=useRef(false);/**
* Scroll event handler.
* Uses `event.direction` and triggers callbacks accordingly.
*/var handleScroll=useCallback(/** @param {ViewScrollEvent} event The event */function(event){if(!enabled||!event.scrolled||!event.direction)return;var scrollTop=event.scrollTop,direction=event.direction;var prevDirection=lastDirectionRef.current;var directionChanged=direction!==prevDirection;// Store current direction and reset flags if direction changed
if(directionChanged){lastDirectionRef.current=direction;if(direction==='down')downTriggeredRef.current=false;if(direction==='up')upTriggeredRef.current=false;}// 🔽 Handle downward scroll
if(direction==='down'){var shouldFire=(!onlyFireOnDirectionChange||directionChanged||!downTriggeredRef.current)&&scrollTop>=offset;if(shouldFire&&typeof onScrollDown==='function'){downTriggeredRef.current=true;// Strip internal/legacy properties
var scrollIn=event.scrollIn,scrollOut=event.scrollOut,scrolled=event.scrolled,publicEvent=_objectWithoutProperties(event,_excluded);onScrollDown(publicEvent);}}// 🔼 Handle upward scroll
if(direction==='up'){var _shouldFire=!onlyFireOnDirectionChange||directionChanged||!upTriggeredRef.current;if(_shouldFire&&typeof onScrollUp==='function'){upTriggeredRef.current=true;var _scrollIn=event.scrollIn,_scrollOut=event.scrollOut,_scrolled=event.scrolled,_publicEvent=_objectWithoutProperties(event,_excluded2);onScrollUp(_publicEvent);}}},[enabled,offset,onlyFireOnDirectionChange,onScrollUp,onScrollDown]);useEffect(function(){if(!enabled)return undefined;var subscription=viewScroll$.subscribe(handleScroll);return function(){return subscription.unsubscribe();};},[enabled,handleScroll]);}