license import { LiveAnnouncer } from '@angular/cdk/a11y' ; import { BreakpointObserver , Breakpoints } from '@angular/cdk/layout' ; import { Overlay , OverlayConfig , OverlayRef } from '@angular/cdk/overlay' ; import { ComponentPortal , ComponentType , PortalInjector , TemplatePortal } from '@angular/cdk/portal' ; import { ComponentRef , EmbeddedViewRef , Inject , Injectable , InjectionToken , Injector , Optional , SkipSelf , TemplateRef , OnDestroy , } from '@angular/core' ; import { take , takeUntil } from 'rxjs/operators' ; import { SimpleSnackBar } from './simple-snack-bar' ; import { MAT_SNACK_BAR_DATA , MatSnackBarConfig } from './snack-bar-config' ; import { MatSnackBarContainer } from './snack-bar-container' ; import { MatSnackBarModule } from './snack-bar-module' ; import { MatSnackBarRef } from './snack-bar-ref' ; /** Injection token that can be used to specify default snack bar. */ export const MAT_SNACK_BAR_DEFAULT_OPTIONS = new InjectionToken < MatSnackBarConfig > ( 'mat-snack-bar-default-options' , { providedIn : 'root' , factory : MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY , } ) ; docs-private export function MAT_SNACK_BAR_DEFAULT_OPTIONS_FACTORY ( ) { return new MatSnackBarConfig ( ) ; } /**
 * Service to dispatch Material Design snack bar messages.
 */ @ Injectable ( { providedIn : MatSnackBarModule } ) export class MatSnackBar implements OnDestroy { /**
     * Reference to the current snack bar in the view *at this level* (in the Angular injector tree).
     * If there is a parent snack-bar service, all operations should delegate to that parent
     * via `_openedSnackBarRef`.
     */ private _snackBarRefAtThisLevel : MatSnackBarRef < any > | null = null ; /** Reference to the currently opened snackbar at *any* level. */ get _openedSnackBarRef ( ) : MatSnackBarRef < any > | null { const parent = this . _parentSnackBar ; return parent ? parent . _openedSnackBarRef : this . _snackBarRefAtThisLevel ; } set _openedSnackBarRef ( value ) { if ( this . _parentSnackBar ) { this . _parentSnackBar . _openedSnackBarRef = value ; } else { this . _snackBarRefAtThisLevel = value ; } } constructor ( private _overlay , private _live , private _injector , private _breakpointObserver , @ Optional ( ) @ SkipSelf ( ) private _parentSnackBar , @ Inject ( MAT_SNACK_BAR_DEFAULT_OPTIONS ) private _defaultConfig ) { } param component param config openFromComponent < T > ( component , config ? ) { return this . _attach ( component , config ) as MatSnackBarRef < T > ; } param template param config openFromTemplate ( template , config ? ) { return this . _attach ( template , config ) ; } param message param action param config open ( message , action = '' , config ? ) { const _config = { ... this . _defaultConfig , ... config } ; _config . data = { message , action } ; if ( ! _config . announcementMessage ) { _config . announcementMessage = message ; } return this . openFromComponent ( SimpleSnackBar , _config ) ; } /**
     * Dismisses the currently-visible snack bar.
     */ dismiss ( ) { if ( this . _openedSnackBarRef ) { this . _openedSnackBarRef . dismiss ( ) ; } } ngOnDestroy ( ) { if ( this . _snackBarRefAtThisLevel ) { this . _snackBarRefAtThisLevel . dismiss ( ) ; } } /**
     * Attaches the snack bar container component to the overlay.
     */ private _attachSnackBarContainer ( overlayRef , config ) { const userInjector = config && config . viewContainerRef && config . viewContainerRef . injector ; const injector = new PortalInjector ( userInjector || this . _injector , new WeakMap ( [ [ MatSnackBarConfig , config ] ] ) ) ; const containerPortal = new ComponentPortal ( MatSnackBarContainer , config . viewContainerRef , injector ) ; const containerRef = overlayRef . attach ( containerPortal ) ; containerRef . instance . snackBarConfig = config ; return containerRef . instance ; } /**
     * Places a new component or a template as the content of the snack bar container.
     */ private _attach < T > ( content , userConfig ? ) { const config = { ... new MatSnackBarConfig ( ) , ... this . _defaultConfig , ... userConfig } ; const overlayRef = this . _createOverlay ( config ) ; const container = this . _attachSnackBarContainer ( overlayRef , config ) ; const snackBarRef = new MatSnackBarRef < T | EmbeddedViewRef < any > > ( container , overlayRef ) ; if ( content instanceof TemplateRef ) { const portal = new TemplatePortal ( content , null ! , { $implicit : config . data , snackBarRef } as any ) ; snackBarRef . instance = container . attachTemplatePortal ( portal ) ; } else { const injector = this . _createInjector ( config , snackBarRef ) ; const portal = new ComponentPortal ( content , undefined , injector ) ; const contentRef = container . attachComponentPortal < T > ( portal ) ; snackBarRef . instance = contentRef . instance ; } this . _breakpointObserver . observe ( Breakpoints . Handset ) . pipe ( takeUntil ( overlayRef . detachments ( ) . pipe ( take ( 1 ) ) ) ) . subscribe ( state => { if ( state . matches ) { overlayRef . overlayElement . classList . add ( 'mat-snack-bar-handset' ) ; } else { overlayRef . overlayElement . classList . remove ( 'mat-snack-bar-handset' ) ; } } ) ; this . _animateSnackBar ( snackBarRef , config ) ; this . _openedSnackBarRef = snackBarRef ; return this . _openedSnackBarRef ; } /** Animates the old snack bar out and the new one in. */ private _animateSnackBar ( snackBarRef , config ) { snackBarRef . afterDismissed ( ) . subscribe ( ( ) => { if ( this . _openedSnackBarRef == snackBarRef ) { this . _openedSnackBarRef = null ; } if ( config . announcementMessage ) { this . _live . clear ( ) ; } } ) ; if ( this . _openedSnackBarRef ) { this . _openedSnackBarRef . afterDismissed ( ) . subscribe ( ( ) => { snackBarRef . containerInstance . enter ( ) ; } ) ; this . _openedSnackBarRef . dismiss ( ) ; } else { snackBarRef . containerInstance . enter ( ) ; } if ( config . duration && config . duration > 0 ) { snackBarRef . afterOpened ( ) . subscribe ( ( ) => snackBarRef . _dismissAfter ( config . duration ! ) ) ; } if ( config . announcementMessage ) { this . _live . announce ( config . announcementMessage , config . politeness ) ; } } param config private _createOverlay ( config ) { const overlayConfig = new OverlayConfig ( ) ; overlayConfig . direction = config . direction ; let positionStrategy = this . _overlay . position ( ) . global ( ) ; const isRtl = config . direction === 'rtl' ; const isLeft = ( config . horizontalPosition === 'left' || ( config . horizontalPosition === 'start' && ! isRtl ) || ( config . horizontalPosition === 'end' && isRtl ) ) ; const isRight = ! isLeft && config . horizontalPosition !== 'center' ; if ( isLeft ) { positionStrategy . left ( '0' ) ; } else if ( isRight ) { positionStrategy . right ( '0' ) ; } else { positionStrategy . centerHorizontally ( ) ; } if ( config . verticalPosition === 'top' ) { positionStrategy . top ( '0' ) ; } else { positionStrategy . bottom ( '0' ) ; } overlayConfig . positionStrategy = positionStrategy ; return this . _overlay . create ( overlayConfig ) ; } param config param snackBarRef private _createInjector < T > ( config , snackBarRef ) { const userInjector = config && config . viewContainerRef && config . viewContainerRef . injector ; return new PortalInjector ( userInjector || this . _injector , new WeakMap < any , any > ( [ [ MatSnackBarRef , snackBarRef ] , [ MAT_SNACK_BAR_DATA , config . data ] ] ) ) ; } }