license import { NgZone } from '@angular/core' ; import { Subscription } from 'rxjs' ; import { ScrollStrategy , getMatScrollStrategyAlreadyAttachedError } from './scroll-strategy' ; import { OverlayReference } from '../overlay-reference' ; import { ScrollDispatcher , ViewportRuler } from '@angular-mdc/web/scrolling' ; import { isElementScrolledOutsideView } from '../position/scroll-clip' ; /**
 * Config options for the RepositionScrollStrategy.
 */ export interface RepositionScrollStrategyConfig { /** Time in milliseconds to throttle the scroll events. */ scrollThrottle ? : number ; /** Whether to close the overlay once the user has scrolled away completely. */ autoClose ? : boolean ; } /**
 * Strategy that will update the element position as the user is scrolling.
 */ export class RepositionScrollStrategy implements ScrollStrategy { private _scrollSubscription : Subscription | null = null ; private _overlayRef : OverlayReference ; constructor ( private _scrollDispatcher , private _viewportRuler , private _ngZone , private _config ? ) { } /** Attaches this scroll strategy to an overlay. */ attach ( overlayRef ) { if ( this . _overlayRef ) { throw getMatScrollStrategyAlreadyAttachedError ( ) ; } this . _overlayRef = overlayRef ; } /** Enables repositioning of the attached overlay on scroll. */ enable ( ) { if ( ! this . _scrollSubscription ) { const throttle = this . _config ? this . _config . scrollThrottle : 0 ; this . _scrollSubscription = this . _scrollDispatcher . scrolled ( throttle ) . subscribe ( ( ) => { this . _overlayRef . updatePosition ( ) ; if ( this . _config && this . _config . autoClose ) { const overlayRect = this . _overlayRef . overlayElement . getBoundingClientRect ( ) ; const { width , height } = this . _viewportRuler . getViewportSize ( ) ; const parentRects = [ { width , height , bottom : height , right : width , top : 0 , left : 0 } ] ; if ( isElementScrolledOutsideView ( overlayRect , parentRects ) ) { this . disable ( ) ; this . _ngZone . run ( ( ) => this . _overlayRef . detach ( ) ) ; } } } ) ; } } /** Disables repositioning of the attached overlay on scroll. */ disable ( ) { if ( this . _scrollSubscription ) { this . _scrollSubscription . unsubscribe ( ) ; this . _scrollSubscription = null ; } } detach ( ) { this . disable ( ) ; this . _overlayRef = null ! ; } }