react-scroll-to-bottom-updated
Version:
React container that will auto scroll to bottom
679 lines (570 loc) • 87.8 kB
JavaScript
"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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