UNPKG

hiding-header

Version:
221 lines (217 loc) 8.47 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function hidingHeader(container, _a) { var _b = _a === void 0 ? {} : _a, _c = _b.heightPropertyName, heightPropertyName = _c === void 0 ? '--hidingHeader-height' : _c, _d = _b.boundsHeightPropertyName, boundsHeightPropertyName = _d === void 0 ? '--hidingHeader-bounds-height' : _d, _e = _b.animationOffsetPropertyName, animationOffsetPropertyName = _e === void 0 ? '--hidingHeader-animation-offset' : _e, _f = _b.snap, snap = _f === void 0 ? true : _f, _g = _b.onHeightChange, onHeightChange = _g === void 0 ? function () { } : _g, _h = _b.onVisibleHeightChange, onVisibleHeightChange = _h === void 0 ? function () { } : _h, _j = _b.onHomeChange, onHomeChange = _j === void 0 ? function () { } : _j; var content = container.querySelector('*'); var lastScrollTopPosition = 0; var contentHeight = (function () { var getContentHeight = function () { return content.clientHeight; }; var setContentHeightProperty = function (height) { container.style.setProperty(heightPropertyName, "".concat(height, "px")); }; var resizeObserver = new ResizeObserver(function () { var newContentHeight = getContentHeight(); if (contentHeight !== newContentHeight) { contentHeight = newContentHeight; setContentHeightProperty(contentHeight); onScroll(); onHeightChange(contentHeight); } }); resizeObserver.observe(content); var initialHeight = getContentHeight(); setContentHeightProperty(initialHeight); return initialHeight; })(); var visibleHeight = contentHeight; var paused = false; var home = true; var lastBoundsHeight = 0; var pointersDown = 0; var parent = container.parentElement; if (parent === null) { throw new Error('Missing parent element.'); } var getParentHeight = function () { return parent.clientHeight; }; var getGlobalTopOffset = function () { return container.offsetTop; }; var getRelativeTopOffset = function () { var _a; return getGlobalTopOffset() - (((_a = container.parentElement) === null || _a === void 0 ? void 0 : _a.offsetTop) || 0); }; var animateOffset = function (initialOffset) { if (initialOffset === 0) { return; // Nothing to animate } content.style.transition = 'none'; container.style.setProperty(animationOffsetPropertyName, "".concat(initialOffset, "px")); content.offsetHeight; // Trigger transition content.style.transition = ''; container.style.setProperty(animationOffsetPropertyName, '0px'); }; var updateBoundsHeight = function (boundsHeight) { if (boundsHeight !== lastBoundsHeight) { container.style.setProperty(boundsHeightPropertyName, "".concat(boundsHeight, "px")); lastBoundsHeight = boundsHeight; } }; var capBoundsHeight = function (rawBoundsHeight) { return Math.min(getParentHeight() - getRelativeTopOffset(), Math.max(contentHeight, rawBoundsHeight)); }; var snapIfPossible = function () { if (snap && visibleHeight !== 0 && visibleHeight !== contentHeight) { if (visibleHeight < contentHeight / 2) { hide(); } else { reveal(); } } }; var onScrollStopDebounced = (function () { var timer; return function () { window.clearTimeout(timer); timer = window.setTimeout(function () { if (snap && pointersDown === 0) { snapIfPossible(); } }, 100); }; })(); var updateVisibleHeight = function () { visibleHeight = (function () { var top = content.getBoundingClientRect().top; var newVisibleHeight = Math.max(0, Math.min(contentHeight + top, contentHeight)); if (visibleHeight !== newVisibleHeight) { onVisibleHeightChange(newVisibleHeight); } return newVisibleHeight; })(); }; var updateHome = function () { home = (function () { var newHome = contentHeight >= lastBoundsHeight; if (home !== newHome) { onHomeChange(newHome); } return newHome; })(); }; var onTransitioning = function () { updateVisibleHeight(); }; (function () { var running = false; var loop = function () { if (!running) { return; } onTransitioning(); requestAnimationFrame(loop); }; // @TODO: remove listeners on destroy() content.addEventListener('transitionstart', function () { running = true; loop(); }); // @TODO: remove listeners on destroy() content.addEventListener('transitionend', function () { running = false; onTransitioning(); }); })(); var onScroll = function () { var globalTopOffset = getGlobalTopOffset(); // Handle bounds height var scrollTopPosition = window.scrollY; var isScrollingDown = scrollTopPosition > lastScrollTopPosition; if (!paused) { var boundsHeight = capBoundsHeight((function () { if (isScrollingDown) { var newBoundsHeight = scrollTopPosition - globalTopOffset; if (lastBoundsHeight < newBoundsHeight) { return newBoundsHeight; } return lastBoundsHeight; } else { var newBoundsHeight = scrollTopPosition - globalTopOffset + contentHeight; if (lastBoundsHeight > newBoundsHeight) { return newBoundsHeight; } return lastBoundsHeight; } })()); updateBoundsHeight(boundsHeight); onScrollStopDebounced(); updateVisibleHeight(); updateHome(); } lastScrollTopPosition = scrollTopPosition; }; var onResize = onScroll; var onPointerDown = function () { pointersDown++; onScroll(); }; var onPointerUp = function () { pointersDown--; onScroll(); }; var initialize = function () { window.addEventListener('scroll', onScroll); window.addEventListener('resize', onResize); document.addEventListener('pointerdown', onPointerDown); document.addEventListener('pointerup', onPointerUp); onScroll(); }; var destroy = function () { window.removeEventListener('scroll', onScroll); window.removeEventListener('resize', onResize); document.removeEventListener('pointerdown', onPointerDown); document.removeEventListener('pointerup', onPointerUp); }; initialize(); var run = function () { paused = false; }; var pause = function () { paused = true; }; var isPaused = function () { return paused; }; var isHome = function () { return home; }; var reveal = function () { var scrollTopPosition = window.scrollY; var globalTopOffset = getGlobalTopOffset(); var boundsHeight = capBoundsHeight(scrollTopPosition - globalTopOffset + contentHeight); animateOffset(lastBoundsHeight - boundsHeight); updateBoundsHeight(boundsHeight); }; var hide = function () { var scrollTopPosition = window.scrollY; var globalTopOffset = getGlobalTopOffset(); var boundsHeight = capBoundsHeight(scrollTopPosition - globalTopOffset); animateOffset(lastBoundsHeight - boundsHeight); updateBoundsHeight(boundsHeight); }; var getHeight = function () { return contentHeight; }; var getVisibleHeight = function () { return visibleHeight; }; return { run: run, pause: pause, isPaused: isPaused, isHome: isHome, reveal: reveal, hide: hide, getHeight: getHeight, getVisibleHeight: getVisibleHeight, destroy: destroy, }; } exports.hidingHeader = hidingHeader;