license import { Directionality } from '@angular/cdk/bidi' ; import { Platform } from '@angular/cdk/platform' ; import { ViewportRuler } from '@angular/cdk/scrolling' ; import { AfterContentChecked , AfterContentInit , Attribute , ChangeDetectionStrategy , ChangeDetectorRef , Component , ContentChildren , Directive , ElementRef , forwardRef , Inject , Input , NgZone , OnDestroy , Optional , QueryList , ViewChild , ViewEncapsulation , } from '@angular/core' ; import { CanColor , CanColorCtor , CanDisable , CanDisableCtor , CanDisableRipple , CanDisableRippleCtor , HasTabIndex , HasTabIndexCtor , MAT_RIPPLE_GLOBAL_OPTIONS , mixinColor , mixinDisabled , mixinDisableRipple , mixinTabIndex , RippleConfig , RippleGlobalOptions , RippleRenderer , RippleTarget , ThemePalette , } from '@angular/material/core' ; import { merge , of as observableOf , Subject } from 'rxjs' ; import { takeUntil } from 'rxjs/operators' ; import { MatInkBar } from '../ink-bar' ; import { FocusMonitor } from '@angular/cdk/a11y' ; docs-private export class MatTabNavBase { constructor ( public _elementRef ) { } } export const _MatTabNavMixinBase = mixinDisableRipple ( mixinColor ( MatTabNavBase , 'primary' ) ) ; /**
 * Navigation component matching the styles of the tab group header.
 * Provides anchored navigation with animated ink bar.
 */ @ Component ( { moduleId : module . id , selector : '[mat-tab-nav-bar]' , exportAs : 'matTabNavBar, matTabNav' , inputs : [ 'color' , 'disableRipple' ] , templateUrl : 'tab-nav-bar.html' , styleUrls : [ 'tab-nav-bar.css' ] , host : { 'class' : 'mat-tab-nav-bar' } , encapsulation : ViewEncapsulation . None , changeDetection : ChangeDetectionStrategy . OnPush , } ) export class MatTabNav extends _MatTabNavMixinBase implements AfterContentChecked , AfterContentInit , CanColor , CanDisableRipple , OnDestroy { /** Subject that emits when the component has been destroyed. */ private readonly _onDestroy = new Subject < void > ( ) ; private _activeLinkChanged : boolean ; private _activeLinkElement : ElementRef < HTMLElement > | null ; @ ViewChild ( MatInkBar ) _inkBar : MatInkBar ; /** Query list of all tab links of the tab navigation. */ @ ContentChildren ( forwardRef ( ( ) => MatTabLink ) , { descendants : true } ) _tabLinks : QueryList < MatTabLink > ; /** Background color of the tab nav. */ @ Input ( ) get backgroundColor ( ) : ThemePalette { return this . _backgroundColor ; } set backgroundColor ( value ) { const nativeElement = this . _elementRef . nativeElement ; nativeElement . classList . remove ( `mat-background-${ this . backgroundColor }` ) ; if ( value ) { nativeElement . classList . add ( `mat-background-${ value }` ) ; } this . _backgroundColor = value ; } private _backgroundColor : ThemePalette ; constructor ( elementRef , @ Optional ( ) private _dir , private _ngZone , private _changeDetectorRef , private _viewportRuler ) { super ( elementRef ) ; } breaking-change updateActiveLink ( element ) { this . _activeLinkChanged = ! ! element ; this . _changeDetectorRef . markForCheck ( ) ; } ngAfterContentInit ( ) { this . _ngZone . runOutsideAngular ( ( ) => { const dirChange = this . _dir ? this . _dir . change : observableOf ( null ) ; return merge ( dirChange , this . _viewportRuler . change ( 10 ) ) . pipe ( takeUntil ( this . _onDestroy ) ) . subscribe ( ( ) => this . _alignInkBar ( ) ) ; } ) ; } /** Checks if the active link has been changed and, if so, will update the ink bar. */ ngAfterContentChecked ( ) { if ( this . _activeLinkChanged ) { const activeTab = this . _tabLinks . find ( tab => tab . active ) ; this . _activeLinkElement = activeTab ? activeTab . _elementRef : null ; this . _alignInkBar ( ) ; this . _activeLinkChanged = false ; } } ngOnDestroy ( ) { this . _onDestroy . next ( ) ; this . _onDestroy . complete ( ) ; } /** Aligns the ink bar to the active link. */ _alignInkBar ( ) { if ( this . _activeLinkElement ) { this . _inkBar . show ( ) ; this . _inkBar . alignToElement ( this . _activeLinkElement . nativeElement ) ; } else { this . _inkBar . hide ( ) ; } } } export class MatTabLinkBase { } export const _MatTabLinkMixinBase = mixinTabIndex ( mixinDisableRipple ( mixinDisabled ( MatTabLinkBase ) ) ) ; /**
 * Link inside of a `mat-tab-nav-bar`.
 */ @ Directive ( { selector : '[mat-tab-link], [matTabLink]' , exportAs : 'matTabLink' , inputs : [ 'disabled' , 'disableRipple' , 'tabIndex' ] , host : { 'class' : 'mat-tab-link' , '[attr.aria-current]' : 'active' , '[attr.aria-disabled]' : 'disabled.toString()' , '[attr.tabIndex]' : 'tabIndex' , '[class.mat-tab-disabled]' : 'disabled' , '[class.mat-tab-label-active]' : 'active' , } } ) export class MatTabLink extends _MatTabLinkMixinBase implements OnDestroy , CanDisable , CanDisableRipple , HasTabIndex , RippleTarget { /** Whether the tab link is active or not. */ protected _isActive : boolean = false ; /** Reference to the RippleRenderer for the tab-link. */ protected _tabLinkRipple : RippleRenderer ; /** Whether the ripples are globally disabled through the RippleGlobalOptions */ private _ripplesGloballyDisabled = false ; /** Whether the link is active. */ @ Input ( ) get active ( ) : boolean { return this . _isActive ; } set active ( value ) { if ( value !== this . _isActive ) { this . _isActive = value ; this . _tabNavBar . updateActiveLink ( this . _elementRef ) ; } } docs-private rippleConfig : RippleConfig = { } ; docs-private get rippleDisabled ( ) : boolean { return this . disabled || this . disableRipple || this . _tabNavBar . disableRipple || this . _ripplesGloballyDisabled ; } constructor ( private _tabNavBar , public _elementRef , ngZone , platform , @ Optional ( ) @ Inject ( MAT_RIPPLE_GLOBAL_OPTIONS ) globalOptions , @ Attribute ( 'tabindex' ) tabIndex , deprecated breaking-change private _focusMonitor ? ) { super ( ) ; this . _tabLinkRipple = new RippleRenderer ( this , ngZone , _elementRef , platform ) ; this . _tabLinkRipple . setupTriggerEvents ( _elementRef . nativeElement ) ; this . tabIndex = parseInt ( tabIndex ) || 0 ; if ( globalOptions ) { this . _ripplesGloballyDisabled = ! ! globalOptions . disabled ; this . rippleConfig = { terminateOnPointerUp : globalOptions . terminateOnPointerUp , animation : globalOptions . animation , } ; } if ( _focusMonitor ) { _focusMonitor . monitor ( _elementRef ) ; } } ngOnDestroy ( ) { this . _tabLinkRipple . _removeTriggerEvents ( ) ; if ( this . _focusMonitor ) { this . _focusMonitor . stopMonitoring ( this . _elementRef ) ; } } }