UNPKG

@ebay/ebayui-core

Version:

Collection of core eBay components; considered to be the building blocks for all composite structures, pages & apps.

76 lines (75 loc) 2.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.scrollTransition = scrollTransition; const on_scroll_end_1 = require("../on-scroll-end"); const supportsScrollBehavior = typeof window !== "undefined" && "scrollBehavior" in document.documentElement.style; /** * Utility to animate scroll position of an element using an `ease-out` curve over 250ms. * Cancels the animation if the user touches back down. */ function scrollTransition(el, to, fn) { if (supportsScrollBehavior) { el.scrollTo({ left: to }); return (0, on_scroll_end_1.onScrollEnd)(el, fn); } let lastPosition; let cancelInterruptTransition; let frame = requestAnimationFrame((startTime) => { const { scrollLeft } = el; const distance = to - scrollLeft; const duration = 450; (function animate(curTime) { const delta = curTime - startTime; if (delta > duration) { el.scrollLeft = to; cancel(); return fn(); } el.scrollLeft = easeInOut(delta / duration) * distance + scrollLeft; frame = requestAnimationFrame(animate); })(startTime); }); // The animation can be interrupted by new touch events. el.addEventListener("touchstart", handleTouchStart); return cancel; function cancel() { cancelAnimationFrame(frame); if (lastPosition === undefined) { cancelTouchStart(); } else { if (cancelInterruptTransition) cancelInterruptTransition(); cancelTouchEnd(); } } function handleTouchStart() { cancel(); lastPosition = el.scrollLeft; // If we were interrupted by a touch start we wait for a touch end to see if we moved. el.addEventListener("touchend", handleTouchEnd); } function handleTouchEnd() { cancelTouchEnd(); // If we haven't moved because of the interrupt we continue to transition. if (lastPosition === el.scrollLeft) { cancelInterruptTransition = scrollTransition(el, to, fn); } } function cancelTouchStart() { el.removeEventListener("touchstart", handleTouchStart); } function cancelTouchEnd() { el.removeEventListener("touchend", handleTouchEnd); } } /** * Ease out timing function. * Based on https://gist.github.com/gre/1650294. * * @param v - A number between 0 and 1. */ function easeInOut(v) { return v < 0.5 ? 2 * v * v : -1 + (4 - 2 * v) * v; }