react-scroll-to-bottom-updated
Version:
React container that will auto scroll to bottom
631 lines (558 loc) • 85.2 kB
JavaScript
import _defineProperty from "@babel/runtime-corejs3/helpers/defineProperty";
import _toConsumableArray from "@babel/runtime-corejs3/helpers/toConsumableArray";
import _slicedToArray from "@babel/runtime-corejs3/helpers/slicedToArray";
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; _forEachInstanceProperty(_context21 = ownKeys(Object(source), true)).call(_context21, function (key) { _defineProperty(target, key, source[key]); }); } else if (_Object$getOwnPropertyDescriptors) { _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)); } else { var _context22; _forEachInstanceProperty(_context22 = ownKeys(Object(source))).call(_context22, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } } return target; }
import "core-js/modules/es.regexp.exec.js";
import "core-js/modules/es.string.replace.js";
import _setInterval from "@babel/runtime-corejs3/core-js-stable/set-interval";
import _indexOfInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/index-of";
import _spliceInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/splice";
import _concatInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/concat";
import _Date$now from "@babel/runtime-corejs3/core-js-stable/date/now";
import _forEachInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/for-each";
import _Object$keys from "@babel/runtime-corejs3/core-js-stable/object/keys";
import _Object$getOwnPropertySymbols from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols";
import _filterInstanceProperty from "@babel/runtime-corejs3/core-js-stable/instance/filter";
import _Object$getOwnPropertyDescriptor from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor";
import _Object$getOwnPropertyDescriptors from "@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors";
import _Object$defineProperties from "@babel/runtime-corejs3/core-js-stable/object/define-properties";
import _Object$defineProperty from "@babel/runtime-corejs3/core-js-stable/object/define-property";
import createEmotion from '@emotion/css/create-instance';
import PropTypes from 'prop-types';
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import createCSSKey from '../createCSSKey';
import createDebug from '../utils/debug';
import EventSpy from '../EventSpy';
import FunctionContext from './FunctionContext';
import InternalContext from './InternalContext';
import SpineTo from '../SpineTo';
import State1Context from './State1Context';
import State2Context from './State2Context';
import StateContext from './StateContext';
import styleConsole from '../utils/styleConsole';
import useStateRef from '../hooks/internal/useStateRef';
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 _setInterval(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 = useMemo(function () {
return createDebug("<ScrollToBottom>", {
force: debugFromProp
});
}, [debugFromProp]);
mode = mode === MODE_TOP ? MODE_TOP : MODE_BOTTOM;
var ignoreScrollEventBeforeRef = useRef(0);
var initialScrollBehaviorRef = useRef(initialScrollBehavior);
var _useStateRef = useStateRef(mode === MODE_TOP ? 0 : '100%'),
_useStateRef2 = _slicedToArray(_useStateRef, 3),
animateTo = _useStateRef2[0],
setAnimateTo = _useStateRef2[1],
animateToRef = _useStateRef2[2];
var _useStateRef3 = useStateRef(null),
_useStateRef4 = _slicedToArray(_useStateRef3, 3),
target = _useStateRef4[0],
setTarget = _useStateRef4[1],
targetRef = _useStateRef4[2]; // Internal context
var animateFromRef = useRef(0);
var offsetHeightRef = useRef(0);
var scrollHeightRef = useRef(0); // State context
var _useState = useState(true),
_useState2 = _slicedToArray(_useState, 2),
atBottom = _useState2[0],
setAtBottom = _useState2[1];
var _useState3 = useState(true),
_useState4 = _slicedToArray(_useState3, 2),
atEnd = _useState4[0],
setAtEnd = _useState4[1];
var _useState5 = useState(true),
_useState6 = _slicedToArray(_useState5, 2),
atTop = _useState6[0],
setAtTop = _useState6[1];
var _useState7 = useState(false),
_useState8 = _slicedToArray(_useState7, 2),
atStart = _useState8[0],
setAtStart = _useState8[1];
var _useStateRef5 = useStateRef(true),
_useStateRef6 = _slicedToArray(_useStateRef5, 3),
sticky = _useStateRef6[0],
setSticky = _useStateRef6[1],
stickyRef = _useStateRef6[2]; // High-rate state context
var scrollPositionObserversRef = useRef([]);
var observeScrollPosition = useCallback(function (fn) {
var target = targetRef.current;
scrollPositionObserversRef.current.push(fn);
target && fn({
scrollTop: target.scrollTop
});
return function () {
var scrollPositionObservers = scrollPositionObserversRef.current;
var index = _indexOfInstanceProperty(scrollPositionObservers).call(scrollPositionObservers, fn);
~index && _spliceInstanceProperty(scrollPositionObservers).call(scrollPositionObservers, index, 1);
};
}, [scrollPositionObserversRef, targetRef]);
var handleSpineToEnd = useCallback(function () {
var animateTo = animateToRef.current;
debug(function () {
var _context;
return _concatInstanceProperty(_context = ['%cSpineTo%c: %conEnd%c is fired.']).call(_context, _toConsumableArray(styleConsole('magenta')), _toConsumableArray(styleConsole('orange')), [{
animateTo: animateTo
}]);
});
ignoreScrollEventBeforeRef.current = _Date$now(); // 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 = 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 [_concatInstanceProperty(_context2 = ["%cscrollTo%c: Will scroll to %c".concat(typeof nextAnimateTo === 'number' ? nextAnimateTo + 'px' : nextAnimateTo.replace(/%/g, '%%'), "%c")]).call(_context2, _toConsumableArray(styleConsole('lime', '')), _toConsumableArray(styleConsole('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 [_concatInstanceProperty(_context3 = ["%cscrollTo%c: Scrolling to end, will set sticky to %ctrue%c."]).call(_context3, _toConsumableArray(styleConsole('lime', '')), _toConsumableArray(styleConsole('purple'))), [{
mode: mode,
nextAnimateTo: nextAnimateTo
}]];
});
setSticky(true);
}
}, [debug, handleSpineToEnd, mode, setAnimateTo, setSticky, targetRef]);
var scrollToBottom = useCallback(function () {
var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
behavior = _ref4.behavior;
debug(function () {
var _context4;
return _concatInstanceProperty(_context4 = ['%cscrollToBottom%c: Called']).call(_context4, _toConsumableArray(styleConsole('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 = useCallback(function () {
var _ref5 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
behavior = _ref5.behavior;
debug(function () {
var _context5;
return _concatInstanceProperty(_context5 = ['%cscrollToTop%c: Called']).call(_context5, _toConsumableArray(styleConsole('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 = useCallback(function () {
var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
behavior = _ref6.behavior;
debug(function () {
var _context6;
return _concatInstanceProperty(_context6 = ['%cscrollToEnd%c: Called']).call(_context6, _toConsumableArray(styleConsole('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 = useCallback(function () {
var _ref7 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
behavior = _ref7.behavior;
debug(function () {
var _context7;
return _concatInstanceProperty(_context7 = ['%cscrollToStart%c: Called']).call(_context7, _toConsumableArray(styleConsole('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 = useCallback(function () {
var target = targetRef.current;
if (target) {
if (initialScrollBehaviorRef.current === 'auto') {
debug(function () {
var _context8;
return _concatInstanceProperty(_context8 = ["%ctarget changed%c: Initial scroll"]).call(_context8, _toConsumableArray(styleConsole('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 [_concatInstanceProperty(_context9 = [_concatInstanceProperty(_context10 = _concatInstanceProperty(_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, _toConsumableArray(styleConsole('orange')), _toConsumableArray(styleConsole('purple')), _toConsumableArray(styleConsole('purple')), _toConsumableArray(styleConsole('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 = 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 [_concatInstanceProperty(_context12 = ["%conScroll%c: %csetSticky%c(%c".concat(nextSticky, "%c)")]).call(_context12, _toConsumableArray(styleConsole('red')), _toConsumableArray(styleConsole('red')), _toConsumableArray(styleConsole('purple'))), _concatInstanceProperty(_context13 = [_concatInstanceProperty(_context14 = _concatInstanceProperty(_context15 = "(animating = %c".concat(animating, "%c && isEnd = %c")).call(_context15, isEnd(animateTo, mode), "%c) || atEnd = %c")).call(_context14, atEnd, "%c")]).call(_context13, _toConsumableArray(styleConsole('purple')), _toConsumableArray(styleConsole('purple')), _toConsumableArray(styleConsole('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 [_concatInstanceProperty(_context16 = ["%conScroll%c: Size changed while sticky, calling %cscrollToSticky()%c"]).call(_context16, _toConsumableArray(styleConsole('red')), _toConsumableArray(styleConsole('orange')), [{
offsetHeightChanged: offsetHeightChanged,
scrollHeightChanged: scrollHeightChanged
}]), {
nextOffsetHeight: nextOffsetHeight,
prevOffsetHeight: offsetHeight,
nextScrollHeight: nextScrollHeight,
prevScrollHeight: scrollHeight
}];
});
scrollToSticky();
}
var actualScrollTop = target.scrollTop;
_forEachInstanceProperty(_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]);
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 = _Date$now();
} else if (_Date$now() - 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 _concatInstanceProperty(_context18 = ["%cInterval check%c: Should sticky but not at end, calling %cscrollToSticky()%c to scroll"]).call(_context18, _toConsumableArray(styleConsole('navy')), _toConsumableArray(styleConsole('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 [_concatInstanceProperty(_context19 = ["%cInterval check%c: Container is emptied, setting sticky back to %ctrue%c"]).call(_context19, _toConsumableArray(styleConsole('navy')), _toConsumableArray(styleConsole('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 = useMemo(function () {
var emotion = emotionPool[nonce] || (emotionPool[nonce] = createEmotion({
key: 'react-scroll-to-bottom--css-' + createCSSKey(),
nonce: nonce
}));
return function (style) {
return emotion.css(style) + '';
};
}, [nonce]);
var internalContext = useMemo(function () {
return {
observeScrollPosition: observeScrollPosition,
setTarget: setTarget,
styleToClassName: styleToClassName
};
}, [observeScrollPosition, setTarget, styleToClassName]);
var state1Context = useMemo(function () {
return {
atBottom: atBottom,
atEnd: atEnd,
atStart: atStart,
atTop: atTop,
mode: mode
};
}, [atBottom, atEnd, atStart, atTop, mode]);
var state2Context = useMemo(function () {
var animating = animateTo !== null;
return {
animating: animating,
animatingToEnd: animating && isEnd(animateTo, mode),
sticky: sticky
};
}, [animateTo, mode, sticky]);
var combinedStateContext = useMemo(function () {
return _objectSpread(_objectSpread({}, state1Context), state2Context);
}, [state1Context, state2Context]);
var functionContext = useMemo(function () {
return {
scrollTo: scrollTo,
scrollToBottom: scrollToBottom,
scrollToEnd: scrollToEnd,
scrollToStart: scrollToStart,
scrollToTop: scrollToTop
};
}, [scrollTo, scrollToBottom, scrollToEnd, scrollToStart, scrollToTop]);
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 [_concatInstanceProperty(_context20 = ["%cRender%c: Render"]).call(_context20, _toConsumableArray(styleConsole('cyan', ''))), {
animateTo: animateTo,
animating: animateTo !== null,
sticky: sticky,
target: target
}];
});
return /*#__PURE__*/React.createElement(InternalContext.Provider, {
value: internalContext
}, /*#__PURE__*/React.createElement(FunctionContext.Provider, {
value: functionContext
}, /*#__PURE__*/React.createElement(StateContext.Provider, {
value: combinedStateContext
}, /*#__PURE__*/React.createElement(State1Context.Provider, {
value: state1Context
}, /*#__PURE__*/React.createElement(State2Context.Provider, {
value: state2Context
}, children, target && /*#__PURE__*/React.createElement(EventSpy, {
debounce: debounce,
name: "scroll",
onEvent: handleScroll,
target: target
}), target && animateTo !== null && /*#__PURE__*/React.createElement(SpineTo, {
name: "scrollTop",
onEnd: handleSpineToEnd,
target: target,
value: animateTo
}))))));
};
Composer.propTypes = {
checkInterval: PropTypes.number,
children: PropTypes.any,
debounce: PropTypes.number,
debug: PropTypes.bool,
initialScrollBehavior: PropTypes.oneOf(['auto', 'smooth']),
mode: PropTypes.oneOf(['bottom', 'top']),
nonce: PropTypes.string,
scroller: PropTypes.func
};
export default Composer;
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9TY3JvbGxUb0JvdHRvbS9Db21wb3Nlci5qcyJdLCJuYW1lcyI6WyJjcmVhdGVFbW90aW9uIiwiUHJvcFR5cGVzIiwiUmVhY3QiLCJ1c2VDYWxsYmFjayIsInVzZUVmZmVjdCIsInVzZU1lbW8iLCJ1c2VSZWYiLCJ1c2VTdGF0ZSIsImNyZWF0ZUNTU0tleSIsImNyZWF0ZURlYnVnIiwiRXZlbnRTcHkiLCJGdW5jdGlvbkNvbnRleHQiLCJJbnRlcm5hbENvbnRleHQiLCJTcGluZVRvIiwiU3RhdGUxQ29udGV4dCIsIlN0YXRlMkNvbnRleHQiLCJTdGF0ZUNvbnRleHQiLCJzdHlsZUNvbnNvbGUiLCJ1c2VTdGF0ZVJlZiIsIkRFRkFVTFRfU0NST0xMRVIiLCJJbmZpbml0eSIsIk1JTl9DSEVDS19JTlRFUlZBTCIsIk1PREVfQk9UVE9NIiwiTU9ERV9UT1AiLCJORUFSX0VORF9USFJFU0hPTEQiLCJTQ1JPTExfREVDSVNJT05fRFVSQVRJT04iLCJlbW90aW9uUG9vbCIsInNldEltbWVkaWF0ZUludGVydmFsIiwiZm4iLCJtcyIsImNvbXB1dGVWaWV3U3RhdGUiLCJtb2RlIiwidGFyZ2V0Iiwib2Zmc2V0SGVpZ2h0Iiwic2Nyb2xsSGVpZ2h0Iiwic2Nyb2xsVG9wIiwiYXRCb3R0b20iLCJhdFRvcCIsImF0RW5kIiwiYXRTdGFydCIsImlzRW5kIiwiYW5pbWF0ZVRvIiwiQ29tcG9zZXIiLCJjaGVja0ludGVydmFsIiwiY2hpbGRyZW4iLCJkZWJvdW5jZSIsImRlYnVnRnJvbVByb3AiLCJkZWJ1ZyIsImluaXRpYWxTY3JvbGxCZWhhdmlvciIsIm5vbmNlIiwic2Nyb2xsZXIiLCJmb3JjZSIsImlnbm9yZVNjcm9sbEV2ZW50QmVmb3JlUmVmIiwiaW5pdGlhbFNjcm9sbEJlaGF2aW9yUmVmIiwic2V0QW5pbWF0ZVRvIiwiYW5pbWF0ZVRvUmVmIiwic2V0VGFyZ2V0IiwidGFyZ2V0UmVmIiwiYW5pbWF0ZUZyb21SZWYiLCJvZmZzZXRIZWlnaHRSZWYiLCJzY3JvbGxIZWlnaHRSZWYiLCJzZXRBdEJvdHRvbSIsInNldEF0RW5kIiwic2V0QXRUb3AiLCJzZXRBdFN0YXJ0Iiwic3RpY2t5Iiwic2V0U3RpY2t5Iiwic3RpY2t5UmVmIiwic2Nyb2xsUG9zaXRpb25PYnNlcnZlcnNSZWYiLCJvYnNlcnZlU2Nyb2xsUG9zaXRpb24iLCJjdXJyZW50IiwicHVzaCIsInNjcm9sbFBvc2l0aW9uT2JzZXJ2ZXJzIiwiaW5kZXgiLCJoYW5kbGVTcGluZVRvRW5kIiwic2Nyb2xsVG8iLCJuZXh0QW5pbWF0ZVRvIiwiYmVoYXZpb3IiLCJjb25zb2xlIiwid2FybiIsInJlcGxhY2UiLCJzY3JvbGxUb0JvdHRvbSIsInNjcm9sbFRvVG9wIiwic2Nyb2xsVG9FbmQiLCJvcHRpb25zIiwic2Nyb2xsVG9TdGFydCIsInNjcm9sbFRvU3RpY2t5IiwiYW5pbWF0ZUZyb20iLCJtYXhWYWx1ZSIsIk1hdGgiLCJtYXgiLCJtaW5WYWx1ZSIsInJhd05leHRWYWx1ZSIsIm5leHRWYWx1ZSIsIm1pbiIsImhhbmRsZVNjcm9sbCIsInRpbWVTdGFtcExvdyIsImFuaW1hdGluZyIsIm5leHRPZmZzZXRIZWlnaHQiLCJuZXh0U2Nyb2xsSGVpZ2h0Iiwib2Zmc2V0SGVpZ2h0Q2hhbmdlZCIsInNjcm9sbEhlaWdodENoYW5nZWQiLCJuZXh0U3RpY2t5IiwicHJldk9mZnNldEhlaWdodCIsInByZXZTY3JvbGxIZWlnaHQiLCJhY3R1YWxTY3JvbGxUb3AiLCJvYnNlcnZlciIsInN0aWNreUJ1dE5vdEF0RW5kU2luY2UiLCJ0aW1lb3V0IiwiY2xlYXJJbnRlcnZhbCIsInN0eWxlVG9DbGFzc05hbWUiLCJlbW90aW9uIiwia2V5Iiwic3R5bGUiLCJjc3MiLCJpbnRlcm5hbENvbnRleHQiLCJzdGF0ZTFDb250ZXh0Iiwic3RhdGUyQ29udGV4dCIsImFuaW1hdGluZ1RvRW5kIiwiY29tYmluZWRTdGF0ZUNvbnRleHQiLCJmdW5jdGlvbkNvbnRleHQiLCJoYW5kbGVGb2N1cyIsImFkZEV2ZW50TGlzdGVuZXIiLCJjYXB0dXJlIiwicGFzc2l2ZSIsInJlbW92ZUV2ZW50TGlzdGVuZXIiLCJwcm9wVHlwZXMiLCJudW1iZXIiLCJhbnkiLCJib29sIiwib25lT2YiLCJzdHJpbmciLCJmdW5jIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLE9BQU9BLGFBQVAsTUFBMEIsOEJBQTFCO0FBQ0EsT0FBT0MsU0FBUCxNQUFzQixZQUF0QjtBQUNBLE9BQU9DLEtBQVAsSUFBZ0JDLFdBQWhCLEVBQTZCQyxTQUE3QixFQUF3Q0MsT0FBeEMsRUFBaURDLE1BQWpELEVBQXlEQyxRQUF6RCxRQUF5RSxPQUF6RTtBQUVBLE9BQU9DLFlBQVAsTUFBeUIsaUJBQXpCO0FBQ0EsT0FBT0MsV0FBUCxNQUF3QixnQkFBeEI7QUFDQSxPQUFPQyxRQUFQLE1BQXFCLGFBQXJCO0FBQ0EsT0FBT0MsZUFBUCxNQUE0QixtQkFBNUI7QUFDQSxPQUFPQyxlQUFQLE1BQTRCLG1CQUE1QjtBQUNBLE9BQU9DLE9BQVAsTUFBb0IsWUFBcEI7QUFDQSxPQUFPQyxhQUFQLE1BQTBCLGlCQUExQjtBQUNBLE9BQU9DLGFBQVAsTUFBMEIsaUJBQTFCO0FBQ0EsT0FBT0MsWUFBUCxNQUF5QixnQkFBekI7QUFDQSxPQUFPQyxZQUFQLE1BQXlCLHVCQUF6QjtBQUNBLE9BQU9DLFdBQVAsTUFBd0IsK0JBQXhCOztBQUVBLElBQU1DLGdCQUFnQixHQUFHLFNBQW5CQSxnQkFBbUI7QUFBQSxTQUFNQyxRQUFOO0FBQUEsQ0FBekI7O0FBQ0EsSUFBTUMsa0JBQWtCLEdBQUcsRUFBM0IsQyxDQUErQjs7QUFDL0IsSUFBTUMsV0FBVyxHQUFHLFFBQXBCO0FBQ0EsSUFBTUMsUUFBUSxHQUFHLEtBQWpCO0FBQ0EsSUFBTUMsa0JBQWtCLEdBQUcsQ0FBM0I7QUFDQSxJQUFNQyx3QkFBd0IsR0FBRyxFQUFqQyxDLENBQXFDO0FBRXJDO0FBQ0E7O0FBQ0EsSUFBTUMsV0FBVyxHQUFHLEVBQXBCOztBQUVBLFNBQVNDLG9CQUFULENBQThCQyxF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