UNPKG

@helpscout/hsds-react

Version:

React component library for Help Scout's Design System

99 lines (79 loc) 2.92 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); exports.__esModule = true; exports.smoothScrollTo = exports.easeInOutCubic = exports.linear = void 0; var _node = require("./node"); var _lodash = _interopRequireDefault(require("lodash.isfunction")); /* istanbul ignore file */ // Source: // https://gist.github.com/gre/1650294 var linear = function linear(t) { return t; }; exports.linear = linear; var easeInOutCubic = function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1; }; // Source // https://jsfiddle.net/s61x7c4e/ // // Testing: // Note: This function cannot be tested in JSDOM. JSDOM lacks the // necessary DOM node numbers (like scrollY or scrollTop) to test // the calculations for this method. These numbers cannot be // mocked/faked :(. // // To properly test this method, we'll need to leverage ACTUAL // browser testing somehow (either in-browser or headless). // // For now, this method has been extensively tested manually // within Storybook. exports.easeInOutCubic = easeInOutCubic; var smoothScrollTo = function smoothScrollTo(_ref) { var node = _ref.node, position = _ref.position, duration = _ref.duration, direction = _ref.direction, callback = _ref.callback, timingFunction = _ref.timingFunction; var scrollNode = (0, _node.isNodeElement)(node) ? node : window; var isWindow = scrollNode === window; var scrollDuration = duration || 500; var scrollDirection = direction || 'y'; var isHorizontalScroll = scrollDirection === 'x'; var scrollTimingFunction = timingFunction || easeInOutCubic; var currentScrollPosition = isWindow ? window.scrollY : scrollNode.scrollTop; if (isHorizontalScroll) { currentScrollPosition = isWindow ? window.scrollX : scrollNode.scrollLeft; } var diff = currentScrollPosition - position; var start; if (!diff) return; var step = function step(timestamp) { if (!start) start = timestamp; // Elapsed miliseconds since start of scrolling. var time = timestamp - start; // Get percent of completion in range [0, 1]. var percent = scrollTimingFunction(Math.min(time / scrollDuration, 1)); var scrollToPosition = currentScrollPosition - diff * percent; if (node.scrollTo) { if (isHorizontalScroll) { node.scrollTo(scrollToPosition, 0); } else { node.scrollTo(0, scrollToPosition); } } else { if (isHorizontalScroll) { node.scrollLeft = scrollToPosition; } else { node.scrollTop = scrollToPosition; } } // Proceed with animation as long as we wanted it to. if (time < scrollDuration) { requestAnimationFrame(step); } else { if ((0, _lodash.default)(callback)) { callback(); } } }; requestAnimationFrame(step); }; exports.smoothScrollTo = smoothScrollTo;