import { Axis } from './types' ; const elementCouldBeVScrolled = ( node ) : boolean => { const styles = window . getComputedStyle ( node ) ; return ( styles . overflowY !== 'hidden' && ! ( styles . overflowY === styles . overflowX && styles . overflowY === 'visible' ) ) ; } ; const elementCouldBeHScrolled = ( node ) : boolean => { const styles = window . getComputedStyle ( node ) ; if ( ( node as HTMLInputElement ) . type === "range" ) { return true ; } return ( styles . overflowX !== 'hidden' && ! ( styles . overflowY === styles . overflowX && styles . overflowX === 'visible' ) ) ; } ; export const locationCouldBeScrolled = ( axis , node ) : boolean => { let current = node ; do { if ( typeof ShadowRoot !== "undefined" && current instanceof ShadowRoot ) { current = current . host as HTMLElement ; } const isScrollable = elementCouldBeScrolled ( axis , current ) ; if ( isScrollable ) { const [ , s , d ] = getScrollVariables ( axis , current ) ; if ( s > d ) { return true ; } } current = current . parentNode as any ; } while ( current && current !== document . body ) ; return false ; } ; const getVScrollVariables = ( { scrollTop , scrollHeight , clientHeight } ) => [ scrollTop , scrollHeight , clientHeight ] ; const getHScrollVariables = ( { scrollLeft , scrollWidth , clientWidth } ) => [ scrollLeft , scrollWidth , clientWidth ] ; const elementCouldBeScrolled = ( axis , node ) : boolean => axis === 'v' ? elementCouldBeVScrolled ( node ) : elementCouldBeHScrolled ( node ) ; const getScrollVariables = ( axis , node ) => axis === 'v' ? getVScrollVariables ( node ) : getHScrollVariables ( node ) ; export const handleScroll = ( axis , endTarget , event , sourceDelta , noOverscroll ) => { const delta = sourceDelta ; let target = event . target as any ; const targetInLock = endTarget . contains ( target ) ; let shouldCancelScroll = false ; const isDeltaPositive = delta > 0 ; let availableScroll = 0 ; let availableScrollTop = 0 ; do { const [ position , scroll , capacity ] = getScrollVariables ( axis , target ) ; const elementScroll = scroll - capacity - position ; if ( position || elementScroll ) { if ( elementCouldBeScrolled ( axis , target ) ) { availableScroll += elementScroll ; availableScrollTop += position ; } } target = target . parentNode as any ; } while ( ( ! targetInLock && target !== document . body ) || ( targetInLock && ( endTarget . contains ( target ) || endTarget === target ) ) ) ; if ( isDeltaPositive && ( ( noOverscroll && availableScroll === 0 ) || ( ! noOverscroll && delta > availableScroll ) ) ) { shouldCancelScroll = true ; } else if ( ! isDeltaPositive && ( ( noOverscroll && availableScrollTop === 0 ) || ( ! noOverscroll && - delta > availableScrollTop ) ) ) { shouldCancelScroll = true ; } return shouldCancelScroll ; } ;