import * as classNames from "classnames"; import * as React from "react"; export enum TreadmillDirection { Vertical } interface ITreadmillProps { direction: TreadmillDirection; panes: number; renderPane: (pane: number) => JSX.Element; /** * If true, CSS Snap will be applied */ snap?: boolean; renderPrePane?: () => JSX.Element; } export class Treadmill extends React.Component { public ref: React.RefObject; public observer: IntersectionObserver; constructor(props) { super(props); this.ref = React.createRef(); } public componentDidMount() { try { this.observer = new IntersectionObserver( this.handleObserve, { root: this.ref.current, rootMargin: "0px", threshold: 0.5, } ); Array.from(document.querySelectorAll(".treadmill__pane")).forEach(pane => { this.observer.observe(pane); }); } catch { // could not create observer } } public componentWillUnmount() { try { this.observer.disconnect(); } catch { // could not disconnect observer } } public render() { return (
{this.props.renderPrePane && (
{this.props.renderPrePane()}
)} {Array.from({ length: this.props.panes }).map((pane, index) => { return (
{this.props.renderPane(index)}
); })}
); } private handleObserve = (entries) => { entries.forEach((entry: IntersectionObserverEntry) => { if (entry.isIntersecting) { if (!entry.target.classList.contains("treadmill__pane--visible")) { entry.target.classList.add("treadmill__pane--visible"); } } }); } }