import * as React from "react" ; import { LayoutChangeEvent , NativeScrollEvent , NativeSyntheticEvent , ScrollView , View , } from "react-native" ; import BaseScrollComponent , { ScrollComponentProps } from "../../../core/scrollcomponent/BaseScrollComponent" ; import TSCast from "../../../utils/TSCast" ; /***
 * 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 : TSCast . cast ( ScrollView ) , isHorizontal : false , scrollThrottle : 16 , } ; private _height : number ; private _width : number ; private _offset : number ; private _isSizeChangedCalledOnce : boolean ; private _scrollViewRef : ScrollView | null = null ; constructor ( args ) { super ( args ) ; this . _height = 0 ; this . _width = 0 ; this . _offset = 0 ; this . _isSizeChangedCalledOnce = false ; } public scrollTo ( x , y , isAnimated ) { if ( this . _scrollViewRef ) { this . _scrollViewRef . scrollTo ( { x , y , animated : isAnimated } ) ; } } public render ( ) { const Scroller = TSCast . cast < ScrollView > ( this . props . externalScrollView ) ; const renderContentContainer = this . props . renderContentContainer ? this . props . renderContentContainer : this . _defaultContainer ; const contentContainerProps = { style : { height : this . props . contentHeight , width : this . props . contentWidth , } , horizontal : this . props . isHorizontal , scrollOffset : this . _offset , windowSize : ( this . props . isHorizontal ? this . _width : this . _height ) + this . props . renderAheadOffset , } ; return ( < Scroller ref = { this . _getScrollViewRef } removeClippedSubviews = { false } scrollEventThrottle = { this . props . scrollThrottle } { ... this . props } horizontal = { this . props . isHorizontal } onScroll = { this . _onScroll } onLayout = { ( ! this . _isSizeChangedCalledOnce || this . props . canChangeSize ) ? this . _onLayout : this . props . onLayout } > < View style = { { flexDirection : this . props . isHorizontal ? "row" : "column" } } > { renderContentContainer ( contentContainerProps , this . props . children ) } { this . props . renderFooter ? this . props . renderFooter ( ) : null } < /View> < /Scroller>); } private _defaultContainer ( props , children ) { return ( < View { ... props } > { children } < /View>); } private _getScrollViewRef = ( scrollView ) => { this . _scrollViewRef = scrollView as ( ScrollView | null ) ; } ; private _onScroll = ( event ? ) : void => { if ( event ) { const contentOffset = event . nativeEvent . contentOffset ; this . _offset = this . props . isHorizontal ? contentOffset . x : contentOffset . y ; this . props . onScroll ( contentOffset . x , contentOffset . y , event ) ; } } ; private _onLayout = ( event ) : void => { if ( this . _height !== event . nativeEvent . layout . height || this . _width !== event . nativeEvent . layout . width ) { this . _height = event . nativeEvent . layout . height ; this . _width = event . nativeEvent . layout . width ; if ( this . props . onSizeChanged ) { this . _isSizeChangedCalledOnce = true ; this . props . onSizeChanged ( event . nativeEvent . layout ) ; } } if ( this . props . onLayout ) { this . props . onLayout ( event ) ; } } ; }