From 51937f7347a276c1ab690b0c57a15e8d523d7f0e Mon Sep 17 00:00:00 2001 From: ardeshir Date: Mon, 1 May 2023 14:45:18 +0000 Subject: [PATCH 1/6] fix long screen issue --- src/index.tsx | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/index.tsx b/src/index.tsx index 2782fbb..586883d 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -143,12 +143,21 @@ export default class InfiniteScroll extends Component { // do nothing when dataLength is unchanged if (this.props.dataLength === prevProps.dataLength) return; - this.actionTriggered = false; - - // update state when new data was sent in - this.setState({ - showLoader: false, - }); + const fetchAgain = + this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } } static getDerivedStateFromProps(nextProps: Props, prevState: State) { From ac995db0494c329fd8f2bd1505a8bc6731eb017d Mon Sep 17 00:00:00 2001 From: ardeshir Date: Tue, 2 May 2023 09:31:43 +0000 Subject: [PATCH 2/6] add dist folder to be able to install via git --- .gitignore | 1 - dist/__tests__/index.test.d.ts | 1 + dist/index.d.ts | 69 +++ dist/index.es.js | 537 +++++++++++++++++ dist/index.es.js.map | 1 + dist/index.js | 544 +++++++++++++++++ dist/index.js.map | 1 + dist/index.umd.js | 545 ++++++++++++++++++ dist/index.umd.js.map | 1 + dist/stories/InfiniteScrollWithHeight.d.ts | 9 + dist/stories/PullDownToRefreshInfScroll.d.ts | 8 + dist/stories/ScrollableTargetInfScroll.d.ts | 8 + dist/stories/ScrolleableTop.d.ts | 8 + .../WindowInfiniteScrollComponent.d.ts | 15 + dist/stories/stories.d.ts | 1 + dist/utils/threshold.d.ts | 10 + 16 files changed, 1758 insertions(+), 1 deletion(-) create mode 100644 dist/__tests__/index.test.d.ts create mode 100644 dist/index.d.ts create mode 100644 dist/index.es.js create mode 100644 dist/index.es.js.map create mode 100644 dist/index.js create mode 100644 dist/index.js.map create mode 100644 dist/index.umd.js create mode 100644 dist/index.umd.js.map create mode 100644 dist/stories/InfiniteScrollWithHeight.d.ts create mode 100644 dist/stories/PullDownToRefreshInfScroll.d.ts create mode 100644 dist/stories/ScrollableTargetInfScroll.d.ts create mode 100644 dist/stories/ScrolleableTop.d.ts create mode 100644 dist/stories/WindowInfiniteScrollComponent.d.ts create mode 100644 dist/stories/stories.d.ts create mode 100644 dist/utils/threshold.d.ts diff --git a/.gitignore b/.gitignore index 755bffe..fbc71c9 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ npm-debug.log node_modules /lib .rts2_* -dist .vscode storybook-static/ coverage/ diff --git a/dist/__tests__/index.test.d.ts b/dist/__tests__/index.test.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/__tests__/index.test.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 0000000..057ff5b --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,69 @@ +import { Component, ReactNode, CSSProperties } from 'react'; +declare type Fn = () => any; +export interface Props { + next: Fn; + hasMore: boolean; + children: ReactNode; + loader: ReactNode; + scrollThreshold?: number | string; + endMessage?: ReactNode; + style?: CSSProperties; + height?: number | string; + scrollableTarget?: ReactNode; + hasChildren?: boolean; + inverse?: boolean; + pullDownToRefresh?: boolean; + pullDownToRefreshContent?: ReactNode; + releaseToRefreshContent?: ReactNode; + pullDownToRefreshThreshold?: number; + refreshFunction?: Fn; + onScroll?: (e: MouseEvent) => any; + dataLength: number; + initialScrollY?: number; + className?: string; +} +interface State { + showLoader: boolean; + pullToRefreshThresholdBreached: boolean; + prevDataLength: number | undefined; +} +export default class InfiniteScroll extends Component { + constructor(props: Props); + private throttledOnScrollListener; + private _scrollableNode; + private el; + private _infScroll; + private lastScrollTop; + private actionTriggered; + private _pullDown; + private startY; + private currentY; + private dragging; + private maxPullDownDistance; + componentDidMount(): void; + componentWillUnmount(): void; + componentDidUpdate(prevProps: Props): void; + static getDerivedStateFromProps( + nextProps: Props, + prevState: State + ): { + prevDataLength: number; + showLoader: boolean; + pullToRefreshThresholdBreached: boolean; + } | null; + getScrollableTarget: () => HTMLElement | null; + onStart: EventListener; + onMove: EventListener; + onEnd: EventListener; + isElementAtTop( + target: HTMLElement, + scrollThreshold?: string | number + ): boolean; + isElementAtBottom( + target: HTMLElement, + scrollThreshold?: string | number + ): boolean; + onScrollListener: (event: MouseEvent) => void; + render(): JSX.Element; +} +export {}; diff --git a/dist/index.es.js b/dist/index.es.js new file mode 100644 index 0000000..cf4c5e5 --- /dev/null +++ b/dist/index.es.js @@ -0,0 +1,537 @@ +import React, { Component } from 'react'; + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function(d, b) { + d.__proto__ = b; + }) || + function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); +} + +var __assign = function() { + __assign = + Object.assign || + function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +/* eslint-disable no-undefined,no-param-reassign,no-shadow */ + +/** + * Throttle execution of a function. Especially useful for rate limiting + * execution of handlers on events like resize and scroll. + * + * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. + * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the + * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time + * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds, + * the internal counter is reset) + * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, + * to `callback` when the throttled-function is executed. + * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end), + * schedule `callback` to execute after `delay` ms. + * + * @return {Function} A new, throttled, function. + */ +function throttle(delay, noTrailing, callback, debounceMode) { + /* + * After wrapper has stopped being called, this timeout ensures that + * `callback` is executed at the proper times in `throttle` and `end` + * debounce modes. + */ + var timeoutID; + var cancelled = false; // Keep track of the last time `callback` was executed. + + var lastExec = 0; // Function to clear existing timeout + + function clearExistingTimeout() { + if (timeoutID) { + clearTimeout(timeoutID); + } + } // Function to cancel next exec + + function cancel() { + clearExistingTimeout(); + cancelled = true; + } // `noTrailing` defaults to falsy. + + if (typeof noTrailing !== 'boolean') { + debounceMode = callback; + callback = noTrailing; + noTrailing = undefined; + } + /* + * The `wrapper` function encapsulates all of the throttling / debouncing + * functionality and when executed will limit the rate at which `callback` + * is executed. + */ + + function wrapper() { + var self = this; + var elapsed = Date.now() - lastExec; + var args = arguments; + + if (cancelled) { + return; + } // Execute `callback` and update the `lastExec` timestamp. + + function exec() { + lastExec = Date.now(); + callback.apply(self, args); + } + /* + * If `debounceMode` is true (at begin) this is used to clear the flag + * to allow future `callback` executions. + */ + + function clear() { + timeoutID = undefined; + } + + if (debounceMode && !timeoutID) { + /* + * Since `wrapper` is being called for the first time and + * `debounceMode` is true (at begin), execute `callback`. + */ + exec(); + } + + clearExistingTimeout(); + + if (debounceMode === undefined && elapsed > delay) { + /* + * In throttle mode, if `delay` time has been exceeded, execute + * `callback`. + */ + exec(); + } else if (noTrailing !== true) { + /* + * In trailing throttle mode, since `delay` time has not been + * exceeded, schedule `callback` to execute `delay` ms after most + * recent execution. + * + * If `debounceMode` is true (at begin), schedule `clear` to execute + * after `delay` ms. + * + * If `debounceMode` is false (at end), schedule `callback` to + * execute after `delay` ms. + */ + timeoutID = setTimeout( + debounceMode ? clear : exec, + debounceMode === undefined ? delay - elapsed : delay + ); + } + } + + wrapper.cancel = cancel; // Return the wrapper function. + + return wrapper; +} + +var ThresholdUnits = { + Pixel: 'Pixel', + Percent: 'Percent', +}; +var defaultThreshold = { + unit: ThresholdUnits.Percent, + value: 0.8, +}; +function parseThreshold(scrollThreshold) { + if (typeof scrollThreshold === 'number') { + return { + unit: ThresholdUnits.Percent, + value: scrollThreshold * 100, + }; + } + if (typeof scrollThreshold === 'string') { + if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { + return { + unit: ThresholdUnits.Pixel, + value: parseFloat(scrollThreshold), + }; + } + if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { + return { + unit: ThresholdUnits.Percent, + value: parseFloat(scrollThreshold), + }; + } + console.warn( + 'scrollThreshold format is invalid. Valid formats: "120px", "50%"...' + ); + return defaultThreshold; + } + console.warn('scrollThreshold should be string or number'); + return defaultThreshold; +} + +var InfiniteScroll = /** @class */ (function(_super) { + __extends(InfiniteScroll, _super); + function InfiniteScroll(props) { + var _this = _super.call(this, props) || this; + _this.lastScrollTop = 0; + _this.actionTriggered = false; + // variables to keep track of pull down behaviour + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + // will be populated in componentDidMount + // based on the height of the pull down element + _this.maxPullDownDistance = 0; + _this.getScrollableTarget = function() { + if (_this.props.scrollableTarget instanceof HTMLElement) + return _this.props.scrollableTarget; + if (typeof _this.props.scrollableTarget === 'string') { + return document.getElementById(_this.props.scrollableTarget); + } + if (_this.props.scrollableTarget === null) { + console.warn( + 'You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ' + ); + } + return null; + }; + _this.onStart = function(evt) { + if (_this.lastScrollTop) return; + _this.dragging = true; + if (evt instanceof MouseEvent) { + _this.startY = evt.pageY; + } else if (evt instanceof TouchEvent) { + _this.startY = evt.touches[0].pageY; + } + _this.currentY = _this.startY; + if (_this._infScroll) { + _this._infScroll.style.willChange = 'transform'; + _this._infScroll.style.transition = + 'transform 0.2s cubic-bezier(0,0,0.31,1)'; + } + }; + _this.onMove = function(evt) { + if (!_this.dragging) return; + if (evt instanceof MouseEvent) { + _this.currentY = evt.pageY; + } else if (evt instanceof TouchEvent) { + _this.currentY = evt.touches[0].pageY; + } + // user is scrolling down to up + if (_this.currentY < _this.startY) return; + if ( + _this.currentY - _this.startY >= + Number(_this.props.pullDownToRefreshThreshold) + ) { + _this.setState({ + pullToRefreshThresholdBreached: true, + }); + } + // so you can drag upto 1.5 times of the maxPullDownDistance + if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) + return; + if (_this._infScroll) { + _this._infScroll.style.overflow = 'visible'; + _this._infScroll.style.transform = + 'translate3d(0px, ' + (_this.currentY - _this.startY) + 'px, 0px)'; + } + }; + _this.onEnd = function() { + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + if (_this.state.pullToRefreshThresholdBreached) { + _this.props.refreshFunction && _this.props.refreshFunction(); + _this.setState({ + pullToRefreshThresholdBreached: false, + }); + } + requestAnimationFrame(function() { + // this._infScroll + if (_this._infScroll) { + _this._infScroll.style.overflow = 'auto'; + _this._infScroll.style.transform = 'none'; + _this._infScroll.style.willChange = 'unset'; + } + }); + }; + _this.onScrollListener = function(event) { + if (typeof _this.props.onScroll === 'function') { + // Execute this callback in next tick so that it does not affect the + // functionality of the library. + setTimeout(function() { + return _this.props.onScroll && _this.props.onScroll(event); + }, 0); + } + var target = + _this.props.height || _this._scrollableNode + ? event.target + : document.documentElement.scrollTop + ? document.documentElement + : document.body; + // return immediately if the action has already been triggered, + // prevents multiple triggers. + if (_this.actionTriggered) return; + var atBottom = _this.props.inverse + ? _this.isElementAtTop(target, _this.props.scrollThreshold) + : _this.isElementAtBottom(target, _this.props.scrollThreshold); + // call the `next` function in the props to trigger the next data fetch + if (atBottom && _this.props.hasMore) { + _this.actionTriggered = true; + _this.setState({ showLoader: true }); + _this.props.next && _this.props.next(); + } + _this.lastScrollTop = target.scrollTop; + }; + _this.state = { + showLoader: false, + pullToRefreshThresholdBreached: false, + prevDataLength: props.dataLength, + }; + _this.throttledOnScrollListener = throttle( + 150, + _this.onScrollListener + ).bind(_this); + _this.onStart = _this.onStart.bind(_this); + _this.onMove = _this.onMove.bind(_this); + _this.onEnd = _this.onEnd.bind(_this); + return _this; + } + InfiniteScroll.prototype.componentDidMount = function() { + if (typeof this.props.dataLength === 'undefined') { + throw new Error( + 'mandatory prop "dataLength" is missing. The prop is needed' + + ' when loading more content. Check README.md for usage' + ); + } + this._scrollableNode = this.getScrollableTarget(); + this.el = this.props.height + ? this._infScroll + : this._scrollableNode || window; + if (this.el) { + this.el.addEventListener('scroll', this.throttledOnScrollListener); + } + if ( + typeof this.props.initialScrollY === 'number' && + this.el && + this.el instanceof HTMLElement && + this.el.scrollHeight > this.props.initialScrollY + ) { + this.el.scrollTo(0, this.props.initialScrollY); + } + if (this.props.pullDownToRefresh && this.el) { + this.el.addEventListener('touchstart', this.onStart); + this.el.addEventListener('touchmove', this.onMove); + this.el.addEventListener('touchend', this.onEnd); + this.el.addEventListener('mousedown', this.onStart); + this.el.addEventListener('mousemove', this.onMove); + this.el.addEventListener('mouseup', this.onEnd); + // get BCR of pullDown element to position it above + this.maxPullDownDistance = + (this._pullDown && + this._pullDown.firstChild && + this._pullDown.firstChild.getBoundingClientRect().height) || + 0; + this.forceUpdate(); + if (typeof this.props.refreshFunction !== 'function') { + throw new Error( + 'Mandatory prop "refreshFunction" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage\'' + ); + } + } + }; + InfiniteScroll.prototype.componentWillUnmount = function() { + if (this.el) { + this.el.removeEventListener('scroll', this.throttledOnScrollListener); + if (this.props.pullDownToRefresh) { + this.el.removeEventListener('touchstart', this.onStart); + this.el.removeEventListener('touchmove', this.onMove); + this.el.removeEventListener('touchend', this.onEnd); + this.el.removeEventListener('mousedown', this.onStart); + this.el.removeEventListener('mousemove', this.onMove); + this.el.removeEventListener('mouseup', this.onEnd); + } + } + }; + InfiniteScroll.prototype.componentDidUpdate = function(prevProps) { + // do nothing when dataLength is unchanged + if (this.props.dataLength === prevProps.dataLength) return; + var fetchAgain = + this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } + }; + InfiniteScroll.getDerivedStateFromProps = function(nextProps, prevState) { + var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; + // reset when data changes + if (dataLengthChanged) { + return __assign(__assign({}, prevState), { + prevDataLength: nextProps.dataLength, + }); + } + return null; + }; + InfiniteScroll.prototype.isElementAtTop = function(target, scrollThreshold) { + if (scrollThreshold === void 0) { + scrollThreshold = 0.8; + } + var clientHeight = + target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return ( + target.scrollTop <= + threshold.value + clientHeight - target.scrollHeight + 1 + ); + } + return ( + target.scrollTop <= + threshold.value / 100 + clientHeight - target.scrollHeight + 1 + ); + }; + InfiniteScroll.prototype.isElementAtBottom = function( + target, + scrollThreshold + ) { + if (scrollThreshold === void 0) { + scrollThreshold = 0.8; + } + var clientHeight = + target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return ( + target.scrollTop + clientHeight >= target.scrollHeight - threshold.value + ); + } + return ( + target.scrollTop + clientHeight >= + (threshold.value / 100) * target.scrollHeight + ); + }; + InfiniteScroll.prototype.render = function() { + var _this = this; + var style = __assign( + { + height: this.props.height || 'auto', + overflow: 'auto', + WebkitOverflowScrolling: 'touch', + }, + this.props.style + ); + var hasChildren = + this.props.hasChildren || + !!( + this.props.children && + this.props.children instanceof Array && + this.props.children.length + ); + // because heighted infiniteScroll visualy breaks + // on drag down as overflow becomes visible + var outerDivStyle = + this.props.pullDownToRefresh && this.props.height + ? { overflow: 'auto' } + : {}; + return React.createElement( + 'div', + { + style: outerDivStyle, + className: 'infinite-scroll-component__outerdiv', + }, + React.createElement( + 'div', + { + className: + 'infinite-scroll-component ' + (this.props.className || ''), + ref: function(infScroll) { + return (_this._infScroll = infScroll); + }, + style: style, + }, + this.props.pullDownToRefresh && + React.createElement( + 'div', + { + style: { position: 'relative' }, + ref: function(pullDown) { + return (_this._pullDown = pullDown); + }, + }, + React.createElement( + 'div', + { + style: { + position: 'absolute', + left: 0, + right: 0, + top: -1 * this.maxPullDownDistance, + }, + }, + this.state.pullToRefreshThresholdBreached + ? this.props.releaseToRefreshContent + : this.props.pullDownToRefreshContent + ) + ), + this.props.children, + !this.state.showLoader && + !hasChildren && + this.props.hasMore && + this.props.loader, + this.state.showLoader && this.props.hasMore && this.props.loader, + !this.props.hasMore && this.props.endMessage + ) + ); + }; + return InfiniteScroll; +})(Component); + +export default InfiniteScroll; +//# sourceMappingURL=index.es.js.map diff --git a/dist/index.es.js.map b/dist/index.es.js.map new file mode 100644 index 0000000..b2384e6 --- /dev/null +++ b/dist/index.es.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.es.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/throttle-debounce/dist/index.esm.js"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\r\n if (m) return m.call(o);\r\n return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the\n * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time\n * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds,\n * the internal counter is reset)\n * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the throttled-function is executed.\n * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end),\n * schedule `callback` to execute after `delay` ms.\n *\n * @return {Function} A new, throttled, function.\n */\nfunction throttle (delay, noTrailing, callback, debounceMode) {\n /*\n * After wrapper has stopped being called, this timeout ensures that\n * `callback` is executed at the proper times in `throttle` and `end`\n * debounce modes.\n */\n var timeoutID;\n var cancelled = false; // Keep track of the last time `callback` was executed.\n\n var lastExec = 0; // Function to clear existing timeout\n\n function clearExistingTimeout() {\n if (timeoutID) {\n clearTimeout(timeoutID);\n }\n } // Function to cancel next exec\n\n\n function cancel() {\n clearExistingTimeout();\n cancelled = true;\n } // `noTrailing` defaults to falsy.\n\n\n if (typeof noTrailing !== 'boolean') {\n debounceMode = callback;\n callback = noTrailing;\n noTrailing = undefined;\n }\n /*\n * The `wrapper` function encapsulates all of the throttling / debouncing\n * functionality and when executed will limit the rate at which `callback`\n * is executed.\n */\n\n\n function wrapper() {\n var self = this;\n var elapsed = Date.now() - lastExec;\n var args = arguments;\n\n if (cancelled) {\n return;\n } // Execute `callback` and update the `lastExec` timestamp.\n\n\n function exec() {\n lastExec = Date.now();\n callback.apply(self, args);\n }\n /*\n * If `debounceMode` is true (at begin) this is used to clear the flag\n * to allow future `callback` executions.\n */\n\n\n function clear() {\n timeoutID = undefined;\n }\n\n if (debounceMode && !timeoutID) {\n /*\n * Since `wrapper` is being called for the first time and\n * `debounceMode` is true (at begin), execute `callback`.\n */\n exec();\n }\n\n clearExistingTimeout();\n\n if (debounceMode === undefined && elapsed > delay) {\n /*\n * In throttle mode, if `delay` time has been exceeded, execute\n * `callback`.\n */\n exec();\n } else if (noTrailing !== true) {\n /*\n * In trailing throttle mode, since `delay` time has not been\n * exceeded, schedule `callback` to execute `delay` ms after most\n * recent execution.\n *\n * If `debounceMode` is true (at begin), schedule `clear` to execute\n * after `delay` ms.\n *\n * If `debounceMode` is false (at end), schedule `callback` to\n * execute after `delay` ms.\n */\n timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);\n }\n }\n\n wrapper.cancel = cancel; // Return the wrapper function.\n\n return wrapper;\n}\n\n/* eslint-disable no-undefined */\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Boolean} [atBegin] Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the debounced-function is executed.\n *\n * @return {Function} A new, debounced function.\n */\n\nfunction debounce (delay, atBegin, callback) {\n return callback === undefined ? throttle(delay, atBegin, false) : throttle(delay, callback, atBegin !== false);\n}\n\nexport { throttle, debounce };\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 0000000..f9cfac7 --- /dev/null +++ b/dist/index.js @@ -0,0 +1,544 @@ +'use strict'; + +function _interopDefault(ex) { + return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex; +} + +var React = require('react'); +var React__default = _interopDefault(React); + +/*! ***************************************************************************** +Copyright (c) Microsoft Corporation. All rights reserved. +Licensed under the Apache License, Version 2.0 (the "License"); you may not use +this file except in compliance with the License. You may obtain a copy of the +License at http://www.apache.org/licenses/LICENSE-2.0 + +THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED +WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, +MERCHANTABLITY OR NON-INFRINGEMENT. + +See the Apache Version 2.0 License for specific language governing permissions +and limitations under the License. +***************************************************************************** */ +/* global Reflect, Promise */ + +var extendStatics = function(d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function(d, b) { + d.__proto__ = b; + }) || + function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return extendStatics(d, b); +}; + +function __extends(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); +} + +var __assign = function() { + __assign = + Object.assign || + function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); +}; + +/* eslint-disable no-undefined,no-param-reassign,no-shadow */ + +/** + * Throttle execution of a function. Especially useful for rate limiting + * execution of handlers on events like resize and scroll. + * + * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. + * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the + * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time + * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds, + * the internal counter is reset) + * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, + * to `callback` when the throttled-function is executed. + * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end), + * schedule `callback` to execute after `delay` ms. + * + * @return {Function} A new, throttled, function. + */ +function throttle(delay, noTrailing, callback, debounceMode) { + /* + * After wrapper has stopped being called, this timeout ensures that + * `callback` is executed at the proper times in `throttle` and `end` + * debounce modes. + */ + var timeoutID; + var cancelled = false; // Keep track of the last time `callback` was executed. + + var lastExec = 0; // Function to clear existing timeout + + function clearExistingTimeout() { + if (timeoutID) { + clearTimeout(timeoutID); + } + } // Function to cancel next exec + + function cancel() { + clearExistingTimeout(); + cancelled = true; + } // `noTrailing` defaults to falsy. + + if (typeof noTrailing !== 'boolean') { + debounceMode = callback; + callback = noTrailing; + noTrailing = undefined; + } + /* + * The `wrapper` function encapsulates all of the throttling / debouncing + * functionality and when executed will limit the rate at which `callback` + * is executed. + */ + + function wrapper() { + var self = this; + var elapsed = Date.now() - lastExec; + var args = arguments; + + if (cancelled) { + return; + } // Execute `callback` and update the `lastExec` timestamp. + + function exec() { + lastExec = Date.now(); + callback.apply(self, args); + } + /* + * If `debounceMode` is true (at begin) this is used to clear the flag + * to allow future `callback` executions. + */ + + function clear() { + timeoutID = undefined; + } + + if (debounceMode && !timeoutID) { + /* + * Since `wrapper` is being called for the first time and + * `debounceMode` is true (at begin), execute `callback`. + */ + exec(); + } + + clearExistingTimeout(); + + if (debounceMode === undefined && elapsed > delay) { + /* + * In throttle mode, if `delay` time has been exceeded, execute + * `callback`. + */ + exec(); + } else if (noTrailing !== true) { + /* + * In trailing throttle mode, since `delay` time has not been + * exceeded, schedule `callback` to execute `delay` ms after most + * recent execution. + * + * If `debounceMode` is true (at begin), schedule `clear` to execute + * after `delay` ms. + * + * If `debounceMode` is false (at end), schedule `callback` to + * execute after `delay` ms. + */ + timeoutID = setTimeout( + debounceMode ? clear : exec, + debounceMode === undefined ? delay - elapsed : delay + ); + } + } + + wrapper.cancel = cancel; // Return the wrapper function. + + return wrapper; +} + +var ThresholdUnits = { + Pixel: 'Pixel', + Percent: 'Percent', +}; +var defaultThreshold = { + unit: ThresholdUnits.Percent, + value: 0.8, +}; +function parseThreshold(scrollThreshold) { + if (typeof scrollThreshold === 'number') { + return { + unit: ThresholdUnits.Percent, + value: scrollThreshold * 100, + }; + } + if (typeof scrollThreshold === 'string') { + if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { + return { + unit: ThresholdUnits.Pixel, + value: parseFloat(scrollThreshold), + }; + } + if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { + return { + unit: ThresholdUnits.Percent, + value: parseFloat(scrollThreshold), + }; + } + console.warn( + 'scrollThreshold format is invalid. Valid formats: "120px", "50%"...' + ); + return defaultThreshold; + } + console.warn('scrollThreshold should be string or number'); + return defaultThreshold; +} + +var InfiniteScroll = /** @class */ (function(_super) { + __extends(InfiniteScroll, _super); + function InfiniteScroll(props) { + var _this = _super.call(this, props) || this; + _this.lastScrollTop = 0; + _this.actionTriggered = false; + // variables to keep track of pull down behaviour + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + // will be populated in componentDidMount + // based on the height of the pull down element + _this.maxPullDownDistance = 0; + _this.getScrollableTarget = function() { + if (_this.props.scrollableTarget instanceof HTMLElement) + return _this.props.scrollableTarget; + if (typeof _this.props.scrollableTarget === 'string') { + return document.getElementById(_this.props.scrollableTarget); + } + if (_this.props.scrollableTarget === null) { + console.warn( + 'You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ' + ); + } + return null; + }; + _this.onStart = function(evt) { + if (_this.lastScrollTop) return; + _this.dragging = true; + if (evt instanceof MouseEvent) { + _this.startY = evt.pageY; + } else if (evt instanceof TouchEvent) { + _this.startY = evt.touches[0].pageY; + } + _this.currentY = _this.startY; + if (_this._infScroll) { + _this._infScroll.style.willChange = 'transform'; + _this._infScroll.style.transition = + 'transform 0.2s cubic-bezier(0,0,0.31,1)'; + } + }; + _this.onMove = function(evt) { + if (!_this.dragging) return; + if (evt instanceof MouseEvent) { + _this.currentY = evt.pageY; + } else if (evt instanceof TouchEvent) { + _this.currentY = evt.touches[0].pageY; + } + // user is scrolling down to up + if (_this.currentY < _this.startY) return; + if ( + _this.currentY - _this.startY >= + Number(_this.props.pullDownToRefreshThreshold) + ) { + _this.setState({ + pullToRefreshThresholdBreached: true, + }); + } + // so you can drag upto 1.5 times of the maxPullDownDistance + if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) + return; + if (_this._infScroll) { + _this._infScroll.style.overflow = 'visible'; + _this._infScroll.style.transform = + 'translate3d(0px, ' + (_this.currentY - _this.startY) + 'px, 0px)'; + } + }; + _this.onEnd = function() { + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + if (_this.state.pullToRefreshThresholdBreached) { + _this.props.refreshFunction && _this.props.refreshFunction(); + _this.setState({ + pullToRefreshThresholdBreached: false, + }); + } + requestAnimationFrame(function() { + // this._infScroll + if (_this._infScroll) { + _this._infScroll.style.overflow = 'auto'; + _this._infScroll.style.transform = 'none'; + _this._infScroll.style.willChange = 'unset'; + } + }); + }; + _this.onScrollListener = function(event) { + if (typeof _this.props.onScroll === 'function') { + // Execute this callback in next tick so that it does not affect the + // functionality of the library. + setTimeout(function() { + return _this.props.onScroll && _this.props.onScroll(event); + }, 0); + } + var target = + _this.props.height || _this._scrollableNode + ? event.target + : document.documentElement.scrollTop + ? document.documentElement + : document.body; + // return immediately if the action has already been triggered, + // prevents multiple triggers. + if (_this.actionTriggered) return; + var atBottom = _this.props.inverse + ? _this.isElementAtTop(target, _this.props.scrollThreshold) + : _this.isElementAtBottom(target, _this.props.scrollThreshold); + // call the `next` function in the props to trigger the next data fetch + if (atBottom && _this.props.hasMore) { + _this.actionTriggered = true; + _this.setState({ showLoader: true }); + _this.props.next && _this.props.next(); + } + _this.lastScrollTop = target.scrollTop; + }; + _this.state = { + showLoader: false, + pullToRefreshThresholdBreached: false, + prevDataLength: props.dataLength, + }; + _this.throttledOnScrollListener = throttle( + 150, + _this.onScrollListener + ).bind(_this); + _this.onStart = _this.onStart.bind(_this); + _this.onMove = _this.onMove.bind(_this); + _this.onEnd = _this.onEnd.bind(_this); + return _this; + } + InfiniteScroll.prototype.componentDidMount = function() { + if (typeof this.props.dataLength === 'undefined') { + throw new Error( + 'mandatory prop "dataLength" is missing. The prop is needed' + + ' when loading more content. Check README.md for usage' + ); + } + this._scrollableNode = this.getScrollableTarget(); + this.el = this.props.height + ? this._infScroll + : this._scrollableNode || window; + if (this.el) { + this.el.addEventListener('scroll', this.throttledOnScrollListener); + } + if ( + typeof this.props.initialScrollY === 'number' && + this.el && + this.el instanceof HTMLElement && + this.el.scrollHeight > this.props.initialScrollY + ) { + this.el.scrollTo(0, this.props.initialScrollY); + } + if (this.props.pullDownToRefresh && this.el) { + this.el.addEventListener('touchstart', this.onStart); + this.el.addEventListener('touchmove', this.onMove); + this.el.addEventListener('touchend', this.onEnd); + this.el.addEventListener('mousedown', this.onStart); + this.el.addEventListener('mousemove', this.onMove); + this.el.addEventListener('mouseup', this.onEnd); + // get BCR of pullDown element to position it above + this.maxPullDownDistance = + (this._pullDown && + this._pullDown.firstChild && + this._pullDown.firstChild.getBoundingClientRect().height) || + 0; + this.forceUpdate(); + if (typeof this.props.refreshFunction !== 'function') { + throw new Error( + 'Mandatory prop "refreshFunction" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage\'' + ); + } + } + }; + InfiniteScroll.prototype.componentWillUnmount = function() { + if (this.el) { + this.el.removeEventListener('scroll', this.throttledOnScrollListener); + if (this.props.pullDownToRefresh) { + this.el.removeEventListener('touchstart', this.onStart); + this.el.removeEventListener('touchmove', this.onMove); + this.el.removeEventListener('touchend', this.onEnd); + this.el.removeEventListener('mousedown', this.onStart); + this.el.removeEventListener('mousemove', this.onMove); + this.el.removeEventListener('mouseup', this.onEnd); + } + } + }; + InfiniteScroll.prototype.componentDidUpdate = function(prevProps) { + // do nothing when dataLength is unchanged + if (this.props.dataLength === prevProps.dataLength) return; + var fetchAgain = + this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } + }; + InfiniteScroll.getDerivedStateFromProps = function(nextProps, prevState) { + var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; + // reset when data changes + if (dataLengthChanged) { + return __assign(__assign({}, prevState), { + prevDataLength: nextProps.dataLength, + }); + } + return null; + }; + InfiniteScroll.prototype.isElementAtTop = function(target, scrollThreshold) { + if (scrollThreshold === void 0) { + scrollThreshold = 0.8; + } + var clientHeight = + target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return ( + target.scrollTop <= + threshold.value + clientHeight - target.scrollHeight + 1 + ); + } + return ( + target.scrollTop <= + threshold.value / 100 + clientHeight - target.scrollHeight + 1 + ); + }; + InfiniteScroll.prototype.isElementAtBottom = function( + target, + scrollThreshold + ) { + if (scrollThreshold === void 0) { + scrollThreshold = 0.8; + } + var clientHeight = + target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return ( + target.scrollTop + clientHeight >= target.scrollHeight - threshold.value + ); + } + return ( + target.scrollTop + clientHeight >= + (threshold.value / 100) * target.scrollHeight + ); + }; + InfiniteScroll.prototype.render = function() { + var _this = this; + var style = __assign( + { + height: this.props.height || 'auto', + overflow: 'auto', + WebkitOverflowScrolling: 'touch', + }, + this.props.style + ); + var hasChildren = + this.props.hasChildren || + !!( + this.props.children && + this.props.children instanceof Array && + this.props.children.length + ); + // because heighted infiniteScroll visualy breaks + // on drag down as overflow becomes visible + var outerDivStyle = + this.props.pullDownToRefresh && this.props.height + ? { overflow: 'auto' } + : {}; + return React__default.createElement( + 'div', + { + style: outerDivStyle, + className: 'infinite-scroll-component__outerdiv', + }, + React__default.createElement( + 'div', + { + className: + 'infinite-scroll-component ' + (this.props.className || ''), + ref: function(infScroll) { + return (_this._infScroll = infScroll); + }, + style: style, + }, + this.props.pullDownToRefresh && + React__default.createElement( + 'div', + { + style: { position: 'relative' }, + ref: function(pullDown) { + return (_this._pullDown = pullDown); + }, + }, + React__default.createElement( + 'div', + { + style: { + position: 'absolute', + left: 0, + right: 0, + top: -1 * this.maxPullDownDistance, + }, + }, + this.state.pullToRefreshThresholdBreached + ? this.props.releaseToRefreshContent + : this.props.pullDownToRefreshContent + ) + ), + this.props.children, + !this.state.showLoader && + !hasChildren && + this.props.hasMore && + this.props.loader, + this.state.showLoader && this.props.hasMore && this.props.loader, + !this.props.hasMore && this.props.endMessage + ) + ); + }; + return InfiniteScroll; +})(React.Component); + +module.exports = InfiniteScroll; +//# sourceMappingURL=index.js.map diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 0000000..ac3f7bc --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/throttle-debounce/dist/index.esm.js"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\r\n if (m) return m.call(o);\r\n return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the\n * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time\n * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds,\n * the internal counter is reset)\n * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the throttled-function is executed.\n * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end),\n * schedule `callback` to execute after `delay` ms.\n *\n * @return {Function} A new, throttled, function.\n */\nfunction throttle (delay, noTrailing, callback, debounceMode) {\n /*\n * After wrapper has stopped being called, this timeout ensures that\n * `callback` is executed at the proper times in `throttle` and `end`\n * debounce modes.\n */\n var timeoutID;\n var cancelled = false; // Keep track of the last time `callback` was executed.\n\n var lastExec = 0; // Function to clear existing timeout\n\n function clearExistingTimeout() {\n if (timeoutID) {\n clearTimeout(timeoutID);\n }\n } // Function to cancel next exec\n\n\n function cancel() {\n clearExistingTimeout();\n cancelled = true;\n } // `noTrailing` defaults to falsy.\n\n\n if (typeof noTrailing !== 'boolean') {\n debounceMode = callback;\n callback = noTrailing;\n noTrailing = undefined;\n }\n /*\n * The `wrapper` function encapsulates all of the throttling / debouncing\n * functionality and when executed will limit the rate at which `callback`\n * is executed.\n */\n\n\n function wrapper() {\n var self = this;\n var elapsed = Date.now() - lastExec;\n var args = arguments;\n\n if (cancelled) {\n return;\n } // Execute `callback` and update the `lastExec` timestamp.\n\n\n function exec() {\n lastExec = Date.now();\n callback.apply(self, args);\n }\n /*\n * If `debounceMode` is true (at begin) this is used to clear the flag\n * to allow future `callback` executions.\n */\n\n\n function clear() {\n timeoutID = undefined;\n }\n\n if (debounceMode && !timeoutID) {\n /*\n * Since `wrapper` is being called for the first time and\n * `debounceMode` is true (at begin), execute `callback`.\n */\n exec();\n }\n\n clearExistingTimeout();\n\n if (debounceMode === undefined && elapsed > delay) {\n /*\n * In throttle mode, if `delay` time has been exceeded, execute\n * `callback`.\n */\n exec();\n } else if (noTrailing !== true) {\n /*\n * In trailing throttle mode, since `delay` time has not been\n * exceeded, schedule `callback` to execute `delay` ms after most\n * recent execution.\n *\n * If `debounceMode` is true (at begin), schedule `clear` to execute\n * after `delay` ms.\n *\n * If `debounceMode` is false (at end), schedule `callback` to\n * execute after `delay` ms.\n */\n timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);\n }\n }\n\n wrapper.cancel = cancel; // Return the wrapper function.\n\n return wrapper;\n}\n\n/* eslint-disable no-undefined */\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Boolean} [atBegin] Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the debounced-function is executed.\n *\n * @return {Function} A new, debounced function.\n */\n\nfunction debounce (delay, atBegin, callback) {\n return callback === undefined ? throttle(delay, atBegin, false) : throttle(delay, callback, atBegin !== false);\n}\n\nexport { throttle, debounce };\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.umd.js b/dist/index.umd.js new file mode 100644 index 0000000..434d3e2 --- /dev/null +++ b/dist/index.umd.js @@ -0,0 +1,545 @@ +var InfiniteScroll = (function(React) { + 'use strict'; + + var React__default = 'default' in React ? React['default'] : React; + + /*! ***************************************************************************** + Copyright (c) Microsoft Corporation. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); you may not use + this file except in compliance with the License. You may obtain a copy of the + License at http://www.apache.org/licenses/LICENSE-2.0 + + THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED + WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, + MERCHANTABLITY OR NON-INFRINGEMENT. + + See the Apache Version 2.0 License for specific language governing permissions + and limitations under the License. + ***************************************************************************** */ + /* global Reflect, Promise */ + + var extendStatics = function(d, b) { + extendStatics = + Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && + function(d, b) { + d.__proto__ = b; + }) || + function(d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + }; + return extendStatics(d, b); + }; + + function __extends(d, b) { + extendStatics(d, b); + function __() { + this.constructor = d; + } + d.prototype = + b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); + } + + var __assign = function() { + __assign = + Object.assign || + function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) + if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; + + /* eslint-disable no-undefined,no-param-reassign,no-shadow */ + + /** + * Throttle execution of a function. Especially useful for rate limiting + * execution of handlers on events like resize and scroll. + * + * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. + * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the + * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time + * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds, + * the internal counter is reset) + * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, + * to `callback` when the throttled-function is executed. + * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end), + * schedule `callback` to execute after `delay` ms. + * + * @return {Function} A new, throttled, function. + */ + function throttle(delay, noTrailing, callback, debounceMode) { + /* + * After wrapper has stopped being called, this timeout ensures that + * `callback` is executed at the proper times in `throttle` and `end` + * debounce modes. + */ + var timeoutID; + var cancelled = false; // Keep track of the last time `callback` was executed. + + var lastExec = 0; // Function to clear existing timeout + + function clearExistingTimeout() { + if (timeoutID) { + clearTimeout(timeoutID); + } + } // Function to cancel next exec + + function cancel() { + clearExistingTimeout(); + cancelled = true; + } // `noTrailing` defaults to falsy. + + if (typeof noTrailing !== 'boolean') { + debounceMode = callback; + callback = noTrailing; + noTrailing = undefined; + } + /* + * The `wrapper` function encapsulates all of the throttling / debouncing + * functionality and when executed will limit the rate at which `callback` + * is executed. + */ + + function wrapper() { + var self = this; + var elapsed = Date.now() - lastExec; + var args = arguments; + + if (cancelled) { + return; + } // Execute `callback` and update the `lastExec` timestamp. + + function exec() { + lastExec = Date.now(); + callback.apply(self, args); + } + /* + * If `debounceMode` is true (at begin) this is used to clear the flag + * to allow future `callback` executions. + */ + + function clear() { + timeoutID = undefined; + } + + if (debounceMode && !timeoutID) { + /* + * Since `wrapper` is being called for the first time and + * `debounceMode` is true (at begin), execute `callback`. + */ + exec(); + } + + clearExistingTimeout(); + + if (debounceMode === undefined && elapsed > delay) { + /* + * In throttle mode, if `delay` time has been exceeded, execute + * `callback`. + */ + exec(); + } else if (noTrailing !== true) { + /* + * In trailing throttle mode, since `delay` time has not been + * exceeded, schedule `callback` to execute `delay` ms after most + * recent execution. + * + * If `debounceMode` is true (at begin), schedule `clear` to execute + * after `delay` ms. + * + * If `debounceMode` is false (at end), schedule `callback` to + * execute after `delay` ms. + */ + timeoutID = setTimeout( + debounceMode ? clear : exec, + debounceMode === undefined ? delay - elapsed : delay + ); + } + } + + wrapper.cancel = cancel; // Return the wrapper function. + + return wrapper; + } + + var ThresholdUnits = { + Pixel: 'Pixel', + Percent: 'Percent', + }; + var defaultThreshold = { + unit: ThresholdUnits.Percent, + value: 0.8, + }; + function parseThreshold(scrollThreshold) { + if (typeof scrollThreshold === 'number') { + return { + unit: ThresholdUnits.Percent, + value: scrollThreshold * 100, + }; + } + if (typeof scrollThreshold === 'string') { + if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { + return { + unit: ThresholdUnits.Pixel, + value: parseFloat(scrollThreshold), + }; + } + if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { + return { + unit: ThresholdUnits.Percent, + value: parseFloat(scrollThreshold), + }; + } + console.warn( + 'scrollThreshold format is invalid. Valid formats: "120px", "50%"...' + ); + return defaultThreshold; + } + console.warn('scrollThreshold should be string or number'); + return defaultThreshold; + } + + var InfiniteScroll = /** @class */ (function(_super) { + __extends(InfiniteScroll, _super); + function InfiniteScroll(props) { + var _this = _super.call(this, props) || this; + _this.lastScrollTop = 0; + _this.actionTriggered = false; + // variables to keep track of pull down behaviour + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + // will be populated in componentDidMount + // based on the height of the pull down element + _this.maxPullDownDistance = 0; + _this.getScrollableTarget = function() { + if (_this.props.scrollableTarget instanceof HTMLElement) + return _this.props.scrollableTarget; + if (typeof _this.props.scrollableTarget === 'string') { + return document.getElementById(_this.props.scrollableTarget); + } + if (_this.props.scrollableTarget === null) { + console.warn( + 'You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ' + ); + } + return null; + }; + _this.onStart = function(evt) { + if (_this.lastScrollTop) return; + _this.dragging = true; + if (evt instanceof MouseEvent) { + _this.startY = evt.pageY; + } else if (evt instanceof TouchEvent) { + _this.startY = evt.touches[0].pageY; + } + _this.currentY = _this.startY; + if (_this._infScroll) { + _this._infScroll.style.willChange = 'transform'; + _this._infScroll.style.transition = + 'transform 0.2s cubic-bezier(0,0,0.31,1)'; + } + }; + _this.onMove = function(evt) { + if (!_this.dragging) return; + if (evt instanceof MouseEvent) { + _this.currentY = evt.pageY; + } else if (evt instanceof TouchEvent) { + _this.currentY = evt.touches[0].pageY; + } + // user is scrolling down to up + if (_this.currentY < _this.startY) return; + if ( + _this.currentY - _this.startY >= + Number(_this.props.pullDownToRefreshThreshold) + ) { + _this.setState({ + pullToRefreshThresholdBreached: true, + }); + } + // so you can drag upto 1.5 times of the maxPullDownDistance + if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) + return; + if (_this._infScroll) { + _this._infScroll.style.overflow = 'visible'; + _this._infScroll.style.transform = + 'translate3d(0px, ' + (_this.currentY - _this.startY) + 'px, 0px)'; + } + }; + _this.onEnd = function() { + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + if (_this.state.pullToRefreshThresholdBreached) { + _this.props.refreshFunction && _this.props.refreshFunction(); + _this.setState({ + pullToRefreshThresholdBreached: false, + }); + } + requestAnimationFrame(function() { + // this._infScroll + if (_this._infScroll) { + _this._infScroll.style.overflow = 'auto'; + _this._infScroll.style.transform = 'none'; + _this._infScroll.style.willChange = 'unset'; + } + }); + }; + _this.onScrollListener = function(event) { + if (typeof _this.props.onScroll === 'function') { + // Execute this callback in next tick so that it does not affect the + // functionality of the library. + setTimeout(function() { + return _this.props.onScroll && _this.props.onScroll(event); + }, 0); + } + var target = + _this.props.height || _this._scrollableNode + ? event.target + : document.documentElement.scrollTop + ? document.documentElement + : document.body; + // return immediately if the action has already been triggered, + // prevents multiple triggers. + if (_this.actionTriggered) return; + var atBottom = _this.props.inverse + ? _this.isElementAtTop(target, _this.props.scrollThreshold) + : _this.isElementAtBottom(target, _this.props.scrollThreshold); + // call the `next` function in the props to trigger the next data fetch + if (atBottom && _this.props.hasMore) { + _this.actionTriggered = true; + _this.setState({ showLoader: true }); + _this.props.next && _this.props.next(); + } + _this.lastScrollTop = target.scrollTop; + }; + _this.state = { + showLoader: false, + pullToRefreshThresholdBreached: false, + prevDataLength: props.dataLength, + }; + _this.throttledOnScrollListener = throttle( + 150, + _this.onScrollListener + ).bind(_this); + _this.onStart = _this.onStart.bind(_this); + _this.onMove = _this.onMove.bind(_this); + _this.onEnd = _this.onEnd.bind(_this); + return _this; + } + InfiniteScroll.prototype.componentDidMount = function() { + if (typeof this.props.dataLength === 'undefined') { + throw new Error( + 'mandatory prop "dataLength" is missing. The prop is needed' + + ' when loading more content. Check README.md for usage' + ); + } + this._scrollableNode = this.getScrollableTarget(); + this.el = this.props.height + ? this._infScroll + : this._scrollableNode || window; + if (this.el) { + this.el.addEventListener('scroll', this.throttledOnScrollListener); + } + if ( + typeof this.props.initialScrollY === 'number' && + this.el && + this.el instanceof HTMLElement && + this.el.scrollHeight > this.props.initialScrollY + ) { + this.el.scrollTo(0, this.props.initialScrollY); + } + if (this.props.pullDownToRefresh && this.el) { + this.el.addEventListener('touchstart', this.onStart); + this.el.addEventListener('touchmove', this.onMove); + this.el.addEventListener('touchend', this.onEnd); + this.el.addEventListener('mousedown', this.onStart); + this.el.addEventListener('mousemove', this.onMove); + this.el.addEventListener('mouseup', this.onEnd); + // get BCR of pullDown element to position it above + this.maxPullDownDistance = + (this._pullDown && + this._pullDown.firstChild && + this._pullDown.firstChild.getBoundingClientRect().height) || + 0; + this.forceUpdate(); + if (typeof this.props.refreshFunction !== 'function') { + throw new Error( + 'Mandatory prop "refreshFunction" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage\'' + ); + } + } + }; + InfiniteScroll.prototype.componentWillUnmount = function() { + if (this.el) { + this.el.removeEventListener('scroll', this.throttledOnScrollListener); + if (this.props.pullDownToRefresh) { + this.el.removeEventListener('touchstart', this.onStart); + this.el.removeEventListener('touchmove', this.onMove); + this.el.removeEventListener('touchend', this.onEnd); + this.el.removeEventListener('mousedown', this.onStart); + this.el.removeEventListener('mousemove', this.onMove); + this.el.removeEventListener('mouseup', this.onEnd); + } + } + }; + InfiniteScroll.prototype.componentDidUpdate = function(prevProps) { + // do nothing when dataLength is unchanged + if (this.props.dataLength === prevProps.dataLength) return; + var fetchAgain = + this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } + }; + InfiniteScroll.getDerivedStateFromProps = function(nextProps, prevState) { + var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; + // reset when data changes + if (dataLengthChanged) { + return __assign(__assign({}, prevState), { + prevDataLength: nextProps.dataLength, + }); + } + return null; + }; + InfiniteScroll.prototype.isElementAtTop = function( + target, + scrollThreshold + ) { + if (scrollThreshold === void 0) { + scrollThreshold = 0.8; + } + var clientHeight = + target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return ( + target.scrollTop <= + threshold.value + clientHeight - target.scrollHeight + 1 + ); + } + return ( + target.scrollTop <= + threshold.value / 100 + clientHeight - target.scrollHeight + 1 + ); + }; + InfiniteScroll.prototype.isElementAtBottom = function( + target, + scrollThreshold + ) { + if (scrollThreshold === void 0) { + scrollThreshold = 0.8; + } + var clientHeight = + target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return ( + target.scrollTop + clientHeight >= + target.scrollHeight - threshold.value + ); + } + return ( + target.scrollTop + clientHeight >= + (threshold.value / 100) * target.scrollHeight + ); + }; + InfiniteScroll.prototype.render = function() { + var _this = this; + var style = __assign( + { + height: this.props.height || 'auto', + overflow: 'auto', + WebkitOverflowScrolling: 'touch', + }, + this.props.style + ); + var hasChildren = + this.props.hasChildren || + !!( + this.props.children && + this.props.children instanceof Array && + this.props.children.length + ); + // because heighted infiniteScroll visualy breaks + // on drag down as overflow becomes visible + var outerDivStyle = + this.props.pullDownToRefresh && this.props.height + ? { overflow: 'auto' } + : {}; + return React__default.createElement( + 'div', + { + style: outerDivStyle, + className: 'infinite-scroll-component__outerdiv', + }, + React__default.createElement( + 'div', + { + className: + 'infinite-scroll-component ' + (this.props.className || ''), + ref: function(infScroll) { + return (_this._infScroll = infScroll); + }, + style: style, + }, + this.props.pullDownToRefresh && + React__default.createElement( + 'div', + { + style: { position: 'relative' }, + ref: function(pullDown) { + return (_this._pullDown = pullDown); + }, + }, + React__default.createElement( + 'div', + { + style: { + position: 'absolute', + left: 0, + right: 0, + top: -1 * this.maxPullDownDistance, + }, + }, + this.state.pullToRefreshThresholdBreached + ? this.props.releaseToRefreshContent + : this.props.pullDownToRefreshContent + ) + ), + this.props.children, + !this.state.showLoader && + !hasChildren && + this.props.hasMore && + this.props.loader, + this.state.showLoader && this.props.hasMore && this.props.loader, + !this.props.hasMore && this.props.endMessage + ) + ); + }; + return InfiniteScroll; + })(React.Component); + + return InfiniteScroll; +})(React); +//# sourceMappingURL=index.umd.js.map diff --git a/dist/index.umd.js.map b/dist/index.umd.js.map new file mode 100644 index 0000000..705087b --- /dev/null +++ b/dist/index.umd.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.umd.js","sources":["../node_modules/tslib/tslib.es6.js","../node_modules/throttle-debounce/dist/index.esm.js"],"sourcesContent":["/*! *****************************************************************************\r\nCopyright (c) Microsoft Corporation. All rights reserved.\r\nLicensed under the Apache License, Version 2.0 (the \"License\"); you may not use\r\nthis file except in compliance with the License. You may obtain a copy of the\r\nLicense at http://www.apache.org/licenses/LICENSE-2.0\r\n\r\nTHIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r\nKIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED\r\nWARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,\r\nMERCHANTABLITY OR NON-INFRINGEMENT.\r\n\r\nSee the Apache Version 2.0 License for specific language governing permissions\r\nand limitations under the License.\r\n***************************************************************************** */\r\n/* global Reflect, Promise */\r\n\r\nvar extendStatics = function(d, b) {\r\n extendStatics = Object.setPrototypeOf ||\r\n ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||\r\n function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };\r\n return extendStatics(d, b);\r\n};\r\n\r\nexport function __extends(d, b) {\r\n extendStatics(d, b);\r\n function __() { this.constructor = d; }\r\n d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());\r\n}\r\n\r\nexport var __assign = function() {\r\n __assign = Object.assign || function __assign(t) {\r\n for (var s, i = 1, n = arguments.length; i < n; i++) {\r\n s = arguments[i];\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];\r\n }\r\n return t;\r\n }\r\n return __assign.apply(this, arguments);\r\n}\r\n\r\nexport function __rest(s, e) {\r\n var t = {};\r\n for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)\r\n t[p] = s[p];\r\n if (s != null && typeof Object.getOwnPropertySymbols === \"function\")\r\n for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {\r\n if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))\r\n t[p[i]] = s[p[i]];\r\n }\r\n return t;\r\n}\r\n\r\nexport function __decorate(decorators, target, key, desc) {\r\n var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;\r\n if (typeof Reflect === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);\r\n else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\r\n return c > 3 && r && Object.defineProperty(target, key, r), r;\r\n}\r\n\r\nexport function __param(paramIndex, decorator) {\r\n return function (target, key) { decorator(target, key, paramIndex); }\r\n}\r\n\r\nexport function __metadata(metadataKey, metadataValue) {\r\n if (typeof Reflect === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(metadataKey, metadataValue);\r\n}\r\n\r\nexport function __awaiter(thisArg, _arguments, P, generator) {\r\n return new (P || (P = Promise))(function (resolve, reject) {\r\n function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }\r\n function rejected(value) { try { step(generator[\"throw\"](value)); } catch (e) { reject(e); } }\r\n function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }\r\n step((generator = generator.apply(thisArg, _arguments || [])).next());\r\n });\r\n}\r\n\r\nexport function __generator(thisArg, body) {\r\n var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;\r\n return g = { next: verb(0), \"throw\": verb(1), \"return\": verb(2) }, typeof Symbol === \"function\" && (g[Symbol.iterator] = function() { return this; }), g;\r\n function verb(n) { return function (v) { return step([n, v]); }; }\r\n function step(op) {\r\n if (f) throw new TypeError(\"Generator is already executing.\");\r\n while (_) try {\r\n if (f = 1, y && (t = op[0] & 2 ? y[\"return\"] : op[0] ? y[\"throw\"] || ((t = y[\"return\"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;\r\n if (y = 0, t) op = [op[0] & 2, t.value];\r\n switch (op[0]) {\r\n case 0: case 1: t = op; break;\r\n case 4: _.label++; return { value: op[1], done: false };\r\n case 5: _.label++; y = op[1]; op = [0]; continue;\r\n case 7: op = _.ops.pop(); _.trys.pop(); continue;\r\n default:\r\n if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }\r\n if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }\r\n if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }\r\n if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }\r\n if (t[2]) _.ops.pop();\r\n _.trys.pop(); continue;\r\n }\r\n op = body.call(thisArg, _);\r\n } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }\r\n if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };\r\n }\r\n}\r\n\r\nexport function __exportStar(m, exports) {\r\n for (var p in m) if (!exports.hasOwnProperty(p)) exports[p] = m[p];\r\n}\r\n\r\nexport function __values(o) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator], i = 0;\r\n if (m) return m.call(o);\r\n return {\r\n next: function () {\r\n if (o && i >= o.length) o = void 0;\r\n return { value: o && o[i++], done: !o };\r\n }\r\n };\r\n}\r\n\r\nexport function __read(o, n) {\r\n var m = typeof Symbol === \"function\" && o[Symbol.iterator];\r\n if (!m) return o;\r\n var i = m.call(o), r, ar = [], e;\r\n try {\r\n while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);\r\n }\r\n catch (error) { e = { error: error }; }\r\n finally {\r\n try {\r\n if (r && !r.done && (m = i[\"return\"])) m.call(i);\r\n }\r\n finally { if (e) throw e.error; }\r\n }\r\n return ar;\r\n}\r\n\r\nexport function __spread() {\r\n for (var ar = [], i = 0; i < arguments.length; i++)\r\n ar = ar.concat(__read(arguments[i]));\r\n return ar;\r\n}\r\n\r\nexport function __spreadArrays() {\r\n for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;\r\n for (var r = Array(s), k = 0, i = 0; i < il; i++)\r\n for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)\r\n r[k] = a[j];\r\n return r;\r\n};\r\n\r\nexport function __await(v) {\r\n return this instanceof __await ? (this.v = v, this) : new __await(v);\r\n}\r\n\r\nexport function __asyncGenerator(thisArg, _arguments, generator) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var g = generator.apply(thisArg, _arguments || []), i, q = [];\r\n return i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i;\r\n function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }\r\n function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }\r\n function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }\r\n function fulfill(value) { resume(\"next\", value); }\r\n function reject(value) { resume(\"throw\", value); }\r\n function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }\r\n}\r\n\r\nexport function __asyncDelegator(o) {\r\n var i, p;\r\n return i = {}, verb(\"next\"), verb(\"throw\", function (e) { throw e; }), verb(\"return\"), i[Symbol.iterator] = function () { return this; }, i;\r\n function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === \"return\" } : f ? f(v) : v; } : f; }\r\n}\r\n\r\nexport function __asyncValues(o) {\r\n if (!Symbol.asyncIterator) throw new TypeError(\"Symbol.asyncIterator is not defined.\");\r\n var m = o[Symbol.asyncIterator], i;\r\n return m ? m.call(o) : (o = typeof __values === \"function\" ? __values(o) : o[Symbol.iterator](), i = {}, verb(\"next\"), verb(\"throw\"), verb(\"return\"), i[Symbol.asyncIterator] = function () { return this; }, i);\r\n function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }\r\n function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }\r\n}\r\n\r\nexport function __makeTemplateObject(cooked, raw) {\r\n if (Object.defineProperty) { Object.defineProperty(cooked, \"raw\", { value: raw }); } else { cooked.raw = raw; }\r\n return cooked;\r\n};\r\n\r\nexport function __importStar(mod) {\r\n if (mod && mod.__esModule) return mod;\r\n var result = {};\r\n if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];\r\n result.default = mod;\r\n return result;\r\n}\r\n\r\nexport function __importDefault(mod) {\r\n return (mod && mod.__esModule) ? mod : { default: mod };\r\n}\r\n","/* eslint-disable no-undefined,no-param-reassign,no-shadow */\n\n/**\n * Throttle execution of a function. Especially useful for rate limiting\n * execution of handlers on events like resize and scroll.\n *\n * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the\n * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time\n * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds,\n * the internal counter is reset)\n * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the throttled-function is executed.\n * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end),\n * schedule `callback` to execute after `delay` ms.\n *\n * @return {Function} A new, throttled, function.\n */\nfunction throttle (delay, noTrailing, callback, debounceMode) {\n /*\n * After wrapper has stopped being called, this timeout ensures that\n * `callback` is executed at the proper times in `throttle` and `end`\n * debounce modes.\n */\n var timeoutID;\n var cancelled = false; // Keep track of the last time `callback` was executed.\n\n var lastExec = 0; // Function to clear existing timeout\n\n function clearExistingTimeout() {\n if (timeoutID) {\n clearTimeout(timeoutID);\n }\n } // Function to cancel next exec\n\n\n function cancel() {\n clearExistingTimeout();\n cancelled = true;\n } // `noTrailing` defaults to falsy.\n\n\n if (typeof noTrailing !== 'boolean') {\n debounceMode = callback;\n callback = noTrailing;\n noTrailing = undefined;\n }\n /*\n * The `wrapper` function encapsulates all of the throttling / debouncing\n * functionality and when executed will limit the rate at which `callback`\n * is executed.\n */\n\n\n function wrapper() {\n var self = this;\n var elapsed = Date.now() - lastExec;\n var args = arguments;\n\n if (cancelled) {\n return;\n } // Execute `callback` and update the `lastExec` timestamp.\n\n\n function exec() {\n lastExec = Date.now();\n callback.apply(self, args);\n }\n /*\n * If `debounceMode` is true (at begin) this is used to clear the flag\n * to allow future `callback` executions.\n */\n\n\n function clear() {\n timeoutID = undefined;\n }\n\n if (debounceMode && !timeoutID) {\n /*\n * Since `wrapper` is being called for the first time and\n * `debounceMode` is true (at begin), execute `callback`.\n */\n exec();\n }\n\n clearExistingTimeout();\n\n if (debounceMode === undefined && elapsed > delay) {\n /*\n * In throttle mode, if `delay` time has been exceeded, execute\n * `callback`.\n */\n exec();\n } else if (noTrailing !== true) {\n /*\n * In trailing throttle mode, since `delay` time has not been\n * exceeded, schedule `callback` to execute `delay` ms after most\n * recent execution.\n *\n * If `debounceMode` is true (at begin), schedule `clear` to execute\n * after `delay` ms.\n *\n * If `debounceMode` is false (at end), schedule `callback` to\n * execute after `delay` ms.\n */\n timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay);\n }\n }\n\n wrapper.cancel = cancel; // Return the wrapper function.\n\n return wrapper;\n}\n\n/* eslint-disable no-undefined */\n/**\n * Debounce execution of a function. Debouncing, unlike throttling,\n * guarantees that a function is only executed a single time, either at the\n * very beginning of a series of calls, or at the very end.\n *\n * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful.\n * @param {Boolean} [atBegin] Optional, defaults to false. If atBegin is false or unspecified, callback will only be executed `delay` milliseconds\n * after the last debounced-function call. If atBegin is true, callback will be executed only at the first debounced-function call.\n * (After the throttled-function has not been called for `delay` milliseconds, the internal counter is reset).\n * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is,\n * to `callback` when the debounced-function is executed.\n *\n * @return {Function} A new, debounced function.\n */\n\nfunction debounce (delay, atBegin, callback) {\n return callback === undefined ? throttle(delay, atBegin, false) : throttle(delay, callback, atBegin !== false);\n}\n\nexport { throttle, debounce };\n"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/stories/InfiniteScrollWithHeight.d.ts b/dist/stories/InfiniteScrollWithHeight.d.ts new file mode 100644 index 0000000..2a8e873 --- /dev/null +++ b/dist/stories/InfiniteScrollWithHeight.d.ts @@ -0,0 +1,9 @@ +import React from 'react'; +export default class App extends React.Component { + state: { + items: unknown[]; + hasMore: boolean; + }; + fetchMoreData: () => void; + render(): JSX.Element; +} diff --git a/dist/stories/PullDownToRefreshInfScroll.d.ts b/dist/stories/PullDownToRefreshInfScroll.d.ts new file mode 100644 index 0000000..eaa5c6b --- /dev/null +++ b/dist/stories/PullDownToRefreshInfScroll.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +export default class App extends React.Component { + state: { + items: unknown[]; + }; + fetchMoreData: () => void; + render(): JSX.Element; +} diff --git a/dist/stories/ScrollableTargetInfScroll.d.ts b/dist/stories/ScrollableTargetInfScroll.d.ts new file mode 100644 index 0000000..eaa5c6b --- /dev/null +++ b/dist/stories/ScrollableTargetInfScroll.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +export default class App extends React.Component { + state: { + items: unknown[]; + }; + fetchMoreData: () => void; + render(): JSX.Element; +} diff --git a/dist/stories/ScrolleableTop.d.ts b/dist/stories/ScrolleableTop.d.ts new file mode 100644 index 0000000..eaa5c6b --- /dev/null +++ b/dist/stories/ScrolleableTop.d.ts @@ -0,0 +1,8 @@ +import React from 'react'; +export default class App extends React.Component { + state: { + items: unknown[]; + }; + fetchMoreData: () => void; + render(): JSX.Element; +} diff --git a/dist/stories/WindowInfiniteScrollComponent.d.ts b/dist/stories/WindowInfiniteScrollComponent.d.ts new file mode 100644 index 0000000..d324620 --- /dev/null +++ b/dist/stories/WindowInfiniteScrollComponent.d.ts @@ -0,0 +1,15 @@ +import React from 'react'; +declare type State = { + data: number[]; +}; +export default class WindowInfiniteScrollComponent extends React.Component< + {}, + State +> { + state: { + data: any[]; + }; + next: () => void; + render(): JSX.Element; +} +export {}; diff --git a/dist/stories/stories.d.ts b/dist/stories/stories.d.ts new file mode 100644 index 0000000..cb0ff5c --- /dev/null +++ b/dist/stories/stories.d.ts @@ -0,0 +1 @@ +export {}; diff --git a/dist/utils/threshold.d.ts b/dist/utils/threshold.d.ts new file mode 100644 index 0000000..5bce098 --- /dev/null +++ b/dist/utils/threshold.d.ts @@ -0,0 +1,10 @@ +export declare const ThresholdUnits: { + Pixel: string; + Percent: string; +}; +export declare function parseThreshold( + scrollThreshold: string | number +): { + unit: string; + value: number; +}; From 6422584de6a2c9ce1754ee89b7bf8c8b52d5c2a9 Mon Sep 17 00:00:00 2001 From: ardeshir Date: Tue, 2 May 2023 09:44:08 +0000 Subject: [PATCH 3/6] add 300px threshold for long screens fetch again --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 586883d..0c9915f 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -146,7 +146,7 @@ export default class InfiniteScroll extends Component { const fetchAgain = this._infScroll && this._scrollableNode && - this._scrollableNode.clientHeight > this._infScroll.scrollHeight; + this._scrollableNode.clientHeight + 300 > this._infScroll.scrollHeight; if (fetchAgain) { this.actionTriggered = true; this.setState({ showLoader: true }); From 687f6002b77365b1498b2ac51834a9c20cada6f5 Mon Sep 17 00:00:00 2001 From: ardeshir Date: Tue, 2 May 2023 09:44:08 +0000 Subject: [PATCH 4/6] add 10% threshold for long screens fetch again --- src/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.tsx b/src/index.tsx index 0c9915f..fe09eca 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -146,7 +146,7 @@ export default class InfiniteScroll extends Component { const fetchAgain = this._infScroll && this._scrollableNode && - this._scrollableNode.clientHeight + 300 > this._infScroll.scrollHeight; + this._scrollableNode.clientHeight * 1.1 > this._infScroll.scrollHeight; if (fetchAgain) { this.actionTriggered = true; this.setState({ showLoader: true }); From f446f5b6a4baca9e6d57dee94f7ba11587fd4b86 Mon Sep 17 00:00:00 2001 From: ardeshir Date: Tue, 2 May 2023 09:52:08 +0000 Subject: [PATCH 5/6] build the project again --- dist/index.d.ts | 111 +-- dist/index.es.js | 682 ++++++------- dist/index.js | 686 ++++++------- dist/index.umd.js | 907 ++++++++---------- dist/stories/InfiniteScrollWithHeight.d.ts | 12 +- dist/stories/PullDownToRefreshInfScroll.d.ts | 10 +- dist/stories/ScrollableTargetInfScroll.d.ts | 10 +- dist/stories/ScrolleableTop.d.ts | 10 +- .../WindowInfiniteScrollComponent.d.ts | 17 +- dist/utils/threshold.d.ts | 12 +- 10 files changed, 1099 insertions(+), 1358 deletions(-) diff --git a/dist/index.d.ts b/dist/index.d.ts index 057ff5b..b904bc7 100644 --- a/dist/index.d.ts +++ b/dist/index.d.ts @@ -1,69 +1,60 @@ import { Component, ReactNode, CSSProperties } from 'react'; declare type Fn = () => any; export interface Props { - next: Fn; - hasMore: boolean; - children: ReactNode; - loader: ReactNode; - scrollThreshold?: number | string; - endMessage?: ReactNode; - style?: CSSProperties; - height?: number | string; - scrollableTarget?: ReactNode; - hasChildren?: boolean; - inverse?: boolean; - pullDownToRefresh?: boolean; - pullDownToRefreshContent?: ReactNode; - releaseToRefreshContent?: ReactNode; - pullDownToRefreshThreshold?: number; - refreshFunction?: Fn; - onScroll?: (e: MouseEvent) => any; - dataLength: number; - initialScrollY?: number; - className?: string; + next: Fn; + hasMore: boolean; + children: ReactNode; + loader: ReactNode; + scrollThreshold?: number | string; + endMessage?: ReactNode; + style?: CSSProperties; + height?: number | string; + scrollableTarget?: ReactNode; + hasChildren?: boolean; + inverse?: boolean; + pullDownToRefresh?: boolean; + pullDownToRefreshContent?: ReactNode; + releaseToRefreshContent?: ReactNode; + pullDownToRefreshThreshold?: number; + refreshFunction?: Fn; + onScroll?: (e: MouseEvent) => any; + dataLength: number; + initialScrollY?: number; + className?: string; } interface State { - showLoader: boolean; - pullToRefreshThresholdBreached: boolean; - prevDataLength: number | undefined; -} -export default class InfiniteScroll extends Component { - constructor(props: Props); - private throttledOnScrollListener; - private _scrollableNode; - private el; - private _infScroll; - private lastScrollTop; - private actionTriggered; - private _pullDown; - private startY; - private currentY; - private dragging; - private maxPullDownDistance; - componentDidMount(): void; - componentWillUnmount(): void; - componentDidUpdate(prevProps: Props): void; - static getDerivedStateFromProps( - nextProps: Props, - prevState: State - ): { - prevDataLength: number; showLoader: boolean; pullToRefreshThresholdBreached: boolean; - } | null; - getScrollableTarget: () => HTMLElement | null; - onStart: EventListener; - onMove: EventListener; - onEnd: EventListener; - isElementAtTop( - target: HTMLElement, - scrollThreshold?: string | number - ): boolean; - isElementAtBottom( - target: HTMLElement, - scrollThreshold?: string | number - ): boolean; - onScrollListener: (event: MouseEvent) => void; - render(): JSX.Element; + prevDataLength: number | undefined; +} +export default class InfiniteScroll extends Component { + constructor(props: Props); + private throttledOnScrollListener; + private _scrollableNode; + private el; + private _infScroll; + private lastScrollTop; + private actionTriggered; + private _pullDown; + private startY; + private currentY; + private dragging; + private maxPullDownDistance; + componentDidMount(): void; + componentWillUnmount(): void; + componentDidUpdate(prevProps: Props): void; + static getDerivedStateFromProps(nextProps: Props, prevState: State): { + prevDataLength: number; + showLoader: boolean; + pullToRefreshThresholdBreached: boolean; + } | null; + getScrollableTarget: () => HTMLElement | null; + onStart: EventListener; + onMove: EventListener; + onEnd: EventListener; + isElementAtTop(target: HTMLElement, scrollThreshold?: string | number): boolean; + isElementAtBottom(target: HTMLElement, scrollThreshold?: string | number): boolean; + onScrollListener: (event: MouseEvent) => void; + render(): JSX.Element; } export {}; diff --git a/dist/index.es.js b/dist/index.es.js index cf4c5e5..187ce13 100644 --- a/dist/index.es.js +++ b/dist/index.es.js @@ -17,39 +17,27 @@ and limitations under the License. /* global Reflect, Promise */ var extendStatics = function(d, b) { - extendStatics = - Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && - function(d, b) { - d.__proto__ = b; - }) || - function(d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return extendStatics(d, b); + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); }; function __extends(d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = - b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { - __assign = - Object.assign || - function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; }; - return __assign.apply(this, arguments); + return __assign.apply(this, arguments); }; /* eslint-disable no-undefined,no-param-reassign,no-shadow */ @@ -70,7 +58,7 @@ var __assign = function() { * * @return {Function} A new, throttled, function. */ -function throttle(delay, noTrailing, callback, debounceMode) { +function throttle (delay, noTrailing, callback, debounceMode) { /* * After wrapper has stopped being called, this timeout ensures that * `callback` is executed at the proper times in `throttle` and `end` @@ -87,11 +75,13 @@ function throttle(delay, noTrailing, callback, debounceMode) { } } // Function to cancel next exec + function cancel() { clearExistingTimeout(); cancelled = true; } // `noTrailing` defaults to falsy. + if (typeof noTrailing !== 'boolean') { debounceMode = callback; callback = noTrailing; @@ -103,6 +93,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { * is executed. */ + function wrapper() { var self = this; var elapsed = Date.now() - lastExec; @@ -112,6 +103,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { return; } // Execute `callback` and update the `lastExec` timestamp. + function exec() { lastExec = Date.now(); callback.apply(self, args); @@ -121,6 +113,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { * to allow future `callback` executions. */ + function clear() { timeoutID = undefined; } @@ -153,10 +146,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { * If `debounceMode` is false (at end), schedule `callback` to * execute after `delay` ms. */ - timeoutID = setTimeout( - debounceMode ? clear : exec, - debounceMode === undefined ? delay - elapsed : delay - ); + timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay); } } @@ -166,372 +156,302 @@ function throttle(delay, noTrailing, callback, debounceMode) { } var ThresholdUnits = { - Pixel: 'Pixel', - Percent: 'Percent', + Pixel: 'Pixel', + Percent: 'Percent', }; var defaultThreshold = { - unit: ThresholdUnits.Percent, - value: 0.8, + unit: ThresholdUnits.Percent, + value: 0.8, }; function parseThreshold(scrollThreshold) { - if (typeof scrollThreshold === 'number') { - return { - unit: ThresholdUnits.Percent, - value: scrollThreshold * 100, - }; - } - if (typeof scrollThreshold === 'string') { - if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { - return { - unit: ThresholdUnits.Pixel, - value: parseFloat(scrollThreshold), - }; + if (typeof scrollThreshold === 'number') { + return { + unit: ThresholdUnits.Percent, + value: scrollThreshold * 100, + }; } - if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { - return { - unit: ThresholdUnits.Percent, - value: parseFloat(scrollThreshold), - }; + if (typeof scrollThreshold === 'string') { + if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { + return { + unit: ThresholdUnits.Pixel, + value: parseFloat(scrollThreshold), + }; + } + if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { + return { + unit: ThresholdUnits.Percent, + value: parseFloat(scrollThreshold), + }; + } + console.warn('scrollThreshold format is invalid. Valid formats: "120px", "50%"...'); + return defaultThreshold; } - console.warn( - 'scrollThreshold format is invalid. Valid formats: "120px", "50%"...' - ); + console.warn('scrollThreshold should be string or number'); return defaultThreshold; - } - console.warn('scrollThreshold should be string or number'); - return defaultThreshold; } -var InfiniteScroll = /** @class */ (function(_super) { - __extends(InfiniteScroll, _super); - function InfiniteScroll(props) { - var _this = _super.call(this, props) || this; - _this.lastScrollTop = 0; - _this.actionTriggered = false; - // variables to keep track of pull down behaviour - _this.startY = 0; - _this.currentY = 0; - _this.dragging = false; - // will be populated in componentDidMount - // based on the height of the pull down element - _this.maxPullDownDistance = 0; - _this.getScrollableTarget = function() { - if (_this.props.scrollableTarget instanceof HTMLElement) - return _this.props.scrollableTarget; - if (typeof _this.props.scrollableTarget === 'string') { - return document.getElementById(_this.props.scrollableTarget); - } - if (_this.props.scrollableTarget === null) { - console.warn( - 'You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ' - ); - } - return null; +var InfiniteScroll = /** @class */ (function (_super) { + __extends(InfiniteScroll, _super); + function InfiniteScroll(props) { + var _this = _super.call(this, props) || this; + _this.lastScrollTop = 0; + _this.actionTriggered = false; + // variables to keep track of pull down behaviour + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + // will be populated in componentDidMount + // based on the height of the pull down element + _this.maxPullDownDistance = 0; + _this.getScrollableTarget = function () { + if (_this.props.scrollableTarget instanceof HTMLElement) + return _this.props.scrollableTarget; + if (typeof _this.props.scrollableTarget === 'string') { + return document.getElementById(_this.props.scrollableTarget); + } + if (_this.props.scrollableTarget === null) { + console.warn("You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n "); + } + return null; + }; + _this.onStart = function (evt) { + if (_this.lastScrollTop) + return; + _this.dragging = true; + if (evt instanceof MouseEvent) { + _this.startY = evt.pageY; + } + else if (evt instanceof TouchEvent) { + _this.startY = evt.touches[0].pageY; + } + _this.currentY = _this.startY; + if (_this._infScroll) { + _this._infScroll.style.willChange = 'transform'; + _this._infScroll.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)"; + } + }; + _this.onMove = function (evt) { + if (!_this.dragging) + return; + if (evt instanceof MouseEvent) { + _this.currentY = evt.pageY; + } + else if (evt instanceof TouchEvent) { + _this.currentY = evt.touches[0].pageY; + } + // user is scrolling down to up + if (_this.currentY < _this.startY) + return; + if (_this.currentY - _this.startY >= + Number(_this.props.pullDownToRefreshThreshold)) { + _this.setState({ + pullToRefreshThresholdBreached: true, + }); + } + // so you can drag upto 1.5 times of the maxPullDownDistance + if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) + return; + if (_this._infScroll) { + _this._infScroll.style.overflow = 'visible'; + _this._infScroll.style.transform = "translate3d(0px, " + (_this.currentY - + _this.startY) + "px, 0px)"; + } + }; + _this.onEnd = function () { + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + if (_this.state.pullToRefreshThresholdBreached) { + _this.props.refreshFunction && _this.props.refreshFunction(); + _this.setState({ + pullToRefreshThresholdBreached: false, + }); + } + requestAnimationFrame(function () { + // this._infScroll + if (_this._infScroll) { + _this._infScroll.style.overflow = 'auto'; + _this._infScroll.style.transform = 'none'; + _this._infScroll.style.willChange = 'unset'; + } + }); + }; + _this.onScrollListener = function (event) { + if (typeof _this.props.onScroll === 'function') { + // Execute this callback in next tick so that it does not affect the + // functionality of the library. + setTimeout(function () { return _this.props.onScroll && _this.props.onScroll(event); }, 0); + } + var target = _this.props.height || _this._scrollableNode + ? event.target + : document.documentElement.scrollTop + ? document.documentElement + : document.body; + // return immediately if the action has already been triggered, + // prevents multiple triggers. + if (_this.actionTriggered) + return; + var atBottom = _this.props.inverse + ? _this.isElementAtTop(target, _this.props.scrollThreshold) + : _this.isElementAtBottom(target, _this.props.scrollThreshold); + // call the `next` function in the props to trigger the next data fetch + if (atBottom && _this.props.hasMore) { + _this.actionTriggered = true; + _this.setState({ showLoader: true }); + _this.props.next && _this.props.next(); + } + _this.lastScrollTop = target.scrollTop; + }; + _this.state = { + showLoader: false, + pullToRefreshThresholdBreached: false, + prevDataLength: props.dataLength, + }; + _this.throttledOnScrollListener = throttle(150, _this.onScrollListener).bind(_this); + _this.onStart = _this.onStart.bind(_this); + _this.onMove = _this.onMove.bind(_this); + _this.onEnd = _this.onEnd.bind(_this); + return _this; + } + InfiniteScroll.prototype.componentDidMount = function () { + if (typeof this.props.dataLength === 'undefined') { + throw new Error("mandatory prop \"dataLength\" is missing. The prop is needed" + + " when loading more content. Check README.md for usage"); + } + this._scrollableNode = this.getScrollableTarget(); + this.el = this.props.height + ? this._infScroll + : this._scrollableNode || window; + if (this.el) { + this.el.addEventListener('scroll', this + .throttledOnScrollListener); + } + if (typeof this.props.initialScrollY === 'number' && + this.el && + this.el instanceof HTMLElement && + this.el.scrollHeight > this.props.initialScrollY) { + this.el.scrollTo(0, this.props.initialScrollY); + } + if (this.props.pullDownToRefresh && this.el) { + this.el.addEventListener('touchstart', this.onStart); + this.el.addEventListener('touchmove', this.onMove); + this.el.addEventListener('touchend', this.onEnd); + this.el.addEventListener('mousedown', this.onStart); + this.el.addEventListener('mousemove', this.onMove); + this.el.addEventListener('mouseup', this.onEnd); + // get BCR of pullDown element to position it above + this.maxPullDownDistance = + (this._pullDown && + this._pullDown.firstChild && + this._pullDown.firstChild.getBoundingClientRect() + .height) || + 0; + this.forceUpdate(); + if (typeof this.props.refreshFunction !== 'function') { + throw new Error("Mandatory prop \"refreshFunction\" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage'"); + } + } }; - _this.onStart = function(evt) { - if (_this.lastScrollTop) return; - _this.dragging = true; - if (evt instanceof MouseEvent) { - _this.startY = evt.pageY; - } else if (evt instanceof TouchEvent) { - _this.startY = evt.touches[0].pageY; - } - _this.currentY = _this.startY; - if (_this._infScroll) { - _this._infScroll.style.willChange = 'transform'; - _this._infScroll.style.transition = - 'transform 0.2s cubic-bezier(0,0,0.31,1)'; - } + InfiniteScroll.prototype.componentWillUnmount = function () { + if (this.el) { + this.el.removeEventListener('scroll', this + .throttledOnScrollListener); + if (this.props.pullDownToRefresh) { + this.el.removeEventListener('touchstart', this.onStart); + this.el.removeEventListener('touchmove', this.onMove); + this.el.removeEventListener('touchend', this.onEnd); + this.el.removeEventListener('mousedown', this.onStart); + this.el.removeEventListener('mousemove', this.onMove); + this.el.removeEventListener('mouseup', this.onEnd); + } + } }; - _this.onMove = function(evt) { - if (!_this.dragging) return; - if (evt instanceof MouseEvent) { - _this.currentY = evt.pageY; - } else if (evt instanceof TouchEvent) { - _this.currentY = evt.touches[0].pageY; - } - // user is scrolling down to up - if (_this.currentY < _this.startY) return; - if ( - _this.currentY - _this.startY >= - Number(_this.props.pullDownToRefreshThreshold) - ) { - _this.setState({ - pullToRefreshThresholdBreached: true, - }); - } - // so you can drag upto 1.5 times of the maxPullDownDistance - if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) - return; - if (_this._infScroll) { - _this._infScroll.style.overflow = 'visible'; - _this._infScroll.style.transform = - 'translate3d(0px, ' + (_this.currentY - _this.startY) + 'px, 0px)'; - } + InfiniteScroll.prototype.componentDidUpdate = function (prevProps) { + // do nothing when dataLength is unchanged + if (this.props.dataLength === prevProps.dataLength) + return; + var fetchAgain = this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight * 1.1 > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } + else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } }; - _this.onEnd = function() { - _this.startY = 0; - _this.currentY = 0; - _this.dragging = false; - if (_this.state.pullToRefreshThresholdBreached) { - _this.props.refreshFunction && _this.props.refreshFunction(); - _this.setState({ - pullToRefreshThresholdBreached: false, - }); - } - requestAnimationFrame(function() { - // this._infScroll - if (_this._infScroll) { - _this._infScroll.style.overflow = 'auto'; - _this._infScroll.style.transform = 'none'; - _this._infScroll.style.willChange = 'unset'; + InfiniteScroll.getDerivedStateFromProps = function (nextProps, prevState) { + var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; + // reset when data changes + if (dataLengthChanged) { + return __assign(__assign({}, prevState), { prevDataLength: nextProps.dataLength }); } - }); + return null; }; - _this.onScrollListener = function(event) { - if (typeof _this.props.onScroll === 'function') { - // Execute this callback in next tick so that it does not affect the - // functionality of the library. - setTimeout(function() { - return _this.props.onScroll && _this.props.onScroll(event); - }, 0); - } - var target = - _this.props.height || _this._scrollableNode - ? event.target - : document.documentElement.scrollTop - ? document.documentElement - : document.body; - // return immediately if the action has already been triggered, - // prevents multiple triggers. - if (_this.actionTriggered) return; - var atBottom = _this.props.inverse - ? _this.isElementAtTop(target, _this.props.scrollThreshold) - : _this.isElementAtBottom(target, _this.props.scrollThreshold); - // call the `next` function in the props to trigger the next data fetch - if (atBottom && _this.props.hasMore) { - _this.actionTriggered = true; - _this.setState({ showLoader: true }); - _this.props.next && _this.props.next(); - } - _this.lastScrollTop = target.scrollTop; + InfiniteScroll.prototype.isElementAtTop = function (target, scrollThreshold) { + if (scrollThreshold === void 0) { scrollThreshold = 0.8; } + var clientHeight = target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return (target.scrollTop <= + threshold.value + clientHeight - target.scrollHeight + 1); + } + return (target.scrollTop <= + threshold.value / 100 + clientHeight - target.scrollHeight + 1); }; - _this.state = { - showLoader: false, - pullToRefreshThresholdBreached: false, - prevDataLength: props.dataLength, + InfiniteScroll.prototype.isElementAtBottom = function (target, scrollThreshold) { + if (scrollThreshold === void 0) { scrollThreshold = 0.8; } + var clientHeight = target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return (target.scrollTop + clientHeight >= target.scrollHeight - threshold.value); + } + return (target.scrollTop + clientHeight >= + (threshold.value / 100) * target.scrollHeight); }; - _this.throttledOnScrollListener = throttle( - 150, - _this.onScrollListener - ).bind(_this); - _this.onStart = _this.onStart.bind(_this); - _this.onMove = _this.onMove.bind(_this); - _this.onEnd = _this.onEnd.bind(_this); - return _this; - } - InfiniteScroll.prototype.componentDidMount = function() { - if (typeof this.props.dataLength === 'undefined') { - throw new Error( - 'mandatory prop "dataLength" is missing. The prop is needed' + - ' when loading more content. Check README.md for usage' - ); - } - this._scrollableNode = this.getScrollableTarget(); - this.el = this.props.height - ? this._infScroll - : this._scrollableNode || window; - if (this.el) { - this.el.addEventListener('scroll', this.throttledOnScrollListener); - } - if ( - typeof this.props.initialScrollY === 'number' && - this.el && - this.el instanceof HTMLElement && - this.el.scrollHeight > this.props.initialScrollY - ) { - this.el.scrollTo(0, this.props.initialScrollY); - } - if (this.props.pullDownToRefresh && this.el) { - this.el.addEventListener('touchstart', this.onStart); - this.el.addEventListener('touchmove', this.onMove); - this.el.addEventListener('touchend', this.onEnd); - this.el.addEventListener('mousedown', this.onStart); - this.el.addEventListener('mousemove', this.onMove); - this.el.addEventListener('mouseup', this.onEnd); - // get BCR of pullDown element to position it above - this.maxPullDownDistance = - (this._pullDown && - this._pullDown.firstChild && - this._pullDown.firstChild.getBoundingClientRect().height) || - 0; - this.forceUpdate(); - if (typeof this.props.refreshFunction !== 'function') { - throw new Error( - 'Mandatory prop "refreshFunction" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage\'' - ); - } - } - }; - InfiniteScroll.prototype.componentWillUnmount = function() { - if (this.el) { - this.el.removeEventListener('scroll', this.throttledOnScrollListener); - if (this.props.pullDownToRefresh) { - this.el.removeEventListener('touchstart', this.onStart); - this.el.removeEventListener('touchmove', this.onMove); - this.el.removeEventListener('touchend', this.onEnd); - this.el.removeEventListener('mousedown', this.onStart); - this.el.removeEventListener('mousemove', this.onMove); - this.el.removeEventListener('mouseup', this.onEnd); - } - } - }; - InfiniteScroll.prototype.componentDidUpdate = function(prevProps) { - // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) return; - var fetchAgain = - this._infScroll && - this._scrollableNode && - this._scrollableNode.clientHeight > this._infScroll.scrollHeight; - if (fetchAgain) { - this.actionTriggered = true; - this.setState({ showLoader: true }); - this.props.next(); - } else { - this.actionTriggered = false; - // update state when new data was sent in - this.setState({ - showLoader: false, - }); - } - }; - InfiniteScroll.getDerivedStateFromProps = function(nextProps, prevState) { - var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; - // reset when data changes - if (dataLengthChanged) { - return __assign(__assign({}, prevState), { - prevDataLength: nextProps.dataLength, - }); - } - return null; - }; - InfiniteScroll.prototype.isElementAtTop = function(target, scrollThreshold) { - if (scrollThreshold === void 0) { - scrollThreshold = 0.8; - } - var clientHeight = - target === document.body || target === document.documentElement - ? window.screen.availHeight - : target.clientHeight; - var threshold = parseThreshold(scrollThreshold); - if (threshold.unit === ThresholdUnits.Pixel) { - return ( - target.scrollTop <= - threshold.value + clientHeight - target.scrollHeight + 1 - ); - } - return ( - target.scrollTop <= - threshold.value / 100 + clientHeight - target.scrollHeight + 1 - ); - }; - InfiniteScroll.prototype.isElementAtBottom = function( - target, - scrollThreshold - ) { - if (scrollThreshold === void 0) { - scrollThreshold = 0.8; - } - var clientHeight = - target === document.body || target === document.documentElement - ? window.screen.availHeight - : target.clientHeight; - var threshold = parseThreshold(scrollThreshold); - if (threshold.unit === ThresholdUnits.Pixel) { - return ( - target.scrollTop + clientHeight >= target.scrollHeight - threshold.value - ); - } - return ( - target.scrollTop + clientHeight >= - (threshold.value / 100) * target.scrollHeight - ); - }; - InfiniteScroll.prototype.render = function() { - var _this = this; - var style = __assign( - { - height: this.props.height || 'auto', - overflow: 'auto', - WebkitOverflowScrolling: 'touch', - }, - this.props.style - ); - var hasChildren = - this.props.hasChildren || - !!( - this.props.children && - this.props.children instanceof Array && - this.props.children.length - ); - // because heighted infiniteScroll visualy breaks - // on drag down as overflow becomes visible - var outerDivStyle = - this.props.pullDownToRefresh && this.props.height - ? { overflow: 'auto' } - : {}; - return React.createElement( - 'div', - { - style: outerDivStyle, - className: 'infinite-scroll-component__outerdiv', - }, - React.createElement( - 'div', - { - className: - 'infinite-scroll-component ' + (this.props.className || ''), - ref: function(infScroll) { - return (_this._infScroll = infScroll); - }, - style: style, - }, - this.props.pullDownToRefresh && - React.createElement( - 'div', - { - style: { position: 'relative' }, - ref: function(pullDown) { - return (_this._pullDown = pullDown); - }, - }, - React.createElement( - 'div', - { - style: { - position: 'absolute', - left: 0, - right: 0, - top: -1 * this.maxPullDownDistance, - }, - }, - this.state.pullToRefreshThresholdBreached - ? this.props.releaseToRefreshContent - : this.props.pullDownToRefreshContent - ) - ), - this.props.children, - !this.state.showLoader && - !hasChildren && - this.props.hasMore && - this.props.loader, - this.state.showLoader && this.props.hasMore && this.props.loader, - !this.props.hasMore && this.props.endMessage - ) - ); - }; - return InfiniteScroll; -})(Component); + InfiniteScroll.prototype.render = function () { + var _this = this; + var style = __assign({ height: this.props.height || 'auto', overflow: 'auto', WebkitOverflowScrolling: 'touch' }, this.props.style); + var hasChildren = this.props.hasChildren || + !!(this.props.children && + this.props.children instanceof Array && + this.props.children.length); + // because heighted infiniteScroll visualy breaks + // on drag down as overflow becomes visible + var outerDivStyle = this.props.pullDownToRefresh && this.props.height + ? { overflow: 'auto' } + : {}; + return (React.createElement("div", { style: outerDivStyle, className: "infinite-scroll-component__outerdiv" }, + React.createElement("div", { className: "infinite-scroll-component " + (this.props.className || ''), ref: function (infScroll) { return (_this._infScroll = infScroll); }, style: style }, + this.props.pullDownToRefresh && (React.createElement("div", { style: { position: 'relative' }, ref: function (pullDown) { return (_this._pullDown = pullDown); } }, + React.createElement("div", { style: { + position: 'absolute', + left: 0, + right: 0, + top: -1 * this.maxPullDownDistance, + } }, this.state.pullToRefreshThresholdBreached + ? this.props.releaseToRefreshContent + : this.props.pullDownToRefreshContent))), + this.props.children, + !this.state.showLoader && + !hasChildren && + this.props.hasMore && + this.props.loader, + this.state.showLoader && this.props.hasMore && this.props.loader, + !this.props.hasMore && this.props.endMessage))); + }; + return InfiniteScroll; +}(Component)); export default InfiniteScroll; //# sourceMappingURL=index.es.js.map diff --git a/dist/index.js b/dist/index.js index f9cfac7..627980c 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,8 +1,6 @@ 'use strict'; -function _interopDefault(ex) { - return ex && typeof ex === 'object' && 'default' in ex ? ex['default'] : ex; -} +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var React = require('react'); var React__default = _interopDefault(React); @@ -24,39 +22,27 @@ and limitations under the License. /* global Reflect, Promise */ var extendStatics = function(d, b) { - extendStatics = - Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && - function(d, b) { - d.__proto__ = b; - }) || - function(d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return extendStatics(d, b); + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); }; function __extends(d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; - } - d.prototype = - b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { - __assign = - Object.assign || - function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; }; - return __assign.apply(this, arguments); + return __assign.apply(this, arguments); }; /* eslint-disable no-undefined,no-param-reassign,no-shadow */ @@ -77,7 +63,7 @@ var __assign = function() { * * @return {Function} A new, throttled, function. */ -function throttle(delay, noTrailing, callback, debounceMode) { +function throttle (delay, noTrailing, callback, debounceMode) { /* * After wrapper has stopped being called, this timeout ensures that * `callback` is executed at the proper times in `throttle` and `end` @@ -94,11 +80,13 @@ function throttle(delay, noTrailing, callback, debounceMode) { } } // Function to cancel next exec + function cancel() { clearExistingTimeout(); cancelled = true; } // `noTrailing` defaults to falsy. + if (typeof noTrailing !== 'boolean') { debounceMode = callback; callback = noTrailing; @@ -110,6 +98,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { * is executed. */ + function wrapper() { var self = this; var elapsed = Date.now() - lastExec; @@ -119,6 +108,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { return; } // Execute `callback` and update the `lastExec` timestamp. + function exec() { lastExec = Date.now(); callback.apply(self, args); @@ -128,6 +118,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { * to allow future `callback` executions. */ + function clear() { timeoutID = undefined; } @@ -160,10 +151,7 @@ function throttle(delay, noTrailing, callback, debounceMode) { * If `debounceMode` is false (at end), schedule `callback` to * execute after `delay` ms. */ - timeoutID = setTimeout( - debounceMode ? clear : exec, - debounceMode === undefined ? delay - elapsed : delay - ); + timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay); } } @@ -173,372 +161,302 @@ function throttle(delay, noTrailing, callback, debounceMode) { } var ThresholdUnits = { - Pixel: 'Pixel', - Percent: 'Percent', + Pixel: 'Pixel', + Percent: 'Percent', }; var defaultThreshold = { - unit: ThresholdUnits.Percent, - value: 0.8, + unit: ThresholdUnits.Percent, + value: 0.8, }; function parseThreshold(scrollThreshold) { - if (typeof scrollThreshold === 'number') { - return { - unit: ThresholdUnits.Percent, - value: scrollThreshold * 100, - }; - } - if (typeof scrollThreshold === 'string') { - if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { - return { - unit: ThresholdUnits.Pixel, - value: parseFloat(scrollThreshold), - }; + if (typeof scrollThreshold === 'number') { + return { + unit: ThresholdUnits.Percent, + value: scrollThreshold * 100, + }; } - if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { - return { - unit: ThresholdUnits.Percent, - value: parseFloat(scrollThreshold), - }; + if (typeof scrollThreshold === 'string') { + if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { + return { + unit: ThresholdUnits.Pixel, + value: parseFloat(scrollThreshold), + }; + } + if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { + return { + unit: ThresholdUnits.Percent, + value: parseFloat(scrollThreshold), + }; + } + console.warn('scrollThreshold format is invalid. Valid formats: "120px", "50%"...'); + return defaultThreshold; } - console.warn( - 'scrollThreshold format is invalid. Valid formats: "120px", "50%"...' - ); + console.warn('scrollThreshold should be string or number'); return defaultThreshold; - } - console.warn('scrollThreshold should be string or number'); - return defaultThreshold; } -var InfiniteScroll = /** @class */ (function(_super) { - __extends(InfiniteScroll, _super); - function InfiniteScroll(props) { - var _this = _super.call(this, props) || this; - _this.lastScrollTop = 0; - _this.actionTriggered = false; - // variables to keep track of pull down behaviour - _this.startY = 0; - _this.currentY = 0; - _this.dragging = false; - // will be populated in componentDidMount - // based on the height of the pull down element - _this.maxPullDownDistance = 0; - _this.getScrollableTarget = function() { - if (_this.props.scrollableTarget instanceof HTMLElement) - return _this.props.scrollableTarget; - if (typeof _this.props.scrollableTarget === 'string') { - return document.getElementById(_this.props.scrollableTarget); - } - if (_this.props.scrollableTarget === null) { - console.warn( - 'You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ' - ); - } - return null; +var InfiniteScroll = /** @class */ (function (_super) { + __extends(InfiniteScroll, _super); + function InfiniteScroll(props) { + var _this = _super.call(this, props) || this; + _this.lastScrollTop = 0; + _this.actionTriggered = false; + // variables to keep track of pull down behaviour + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + // will be populated in componentDidMount + // based on the height of the pull down element + _this.maxPullDownDistance = 0; + _this.getScrollableTarget = function () { + if (_this.props.scrollableTarget instanceof HTMLElement) + return _this.props.scrollableTarget; + if (typeof _this.props.scrollableTarget === 'string') { + return document.getElementById(_this.props.scrollableTarget); + } + if (_this.props.scrollableTarget === null) { + console.warn("You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n "); + } + return null; + }; + _this.onStart = function (evt) { + if (_this.lastScrollTop) + return; + _this.dragging = true; + if (evt instanceof MouseEvent) { + _this.startY = evt.pageY; + } + else if (evt instanceof TouchEvent) { + _this.startY = evt.touches[0].pageY; + } + _this.currentY = _this.startY; + if (_this._infScroll) { + _this._infScroll.style.willChange = 'transform'; + _this._infScroll.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)"; + } + }; + _this.onMove = function (evt) { + if (!_this.dragging) + return; + if (evt instanceof MouseEvent) { + _this.currentY = evt.pageY; + } + else if (evt instanceof TouchEvent) { + _this.currentY = evt.touches[0].pageY; + } + // user is scrolling down to up + if (_this.currentY < _this.startY) + return; + if (_this.currentY - _this.startY >= + Number(_this.props.pullDownToRefreshThreshold)) { + _this.setState({ + pullToRefreshThresholdBreached: true, + }); + } + // so you can drag upto 1.5 times of the maxPullDownDistance + if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) + return; + if (_this._infScroll) { + _this._infScroll.style.overflow = 'visible'; + _this._infScroll.style.transform = "translate3d(0px, " + (_this.currentY - + _this.startY) + "px, 0px)"; + } + }; + _this.onEnd = function () { + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + if (_this.state.pullToRefreshThresholdBreached) { + _this.props.refreshFunction && _this.props.refreshFunction(); + _this.setState({ + pullToRefreshThresholdBreached: false, + }); + } + requestAnimationFrame(function () { + // this._infScroll + if (_this._infScroll) { + _this._infScroll.style.overflow = 'auto'; + _this._infScroll.style.transform = 'none'; + _this._infScroll.style.willChange = 'unset'; + } + }); + }; + _this.onScrollListener = function (event) { + if (typeof _this.props.onScroll === 'function') { + // Execute this callback in next tick so that it does not affect the + // functionality of the library. + setTimeout(function () { return _this.props.onScroll && _this.props.onScroll(event); }, 0); + } + var target = _this.props.height || _this._scrollableNode + ? event.target + : document.documentElement.scrollTop + ? document.documentElement + : document.body; + // return immediately if the action has already been triggered, + // prevents multiple triggers. + if (_this.actionTriggered) + return; + var atBottom = _this.props.inverse + ? _this.isElementAtTop(target, _this.props.scrollThreshold) + : _this.isElementAtBottom(target, _this.props.scrollThreshold); + // call the `next` function in the props to trigger the next data fetch + if (atBottom && _this.props.hasMore) { + _this.actionTriggered = true; + _this.setState({ showLoader: true }); + _this.props.next && _this.props.next(); + } + _this.lastScrollTop = target.scrollTop; + }; + _this.state = { + showLoader: false, + pullToRefreshThresholdBreached: false, + prevDataLength: props.dataLength, + }; + _this.throttledOnScrollListener = throttle(150, _this.onScrollListener).bind(_this); + _this.onStart = _this.onStart.bind(_this); + _this.onMove = _this.onMove.bind(_this); + _this.onEnd = _this.onEnd.bind(_this); + return _this; + } + InfiniteScroll.prototype.componentDidMount = function () { + if (typeof this.props.dataLength === 'undefined') { + throw new Error("mandatory prop \"dataLength\" is missing. The prop is needed" + + " when loading more content. Check README.md for usage"); + } + this._scrollableNode = this.getScrollableTarget(); + this.el = this.props.height + ? this._infScroll + : this._scrollableNode || window; + if (this.el) { + this.el.addEventListener('scroll', this + .throttledOnScrollListener); + } + if (typeof this.props.initialScrollY === 'number' && + this.el && + this.el instanceof HTMLElement && + this.el.scrollHeight > this.props.initialScrollY) { + this.el.scrollTo(0, this.props.initialScrollY); + } + if (this.props.pullDownToRefresh && this.el) { + this.el.addEventListener('touchstart', this.onStart); + this.el.addEventListener('touchmove', this.onMove); + this.el.addEventListener('touchend', this.onEnd); + this.el.addEventListener('mousedown', this.onStart); + this.el.addEventListener('mousemove', this.onMove); + this.el.addEventListener('mouseup', this.onEnd); + // get BCR of pullDown element to position it above + this.maxPullDownDistance = + (this._pullDown && + this._pullDown.firstChild && + this._pullDown.firstChild.getBoundingClientRect() + .height) || + 0; + this.forceUpdate(); + if (typeof this.props.refreshFunction !== 'function') { + throw new Error("Mandatory prop \"refreshFunction\" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage'"); + } + } }; - _this.onStart = function(evt) { - if (_this.lastScrollTop) return; - _this.dragging = true; - if (evt instanceof MouseEvent) { - _this.startY = evt.pageY; - } else if (evt instanceof TouchEvent) { - _this.startY = evt.touches[0].pageY; - } - _this.currentY = _this.startY; - if (_this._infScroll) { - _this._infScroll.style.willChange = 'transform'; - _this._infScroll.style.transition = - 'transform 0.2s cubic-bezier(0,0,0.31,1)'; - } + InfiniteScroll.prototype.componentWillUnmount = function () { + if (this.el) { + this.el.removeEventListener('scroll', this + .throttledOnScrollListener); + if (this.props.pullDownToRefresh) { + this.el.removeEventListener('touchstart', this.onStart); + this.el.removeEventListener('touchmove', this.onMove); + this.el.removeEventListener('touchend', this.onEnd); + this.el.removeEventListener('mousedown', this.onStart); + this.el.removeEventListener('mousemove', this.onMove); + this.el.removeEventListener('mouseup', this.onEnd); + } + } }; - _this.onMove = function(evt) { - if (!_this.dragging) return; - if (evt instanceof MouseEvent) { - _this.currentY = evt.pageY; - } else if (evt instanceof TouchEvent) { - _this.currentY = evt.touches[0].pageY; - } - // user is scrolling down to up - if (_this.currentY < _this.startY) return; - if ( - _this.currentY - _this.startY >= - Number(_this.props.pullDownToRefreshThreshold) - ) { - _this.setState({ - pullToRefreshThresholdBreached: true, - }); - } - // so you can drag upto 1.5 times of the maxPullDownDistance - if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) - return; - if (_this._infScroll) { - _this._infScroll.style.overflow = 'visible'; - _this._infScroll.style.transform = - 'translate3d(0px, ' + (_this.currentY - _this.startY) + 'px, 0px)'; - } + InfiniteScroll.prototype.componentDidUpdate = function (prevProps) { + // do nothing when dataLength is unchanged + if (this.props.dataLength === prevProps.dataLength) + return; + var fetchAgain = this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight * 1.1 > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } + else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } }; - _this.onEnd = function() { - _this.startY = 0; - _this.currentY = 0; - _this.dragging = false; - if (_this.state.pullToRefreshThresholdBreached) { - _this.props.refreshFunction && _this.props.refreshFunction(); - _this.setState({ - pullToRefreshThresholdBreached: false, - }); - } - requestAnimationFrame(function() { - // this._infScroll - if (_this._infScroll) { - _this._infScroll.style.overflow = 'auto'; - _this._infScroll.style.transform = 'none'; - _this._infScroll.style.willChange = 'unset'; + InfiniteScroll.getDerivedStateFromProps = function (nextProps, prevState) { + var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; + // reset when data changes + if (dataLengthChanged) { + return __assign(__assign({}, prevState), { prevDataLength: nextProps.dataLength }); } - }); + return null; }; - _this.onScrollListener = function(event) { - if (typeof _this.props.onScroll === 'function') { - // Execute this callback in next tick so that it does not affect the - // functionality of the library. - setTimeout(function() { - return _this.props.onScroll && _this.props.onScroll(event); - }, 0); - } - var target = - _this.props.height || _this._scrollableNode - ? event.target - : document.documentElement.scrollTop - ? document.documentElement - : document.body; - // return immediately if the action has already been triggered, - // prevents multiple triggers. - if (_this.actionTriggered) return; - var atBottom = _this.props.inverse - ? _this.isElementAtTop(target, _this.props.scrollThreshold) - : _this.isElementAtBottom(target, _this.props.scrollThreshold); - // call the `next` function in the props to trigger the next data fetch - if (atBottom && _this.props.hasMore) { - _this.actionTriggered = true; - _this.setState({ showLoader: true }); - _this.props.next && _this.props.next(); - } - _this.lastScrollTop = target.scrollTop; + InfiniteScroll.prototype.isElementAtTop = function (target, scrollThreshold) { + if (scrollThreshold === void 0) { scrollThreshold = 0.8; } + var clientHeight = target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return (target.scrollTop <= + threshold.value + clientHeight - target.scrollHeight + 1); + } + return (target.scrollTop <= + threshold.value / 100 + clientHeight - target.scrollHeight + 1); }; - _this.state = { - showLoader: false, - pullToRefreshThresholdBreached: false, - prevDataLength: props.dataLength, + InfiniteScroll.prototype.isElementAtBottom = function (target, scrollThreshold) { + if (scrollThreshold === void 0) { scrollThreshold = 0.8; } + var clientHeight = target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return (target.scrollTop + clientHeight >= target.scrollHeight - threshold.value); + } + return (target.scrollTop + clientHeight >= + (threshold.value / 100) * target.scrollHeight); }; - _this.throttledOnScrollListener = throttle( - 150, - _this.onScrollListener - ).bind(_this); - _this.onStart = _this.onStart.bind(_this); - _this.onMove = _this.onMove.bind(_this); - _this.onEnd = _this.onEnd.bind(_this); - return _this; - } - InfiniteScroll.prototype.componentDidMount = function() { - if (typeof this.props.dataLength === 'undefined') { - throw new Error( - 'mandatory prop "dataLength" is missing. The prop is needed' + - ' when loading more content. Check README.md for usage' - ); - } - this._scrollableNode = this.getScrollableTarget(); - this.el = this.props.height - ? this._infScroll - : this._scrollableNode || window; - if (this.el) { - this.el.addEventListener('scroll', this.throttledOnScrollListener); - } - if ( - typeof this.props.initialScrollY === 'number' && - this.el && - this.el instanceof HTMLElement && - this.el.scrollHeight > this.props.initialScrollY - ) { - this.el.scrollTo(0, this.props.initialScrollY); - } - if (this.props.pullDownToRefresh && this.el) { - this.el.addEventListener('touchstart', this.onStart); - this.el.addEventListener('touchmove', this.onMove); - this.el.addEventListener('touchend', this.onEnd); - this.el.addEventListener('mousedown', this.onStart); - this.el.addEventListener('mousemove', this.onMove); - this.el.addEventListener('mouseup', this.onEnd); - // get BCR of pullDown element to position it above - this.maxPullDownDistance = - (this._pullDown && - this._pullDown.firstChild && - this._pullDown.firstChild.getBoundingClientRect().height) || - 0; - this.forceUpdate(); - if (typeof this.props.refreshFunction !== 'function') { - throw new Error( - 'Mandatory prop "refreshFunction" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage\'' - ); - } - } - }; - InfiniteScroll.prototype.componentWillUnmount = function() { - if (this.el) { - this.el.removeEventListener('scroll', this.throttledOnScrollListener); - if (this.props.pullDownToRefresh) { - this.el.removeEventListener('touchstart', this.onStart); - this.el.removeEventListener('touchmove', this.onMove); - this.el.removeEventListener('touchend', this.onEnd); - this.el.removeEventListener('mousedown', this.onStart); - this.el.removeEventListener('mousemove', this.onMove); - this.el.removeEventListener('mouseup', this.onEnd); - } - } - }; - InfiniteScroll.prototype.componentDidUpdate = function(prevProps) { - // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) return; - var fetchAgain = - this._infScroll && - this._scrollableNode && - this._scrollableNode.clientHeight > this._infScroll.scrollHeight; - if (fetchAgain) { - this.actionTriggered = true; - this.setState({ showLoader: true }); - this.props.next(); - } else { - this.actionTriggered = false; - // update state when new data was sent in - this.setState({ - showLoader: false, - }); - } - }; - InfiniteScroll.getDerivedStateFromProps = function(nextProps, prevState) { - var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; - // reset when data changes - if (dataLengthChanged) { - return __assign(__assign({}, prevState), { - prevDataLength: nextProps.dataLength, - }); - } - return null; - }; - InfiniteScroll.prototype.isElementAtTop = function(target, scrollThreshold) { - if (scrollThreshold === void 0) { - scrollThreshold = 0.8; - } - var clientHeight = - target === document.body || target === document.documentElement - ? window.screen.availHeight - : target.clientHeight; - var threshold = parseThreshold(scrollThreshold); - if (threshold.unit === ThresholdUnits.Pixel) { - return ( - target.scrollTop <= - threshold.value + clientHeight - target.scrollHeight + 1 - ); - } - return ( - target.scrollTop <= - threshold.value / 100 + clientHeight - target.scrollHeight + 1 - ); - }; - InfiniteScroll.prototype.isElementAtBottom = function( - target, - scrollThreshold - ) { - if (scrollThreshold === void 0) { - scrollThreshold = 0.8; - } - var clientHeight = - target === document.body || target === document.documentElement - ? window.screen.availHeight - : target.clientHeight; - var threshold = parseThreshold(scrollThreshold); - if (threshold.unit === ThresholdUnits.Pixel) { - return ( - target.scrollTop + clientHeight >= target.scrollHeight - threshold.value - ); - } - return ( - target.scrollTop + clientHeight >= - (threshold.value / 100) * target.scrollHeight - ); - }; - InfiniteScroll.prototype.render = function() { - var _this = this; - var style = __assign( - { - height: this.props.height || 'auto', - overflow: 'auto', - WebkitOverflowScrolling: 'touch', - }, - this.props.style - ); - var hasChildren = - this.props.hasChildren || - !!( - this.props.children && - this.props.children instanceof Array && - this.props.children.length - ); - // because heighted infiniteScroll visualy breaks - // on drag down as overflow becomes visible - var outerDivStyle = - this.props.pullDownToRefresh && this.props.height - ? { overflow: 'auto' } - : {}; - return React__default.createElement( - 'div', - { - style: outerDivStyle, - className: 'infinite-scroll-component__outerdiv', - }, - React__default.createElement( - 'div', - { - className: - 'infinite-scroll-component ' + (this.props.className || ''), - ref: function(infScroll) { - return (_this._infScroll = infScroll); - }, - style: style, - }, - this.props.pullDownToRefresh && - React__default.createElement( - 'div', - { - style: { position: 'relative' }, - ref: function(pullDown) { - return (_this._pullDown = pullDown); - }, - }, - React__default.createElement( - 'div', - { - style: { - position: 'absolute', - left: 0, - right: 0, - top: -1 * this.maxPullDownDistance, - }, - }, - this.state.pullToRefreshThresholdBreached - ? this.props.releaseToRefreshContent - : this.props.pullDownToRefreshContent - ) - ), - this.props.children, - !this.state.showLoader && - !hasChildren && - this.props.hasMore && - this.props.loader, - this.state.showLoader && this.props.hasMore && this.props.loader, - !this.props.hasMore && this.props.endMessage - ) - ); - }; - return InfiniteScroll; -})(React.Component); + InfiniteScroll.prototype.render = function () { + var _this = this; + var style = __assign({ height: this.props.height || 'auto', overflow: 'auto', WebkitOverflowScrolling: 'touch' }, this.props.style); + var hasChildren = this.props.hasChildren || + !!(this.props.children && + this.props.children instanceof Array && + this.props.children.length); + // because heighted infiniteScroll visualy breaks + // on drag down as overflow becomes visible + var outerDivStyle = this.props.pullDownToRefresh && this.props.height + ? { overflow: 'auto' } + : {}; + return (React__default.createElement("div", { style: outerDivStyle, className: "infinite-scroll-component__outerdiv" }, + React__default.createElement("div", { className: "infinite-scroll-component " + (this.props.className || ''), ref: function (infScroll) { return (_this._infScroll = infScroll); }, style: style }, + this.props.pullDownToRefresh && (React__default.createElement("div", { style: { position: 'relative' }, ref: function (pullDown) { return (_this._pullDown = pullDown); } }, + React__default.createElement("div", { style: { + position: 'absolute', + left: 0, + right: 0, + top: -1 * this.maxPullDownDistance, + } }, this.state.pullToRefreshThresholdBreached + ? this.props.releaseToRefreshContent + : this.props.pullDownToRefreshContent))), + this.props.children, + !this.state.showLoader && + !hasChildren && + this.props.hasMore && + this.props.loader, + this.state.showLoader && this.props.hasMore && this.props.loader, + !this.props.hasMore && this.props.endMessage))); + }; + return InfiniteScroll; +}(React.Component)); module.exports = InfiniteScroll; //# sourceMappingURL=index.js.map diff --git a/dist/index.umd.js b/dist/index.umd.js index 434d3e2..c69e722 100644 --- a/dist/index.umd.js +++ b/dist/index.umd.js @@ -1,9 +1,9 @@ -var InfiniteScroll = (function(React) { - 'use strict'; +var InfiniteScroll = (function (React) { + 'use strict'; - var React__default = 'default' in React ? React['default'] : React; + var React__default = 'default' in React ? React['default'] : React; - /*! ***************************************************************************** + /*! ***************************************************************************** Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the @@ -17,529 +17,446 @@ var InfiniteScroll = (function(React) { See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. ***************************************************************************** */ - /* global Reflect, Promise */ + /* global Reflect, Promise */ - var extendStatics = function(d, b) { - extendStatics = - Object.setPrototypeOf || - ({ __proto__: [] } instanceof Array && - function(d, b) { - d.__proto__ = b; - }) || - function(d, b) { - for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; - }; - return extendStatics(d, b); - }; + var extendStatics = function(d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; - function __extends(d, b) { - extendStatics(d, b); - function __() { - this.constructor = d; + function __extends(d, b) { + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } - d.prototype = - b === null ? Object.create(b) : ((__.prototype = b.prototype), new __()); - } - var __assign = function() { - __assign = - Object.assign || - function __assign(t) { - for (var s, i = 1, n = arguments.length; i < n; i++) { - s = arguments[i]; - for (var p in s) - if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; - } - return t; - }; - return __assign.apply(this, arguments); - }; + var __assign = function() { + __assign = Object.assign || function __assign(t) { + for (var s, i = 1, n = arguments.length; i < n; i++) { + s = arguments[i]; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; + } + return t; + }; + return __assign.apply(this, arguments); + }; - /* eslint-disable no-undefined,no-param-reassign,no-shadow */ + /* eslint-disable no-undefined,no-param-reassign,no-shadow */ - /** - * Throttle execution of a function. Especially useful for rate limiting - * execution of handlers on events like resize and scroll. - * - * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. - * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the - * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time - * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds, - * the internal counter is reset) - * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, - * to `callback` when the throttled-function is executed. - * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end), - * schedule `callback` to execute after `delay` ms. - * - * @return {Function} A new, throttled, function. - */ - function throttle(delay, noTrailing, callback, debounceMode) { - /* - * After wrapper has stopped being called, this timeout ensures that - * `callback` is executed at the proper times in `throttle` and `end` - * debounce modes. + /** + * Throttle execution of a function. Especially useful for rate limiting + * execution of handlers on events like resize and scroll. + * + * @param {Number} delay A zero-or-greater delay in milliseconds. For event callbacks, values around 100 or 250 (or even higher) are most useful. + * @param {Boolean} [noTrailing] Optional, defaults to false. If noTrailing is true, callback will only execute every `delay` milliseconds while the + * throttled-function is being called. If noTrailing is false or unspecified, callback will be executed one final time + * after the last throttled-function call. (After the throttled-function has not been called for `delay` milliseconds, + * the internal counter is reset) + * @param {Function} callback A function to be executed after delay milliseconds. The `this` context and all arguments are passed through, as-is, + * to `callback` when the throttled-function is executed. + * @param {Boolean} [debounceMode] If `debounceMode` is true (at begin), schedule `clear` to execute after `delay` ms. If `debounceMode` is false (at end), + * schedule `callback` to execute after `delay` ms. + * + * @return {Function} A new, throttled, function. */ - var timeoutID; - var cancelled = false; // Keep track of the last time `callback` was executed. + function throttle (delay, noTrailing, callback, debounceMode) { + /* + * After wrapper has stopped being called, this timeout ensures that + * `callback` is executed at the proper times in `throttle` and `end` + * debounce modes. + */ + var timeoutID; + var cancelled = false; // Keep track of the last time `callback` was executed. - var lastExec = 0; // Function to clear existing timeout + var lastExec = 0; // Function to clear existing timeout - function clearExistingTimeout() { - if (timeoutID) { - clearTimeout(timeoutID); - } - } // Function to cancel next exec + function clearExistingTimeout() { + if (timeoutID) { + clearTimeout(timeoutID); + } + } // Function to cancel next exec - function cancel() { - clearExistingTimeout(); - cancelled = true; - } // `noTrailing` defaults to falsy. - if (typeof noTrailing !== 'boolean') { - debounceMode = callback; - callback = noTrailing; - noTrailing = undefined; - } - /* - * The `wrapper` function encapsulates all of the throttling / debouncing - * functionality and when executed will limit the rate at which `callback` - * is executed. - */ + function cancel() { + clearExistingTimeout(); + cancelled = true; + } // `noTrailing` defaults to falsy. - function wrapper() { - var self = this; - var elapsed = Date.now() - lastExec; - var args = arguments; - if (cancelled) { - return; - } // Execute `callback` and update the `lastExec` timestamp. - - function exec() { - lastExec = Date.now(); - callback.apply(self, args); + if (typeof noTrailing !== 'boolean') { + debounceMode = callback; + callback = noTrailing; + noTrailing = undefined; } /* - * If `debounceMode` is true (at begin) this is used to clear the flag - * to allow future `callback` executions. + * The `wrapper` function encapsulates all of the throttling / debouncing + * functionality and when executed will limit the rate at which `callback` + * is executed. */ - function clear() { - timeoutID = undefined; - } - if (debounceMode && !timeoutID) { - /* - * Since `wrapper` is being called for the first time and - * `debounceMode` is true (at begin), execute `callback`. - */ - exec(); - } + function wrapper() { + var self = this; + var elapsed = Date.now() - lastExec; + var args = arguments; - clearExistingTimeout(); + if (cancelled) { + return; + } // Execute `callback` and update the `lastExec` timestamp. - if (debounceMode === undefined && elapsed > delay) { - /* - * In throttle mode, if `delay` time has been exceeded, execute - * `callback`. - */ - exec(); - } else if (noTrailing !== true) { + + function exec() { + lastExec = Date.now(); + callback.apply(self, args); + } /* - * In trailing throttle mode, since `delay` time has not been - * exceeded, schedule `callback` to execute `delay` ms after most - * recent execution. - * - * If `debounceMode` is true (at begin), schedule `clear` to execute - * after `delay` ms. - * - * If `debounceMode` is false (at end), schedule `callback` to - * execute after `delay` ms. + * If `debounceMode` is true (at begin) this is used to clear the flag + * to allow future `callback` executions. */ - timeoutID = setTimeout( - debounceMode ? clear : exec, - debounceMode === undefined ? delay - elapsed : delay - ); - } - } - wrapper.cancel = cancel; // Return the wrapper function. - return wrapper; - } + function clear() { + timeoutID = undefined; + } - var ThresholdUnits = { - Pixel: 'Pixel', - Percent: 'Percent', - }; - var defaultThreshold = { - unit: ThresholdUnits.Percent, - value: 0.8, - }; - function parseThreshold(scrollThreshold) { - if (typeof scrollThreshold === 'number') { - return { - unit: ThresholdUnits.Percent, - value: scrollThreshold * 100, - }; - } - if (typeof scrollThreshold === 'string') { - if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { - return { - unit: ThresholdUnits.Pixel, - value: parseFloat(scrollThreshold), - }; - } - if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { - return { - unit: ThresholdUnits.Percent, - value: parseFloat(scrollThreshold), - }; + if (debounceMode && !timeoutID) { + /* + * Since `wrapper` is being called for the first time and + * `debounceMode` is true (at begin), execute `callback`. + */ + exec(); + } + + clearExistingTimeout(); + + if (debounceMode === undefined && elapsed > delay) { + /* + * In throttle mode, if `delay` time has been exceeded, execute + * `callback`. + */ + exec(); + } else if (noTrailing !== true) { + /* + * In trailing throttle mode, since `delay` time has not been + * exceeded, schedule `callback` to execute `delay` ms after most + * recent execution. + * + * If `debounceMode` is true (at begin), schedule `clear` to execute + * after `delay` ms. + * + * If `debounceMode` is false (at end), schedule `callback` to + * execute after `delay` ms. + */ + timeoutID = setTimeout(debounceMode ? clear : exec, debounceMode === undefined ? delay - elapsed : delay); + } } - console.warn( - 'scrollThreshold format is invalid. Valid formats: "120px", "50%"...' - ); - return defaultThreshold; + + wrapper.cancel = cancel; // Return the wrapper function. + + return wrapper; } - console.warn('scrollThreshold should be string or number'); - return defaultThreshold; - } - var InfiniteScroll = /** @class */ (function(_super) { - __extends(InfiniteScroll, _super); - function InfiniteScroll(props) { - var _this = _super.call(this, props) || this; - _this.lastScrollTop = 0; - _this.actionTriggered = false; - // variables to keep track of pull down behaviour - _this.startY = 0; - _this.currentY = 0; - _this.dragging = false; - // will be populated in componentDidMount - // based on the height of the pull down element - _this.maxPullDownDistance = 0; - _this.getScrollableTarget = function() { - if (_this.props.scrollableTarget instanceof HTMLElement) - return _this.props.scrollableTarget; - if (typeof _this.props.scrollableTarget === 'string') { - return document.getElementById(_this.props.scrollableTarget); - } - if (_this.props.scrollableTarget === null) { - console.warn( - 'You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n ' - ); - } - return null; - }; - _this.onStart = function(evt) { - if (_this.lastScrollTop) return; - _this.dragging = true; - if (evt instanceof MouseEvent) { - _this.startY = evt.pageY; - } else if (evt instanceof TouchEvent) { - _this.startY = evt.touches[0].pageY; - } - _this.currentY = _this.startY; - if (_this._infScroll) { - _this._infScroll.style.willChange = 'transform'; - _this._infScroll.style.transition = - 'transform 0.2s cubic-bezier(0,0,0.31,1)'; - } - }; - _this.onMove = function(evt) { - if (!_this.dragging) return; - if (evt instanceof MouseEvent) { - _this.currentY = evt.pageY; - } else if (evt instanceof TouchEvent) { - _this.currentY = evt.touches[0].pageY; - } - // user is scrolling down to up - if (_this.currentY < _this.startY) return; - if ( - _this.currentY - _this.startY >= - Number(_this.props.pullDownToRefreshThreshold) - ) { - _this.setState({ - pullToRefreshThresholdBreached: true, - }); - } - // so you can drag upto 1.5 times of the maxPullDownDistance - if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) - return; - if (_this._infScroll) { - _this._infScroll.style.overflow = 'visible'; - _this._infScroll.style.transform = - 'translate3d(0px, ' + (_this.currentY - _this.startY) + 'px, 0px)'; - } - }; - _this.onEnd = function() { - _this.startY = 0; - _this.currentY = 0; - _this.dragging = false; - if (_this.state.pullToRefreshThresholdBreached) { - _this.props.refreshFunction && _this.props.refreshFunction(); - _this.setState({ - pullToRefreshThresholdBreached: false, - }); - } - requestAnimationFrame(function() { - // this._infScroll - if (_this._infScroll) { - _this._infScroll.style.overflow = 'auto'; - _this._infScroll.style.transform = 'none'; - _this._infScroll.style.willChange = 'unset'; - } - }); - }; - _this.onScrollListener = function(event) { - if (typeof _this.props.onScroll === 'function') { - // Execute this callback in next tick so that it does not affect the - // functionality of the library. - setTimeout(function() { - return _this.props.onScroll && _this.props.onScroll(event); - }, 0); + var ThresholdUnits = { + Pixel: 'Pixel', + Percent: 'Percent', + }; + var defaultThreshold = { + unit: ThresholdUnits.Percent, + value: 0.8, + }; + function parseThreshold(scrollThreshold) { + if (typeof scrollThreshold === 'number') { + return { + unit: ThresholdUnits.Percent, + value: scrollThreshold * 100, + }; } - var target = - _this.props.height || _this._scrollableNode - ? event.target - : document.documentElement.scrollTop - ? document.documentElement - : document.body; - // return immediately if the action has already been triggered, - // prevents multiple triggers. - if (_this.actionTriggered) return; - var atBottom = _this.props.inverse - ? _this.isElementAtTop(target, _this.props.scrollThreshold) - : _this.isElementAtBottom(target, _this.props.scrollThreshold); - // call the `next` function in the props to trigger the next data fetch - if (atBottom && _this.props.hasMore) { - _this.actionTriggered = true; - _this.setState({ showLoader: true }); - _this.props.next && _this.props.next(); + if (typeof scrollThreshold === 'string') { + if (scrollThreshold.match(/^(\d*(\.\d+)?)px$/)) { + return { + unit: ThresholdUnits.Pixel, + value: parseFloat(scrollThreshold), + }; + } + if (scrollThreshold.match(/^(\d*(\.\d+)?)%$/)) { + return { + unit: ThresholdUnits.Percent, + value: parseFloat(scrollThreshold), + }; + } + console.warn('scrollThreshold format is invalid. Valid formats: "120px", "50%"...'); + return defaultThreshold; } - _this.lastScrollTop = target.scrollTop; - }; - _this.state = { - showLoader: false, - pullToRefreshThresholdBreached: false, - prevDataLength: props.dataLength, - }; - _this.throttledOnScrollListener = throttle( - 150, - _this.onScrollListener - ).bind(_this); - _this.onStart = _this.onStart.bind(_this); - _this.onMove = _this.onMove.bind(_this); - _this.onEnd = _this.onEnd.bind(_this); - return _this; + console.warn('scrollThreshold should be string or number'); + return defaultThreshold; } - InfiniteScroll.prototype.componentDidMount = function() { - if (typeof this.props.dataLength === 'undefined') { - throw new Error( - 'mandatory prop "dataLength" is missing. The prop is needed' + - ' when loading more content. Check README.md for usage' - ); - } - this._scrollableNode = this.getScrollableTarget(); - this.el = this.props.height - ? this._infScroll - : this._scrollableNode || window; - if (this.el) { - this.el.addEventListener('scroll', this.throttledOnScrollListener); - } - if ( - typeof this.props.initialScrollY === 'number' && - this.el && - this.el instanceof HTMLElement && - this.el.scrollHeight > this.props.initialScrollY - ) { - this.el.scrollTo(0, this.props.initialScrollY); - } - if (this.props.pullDownToRefresh && this.el) { - this.el.addEventListener('touchstart', this.onStart); - this.el.addEventListener('touchmove', this.onMove); - this.el.addEventListener('touchend', this.onEnd); - this.el.addEventListener('mousedown', this.onStart); - this.el.addEventListener('mousemove', this.onMove); - this.el.addEventListener('mouseup', this.onEnd); - // get BCR of pullDown element to position it above - this.maxPullDownDistance = - (this._pullDown && - this._pullDown.firstChild && - this._pullDown.firstChild.getBoundingClientRect().height) || - 0; - this.forceUpdate(); - if (typeof this.props.refreshFunction !== 'function') { - throw new Error( - 'Mandatory prop "refreshFunction" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage\'' - ); - } - } - }; - InfiniteScroll.prototype.componentWillUnmount = function() { - if (this.el) { - this.el.removeEventListener('scroll', this.throttledOnScrollListener); - if (this.props.pullDownToRefresh) { - this.el.removeEventListener('touchstart', this.onStart); - this.el.removeEventListener('touchmove', this.onMove); - this.el.removeEventListener('touchend', this.onEnd); - this.el.removeEventListener('mousedown', this.onStart); - this.el.removeEventListener('mousemove', this.onMove); - this.el.removeEventListener('mouseup', this.onEnd); + + var InfiniteScroll = /** @class */ (function (_super) { + __extends(InfiniteScroll, _super); + function InfiniteScroll(props) { + var _this = _super.call(this, props) || this; + _this.lastScrollTop = 0; + _this.actionTriggered = false; + // variables to keep track of pull down behaviour + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + // will be populated in componentDidMount + // based on the height of the pull down element + _this.maxPullDownDistance = 0; + _this.getScrollableTarget = function () { + if (_this.props.scrollableTarget instanceof HTMLElement) + return _this.props.scrollableTarget; + if (typeof _this.props.scrollableTarget === 'string') { + return document.getElementById(_this.props.scrollableTarget); + } + if (_this.props.scrollableTarget === null) { + console.warn("You are trying to pass scrollableTarget but it is null. This might\n happen because the element may not have been added to DOM yet.\n See https://github.com/ankeetmaini/react-infinite-scroll-component/issues/59 for more info.\n "); + } + return null; + }; + _this.onStart = function (evt) { + if (_this.lastScrollTop) + return; + _this.dragging = true; + if (evt instanceof MouseEvent) { + _this.startY = evt.pageY; + } + else if (evt instanceof TouchEvent) { + _this.startY = evt.touches[0].pageY; + } + _this.currentY = _this.startY; + if (_this._infScroll) { + _this._infScroll.style.willChange = 'transform'; + _this._infScroll.style.transition = "transform 0.2s cubic-bezier(0,0,0.31,1)"; + } + }; + _this.onMove = function (evt) { + if (!_this.dragging) + return; + if (evt instanceof MouseEvent) { + _this.currentY = evt.pageY; + } + else if (evt instanceof TouchEvent) { + _this.currentY = evt.touches[0].pageY; + } + // user is scrolling down to up + if (_this.currentY < _this.startY) + return; + if (_this.currentY - _this.startY >= + Number(_this.props.pullDownToRefreshThreshold)) { + _this.setState({ + pullToRefreshThresholdBreached: true, + }); + } + // so you can drag upto 1.5 times of the maxPullDownDistance + if (_this.currentY - _this.startY > _this.maxPullDownDistance * 1.5) + return; + if (_this._infScroll) { + _this._infScroll.style.overflow = 'visible'; + _this._infScroll.style.transform = "translate3d(0px, " + (_this.currentY - + _this.startY) + "px, 0px)"; + } + }; + _this.onEnd = function () { + _this.startY = 0; + _this.currentY = 0; + _this.dragging = false; + if (_this.state.pullToRefreshThresholdBreached) { + _this.props.refreshFunction && _this.props.refreshFunction(); + _this.setState({ + pullToRefreshThresholdBreached: false, + }); + } + requestAnimationFrame(function () { + // this._infScroll + if (_this._infScroll) { + _this._infScroll.style.overflow = 'auto'; + _this._infScroll.style.transform = 'none'; + _this._infScroll.style.willChange = 'unset'; + } + }); + }; + _this.onScrollListener = function (event) { + if (typeof _this.props.onScroll === 'function') { + // Execute this callback in next tick so that it does not affect the + // functionality of the library. + setTimeout(function () { return _this.props.onScroll && _this.props.onScroll(event); }, 0); + } + var target = _this.props.height || _this._scrollableNode + ? event.target + : document.documentElement.scrollTop + ? document.documentElement + : document.body; + // return immediately if the action has already been triggered, + // prevents multiple triggers. + if (_this.actionTriggered) + return; + var atBottom = _this.props.inverse + ? _this.isElementAtTop(target, _this.props.scrollThreshold) + : _this.isElementAtBottom(target, _this.props.scrollThreshold); + // call the `next` function in the props to trigger the next data fetch + if (atBottom && _this.props.hasMore) { + _this.actionTriggered = true; + _this.setState({ showLoader: true }); + _this.props.next && _this.props.next(); + } + _this.lastScrollTop = target.scrollTop; + }; + _this.state = { + showLoader: false, + pullToRefreshThresholdBreached: false, + prevDataLength: props.dataLength, + }; + _this.throttledOnScrollListener = throttle(150, _this.onScrollListener).bind(_this); + _this.onStart = _this.onStart.bind(_this); + _this.onMove = _this.onMove.bind(_this); + _this.onEnd = _this.onEnd.bind(_this); + return _this; } - } - }; - InfiniteScroll.prototype.componentDidUpdate = function(prevProps) { - // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) return; - var fetchAgain = - this._infScroll && - this._scrollableNode && - this._scrollableNode.clientHeight > this._infScroll.scrollHeight; - if (fetchAgain) { - this.actionTriggered = true; - this.setState({ showLoader: true }); - this.props.next(); - } else { - this.actionTriggered = false; - // update state when new data was sent in - this.setState({ - showLoader: false, - }); - } - }; - InfiniteScroll.getDerivedStateFromProps = function(nextProps, prevState) { - var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; - // reset when data changes - if (dataLengthChanged) { - return __assign(__assign({}, prevState), { - prevDataLength: nextProps.dataLength, - }); - } - return null; - }; - InfiniteScroll.prototype.isElementAtTop = function( - target, - scrollThreshold - ) { - if (scrollThreshold === void 0) { - scrollThreshold = 0.8; - } - var clientHeight = - target === document.body || target === document.documentElement - ? window.screen.availHeight - : target.clientHeight; - var threshold = parseThreshold(scrollThreshold); - if (threshold.unit === ThresholdUnits.Pixel) { - return ( - target.scrollTop <= - threshold.value + clientHeight - target.scrollHeight + 1 - ); - } - return ( - target.scrollTop <= - threshold.value / 100 + clientHeight - target.scrollHeight + 1 - ); - }; - InfiniteScroll.prototype.isElementAtBottom = function( - target, - scrollThreshold - ) { - if (scrollThreshold === void 0) { - scrollThreshold = 0.8; - } - var clientHeight = - target === document.body || target === document.documentElement - ? window.screen.availHeight - : target.clientHeight; - var threshold = parseThreshold(scrollThreshold); - if (threshold.unit === ThresholdUnits.Pixel) { - return ( - target.scrollTop + clientHeight >= - target.scrollHeight - threshold.value - ); - } - return ( - target.scrollTop + clientHeight >= - (threshold.value / 100) * target.scrollHeight - ); - }; - InfiniteScroll.prototype.render = function() { - var _this = this; - var style = __assign( - { - height: this.props.height || 'auto', - overflow: 'auto', - WebkitOverflowScrolling: 'touch', - }, - this.props.style - ); - var hasChildren = - this.props.hasChildren || - !!( - this.props.children && - this.props.children instanceof Array && - this.props.children.length - ); - // because heighted infiniteScroll visualy breaks - // on drag down as overflow becomes visible - var outerDivStyle = - this.props.pullDownToRefresh && this.props.height - ? { overflow: 'auto' } - : {}; - return React__default.createElement( - 'div', - { - style: outerDivStyle, - className: 'infinite-scroll-component__outerdiv', - }, - React__default.createElement( - 'div', - { - className: - 'infinite-scroll-component ' + (this.props.className || ''), - ref: function(infScroll) { - return (_this._infScroll = infScroll); - }, - style: style, - }, - this.props.pullDownToRefresh && - React__default.createElement( - 'div', - { - style: { position: 'relative' }, - ref: function(pullDown) { - return (_this._pullDown = pullDown); - }, - }, - React__default.createElement( - 'div', - { - style: { - position: 'absolute', - left: 0, - right: 0, - top: -1 * this.maxPullDownDistance, - }, - }, - this.state.pullToRefreshThresholdBreached - ? this.props.releaseToRefreshContent - : this.props.pullDownToRefreshContent - ) - ), - this.props.children, - !this.state.showLoader && - !hasChildren && - this.props.hasMore && - this.props.loader, - this.state.showLoader && this.props.hasMore && this.props.loader, - !this.props.hasMore && this.props.endMessage - ) - ); - }; + InfiniteScroll.prototype.componentDidMount = function () { + if (typeof this.props.dataLength === 'undefined') { + throw new Error("mandatory prop \"dataLength\" is missing. The prop is needed" + + " when loading more content. Check README.md for usage"); + } + this._scrollableNode = this.getScrollableTarget(); + this.el = this.props.height + ? this._infScroll + : this._scrollableNode || window; + if (this.el) { + this.el.addEventListener('scroll', this + .throttledOnScrollListener); + } + if (typeof this.props.initialScrollY === 'number' && + this.el && + this.el instanceof HTMLElement && + this.el.scrollHeight > this.props.initialScrollY) { + this.el.scrollTo(0, this.props.initialScrollY); + } + if (this.props.pullDownToRefresh && this.el) { + this.el.addEventListener('touchstart', this.onStart); + this.el.addEventListener('touchmove', this.onMove); + this.el.addEventListener('touchend', this.onEnd); + this.el.addEventListener('mousedown', this.onStart); + this.el.addEventListener('mousemove', this.onMove); + this.el.addEventListener('mouseup', this.onEnd); + // get BCR of pullDown element to position it above + this.maxPullDownDistance = + (this._pullDown && + this._pullDown.firstChild && + this._pullDown.firstChild.getBoundingClientRect() + .height) || + 0; + this.forceUpdate(); + if (typeof this.props.refreshFunction !== 'function') { + throw new Error("Mandatory prop \"refreshFunction\" missing.\n Pull Down To Refresh functionality will not work\n as expected. Check README.md for usage'"); + } + } + }; + InfiniteScroll.prototype.componentWillUnmount = function () { + if (this.el) { + this.el.removeEventListener('scroll', this + .throttledOnScrollListener); + if (this.props.pullDownToRefresh) { + this.el.removeEventListener('touchstart', this.onStart); + this.el.removeEventListener('touchmove', this.onMove); + this.el.removeEventListener('touchend', this.onEnd); + this.el.removeEventListener('mousedown', this.onStart); + this.el.removeEventListener('mousemove', this.onMove); + this.el.removeEventListener('mouseup', this.onEnd); + } + } + }; + InfiniteScroll.prototype.componentDidUpdate = function (prevProps) { + // do nothing when dataLength is unchanged + if (this.props.dataLength === prevProps.dataLength) + return; + var fetchAgain = this._infScroll && + this._scrollableNode && + this._scrollableNode.clientHeight * 1.1 > this._infScroll.scrollHeight; + if (fetchAgain) { + this.actionTriggered = true; + this.setState({ showLoader: true }); + this.props.next(); + } + else { + this.actionTriggered = false; + // update state when new data was sent in + this.setState({ + showLoader: false, + }); + } + }; + InfiniteScroll.getDerivedStateFromProps = function (nextProps, prevState) { + var dataLengthChanged = nextProps.dataLength !== prevState.prevDataLength; + // reset when data changes + if (dataLengthChanged) { + return __assign(__assign({}, prevState), { prevDataLength: nextProps.dataLength }); + } + return null; + }; + InfiniteScroll.prototype.isElementAtTop = function (target, scrollThreshold) { + if (scrollThreshold === void 0) { scrollThreshold = 0.8; } + var clientHeight = target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return (target.scrollTop <= + threshold.value + clientHeight - target.scrollHeight + 1); + } + return (target.scrollTop <= + threshold.value / 100 + clientHeight - target.scrollHeight + 1); + }; + InfiniteScroll.prototype.isElementAtBottom = function (target, scrollThreshold) { + if (scrollThreshold === void 0) { scrollThreshold = 0.8; } + var clientHeight = target === document.body || target === document.documentElement + ? window.screen.availHeight + : target.clientHeight; + var threshold = parseThreshold(scrollThreshold); + if (threshold.unit === ThresholdUnits.Pixel) { + return (target.scrollTop + clientHeight >= target.scrollHeight - threshold.value); + } + return (target.scrollTop + clientHeight >= + (threshold.value / 100) * target.scrollHeight); + }; + InfiniteScroll.prototype.render = function () { + var _this = this; + var style = __assign({ height: this.props.height || 'auto', overflow: 'auto', WebkitOverflowScrolling: 'touch' }, this.props.style); + var hasChildren = this.props.hasChildren || + !!(this.props.children && + this.props.children instanceof Array && + this.props.children.length); + // because heighted infiniteScroll visualy breaks + // on drag down as overflow becomes visible + var outerDivStyle = this.props.pullDownToRefresh && this.props.height + ? { overflow: 'auto' } + : {}; + return (React__default.createElement("div", { style: outerDivStyle, className: "infinite-scroll-component__outerdiv" }, + React__default.createElement("div", { className: "infinite-scroll-component " + (this.props.className || ''), ref: function (infScroll) { return (_this._infScroll = infScroll); }, style: style }, + this.props.pullDownToRefresh && (React__default.createElement("div", { style: { position: 'relative' }, ref: function (pullDown) { return (_this._pullDown = pullDown); } }, + React__default.createElement("div", { style: { + position: 'absolute', + left: 0, + right: 0, + top: -1 * this.maxPullDownDistance, + } }, this.state.pullToRefreshThresholdBreached + ? this.props.releaseToRefreshContent + : this.props.pullDownToRefreshContent))), + this.props.children, + !this.state.showLoader && + !hasChildren && + this.props.hasMore && + this.props.loader, + this.state.showLoader && this.props.hasMore && this.props.loader, + !this.props.hasMore && this.props.endMessage))); + }; + return InfiniteScroll; + }(React.Component)); + return InfiniteScroll; - })(React.Component); - return InfiniteScroll; -})(React); +}(React)); //# sourceMappingURL=index.umd.js.map diff --git a/dist/stories/InfiniteScrollWithHeight.d.ts b/dist/stories/InfiniteScrollWithHeight.d.ts index 2a8e873..8c1feaf 100644 --- a/dist/stories/InfiniteScrollWithHeight.d.ts +++ b/dist/stories/InfiniteScrollWithHeight.d.ts @@ -1,9 +1,9 @@ import React from 'react'; export default class App extends React.Component { - state: { - items: unknown[]; - hasMore: boolean; - }; - fetchMoreData: () => void; - render(): JSX.Element; + state: { + items: unknown[]; + hasMore: boolean; + }; + fetchMoreData: () => void; + render(): JSX.Element; } diff --git a/dist/stories/PullDownToRefreshInfScroll.d.ts b/dist/stories/PullDownToRefreshInfScroll.d.ts index eaa5c6b..0aea5b5 100644 --- a/dist/stories/PullDownToRefreshInfScroll.d.ts +++ b/dist/stories/PullDownToRefreshInfScroll.d.ts @@ -1,8 +1,8 @@ import React from 'react'; export default class App extends React.Component { - state: { - items: unknown[]; - }; - fetchMoreData: () => void; - render(): JSX.Element; + state: { + items: unknown[]; + }; + fetchMoreData: () => void; + render(): JSX.Element; } diff --git a/dist/stories/ScrollableTargetInfScroll.d.ts b/dist/stories/ScrollableTargetInfScroll.d.ts index eaa5c6b..0aea5b5 100644 --- a/dist/stories/ScrollableTargetInfScroll.d.ts +++ b/dist/stories/ScrollableTargetInfScroll.d.ts @@ -1,8 +1,8 @@ import React from 'react'; export default class App extends React.Component { - state: { - items: unknown[]; - }; - fetchMoreData: () => void; - render(): JSX.Element; + state: { + items: unknown[]; + }; + fetchMoreData: () => void; + render(): JSX.Element; } diff --git a/dist/stories/ScrolleableTop.d.ts b/dist/stories/ScrolleableTop.d.ts index eaa5c6b..0aea5b5 100644 --- a/dist/stories/ScrolleableTop.d.ts +++ b/dist/stories/ScrolleableTop.d.ts @@ -1,8 +1,8 @@ import React from 'react'; export default class App extends React.Component { - state: { - items: unknown[]; - }; - fetchMoreData: () => void; - render(): JSX.Element; + state: { + items: unknown[]; + }; + fetchMoreData: () => void; + render(): JSX.Element; } diff --git a/dist/stories/WindowInfiniteScrollComponent.d.ts b/dist/stories/WindowInfiniteScrollComponent.d.ts index d324620..5a4472f 100644 --- a/dist/stories/WindowInfiniteScrollComponent.d.ts +++ b/dist/stories/WindowInfiniteScrollComponent.d.ts @@ -1,15 +1,12 @@ import React from 'react'; declare type State = { - data: number[]; + data: number[]; }; -export default class WindowInfiniteScrollComponent extends React.Component< - {}, - State -> { - state: { - data: any[]; - }; - next: () => void; - render(): JSX.Element; +export default class WindowInfiniteScrollComponent extends React.Component<{}, State> { + state: { + data: any[]; + }; + next: () => void; + render(): JSX.Element; } export {}; diff --git a/dist/utils/threshold.d.ts b/dist/utils/threshold.d.ts index 5bce098..dfe12fb 100644 --- a/dist/utils/threshold.d.ts +++ b/dist/utils/threshold.d.ts @@ -1,10 +1,8 @@ export declare const ThresholdUnits: { - Pixel: string; - Percent: string; + Pixel: string; + Percent: string; }; -export declare function parseThreshold( - scrollThreshold: string | number -): { - unit: string; - value: number; +export declare function parseThreshold(scrollThreshold: string | number): { + unit: string; + value: number; }; From fd84ab35b2ee8bd9de61abd3efb3ff5ec3fbc1d9 Mon Sep 17 00:00:00 2001 From: ardeshir Date: Mon, 8 May 2023 09:39:31 +0000 Subject: [PATCH 6/6] fix - Fix extra fetch call --- dist/index.es.js | 2 +- dist/index.js | 2 +- dist/index.umd.js | 2 +- src/index.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/dist/index.es.js b/dist/index.es.js index 187ce13..1a2d83e 100644 --- a/dist/index.es.js +++ b/dist/index.es.js @@ -368,7 +368,7 @@ var InfiniteScroll = /** @class */ (function (_super) { }; InfiniteScroll.prototype.componentDidUpdate = function (prevProps) { // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) + if (this.props.dataLength === prevProps.dataLength || this.props.dataLength === 0) return; var fetchAgain = this._infScroll && this._scrollableNode && diff --git a/dist/index.js b/dist/index.js index 627980c..872623f 100644 --- a/dist/index.js +++ b/dist/index.js @@ -373,7 +373,7 @@ var InfiniteScroll = /** @class */ (function (_super) { }; InfiniteScroll.prototype.componentDidUpdate = function (prevProps) { // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) + if (this.props.dataLength === prevProps.dataLength || this.props.dataLength === 0) return; var fetchAgain = this._infScroll && this._scrollableNode && diff --git a/dist/index.umd.js b/dist/index.umd.js index c69e722..0f83e7a 100644 --- a/dist/index.umd.js +++ b/dist/index.umd.js @@ -371,7 +371,7 @@ var InfiniteScroll = (function (React) { }; InfiniteScroll.prototype.componentDidUpdate = function (prevProps) { // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) + if (this.props.dataLength === prevProps.dataLength || this.props.dataLength === 0) return; var fetchAgain = this._infScroll && this._scrollableNode && diff --git a/src/index.tsx b/src/index.tsx index fe09eca..35e3911 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -141,7 +141,7 @@ export default class InfiniteScroll extends Component { componentDidUpdate(prevProps: Props) { // do nothing when dataLength is unchanged - if (this.props.dataLength === prevProps.dataLength) return; + if (this.props.dataLength === prevProps.dataLength || this.props.dataLength === 0) return; const fetchAgain = this._infScroll &&