import React, { Component } from 'react';
// This is a copy of https://github.com/CassetteRocks/react-infinite-scroller with https://github.com/CassetteRocks/react-infinite-scroller/pull/38/files merged
class InfiniteScroll extends Component {
    constructor(props) {
        super(props);
        this.detachScrollListener = () => { };
        this.scrollListener = this.scrollListener.bind(this);
    }
    componentDidMount() {
        this.pageLoaded = this.props.pageStart;
        this.attachScrollListener();
        if (this.props.initialLoad) {
            this.scrollListener();
        }
        // when component mounts try to load more only when initial data was already rendered
        else if (this.props.data?.length && this.props.hasMore) {
            this.scrollComponent?.scrollHeight && this.scrollListener();
        }
    }
    componentDidUpdate(prevProps) {
        this.attachScrollListener();
        // scroll element might be not scrollable - trigger scroll listener when new data changes the scroll element height
        if (prevProps.data?.length !== this.props.data?.length &&
            this.props.hasMore) {
            // To avoid infinite loop of `loadMore` in `jsdom` we require the scroll element to have height before we trigger `scrollListener` as a reaction to new `props.data`.
            this.scrollComponent?.scrollHeight && this.scrollListener();
        }
    }
    render() {
        const { children, hasMore, loader, scrollElement, dataHook } = this.props;
        let ref;
        if (scrollElement) {
            ref = () => (this.scrollComponent = scrollElement);
        }
        else {
            ref = node => (this.scrollComponent = node);
        }
        return React.createElement('div', { ref, 'data-hook': dataHook }, children, hasMore && (loader || this._defaultLoader));
    }
    calculateTopPosition(el) {
        if (!el) {
            return 0;
        }
        return el.offsetTop + this.calculateTopPosition(el.offsetParent);
    }
    scrollListener() {
        const el = this.scrollComponent;
        let offset;
        if (this.props.scrollElement) {
            if (this.props.isReverse) {
                offset = el.scrollTop;
            }
            else {
                offset = el.scrollHeight - el.scrollTop - el.clientHeight;
            }
        }
        else if (this.props.useWindow) {
            const scrollTop = window.pageYOffset !== undefined
                ? window.pageYOffset
                : (document.documentElement ||
                    document.body.parentNode ||
                    document.body).scrollTop;
            if (this.props.isReverse) {
                offset = scrollTop;
            }
            else {
                offset =
                    this.calculateTopPosition(el) +
                        el.offsetHeight -
                        scrollTop -
                        window.innerHeight;
            }
        }
        else if (this.props.isReverse) {
            offset = el.parentNode.scrollTop;
        }
        else {
            offset =
                el.scrollHeight - el.parentNode.scrollTop - el.parentNode.clientHeight;
        }
        if (offset < Number(this.props.threshold)) {
            this.detachScrollListener();
            // Call loadMore after detachScrollListener to allow for non-async loadMore functions
            if (typeof this.props.loadMore === 'function' && this.props.hasMore) {
                this.props.loadMore((this.pageLoaded += 1));
            }
        }
    }
    attachScrollListener() {
        this.detachScrollListener();
        if (!this.props.hasMore) {
            return;
        }
        let scrollEl = window;
        if (this.props.scrollElement) {
            scrollEl = this.scrollComponent;
        }
        else if (this.props.useWindow === false) {
            scrollEl = this.scrollComponent.parentNode;
        }
        scrollEl.addEventListener('scroll', this.scrollListener);
        scrollEl.addEventListener('resize', this.scrollListener);
        this.detachScrollListener = () => {
            scrollEl.removeEventListener('scroll', this.scrollListener);
            scrollEl.removeEventListener('resize', this.scrollListener);
            this.detachScrollListener = () => { };
        };
    }
    componentWillUnmount() {
        this.detachScrollListener();
    }
    // Set a default loader for all your `InfiniteScroll` components
    setDefaultLoader(loader) {
        this._defaultLoader = loader;
    }
}
InfiniteScroll.defaultProps = {
    hasMore: false,
    initialLoad: true,
    pageStart: 0,
    threshold: 250,
    useWindow: true,
    isReverse: false,
    scrollElement: null,
};
export default InfiniteScroll;
//# sourceMappingURL=InfiniteScroll.js.map