import * as React from "react"; import { Dimension } from "../../../core/dependencies/LayoutProvider"; import BaseScrollComponent, { ScrollComponentProps } from "../../../core/scrollcomponent/BaseScrollComponent"; import BaseScrollView, { ScrollEvent } from "../../../core/scrollcomponent/BaseScrollView"; import ScrollViewer from "./ScrollViewer"; import debounce = require("lodash.debounce"); /*** * The responsibility of a scroll component is to report its size, scroll events and provide a way to scroll to a given offset. * RecyclerListView works on top of this interface and doesn't care about the implementation. To support web we only had to provide * another component written on top of web elements */ export default class ScrollComponent extends BaseScrollComponent { public static defaultProps = { contentHeight: 0, contentWidth: 0, externalScrollView: ScrollViewer, isHorizontal: false, scrollThrottle: 16, canChangeSize: false, }; private static _defaultContainer(props: object, children: React.ReactNode): React.ReactNode | null { return (
{children}
); } private _height: number; private _width: number; private _scrollViewRef: BaseScrollView | null = null; // tslint:disable-next-line:ban-types - DebouncedFunc type is not exported from lodash private readonly _debouncedOnWindowResize: any; constructor(args: ScrollComponentProps) { super(args); this._height = 0; this._width = 0; this._debouncedOnWindowResize = debounce(this._onWindowResize, 100); } public componentDidMount(): void { window.addEventListener("resize", this._debouncedOnWindowResize); } public componentWillUnmount(): void { window.removeEventListener("resize", this._debouncedOnWindowResize); } public scrollTo(x: number, y: number, animated: boolean): void { if (this._scrollViewRef) { this._scrollViewRef.scrollTo({ x, y, animated }); } } public render(): JSX.Element { const Scroller = this.props.externalScrollView as any; //TSI const headerFooterWrapperStyle: React.CSSProperties | undefined = this.props.isHorizontal ? { left: this.props.contentWidth, position: "absolute", top: 0, } : undefined; const renderContentContainer = this.props.renderContentContainer ? this.props.renderContentContainer : ScrollComponent._defaultContainer; const style = { height: this.props.contentHeight, width: this.props.contentWidth, }; return ( this._scrollViewRef = scrollView as (BaseScrollView | null)} {...this.props} horizontal={this.props.isHorizontal} onScroll={this._onScroll} onSizeChanged={this._onSizeChanged}> {this.props.renderHeader && (
{this.props.renderHeader()}
)} {renderContentContainer({ style }, this.props.children)} {this.props.renderFooter && (
{this.props.renderFooter()}
)}
); } private _onScroll = (e: ScrollEvent): void => { this.props.onScroll(e.nativeEvent.contentOffset.x, e.nativeEvent.contentOffset.y, e); } private _onSizeChanged = (event: Dimension): void => { if (this.props.onSizeChanged) { this.props.onSizeChanged(event); } } private _onWindowResize = (): void => { if (this.props.onWindowResize) { this.props.onWindowResize({ width: window.innerWidth, height: window.innerHeight, }); } } }