import * as _ from "lodash"; import * as React from "react"; import { FilePond, IFilePondProps } from "../FilePond"; interface ICollectionProps { /** Required */ total: number; available: number; renderItem: (index: number) => JSX.Element; identifyItem: (index: number) => string; /** Optional */ onScrolledBottom?: () => void; scrolledBottomOffset?: number; renderHeader?: () => JSX.Element; uploader?: IFilePondProps; } export class Collection extends React.Component { public bottomScrollRef: React.RefObject; public observer: IntersectionObserver; constructor(props) { super(props) this.bottomScrollRef = React.createRef(); } public componentDidMount() { this.addIntersectionObserver(); } public componentDidUpdate() { // refresh the intersection observer since it is at a new location this.removeIntersectionObserver(); this.addIntersectionObserver(); } public componentWillUnmount() { this.removeIntersectionObserver(); } public render() { return (
{this.props.renderHeader && (
{this.props.renderHeader()}
)} {this.props.uploader && (
)} {Array.from({ length: this.props.total }).map((item, index) => { return (
{this.props.renderItem(index)} {index === this.props.available - 1 && this.props.onScrolledBottom && (
)}
); })}
); } private addIntersectionObserver = () => { // Guard against not setting if (_.isNil(this.props.onScrolledBottom)) return; try { this.observer = new IntersectionObserver((entries) => { const isVisible = entries[0].isIntersecting; // Guard against leaving visiblity if (!isVisible) return; this.props.onScrolledBottom(); }, { rootMargin: "0px", threshold: 0.1, } ); this.observer.observe(this.bottomScrollRef.current); } catch { // could not create observer } } private removeIntersectionObserver = () => { // Guard against no set observer if (_.isNil(this.observer)) return; try { this.observer.disconnect(); } catch { // could not create observer } } }