UNPKG

react-scroll-to-bottom-updated

Version:
679 lines (570 loc) 87.8 kB
"use strict"; var _typeof = require("@babel/runtime-corejs3/helpers/typeof"); var _Object$keys = require("@babel/runtime-corejs3/core-js-stable/object/keys"); var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"); var _filterInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/filter"); var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"); var _forEachInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/for-each"); var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"); var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties"); var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property"); var _WeakMap = require("@babel/runtime-corejs3/core-js-stable/weak-map"); var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); _Object$defineProperty(exports, "__esModule", { value: true }); exports["default"] = void 0; require("core-js/modules/es.regexp.exec.js"); require("core-js/modules/es.string.replace.js"); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty")); var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/toConsumableArray")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/slicedToArray")); var _setInterval2 = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/set-interval")); var _indexOf = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/index-of")); var _splice = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/splice")); var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat")); var _now = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/date/now")); var _forEach = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/for-each")); var _createInstance = _interopRequireDefault(require("@emotion/css/create-instance")); var _propTypes = _interopRequireDefault(require("prop-types")); var _react = _interopRequireWildcard(require("react")); var _createCSSKey = _interopRequireDefault(require("../createCSSKey")); var _debug = _interopRequireDefault(require("../utils/debug")); var _EventSpy = _interopRequireDefault(require("../EventSpy")); var _FunctionContext = _interopRequireDefault(require("./FunctionContext")); var _InternalContext = _interopRequireDefault(require("./InternalContext")); var _SpineTo = _interopRequireDefault(require("../SpineTo")); var _State1Context = _interopRequireDefault(require("./State1Context")); var _State2Context = _interopRequireDefault(require("./State2Context")); var _StateContext = _interopRequireDefault(require("./StateContext")); var _styleConsole = _interopRequireDefault(require("../utils/styleConsole")); var _useStateRef7 = _interopRequireDefault(require("../hooks/internal/useStateRef")); function _getRequireWildcardCache(nodeInterop) { if (typeof _WeakMap !== "function") return null; var cacheBabelInterop = new _WeakMap(); var cacheNodeInterop = new _WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = _Object$defineProperty && _Object$getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? _Object$getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { _Object$defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; } function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); if (enumerableOnly) { symbols = _filterInstanceProperty(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { var _context21; _forEachInstanceProperty2(_context21 = ownKeys(Object(source), true)).call(_context21, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (_Object$getOwnPropertyDescriptors) { _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)); } else { var _context22; _forEachInstanceProperty2(_context22 = ownKeys(Object(source))).call(_context22, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } } return target; } var DEFAULT_SCROLLER = function DEFAULT_SCROLLER() { return Infinity; }; var MIN_CHECK_INTERVAL = 17; // 1 frame var MODE_BOTTOM = 'bottom'; var MODE_TOP = 'top'; var NEAR_END_THRESHOLD = 1; var SCROLL_DECISION_DURATION = 34; // 2 frames // We pool the emotion object by nonce. // This is to make sure we don't generate too many unneeded <style> tags. var emotionPool = {}; function setImmediateInterval(fn, ms) { fn(); return (0, _setInterval2["default"])(fn, ms); } function computeViewState(_ref) { var mode = _ref.mode, _ref$target = _ref.target, offsetHeight = _ref$target.offsetHeight, scrollHeight = _ref$target.scrollHeight, scrollTop = _ref$target.scrollTop; var atBottom = scrollHeight - scrollTop - offsetHeight < NEAR_END_THRESHOLD; var atTop = scrollTop < NEAR_END_THRESHOLD; var atEnd = mode === MODE_TOP ? atTop : atBottom; var atStart = mode !== MODE_TOP ? atTop : atBottom; return { atBottom: atBottom, atEnd: atEnd, atStart: atStart, atTop: atTop }; } function isEnd(animateTo, mode) { return animateTo === (mode === MODE_TOP ? 0 : '100%'); } var Composer = function Composer(_ref2) { var _ref2$checkInterval = _ref2.checkInterval, checkInterval = _ref2$checkInterval === void 0 ? 100 : _ref2$checkInterval, children = _ref2.children, _ref2$debounce = _ref2.debounce, debounce = _ref2$debounce === void 0 ? 17 : _ref2$debounce, debugFromProp = _ref2.debug, _ref2$initialScrollBe = _ref2.initialScrollBehavior, initialScrollBehavior = _ref2$initialScrollBe === void 0 ? 'smooth' : _ref2$initialScrollBe, mode = _ref2.mode, nonce = _ref2.nonce, _ref2$scroller = _ref2.scroller, scroller = _ref2$scroller === void 0 ? DEFAULT_SCROLLER : _ref2$scroller; var debug = (0, _react.useMemo)(function () { return (0, _debug["default"])("<ScrollToBottom>", { force: debugFromProp }); }, [debugFromProp]); mode = mode === MODE_TOP ? MODE_TOP : MODE_BOTTOM; var ignoreScrollEventBeforeRef = (0, _react.useRef)(0); var initialScrollBehaviorRef = (0, _react.useRef)(initialScrollBehavior); var _useStateRef = (0, _useStateRef7["default"])(mode === MODE_TOP ? 0 : '100%'), _useStateRef2 = (0, _slicedToArray2["default"])(_useStateRef, 3), animateTo = _useStateRef2[0], setAnimateTo = _useStateRef2[1], animateToRef = _useStateRef2[2]; var _useStateRef3 = (0, _useStateRef7["default"])(null), _useStateRef4 = (0, _slicedToArray2["default"])(_useStateRef3, 3), target = _useStateRef4[0], setTarget = _useStateRef4[1], targetRef = _useStateRef4[2]; // Internal context var animateFromRef = (0, _react.useRef)(0); var offsetHeightRef = (0, _react.useRef)(0); var scrollHeightRef = (0, _react.useRef)(0); // State context var _useState = (0, _react.useState)(true), _useState2 = (0, _slicedToArray2["default"])(_useState, 2), atBottom = _useState2[0], setAtBottom = _useState2[1]; var _useState3 = (0, _react.useState)(true), _useState4 = (0, _slicedToArray2["default"])(_useState3, 2), atEnd = _useState4[0], setAtEnd = _useState4[1]; var _useState5 = (0, _react.useState)(true), _useState6 = (0, _slicedToArray2["default"])(_useState5, 2), atTop = _useState6[0], setAtTop = _useState6[1]; var _useState7 = (0, _react.useState)(false), _useState8 = (0, _slicedToArray2["default"])(_useState7, 2), atStart = _useState8[0], setAtStart = _useState8[1]; var _useStateRef5 = (0, _useStateRef7["default"])(true), _useStateRef6 = (0, _slicedToArray2["default"])(_useStateRef5, 3), sticky = _useStateRef6[0], setSticky = _useStateRef6[1], stickyRef = _useStateRef6[2]; // High-rate state context var scrollPositionObserversRef = (0, _react.useRef)([]); var observeScrollPosition = (0, _react.useCallback)(function (fn) { var target = targetRef.current; scrollPositionObserversRef.current.push(fn); target && fn({ scrollTop: target.scrollTop }); return function () { var scrollPositionObservers = scrollPositionObserversRef.current; var index = (0, _indexOf["default"])(scrollPositionObservers).call(scrollPositionObservers, fn); ~index && (0, _splice["default"])(scrollPositionObservers).call(scrollPositionObservers, index, 1); }; }, [scrollPositionObserversRef, targetRef]); var handleSpineToEnd = (0, _react.useCallback)(function () { var animateTo = animateToRef.current; debug(function () { var _context; return (0, _concat["default"])(_context = ['%cSpineTo%c: %conEnd%c is fired.']).call(_context, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('magenta')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('orange')), [{ animateTo: animateTo }]); }); ignoreScrollEventBeforeRef.current = (0, _now["default"])(); // handleScrollEnd may end at a position which should lose stickiness. // In that case, we will need to set sticky to false to stop the interval check. // Test case: // 1. Add a scroller that always return 0 // 2. Show a panel with mode === MODE_BOTTOM // 3. Programmatically scroll to 0 (set element.scrollTop = 0) // Expected: it should not repetitively call scrollTo(0) // it should set stickiness to false isEnd(animateTo, mode) || setSticky(false); setAnimateTo(null); }, [animateToRef, debug, ignoreScrollEventBeforeRef, mode, setAnimateTo, setSticky]); // Function context var scrollTo = (0, _react.useCallback)(function (nextAnimateTo) { var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, behavior = _ref3.behavior; var target = targetRef.current; if (typeof nextAnimateTo !== 'number' && nextAnimateTo !== '100%') { return console.warn('react-scroll-to-bottom: Arguments passed to scrollTo() must be either number or "100%".'); } // If it is trying to scroll to a position which is not "atEnd", it should set sticky to false after scroll ended. debug(function () { var _context2; return [(0, _concat["default"])(_context2 = ["%cscrollTo%c: Will scroll to %c".concat(typeof nextAnimateTo === 'number' ? nextAnimateTo + 'px' : nextAnimateTo.replace(/%/g, '%%'), "%c")]).call(_context2, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('lime', '')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple'))), { behavior: behavior, nextAnimateTo: nextAnimateTo, target: target }]; }); if (behavior === 'auto') { // Stop any existing animation handleSpineToEnd(); if (target) { // Jump to the scroll position target.scrollTop = nextAnimateTo === '100%' ? target.scrollHeight - target.offsetHeight : nextAnimateTo; } } else { behavior !== 'smooth' && console.warn('react-scroll-to-bottom: Please set "behavior" when calling "scrollTo". In future versions, the default behavior will be changed from smooth scrolling to discrete scrolling to align with HTML Standard.'); setAnimateTo(nextAnimateTo); } // This is for handling a case. When calling scrollTo('100%', { behavior: 'auto' }) multiple times, it would lose stickiness. if (isEnd(nextAnimateTo, mode)) { debug(function () { var _context3; return [(0, _concat["default"])(_context3 = ["%cscrollTo%c: Scrolling to end, will set sticky to %ctrue%c."]).call(_context3, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('lime', '')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple'))), [{ mode: mode, nextAnimateTo: nextAnimateTo }]]; }); setSticky(true); } }, [debug, handleSpineToEnd, mode, setAnimateTo, setSticky, targetRef]); var scrollToBottom = (0, _react.useCallback)(function () { var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, behavior = _ref4.behavior; debug(function () { var _context4; return (0, _concat["default"])(_context4 = ['%cscrollToBottom%c: Called']).call(_context4, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('yellow', ''))); }); behavior !== 'smooth' && console.warn('react-scroll-to-bottom: Please set "behavior" when calling "scrollToBottom". In future versions, the default behavior will be changed from smooth scrolling to discrete scrolling to align with HTML Standard.'); scrollTo('100%', { behavior: behavior || 'smooth' }); }, [debug, scrollTo]); var scrollToTop = (0, _react.useCallback)(function () { var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, behavior = _ref5.behavior; debug(function () { var _context5; return (0, _concat["default"])(_context5 = ['%cscrollToTop%c: Called']).call(_context5, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('yellow', ''))); }); behavior !== 'smooth' && console.warn('react-scroll-to-bottom: Please set "behavior" when calling "scrollToTop". In future versions, the default behavior will be changed from smooth scrolling to discrete scrolling to align with HTML Standard.'); scrollTo(0, { behavior: behavior || 'smooth' }); }, [debug, scrollTo]); var scrollToEnd = (0, _react.useCallback)(function () { var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, behavior = _ref6.behavior; debug(function () { var _context6; return (0, _concat["default"])(_context6 = ['%cscrollToEnd%c: Called']).call(_context6, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('yellow', ''))); }); behavior !== 'smooth' && console.warn('react-scroll-to-bottom: Please set "behavior" when calling "scrollToEnd". In future versions, the default behavior will be changed from smooth scrolling to discrete scrolling to align with HTML Standard.'); var options = { behavior: behavior || 'smooth' }; mode === MODE_TOP ? scrollToTop(options) : scrollToBottom(options); }, [debug, mode, scrollToBottom, scrollToTop]); var scrollToStart = (0, _react.useCallback)(function () { var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, behavior = _ref7.behavior; debug(function () { var _context7; return (0, _concat["default"])(_context7 = ['%cscrollToStart%c: Called']).call(_context7, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('yellow', ''))); }); behavior !== 'smooth' && console.warn('react-scroll-to-bottom: Please set "behavior" when calling "scrollToStart". In future versions, the default behavior will be changed from smooth scrolling to discrete scrolling to align with HTML Standard.'); var options = { behavior: behavior || 'smooth' }; mode === MODE_TOP ? scrollToBottom(options) : scrollToTop(options); }, [debug, mode, scrollToBottom, scrollToTop]); var scrollToSticky = (0, _react.useCallback)(function () { var target = targetRef.current; if (target) { if (initialScrollBehaviorRef.current === 'auto') { debug(function () { var _context8; return (0, _concat["default"])(_context8 = ["%ctarget changed%c: Initial scroll"]).call(_context8, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('blue'))); }); target.scrollTop = mode === MODE_TOP ? 0 : target.scrollHeight - target.offsetHeight; initialScrollBehaviorRef.current = false; return; } // This is very similar to scrollToEnd(). // Instead of scrolling to end, it will call props.scroller() to determines how far it should scroll. // This function could be called while it is auto-scrolling. var animateFrom = animateFromRef.current; var offsetHeight = target.offsetHeight, scrollHeight = target.scrollHeight, scrollTop = target.scrollTop; var maxValue = mode === MODE_TOP ? 0 : Math.max(0, scrollHeight - offsetHeight - scrollTop); var minValue = Math.max(0, animateFrom - scrollTop); var rawNextValue = scroller({ maxValue: maxValue, minValue: minValue, offsetHeight: offsetHeight, scrollHeight: scrollHeight, scrollTop: scrollTop }); var nextValue = Math.max(0, Math.min(maxValue, rawNextValue)); var nextAnimateTo; if (mode === MODE_TOP || nextValue !== maxValue) { nextAnimateTo = scrollTop + nextValue; } else { // When scrolling to bottom, we should scroll to "100%". // Otherwise, if we scroll to any number, it will lose stickiness when elements are adding too fast. // "100%" is a special argument intended to make sure stickiness is not lost while new elements are being added. nextAnimateTo = '100%'; } debug(function () { var _context9, _context10, _context11; return [(0, _concat["default"])(_context9 = [(0, _concat["default"])(_context10 = (0, _concat["default"])(_context11 = "%cscrollToSticky%c: Will animate from %c".concat(animateFrom, "px%c to %c")).call(_context11, typeof nextAnimateTo === 'number' ? nextAnimateTo + 'px' : nextAnimateTo.replace(/%/g, '%%'), "%c (%c")).call(_context10, (nextAnimateTo === '100%' ? maxValue : nextAnimateTo) + animateFrom, "px%c)")]).call(_context9, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('orange')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple'))), { animateFrom: animateFrom, maxValue: maxValue, minValue: minValue, nextAnimateTo: nextAnimateTo, nextValue: nextValue, offsetHeight: offsetHeight, rawNextValue: rawNextValue, scrollHeight: scrollHeight, scrollTop: scrollTop }]; }); scrollTo(nextAnimateTo, { behavior: 'smooth' }); } }, [animateFromRef, debug, mode, scroller, scrollTo, targetRef]); var handleScroll = (0, _react.useCallback)(function (_ref8) { var _context17; var timeStampLow = _ref8.timeStampLow; var animateTo = animateToRef.current; var target = targetRef.current; var animating = animateTo !== null; // Currently, there are no reliable way to check if the "scroll" event is trigger due to // user gesture, programmatic scrolling, or Chrome-synthesized "scroll" event to compensate size change. // Thus, we use our best-effort to guess if it is triggered by user gesture, and disable sticky if it is heading towards the start direction. if (timeStampLow <= ignoreScrollEventBeforeRef.current || !target) { // Since we debounce "scroll" event, this handler might be called after spineTo.onEnd (a.k.a. artificial scrolling). // We should ignore debounced event fired after scrollEnd, because without skipping them, the userInitiatedScroll calculated below will not be accurate. // Thus, on a fast machine, adding elements super fast will lose the "stickiness". return; } var _computeViewState = computeViewState({ mode: mode, target: target }), atBottom = _computeViewState.atBottom, atEnd = _computeViewState.atEnd, atStart = _computeViewState.atStart, atTop = _computeViewState.atTop; setAtBottom(atBottom); setAtEnd(atEnd); setAtStart(atStart); setAtTop(atTop); // Chrome will emit "synthetic" scroll event if the container is resized or an element is added // We need to ignore these "synthetic" events // Repro: In playground, press 4-1-5-1-1 (small, add one, normal, add one, add one) // Nomatter how fast or slow the sequence is being pressed, it should still stick to the bottom var nextOffsetHeight = target.offsetHeight, nextScrollHeight = target.scrollHeight; var offsetHeight = offsetHeightRef.current; var scrollHeight = scrollHeightRef.current; var offsetHeightChanged = nextOffsetHeight !== offsetHeight; var scrollHeightChanged = nextScrollHeight !== scrollHeight; if (offsetHeightChanged) { offsetHeightRef.current = nextOffsetHeight; } if (scrollHeightChanged) { scrollHeightRef.current = nextScrollHeight; } // Sticky means: // - If it is scrolled programatically, we are still in sticky mode // - If it is scrolled by the user, then sticky means if we are at the end // Only update stickiness if the scroll event is not due to synthetic scroll done by Chrome if (!offsetHeightChanged && !scrollHeightChanged) { // We are sticky if we are animating to the end, or we are already at the end. // We can be "animating but not sticky" by calling "scrollTo(100)" where the container scrollHeight is 200px. var nextSticky = animating && isEnd(animateTo, mode) || atEnd; if (stickyRef.current !== nextSticky) { debug(function () { var _context12, _context13, _context14, _context15; return [(0, _concat["default"])(_context12 = ["%conScroll%c: %csetSticky%c(%c".concat(nextSticky, "%c)")]).call(_context12, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('red')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('red')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple'))), (0, _concat["default"])(_context13 = [(0, _concat["default"])(_context14 = (0, _concat["default"])(_context15 = "(animating = %c".concat(animating, "%c && isEnd = %c")).call(_context15, isEnd(animateTo, mode), "%c) || atEnd = %c")).call(_context14, atEnd, "%c")]).call(_context13, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple')), [{ animating: animating, animateTo: animateTo, atEnd: atEnd, mode: mode, offsetHeight: target.offsetHeight, scrollHeight: target.scrollHeight, sticky: stickyRef.current, nextSticky: nextSticky }])]; }); setSticky(nextSticky); } } else if (stickyRef.current) { debug(function () { var _context16; return [(0, _concat["default"])(_context16 = ["%conScroll%c: Size changed while sticky, calling %cscrollToSticky()%c"]).call(_context16, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('red')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('orange')), [{ offsetHeightChanged: offsetHeightChanged, scrollHeightChanged: scrollHeightChanged }]), { nextOffsetHeight: nextOffsetHeight, prevOffsetHeight: offsetHeight, nextScrollHeight: nextScrollHeight, prevScrollHeight: scrollHeight }]; }); scrollToSticky(); } var actualScrollTop = target.scrollTop; (0, _forEach["default"])(_context17 = scrollPositionObserversRef.current).call(_context17, function (observer) { return observer({ scrollTop: actualScrollTop }); }); }, [animateToRef, debug, ignoreScrollEventBeforeRef, mode, offsetHeightRef, scrollHeightRef, scrollPositionObserversRef, scrollToSticky, setAtBottom, setAtEnd, setAtStart, setAtTop, setSticky, stickyRef, targetRef]); (0, _react.useEffect)(function () { if (target) { var stickyButNotAtEndSince = false; var timeout = setImmediateInterval(function () { var target = targetRef.current; var animating = animateToRef.current !== null; if (stickyRef.current) { if (!computeViewState({ mode: mode, target: target }).atEnd) { if (!stickyButNotAtEndSince) { stickyButNotAtEndSince = (0, _now["default"])(); } else if ((0, _now["default"])() - stickyButNotAtEndSince > SCROLL_DECISION_DURATION) { // Quirks: In Firefox, after user scroll down, Firefox do two things: // 1. Set to a new "scrollTop" // 2. Fire "scroll" event // For what we observed, #1 is fired about 20ms before #2. There is a chance that this stickyCheckTimeout is being scheduled between 1 and 2. // That means, if we just look at #1 to decide if we should scroll, we will always scroll, in oppose to the user's intention. // Repro: Open Firefox, set checkInterval to a lower number, and try to scroll by dragging the scroll handler. It will jump back. // The "animating" check will make sure stickiness is not lost when elements are adding at a very fast pace. if (!animating) { animateFromRef.current = target.scrollTop; debug(function () { var _context18; return (0, _concat["default"])(_context18 = ["%cInterval check%c: Should sticky but not at end, calling %cscrollToSticky()%c to scroll"]).call(_context18, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('navy')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('orange'))); }); scrollToSticky(); } stickyButNotAtEndSince = false; } } else { stickyButNotAtEndSince = false; } } else if (target.scrollHeight <= target.offsetHeight && !stickyRef.current) { // When the container is emptied, we will set sticky back to true. debug(function () { var _context19; return [(0, _concat["default"])(_context19 = ["%cInterval check%c: Container is emptied, setting sticky back to %ctrue%c"]).call(_context19, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('navy')), (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('purple'))), [{ offsetHeight: target.offsetHeight, scrollHeight: target.scrollHeight, sticky: stickyRef.current }]]; }); setSticky(true); } }, Math.max(MIN_CHECK_INTERVAL, checkInterval) || MIN_CHECK_INTERVAL); return function () { return clearInterval(timeout); }; } }, [animateToRef, checkInterval, debug, mode, scrollToSticky, setSticky, stickyRef, target, targetRef]); var styleToClassName = (0, _react.useMemo)(function () { var emotion = emotionPool[nonce] || (emotionPool[nonce] = (0, _createInstance["default"])({ key: 'react-scroll-to-bottom--css-' + (0, _createCSSKey["default"])(), nonce: nonce })); return function (style) { return emotion.css(style) + ''; }; }, [nonce]); var internalContext = (0, _react.useMemo)(function () { return { observeScrollPosition: observeScrollPosition, setTarget: setTarget, styleToClassName: styleToClassName }; }, [observeScrollPosition, setTarget, styleToClassName]); var state1Context = (0, _react.useMemo)(function () { return { atBottom: atBottom, atEnd: atEnd, atStart: atStart, atTop: atTop, mode: mode }; }, [atBottom, atEnd, atStart, atTop, mode]); var state2Context = (0, _react.useMemo)(function () { var animating = animateTo !== null; return { animating: animating, animatingToEnd: animating && isEnd(animateTo, mode), sticky: sticky }; }, [animateTo, mode, sticky]); var combinedStateContext = (0, _react.useMemo)(function () { return _objectSpread(_objectSpread({}, state1Context), state2Context); }, [state1Context, state2Context]); var functionContext = (0, _react.useMemo)(function () { return { scrollTo: scrollTo, scrollToBottom: scrollToBottom, scrollToEnd: scrollToEnd, scrollToStart: scrollToStart, scrollToTop: scrollToTop }; }, [scrollTo, scrollToBottom, scrollToEnd, scrollToStart, scrollToTop]); (0, _react.useEffect)(function () { // We need to update the "scrollHeight" value to latest when the user do a focus inside the box. // // This is because: // - In our code that mitigate Chrome synthetic scrolling, that code will look at whether "scrollHeight" value is latest or not. // - That code only run on "scroll" event. // - That means, on every "scroll" event, if the "scrollHeight" value is not latest, we will skip modifying the stickiness. // - That means, if the user "focus" to an element that cause the scroll view to scroll to the bottom, the user agent will fire "scroll" event. // Since the "scrollHeight" is not latest value, this "scroll" event will be ignored and stickiness will not be modified. // - That means, if the user "focus" to a newly added element that is at the end of the scroll view, the "scroll to bottom" button will continue to show. // // Repro in Chrome: // 1. Fill up a scroll view // 2. Scroll up, the "scroll to bottom" button should show up // 3. Click "Add a button" // 4. Click on the scroll view (to pseudo-focus on it) // 5. Press TAB, the scroll view will be at the bottom // // Expect: // - The "scroll to bottom" button should be gone. if (target) { var handleFocus = function handleFocus() { scrollHeightRef.current = target.scrollHeight; }; target.addEventListener('focus', handleFocus, { capture: true, passive: true }); return function () { return target.removeEventListener('focus', handleFocus); }; } }, [target]); debug(function () { var _context20; return [(0, _concat["default"])(_context20 = ["%cRender%c: Render"]).call(_context20, (0, _toConsumableArray2["default"])((0, _styleConsole["default"])('cyan', ''))), { animateTo: animateTo, animating: animateTo !== null, sticky: sticky, target: target }]; }); return /*#__PURE__*/_react["default"].createElement(_InternalContext["default"].Provider, { value: internalContext }, /*#__PURE__*/_react["default"].createElement(_FunctionContext["default"].Provider, { value: functionContext }, /*#__PURE__*/_react["default"].createElement(_StateContext["default"].Provider, { value: combinedStateContext }, /*#__PURE__*/_react["default"].createElement(_State1Context["default"].Provider, { value: state1Context }, /*#__PURE__*/_react["default"].createElement(_State2Context["default"].Provider, { value: state2Context }, children, target && /*#__PURE__*/_react["default"].createElement(_EventSpy["default"], { debounce: debounce, name: "scroll", onEvent: handleScroll, target: target }), target && animateTo !== null && /*#__PURE__*/_react["default"].createElement(_SpineTo["default"], { name: "scrollTop", onEnd: handleSpineToEnd, target: target, value: animateTo })))))); }; Composer.propTypes = { checkInterval: _propTypes["default"].number, children: _propTypes["default"].any, debounce: _propTypes["default"].number, debug: _propTypes["default"].bool, initialScrollBehavior: _propTypes["default"].oneOf(['auto', 'smooth']), mode: _propTypes["default"].oneOf(['bottom', 'top']), nonce: _propTypes["default"].string, scroller: _propTypes["default"].func }; var _default = Composer; exports["default"] = _default; //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9TY3JvbGxUb0JvdHRvbS9Db21wb3Nlci5qcyJdLCJuYW1lcyI6WyJERUZBVUxUX1NDUk9MTEVSIiwiSW5maW5pdHkiLCJNSU5fQ0hFQ0tfSU5URVJWQUwiLCJNT0RFX0JPVFRPTSIsIk1PREVfVE9QIiwiTkVBUl9FTkRfVEhSRVNIT0xEIiwiU0NST0xMX0RFQ0lTSU9OX0RVUkFUSU9OIiwiZW1vdGlvblBvb2wiLCJzZXRJbW1lZGlhdGVJbnRlcnZhbCIsImZuIiwibXMiLCJjb21wdXRlVmlld1N0YXRlIiwibW9kZSIsInRhcmdldCIsIm9mZnNldEhlaWdodCIsInNjcm9sbEhlaWdodCIsInNjcm9sbFRvcCIsImF0Qm90dG9tIiwiYXRUb3AiLCJhdEVuZCIsImF0U3RhcnQiLCJpc0VuZCIsImFuaW1hdGVUbyIsIkNvbXBvc2VyIiwiY2hlY2tJbnRlcnZhbCIsImNoaWxkcmVuIiwiZGVib3VuY2UiLCJkZWJ1Z0Zyb21Qcm9wIiwiZGVidWciLCJpbml0aWFsU2Nyb2xsQmVoYXZpb3IiLCJub25jZSIsInNjcm9sbGVyIiwiZm9yY2UiLCJpZ25vcmVTY3JvbGxFdmVudEJlZm9yZVJlZiIsImluaXRpYWxTY3JvbGxCZWhhdmlvclJlZiIsInNldEFuaW1hdGVUbyIsImFuaW1hdGVUb1JlZiIsInNldFRhcmdldCIsInRhcmdldFJlZiIsImFuaW1hdGVGcm9tUmVmIiwib2Zmc2V0SGVpZ2h0UmVmIiwic2Nyb2xsSGVpZ2h0UmVmIiwic2V0QXRCb3R0b20iLCJzZXRBdEVuZCIsInNldEF0VG9wIiwic2V0QXRTdGFydCIsInN0aWNreSIsInNldFN0aWNreSIsInN0aWNreVJlZiIsInNjcm9sbFBvc2l0aW9uT2JzZXJ2ZXJzUmVmIiwib2JzZXJ2ZVNjcm9sbFBvc2l0aW9uIiwiY3VycmVudCIsInB1c2giLCJzY3JvbGxQb3NpdGlvbk9ic2VydmVycyIsImluZGV4IiwiaGFuZGxlU3BpbmVUb0VuZCIsInNjcm9sbFRvIiwibmV4dEFuaW1hdGVUbyIsImJlaGF2aW9yIiwiY29uc29sZSIsIndhcm4iLCJyZXBsYWNlIiwic2Nyb2xsVG9Cb3R0b20iLCJzY3JvbGxUb1RvcCIsInNjcm9sbFRvRW5kIiwib3B0aW9ucyIsInNjcm9sbFRvU3RhcnQiLCJzY3JvbGxUb1N0aWNreSIsImFuaW1hdGVGcm9tIiwibWF4VmFsdWUiLCJNYXRoIiwibWF4IiwibWluVmFsdWUiLCJyYXdOZXh0VmFsdWUiLCJuZXh0VmFsdWUiLCJtaW4iLCJoYW5kbGVTY3JvbGwiLCJ0aW1lU3RhbXBMb3ciLCJhbmltYXRpbmciLCJuZXh0T2Zmc2V0SGVpZ2h0IiwibmV4dFNjcm9sbEhlaWdodCIsIm9mZnNldEhlaWdodENoYW5nZWQiLCJzY3JvbGxIZWlnaHRDaGFuZ2VkIiwibmV4dFN0aWNreSIsInByZXZPZmZzZXRIZWlnaHQiLCJwcmV2U2Nyb2xsSGVpZ2h0IiwiYWN0dWFsU2Nyb2xsVG9wIiwib2JzZXJ2ZXIiLCJzdGlja3lCdXROb3RBdEVuZFNpbmNlIiwidGltZW91dCIsImNsZWFySW50ZXJ2YWwiLCJzdHlsZVRvQ2xhc3NOYW1lIiwiZW1vdGlvbiIsImtleSIsInN0eWxlIiwiY3NzIiwiaW50ZXJuYWxDb250ZXh0Iiwic3RhdGUxQ29udGV4dCIsInN0YXRlMkNvbnRleHQiLCJhbmltYXRpbmdUb0VuZCIsImNvbWJpbmVkU3RhdGVDb250ZXh0IiwiZnVuY3Rpb25Db250ZXh0IiwiaGFuZGxlRm9jdXMiLCJhZGRFdmVudExpc3RlbmVyIiwiY2FwdHVyZSIsInBhc3NpdmUiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwicHJvcFR5cGVzIiwiUHJvcFR5cGVzIiwibnVtYmVyIiwiYW55IiwiYm9vbCIsIm9uZU9mIiwic3RyaW5nIiwiZnVuYyJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBOztBQUNBOztBQUNBOztBQUVBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztBQUNBOztB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