tabs.mjs 169 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128
  1. import * as i1$2 from '@angular/common';
  2. import { DOCUMENT, CommonModule } from '@angular/common';
  3. import * as i0 from '@angular/core';
  4. import { forwardRef, Directive, Inject, EventEmitter, Optional, Output, Input, Component, ViewEncapsulation, ChangeDetectionStrategy, ViewChild, InjectionToken, TemplateRef, ContentChild, ContentChildren, QueryList, Attribute, NgModule } from '@angular/core';
  5. import * as i5 from '@angular/material/core';
  6. import { mixinDisabled, mixinColor, mixinDisableRipple, mixinTabIndex, MAT_RIPPLE_GLOBAL_OPTIONS, MatCommonModule, MatRippleModule } from '@angular/material/core';
  7. import * as i2 from '@angular/cdk/portal';
  8. import { CdkPortalOutlet, CdkPortal, TemplatePortal, PortalModule } from '@angular/cdk/portal';
  9. import * as i5$1 from '@angular/cdk/observers';
  10. import { ObserversModule } from '@angular/cdk/observers';
  11. import * as i4 from '@angular/cdk/a11y';
  12. import { FocusKeyManager, A11yModule } from '@angular/cdk/a11y';
  13. import * as i1 from '@angular/cdk/bidi';
  14. import { Subscription, Subject, fromEvent, of, merge, EMPTY, Observable, timer, BehaviorSubject } from 'rxjs';
  15. import { startWith, distinctUntilChanged, takeUntil, take, switchMap, skip, filter } from 'rxjs/operators';
  16. import { trigger, state, style, transition, animate } from '@angular/animations';
  17. import { coerceBooleanProperty, coerceNumberProperty } from '@angular/cdk/coercion';
  18. import * as i1$1 from '@angular/cdk/scrolling';
  19. import * as i3 from '@angular/cdk/platform';
  20. import { normalizePassiveListenerOptions } from '@angular/cdk/platform';
  21. import { ANIMATION_MODULE_TYPE } from '@angular/platform-browser/animations';
  22. import { hasModifierKey, SPACE, ENTER } from '@angular/cdk/keycodes';
  23. /**
  24. * Animations used by the Material tabs.
  25. * @docs-private
  26. */
  27. const matTabsAnimations = {
  28. /** Animation translates a tab along the X axis. */
  29. translateTab: trigger('translateTab', [
  30. // Transitions to `none` instead of 0, because some browsers might blur the content.
  31. state('center, void, left-origin-center, right-origin-center', style({ transform: 'none' })),
  32. // If the tab is either on the left or right, we additionally add a `min-height` of 1px
  33. // in order to ensure that the element has a height before its state changes. This is
  34. // necessary because Chrome does seem to skip the transition in RTL mode if the element does
  35. // not have a static height and is not rendered. See related issue: #9465
  36. state('left', style({
  37. transform: 'translate3d(-100%, 0, 0)',
  38. minHeight: '1px',
  39. // Normally this is redundant since we detach the content from the DOM, but if the user
  40. // opted into keeping the content in the DOM, we have to hide it so it isn't focusable.
  41. visibility: 'hidden',
  42. })),
  43. state('right', style({
  44. transform: 'translate3d(100%, 0, 0)',
  45. minHeight: '1px',
  46. visibility: 'hidden',
  47. })),
  48. transition('* => left, * => right, left => center, right => center', animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)')),
  49. transition('void => left-origin-center', [
  50. style({ transform: 'translate3d(-100%, 0, 0)', visibility: 'hidden' }),
  51. animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),
  52. ]),
  53. transition('void => right-origin-center', [
  54. style({ transform: 'translate3d(100%, 0, 0)', visibility: 'hidden' }),
  55. animate('{{animationDuration}} cubic-bezier(0.35, 0, 0.25, 1)'),
  56. ]),
  57. ]),
  58. };
  59. /**
  60. * The portal host directive for the contents of the tab.
  61. * @docs-private
  62. */
  63. class MatTabBodyPortal extends CdkPortalOutlet {
  64. constructor(componentFactoryResolver, viewContainerRef, _host, _document) {
  65. super(componentFactoryResolver, viewContainerRef, _document);
  66. this._host = _host;
  67. /** Subscription to events for when the tab body begins centering. */
  68. this._centeringSub = Subscription.EMPTY;
  69. /** Subscription to events for when the tab body finishes leaving from center position. */
  70. this._leavingSub = Subscription.EMPTY;
  71. }
  72. /** Set initial visibility or set up subscription for changing visibility. */
  73. ngOnInit() {
  74. super.ngOnInit();
  75. this._centeringSub = this._host._beforeCentering
  76. .pipe(startWith(this._host._isCenterPosition(this._host._position)))
  77. .subscribe((isCentering) => {
  78. if (isCentering && !this.hasAttached()) {
  79. this.attach(this._host._content);
  80. }
  81. });
  82. this._leavingSub = this._host._afterLeavingCenter.subscribe(() => {
  83. if (!this._host.preserveContent) {
  84. this.detach();
  85. }
  86. });
  87. }
  88. /** Clean up centering subscription. */
  89. ngOnDestroy() {
  90. super.ngOnDestroy();
  91. this._centeringSub.unsubscribe();
  92. this._leavingSub.unsubscribe();
  93. }
  94. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabBodyPortal, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ViewContainerRef }, { token: forwardRef(() => MatTabBody) }, { token: DOCUMENT }], target: i0.ɵɵFactoryTarget.Directive }); }
  95. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatTabBodyPortal, selector: "[matTabBodyHost]", usesInheritance: true, ngImport: i0 }); }
  96. }
  97. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabBodyPortal, decorators: [{
  98. type: Directive,
  99. args: [{
  100. selector: '[matTabBodyHost]',
  101. }]
  102. }], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ViewContainerRef }, { type: MatTabBody, decorators: [{
  103. type: Inject,
  104. args: [forwardRef(() => MatTabBody)]
  105. }] }, { type: undefined, decorators: [{
  106. type: Inject,
  107. args: [DOCUMENT]
  108. }] }]; } });
  109. /**
  110. * Base class with all of the `MatTabBody` functionality.
  111. * @docs-private
  112. */
  113. class _MatTabBodyBase {
  114. /** The shifted index position of the tab body, where zero represents the active center tab. */
  115. set position(position) {
  116. this._positionIndex = position;
  117. this._computePositionAnimationState();
  118. }
  119. constructor(_elementRef, _dir, changeDetectorRef) {
  120. this._elementRef = _elementRef;
  121. this._dir = _dir;
  122. /** Subscription to the directionality change observable. */
  123. this._dirChangeSubscription = Subscription.EMPTY;
  124. /** Emits when an animation on the tab is complete. */
  125. this._translateTabComplete = new Subject();
  126. /** Event emitted when the tab begins to animate towards the center as the active tab. */
  127. this._onCentering = new EventEmitter();
  128. /** Event emitted before the centering of the tab begins. */
  129. this._beforeCentering = new EventEmitter();
  130. /** Event emitted before the centering of the tab begins. */
  131. this._afterLeavingCenter = new EventEmitter();
  132. /** Event emitted when the tab completes its animation towards the center. */
  133. this._onCentered = new EventEmitter(true);
  134. // Note that the default value will always be overwritten by `MatTabBody`, but we need one
  135. // anyway to prevent the animations module from throwing an error if the body is used on its own.
  136. /** Duration for the tab's animation. */
  137. this.animationDuration = '500ms';
  138. /** Whether the tab's content should be kept in the DOM while it's off-screen. */
  139. this.preserveContent = false;
  140. if (_dir) {
  141. this._dirChangeSubscription = _dir.change.subscribe((dir) => {
  142. this._computePositionAnimationState(dir);
  143. changeDetectorRef.markForCheck();
  144. });
  145. }
  146. // Ensure that we get unique animation events, because the `.done` callback can get
  147. // invoked twice in some browsers. See https://github.com/angular/angular/issues/24084.
  148. this._translateTabComplete
  149. .pipe(distinctUntilChanged((x, y) => {
  150. return x.fromState === y.fromState && x.toState === y.toState;
  151. }))
  152. .subscribe(event => {
  153. // If the transition to the center is complete, emit an event.
  154. if (this._isCenterPosition(event.toState) && this._isCenterPosition(this._position)) {
  155. this._onCentered.emit();
  156. }
  157. if (this._isCenterPosition(event.fromState) && !this._isCenterPosition(this._position)) {
  158. this._afterLeavingCenter.emit();
  159. }
  160. });
  161. }
  162. /**
  163. * After initialized, check if the content is centered and has an origin. If so, set the
  164. * special position states that transition the tab from the left or right before centering.
  165. */
  166. ngOnInit() {
  167. if (this._position == 'center' && this.origin != null) {
  168. this._position = this._computePositionFromOrigin(this.origin);
  169. }
  170. }
  171. ngOnDestroy() {
  172. this._dirChangeSubscription.unsubscribe();
  173. this._translateTabComplete.complete();
  174. }
  175. _onTranslateTabStarted(event) {
  176. const isCentering = this._isCenterPosition(event.toState);
  177. this._beforeCentering.emit(isCentering);
  178. if (isCentering) {
  179. this._onCentering.emit(this._elementRef.nativeElement.clientHeight);
  180. }
  181. }
  182. /** The text direction of the containing app. */
  183. _getLayoutDirection() {
  184. return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';
  185. }
  186. /** Whether the provided position state is considered center, regardless of origin. */
  187. _isCenterPosition(position) {
  188. return (position == 'center' || position == 'left-origin-center' || position == 'right-origin-center');
  189. }
  190. /** Computes the position state that will be used for the tab-body animation trigger. */
  191. _computePositionAnimationState(dir = this._getLayoutDirection()) {
  192. if (this._positionIndex < 0) {
  193. this._position = dir == 'ltr' ? 'left' : 'right';
  194. }
  195. else if (this._positionIndex > 0) {
  196. this._position = dir == 'ltr' ? 'right' : 'left';
  197. }
  198. else {
  199. this._position = 'center';
  200. }
  201. }
  202. /**
  203. * Computes the position state based on the specified origin position. This is used if the
  204. * tab is becoming visible immediately after creation.
  205. */
  206. _computePositionFromOrigin(origin) {
  207. const dir = this._getLayoutDirection();
  208. if ((dir == 'ltr' && origin <= 0) || (dir == 'rtl' && origin > 0)) {
  209. return 'left-origin-center';
  210. }
  211. return 'right-origin-center';
  212. }
  213. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabBodyBase, deps: [{ token: i0.ElementRef }, { token: i1.Directionality, optional: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Directive }); }
  214. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabBodyBase, inputs: { _content: ["content", "_content"], origin: "origin", animationDuration: "animationDuration", preserveContent: "preserveContent", position: "position" }, outputs: { _onCentering: "_onCentering", _beforeCentering: "_beforeCentering", _afterLeavingCenter: "_afterLeavingCenter", _onCentered: "_onCentered" }, ngImport: i0 }); }
  215. }
  216. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabBodyBase, decorators: [{
  217. type: Directive
  218. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.Directionality, decorators: [{
  219. type: Optional
  220. }] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { _onCentering: [{
  221. type: Output
  222. }], _beforeCentering: [{
  223. type: Output
  224. }], _afterLeavingCenter: [{
  225. type: Output
  226. }], _onCentered: [{
  227. type: Output
  228. }], _content: [{
  229. type: Input,
  230. args: ['content']
  231. }], origin: [{
  232. type: Input
  233. }], animationDuration: [{
  234. type: Input
  235. }], preserveContent: [{
  236. type: Input
  237. }], position: [{
  238. type: Input
  239. }] } });
  240. /**
  241. * Wrapper for the contents of a tab.
  242. * @docs-private
  243. */
  244. class MatTabBody extends _MatTabBodyBase {
  245. constructor(elementRef, dir, changeDetectorRef) {
  246. super(elementRef, dir, changeDetectorRef);
  247. }
  248. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabBody, deps: [{ token: i0.ElementRef }, { token: i1.Directionality, optional: true }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
  249. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTabBody, selector: "mat-tab-body", host: { classAttribute: "mat-mdc-tab-body" }, viewQueries: [{ propertyName: "_portalHost", first: true, predicate: CdkPortalOutlet, descendants: true }], usesInheritance: true, ngImport: i0, template: "<div class=\"mat-mdc-tab-body-content\" #content\n [@translateTab]=\"{\n value: _position,\n params: {animationDuration: animationDuration}\n }\"\n (@translateTab.start)=\"_onTranslateTabStarted($event)\"\n (@translateTab.done)=\"_translateTabComplete.next($event)\"\n cdkScrollable>\n <ng-template matTabBodyHost></ng-template>\n</div>\n", styles: [".mat-mdc-tab-body{top:0;left:0;right:0;bottom:0;position:absolute;display:block;overflow:hidden;outline:0;flex-basis:100%}.mat-mdc-tab-body.mat-mdc-tab-body-active{position:relative;overflow-x:hidden;overflow-y:auto;z-index:1;flex-grow:1}.mat-mdc-tab-group.mat-mdc-tab-group-dynamic-height .mat-mdc-tab-body.mat-mdc-tab-body-active{overflow-y:hidden}.mat-mdc-tab-body-content{height:100%;overflow:auto}.mat-mdc-tab-group-dynamic-height .mat-mdc-tab-body-content{overflow:hidden}.mat-mdc-tab-body-content[style*=\"visibility: hidden\"]{display:none}"], dependencies: [{ kind: "directive", type: MatTabBodyPortal, selector: "[matTabBodyHost]" }], animations: [matTabsAnimations.translateTab], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
  250. }
  251. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabBody, decorators: [{
  252. type: Component,
  253. args: [{ selector: 'mat-tab-body', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, animations: [matTabsAnimations.translateTab], host: {
  254. 'class': 'mat-mdc-tab-body',
  255. }, template: "<div class=\"mat-mdc-tab-body-content\" #content\n [@translateTab]=\"{\n value: _position,\n params: {animationDuration: animationDuration}\n }\"\n (@translateTab.start)=\"_onTranslateTabStarted($event)\"\n (@translateTab.done)=\"_translateTabComplete.next($event)\"\n cdkScrollable>\n <ng-template matTabBodyHost></ng-template>\n</div>\n", styles: [".mat-mdc-tab-body{top:0;left:0;right:0;bottom:0;position:absolute;display:block;overflow:hidden;outline:0;flex-basis:100%}.mat-mdc-tab-body.mat-mdc-tab-body-active{position:relative;overflow-x:hidden;overflow-y:auto;z-index:1;flex-grow:1}.mat-mdc-tab-group.mat-mdc-tab-group-dynamic-height .mat-mdc-tab-body.mat-mdc-tab-body-active{overflow-y:hidden}.mat-mdc-tab-body-content{height:100%;overflow:auto}.mat-mdc-tab-group-dynamic-height .mat-mdc-tab-body-content{overflow:hidden}.mat-mdc-tab-body-content[style*=\"visibility: hidden\"]{display:none}"] }]
  256. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.Directionality, decorators: [{
  257. type: Optional
  258. }] }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { _portalHost: [{
  259. type: ViewChild,
  260. args: [CdkPortalOutlet]
  261. }] } });
  262. /**
  263. * Injection token that can be used to reference instances of `MatTabContent`. It serves as
  264. * alternative token to the actual `MatTabContent` class which could cause unnecessary
  265. * retention of the class and its directive metadata.
  266. */
  267. const MAT_TAB_CONTENT = new InjectionToken('MatTabContent');
  268. /** Decorates the `ng-template` tags and reads out the template from it. */
  269. class MatTabContent {
  270. constructor(/** Content for the tab. */ template) {
  271. this.template = template;
  272. }
  273. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabContent, deps: [{ token: i0.TemplateRef }], target: i0.ɵɵFactoryTarget.Directive }); }
  274. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatTabContent, selector: "[matTabContent]", providers: [{ provide: MAT_TAB_CONTENT, useExisting: MatTabContent }], ngImport: i0 }); }
  275. }
  276. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabContent, decorators: [{
  277. type: Directive,
  278. args: [{
  279. selector: '[matTabContent]',
  280. providers: [{ provide: MAT_TAB_CONTENT, useExisting: MatTabContent }],
  281. }]
  282. }], ctorParameters: function () { return [{ type: i0.TemplateRef }]; } });
  283. /**
  284. * Injection token that can be used to reference instances of `MatTabLabel`. It serves as
  285. * alternative token to the actual `MatTabLabel` class which could cause unnecessary
  286. * retention of the class and its directive metadata.
  287. */
  288. const MAT_TAB_LABEL = new InjectionToken('MatTabLabel');
  289. /**
  290. * Used to provide a tab label to a tab without causing a circular dependency.
  291. * @docs-private
  292. */
  293. const MAT_TAB = new InjectionToken('MAT_TAB');
  294. /** Used to flag tab labels for use with the portal directive */
  295. class MatTabLabel extends CdkPortal {
  296. constructor(templateRef, viewContainerRef, _closestTab) {
  297. super(templateRef, viewContainerRef);
  298. this._closestTab = _closestTab;
  299. }
  300. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabLabel, deps: [{ token: i0.TemplateRef }, { token: i0.ViewContainerRef }, { token: MAT_TAB, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  301. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatTabLabel, selector: "[mat-tab-label], [matTabLabel]", providers: [{ provide: MAT_TAB_LABEL, useExisting: MatTabLabel }], usesInheritance: true, ngImport: i0 }); }
  302. }
  303. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabLabel, decorators: [{
  304. type: Directive,
  305. args: [{
  306. selector: '[mat-tab-label], [matTabLabel]',
  307. providers: [{ provide: MAT_TAB_LABEL, useExisting: MatTabLabel }],
  308. }]
  309. }], ctorParameters: function () { return [{ type: i0.TemplateRef }, { type: i0.ViewContainerRef }, { type: undefined, decorators: [{
  310. type: Inject,
  311. args: [MAT_TAB]
  312. }, {
  313. type: Optional
  314. }] }]; } });
  315. /** Class that is applied when a tab indicator is active. */
  316. const ACTIVE_CLASS = 'mdc-tab-indicator--active';
  317. /** Class that is applied when the tab indicator should not transition. */
  318. const NO_TRANSITION_CLASS = 'mdc-tab-indicator--no-transition';
  319. /**
  320. * Abstraction around the MDC tab indicator that acts as the tab header's ink bar.
  321. * @docs-private
  322. */
  323. class MatInkBar {
  324. constructor(_items) {
  325. this._items = _items;
  326. }
  327. /** Hides the ink bar. */
  328. hide() {
  329. this._items.forEach(item => item.deactivateInkBar());
  330. }
  331. /** Aligns the ink bar to a DOM node. */
  332. alignToElement(element) {
  333. const correspondingItem = this._items.find(item => item.elementRef.nativeElement === element);
  334. const currentItem = this._currentItem;
  335. if (correspondingItem === currentItem) {
  336. return;
  337. }
  338. currentItem?.deactivateInkBar();
  339. if (correspondingItem) {
  340. const clientRect = currentItem?.elementRef.nativeElement.getBoundingClientRect?.();
  341. // The ink bar won't animate unless we give it the `ClientRect` of the previous item.
  342. correspondingItem.activateInkBar(clientRect);
  343. this._currentItem = correspondingItem;
  344. }
  345. }
  346. }
  347. /**
  348. * Mixin that can be used to apply the `MatInkBarItem` behavior to a class.
  349. * Base on MDC's `MDCSlidingTabIndicatorFoundation`:
  350. * https://github.com/material-components/material-components-web/blob/c0a11ef0d000a098fd0c372be8f12d6a99302855/packages/mdc-tab-indicator/sliding-foundation.ts
  351. * @docs-private
  352. */
  353. function mixinInkBarItem(base) {
  354. return class extends base {
  355. constructor(...args) {
  356. super(...args);
  357. this._fitToContent = false;
  358. }
  359. /** Whether the ink bar should fit to the entire tab or just its content. */
  360. get fitInkBarToContent() {
  361. return this._fitToContent;
  362. }
  363. set fitInkBarToContent(v) {
  364. const newValue = coerceBooleanProperty(v);
  365. if (this._fitToContent !== newValue) {
  366. this._fitToContent = newValue;
  367. if (this._inkBarElement) {
  368. this._appendInkBarElement();
  369. }
  370. }
  371. }
  372. /** Aligns the ink bar to the current item. */
  373. activateInkBar(previousIndicatorClientRect) {
  374. const element = this.elementRef.nativeElement;
  375. // Early exit if no indicator is present to handle cases where an indicator
  376. // may be activated without a prior indicator state
  377. if (!previousIndicatorClientRect ||
  378. !element.getBoundingClientRect ||
  379. !this._inkBarContentElement) {
  380. element.classList.add(ACTIVE_CLASS);
  381. return;
  382. }
  383. // This animation uses the FLIP approach. You can read more about it at the link below:
  384. // https://aerotwist.com/blog/flip-your-animations/
  385. // Calculate the dimensions based on the dimensions of the previous indicator
  386. const currentClientRect = element.getBoundingClientRect();
  387. const widthDelta = previousIndicatorClientRect.width / currentClientRect.width;
  388. const xPosition = previousIndicatorClientRect.left - currentClientRect.left;
  389. element.classList.add(NO_TRANSITION_CLASS);
  390. this._inkBarContentElement.style.setProperty('transform', `translateX(${xPosition}px) scaleX(${widthDelta})`);
  391. // Force repaint before updating classes and transform to ensure the transform properly takes effect
  392. element.getBoundingClientRect();
  393. element.classList.remove(NO_TRANSITION_CLASS);
  394. element.classList.add(ACTIVE_CLASS);
  395. this._inkBarContentElement.style.setProperty('transform', '');
  396. }
  397. /** Removes the ink bar from the current item. */
  398. deactivateInkBar() {
  399. this.elementRef.nativeElement.classList.remove(ACTIVE_CLASS);
  400. }
  401. /** Initializes the foundation. */
  402. ngOnInit() {
  403. this._createInkBarElement();
  404. }
  405. /** Destroys the foundation. */
  406. ngOnDestroy() {
  407. this._inkBarElement?.remove();
  408. this._inkBarElement = this._inkBarContentElement = null;
  409. }
  410. /** Creates and appends the ink bar element. */
  411. _createInkBarElement() {
  412. const documentNode = this.elementRef.nativeElement.ownerDocument || document;
  413. this._inkBarElement = documentNode.createElement('span');
  414. this._inkBarContentElement = documentNode.createElement('span');
  415. this._inkBarElement.className = 'mdc-tab-indicator';
  416. this._inkBarContentElement.className =
  417. 'mdc-tab-indicator__content mdc-tab-indicator__content--underline';
  418. this._inkBarElement.appendChild(this._inkBarContentElement);
  419. this._appendInkBarElement();
  420. }
  421. /**
  422. * Appends the ink bar to the tab host element or content, depending on whether
  423. * the ink bar should fit to content.
  424. */
  425. _appendInkBarElement() {
  426. if (!this._inkBarElement && (typeof ngDevMode === 'undefined' || ngDevMode)) {
  427. throw Error('Ink bar element has not been created and cannot be appended');
  428. }
  429. const parentElement = this._fitToContent
  430. ? this.elementRef.nativeElement.querySelector('.mdc-tab__content')
  431. : this.elementRef.nativeElement;
  432. if (!parentElement && (typeof ngDevMode === 'undefined' || ngDevMode)) {
  433. throw Error('Missing element to host the ink bar');
  434. }
  435. parentElement.appendChild(this._inkBarElement);
  436. }
  437. };
  438. }
  439. /**
  440. * The default positioner function for the MatInkBar.
  441. * @docs-private
  442. */
  443. function _MAT_INK_BAR_POSITIONER_FACTORY() {
  444. const method = (element) => ({
  445. left: element ? (element.offsetLeft || 0) + 'px' : '0',
  446. width: element ? (element.offsetWidth || 0) + 'px' : '0',
  447. });
  448. return method;
  449. }
  450. /** Injection token for the MatInkBar's Positioner. */
  451. const _MAT_INK_BAR_POSITIONER = new InjectionToken('MatInkBarPositioner', {
  452. providedIn: 'root',
  453. factory: _MAT_INK_BAR_POSITIONER_FACTORY,
  454. });
  455. // Boilerplate for applying mixins to MatTabLabelWrapper.
  456. /** @docs-private */
  457. const _MatTabLabelWrapperMixinBase = mixinDisabled(class {
  458. });
  459. /**
  460. * Used in the `mat-tab-group` view to display tab labels.
  461. * @docs-private
  462. */
  463. class _MatTabLabelWrapperBase extends _MatTabLabelWrapperMixinBase {
  464. constructor(elementRef) {
  465. super();
  466. this.elementRef = elementRef;
  467. }
  468. /** Sets focus on the wrapper element */
  469. focus() {
  470. this.elementRef.nativeElement.focus();
  471. }
  472. getOffsetLeft() {
  473. return this.elementRef.nativeElement.offsetLeft;
  474. }
  475. getOffsetWidth() {
  476. return this.elementRef.nativeElement.offsetWidth;
  477. }
  478. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabLabelWrapperBase, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Directive }); }
  479. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabLabelWrapperBase, usesInheritance: true, ngImport: i0 }); }
  480. }
  481. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabLabelWrapperBase, decorators: [{
  482. type: Directive
  483. }], ctorParameters: function () { return [{ type: i0.ElementRef }]; } });
  484. const _MatTabLabelWrapperBaseWithInkBarItem = mixinInkBarItem(_MatTabLabelWrapperBase);
  485. /**
  486. * Used in the `mat-tab-group` view to display tab labels.
  487. * @docs-private
  488. */
  489. class MatTabLabelWrapper extends _MatTabLabelWrapperBaseWithInkBarItem {
  490. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabLabelWrapper, deps: null, target: i0.ɵɵFactoryTarget.Directive }); }
  491. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatTabLabelWrapper, selector: "[matTabLabelWrapper]", inputs: { disabled: "disabled", fitInkBarToContent: "fitInkBarToContent" }, host: { properties: { "class.mat-mdc-tab-disabled": "disabled", "attr.aria-disabled": "!!disabled" } }, usesInheritance: true, ngImport: i0 }); }
  492. }
  493. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabLabelWrapper, decorators: [{
  494. type: Directive,
  495. args: [{
  496. selector: '[matTabLabelWrapper]',
  497. inputs: ['disabled', 'fitInkBarToContent'],
  498. host: {
  499. '[class.mat-mdc-tab-disabled]': 'disabled',
  500. '[attr.aria-disabled]': '!!disabled',
  501. },
  502. }]
  503. }] });
  504. // Boilerplate for applying mixins to MatTab.
  505. /** @docs-private */
  506. const _MatTabMixinBase = mixinDisabled(class {
  507. });
  508. /**
  509. * Used to provide a tab group to a tab without causing a circular dependency.
  510. * @docs-private
  511. */
  512. const MAT_TAB_GROUP = new InjectionToken('MAT_TAB_GROUP');
  513. /** @docs-private */
  514. class _MatTabBase extends _MatTabMixinBase {
  515. /** @docs-private */
  516. get content() {
  517. return this._contentPortal;
  518. }
  519. constructor(_viewContainerRef, _closestTabGroup) {
  520. super();
  521. this._viewContainerRef = _viewContainerRef;
  522. this._closestTabGroup = _closestTabGroup;
  523. /** Plain text label for the tab, used when there is no template label. */
  524. this.textLabel = '';
  525. /** Portal that will be the hosted content of the tab */
  526. this._contentPortal = null;
  527. /** Emits whenever the internal state of the tab changes. */
  528. this._stateChanges = new Subject();
  529. /**
  530. * The relatively indexed position where 0 represents the center, negative is left, and positive
  531. * represents the right.
  532. */
  533. this.position = null;
  534. /**
  535. * The initial relatively index origin of the tab if it was created and selected after there
  536. * was already a selected tab. Provides context of what position the tab should originate from.
  537. */
  538. this.origin = null;
  539. /**
  540. * Whether the tab is currently active.
  541. */
  542. this.isActive = false;
  543. }
  544. ngOnChanges(changes) {
  545. if (changes.hasOwnProperty('textLabel') || changes.hasOwnProperty('disabled')) {
  546. this._stateChanges.next();
  547. }
  548. }
  549. ngOnDestroy() {
  550. this._stateChanges.complete();
  551. }
  552. ngOnInit() {
  553. this._contentPortal = new TemplatePortal(this._explicitContent || this._implicitContent, this._viewContainerRef);
  554. }
  555. /**
  556. * This has been extracted to a util because of TS 4 and VE.
  557. * View Engine doesn't support property rename inheritance.
  558. * TS 4.0 doesn't allow properties to override accessors or vice-versa.
  559. * @docs-private
  560. */
  561. _setTemplateLabelInput(value) {
  562. // Only update the label if the query managed to find one. This works around an issue where a
  563. // user may have manually set `templateLabel` during creation mode, which would then get
  564. // clobbered by `undefined` when the query resolves. Also note that we check that the closest
  565. // tab matches the current one so that we don't pick up labels from nested tabs.
  566. if (value && value._closestTab === this) {
  567. this._templateLabel = value;
  568. }
  569. }
  570. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabBase, deps: [{ token: i0.ViewContainerRef }, { token: MAT_TAB_GROUP, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  571. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabBase, inputs: { textLabel: ["label", "textLabel"], ariaLabel: ["aria-label", "ariaLabel"], ariaLabelledby: ["aria-labelledby", "ariaLabelledby"], labelClass: "labelClass", bodyClass: "bodyClass" }, viewQueries: [{ propertyName: "_implicitContent", first: true, predicate: TemplateRef, descendants: true, static: true }], usesInheritance: true, usesOnChanges: true, ngImport: i0 }); }
  572. }
  573. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabBase, decorators: [{
  574. type: Directive
  575. }], ctorParameters: function () { return [{ type: i0.ViewContainerRef }, { type: undefined, decorators: [{
  576. type: Inject,
  577. args: [MAT_TAB_GROUP]
  578. }, {
  579. type: Optional
  580. }] }]; }, propDecorators: { _implicitContent: [{
  581. type: ViewChild,
  582. args: [TemplateRef, { static: true }]
  583. }], textLabel: [{
  584. type: Input,
  585. args: ['label']
  586. }], ariaLabel: [{
  587. type: Input,
  588. args: ['aria-label']
  589. }], ariaLabelledby: [{
  590. type: Input,
  591. args: ['aria-labelledby']
  592. }], labelClass: [{
  593. type: Input
  594. }], bodyClass: [{
  595. type: Input
  596. }] } });
  597. class MatTab extends _MatTabBase {
  598. constructor() {
  599. super(...arguments);
  600. /**
  601. * Template provided in the tab content that will be used if present, used to enable lazy-loading
  602. */
  603. this._explicitContent = undefined;
  604. }
  605. /** Content for the tab label given by `<ng-template mat-tab-label>`. */
  606. get templateLabel() {
  607. return this._templateLabel;
  608. }
  609. set templateLabel(value) {
  610. this._setTemplateLabelInput(value);
  611. }
  612. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTab, deps: null, target: i0.ɵɵFactoryTarget.Component }); }
  613. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTab, selector: "mat-tab", inputs: { disabled: "disabled" }, providers: [{ provide: MAT_TAB, useExisting: MatTab }], queries: [{ propertyName: "_explicitContent", first: true, predicate: MatTabContent, descendants: true, read: TemplateRef, static: true }, { propertyName: "templateLabel", first: true, predicate: MatTabLabel, descendants: true }], exportAs: ["matTab"], usesInheritance: true, ngImport: i0, template: "<!-- Create a template for the content of the <mat-tab> so that we can grab a reference to this\n TemplateRef and use it in a Portal to render the tab content in the appropriate place in the\n tab-group. -->\n<ng-template><ng-content></ng-content></ng-template>\n", changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
  614. }
  615. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTab, decorators: [{
  616. type: Component,
  617. args: [{ selector: 'mat-tab', inputs: ['disabled'], changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.None, exportAs: 'matTab', providers: [{ provide: MAT_TAB, useExisting: MatTab }], template: "<!-- Create a template for the content of the <mat-tab> so that we can grab a reference to this\n TemplateRef and use it in a Portal to render the tab content in the appropriate place in the\n tab-group. -->\n<ng-template><ng-content></ng-content></ng-template>\n" }]
  618. }], propDecorators: { _explicitContent: [{
  619. type: ContentChild,
  620. args: [MatTabContent, { read: TemplateRef, static: true }]
  621. }], templateLabel: [{
  622. type: ContentChild,
  623. args: [MatTabLabel]
  624. }] } });
  625. /** Config used to bind passive event listeners */
  626. const passiveEventListenerOptions = normalizePassiveListenerOptions({
  627. passive: true,
  628. });
  629. /**
  630. * Amount of milliseconds to wait before starting to scroll the header automatically.
  631. * Set a little conservatively in order to handle fake events dispatched on touch devices.
  632. */
  633. const HEADER_SCROLL_DELAY = 650;
  634. /**
  635. * Interval in milliseconds at which to scroll the header
  636. * while the user is holding their pointer.
  637. */
  638. const HEADER_SCROLL_INTERVAL = 100;
  639. /**
  640. * Base class for a tab header that supported pagination.
  641. * @docs-private
  642. */
  643. class MatPaginatedTabHeader {
  644. /**
  645. * Whether pagination should be disabled. This can be used to avoid unnecessary
  646. * layout recalculations if it's known that pagination won't be required.
  647. */
  648. get disablePagination() {
  649. return this._disablePagination;
  650. }
  651. set disablePagination(value) {
  652. this._disablePagination = coerceBooleanProperty(value);
  653. }
  654. /** The index of the active tab. */
  655. get selectedIndex() {
  656. return this._selectedIndex;
  657. }
  658. set selectedIndex(value) {
  659. value = coerceNumberProperty(value);
  660. if (this._selectedIndex != value) {
  661. this._selectedIndexChanged = true;
  662. this._selectedIndex = value;
  663. if (this._keyManager) {
  664. this._keyManager.updateActiveItem(value);
  665. }
  666. }
  667. }
  668. constructor(_elementRef, _changeDetectorRef, _viewportRuler, _dir, _ngZone, _platform, _animationMode) {
  669. this._elementRef = _elementRef;
  670. this._changeDetectorRef = _changeDetectorRef;
  671. this._viewportRuler = _viewportRuler;
  672. this._dir = _dir;
  673. this._ngZone = _ngZone;
  674. this._platform = _platform;
  675. this._animationMode = _animationMode;
  676. /** The distance in pixels that the tab labels should be translated to the left. */
  677. this._scrollDistance = 0;
  678. /** Whether the header should scroll to the selected index after the view has been checked. */
  679. this._selectedIndexChanged = false;
  680. /** Emits when the component is destroyed. */
  681. this._destroyed = new Subject();
  682. /** Whether the controls for pagination should be displayed */
  683. this._showPaginationControls = false;
  684. /** Whether the tab list can be scrolled more towards the end of the tab label list. */
  685. this._disableScrollAfter = true;
  686. /** Whether the tab list can be scrolled more towards the beginning of the tab label list. */
  687. this._disableScrollBefore = true;
  688. /** Stream that will stop the automated scrolling. */
  689. this._stopScrolling = new Subject();
  690. this._disablePagination = false;
  691. this._selectedIndex = 0;
  692. /** Event emitted when the option is selected. */
  693. this.selectFocusedIndex = new EventEmitter();
  694. /** Event emitted when a label is focused. */
  695. this.indexFocused = new EventEmitter();
  696. // Bind the `mouseleave` event on the outside since it doesn't change anything in the view.
  697. _ngZone.runOutsideAngular(() => {
  698. fromEvent(_elementRef.nativeElement, 'mouseleave')
  699. .pipe(takeUntil(this._destroyed))
  700. .subscribe(() => {
  701. this._stopInterval();
  702. });
  703. });
  704. }
  705. ngAfterViewInit() {
  706. // We need to handle these events manually, because we want to bind passive event listeners.
  707. fromEvent(this._previousPaginator.nativeElement, 'touchstart', passiveEventListenerOptions)
  708. .pipe(takeUntil(this._destroyed))
  709. .subscribe(() => {
  710. this._handlePaginatorPress('before');
  711. });
  712. fromEvent(this._nextPaginator.nativeElement, 'touchstart', passiveEventListenerOptions)
  713. .pipe(takeUntil(this._destroyed))
  714. .subscribe(() => {
  715. this._handlePaginatorPress('after');
  716. });
  717. }
  718. ngAfterContentInit() {
  719. const dirChange = this._dir ? this._dir.change : of('ltr');
  720. const resize = this._viewportRuler.change(150);
  721. const realign = () => {
  722. this.updatePagination();
  723. this._alignInkBarToSelectedTab();
  724. };
  725. this._keyManager = new FocusKeyManager(this._items)
  726. .withHorizontalOrientation(this._getLayoutDirection())
  727. .withHomeAndEnd()
  728. .withWrap()
  729. // Allow focus to land on disabled tabs, as per https://w3c.github.io/aria-practices/#kbd_disabled_controls
  730. .skipPredicate(() => false);
  731. this._keyManager.updateActiveItem(this._selectedIndex);
  732. // Defer the first call in order to allow for slower browsers to lay out the elements.
  733. // This helps in cases where the user lands directly on a page with paginated tabs.
  734. // Note that we use `onStable` instead of `requestAnimationFrame`, because the latter
  735. // can hold up tests that are in a background tab.
  736. this._ngZone.onStable.pipe(take(1)).subscribe(realign);
  737. // On dir change or window resize, realign the ink bar and update the orientation of
  738. // the key manager if the direction has changed.
  739. merge(dirChange, resize, this._items.changes, this._itemsResized())
  740. .pipe(takeUntil(this._destroyed))
  741. .subscribe(() => {
  742. // We need to defer this to give the browser some time to recalculate
  743. // the element dimensions. The call has to be wrapped in `NgZone.run`,
  744. // because the viewport change handler runs outside of Angular.
  745. this._ngZone.run(() => {
  746. Promise.resolve().then(() => {
  747. // Clamp the scroll distance, because it can change with the number of tabs.
  748. this._scrollDistance = Math.max(0, Math.min(this._getMaxScrollDistance(), this._scrollDistance));
  749. realign();
  750. });
  751. });
  752. this._keyManager.withHorizontalOrientation(this._getLayoutDirection());
  753. });
  754. // If there is a change in the focus key manager we need to emit the `indexFocused`
  755. // event in order to provide a public event that notifies about focus changes. Also we realign
  756. // the tabs container by scrolling the new focused tab into the visible section.
  757. this._keyManager.change.subscribe(newFocusIndex => {
  758. this.indexFocused.emit(newFocusIndex);
  759. this._setTabFocus(newFocusIndex);
  760. });
  761. }
  762. /** Sends any changes that could affect the layout of the items. */
  763. _itemsResized() {
  764. if (typeof ResizeObserver !== 'function') {
  765. return EMPTY;
  766. }
  767. return this._items.changes.pipe(startWith(this._items), switchMap((tabItems) => new Observable((observer) => this._ngZone.runOutsideAngular(() => {
  768. const resizeObserver = new ResizeObserver(entries => observer.next(entries));
  769. tabItems.forEach(item => resizeObserver.observe(item.elementRef.nativeElement));
  770. return () => {
  771. resizeObserver.disconnect();
  772. };
  773. }))),
  774. // Skip the first emit since the resize observer emits when an item
  775. // is observed for new items when the tab is already inserted
  776. skip(1),
  777. // Skip emissions where all the elements are invisible since we don't want
  778. // the header to try and re-render with invalid measurements. See #25574.
  779. filter(entries => entries.some(e => e.contentRect.width > 0 && e.contentRect.height > 0)));
  780. }
  781. ngAfterContentChecked() {
  782. // If the number of tab labels have changed, check if scrolling should be enabled
  783. if (this._tabLabelCount != this._items.length) {
  784. this.updatePagination();
  785. this._tabLabelCount = this._items.length;
  786. this._changeDetectorRef.markForCheck();
  787. }
  788. // If the selected index has changed, scroll to the label and check if the scrolling controls
  789. // should be disabled.
  790. if (this._selectedIndexChanged) {
  791. this._scrollToLabel(this._selectedIndex);
  792. this._checkScrollingControls();
  793. this._alignInkBarToSelectedTab();
  794. this._selectedIndexChanged = false;
  795. this._changeDetectorRef.markForCheck();
  796. }
  797. // If the scroll distance has been changed (tab selected, focused, scroll controls activated),
  798. // then translate the header to reflect this.
  799. if (this._scrollDistanceChanged) {
  800. this._updateTabScrollPosition();
  801. this._scrollDistanceChanged = false;
  802. this._changeDetectorRef.markForCheck();
  803. }
  804. }
  805. ngOnDestroy() {
  806. this._keyManager?.destroy();
  807. this._destroyed.next();
  808. this._destroyed.complete();
  809. this._stopScrolling.complete();
  810. }
  811. /** Handles keyboard events on the header. */
  812. _handleKeydown(event) {
  813. // We don't handle any key bindings with a modifier key.
  814. if (hasModifierKey(event)) {
  815. return;
  816. }
  817. switch (event.keyCode) {
  818. case ENTER:
  819. case SPACE:
  820. if (this.focusIndex !== this.selectedIndex) {
  821. const item = this._items.get(this.focusIndex);
  822. if (item && !item.disabled) {
  823. this.selectFocusedIndex.emit(this.focusIndex);
  824. this._itemSelected(event);
  825. }
  826. }
  827. break;
  828. default:
  829. this._keyManager.onKeydown(event);
  830. }
  831. }
  832. /**
  833. * Callback for when the MutationObserver detects that the content has changed.
  834. */
  835. _onContentChanges() {
  836. const textContent = this._elementRef.nativeElement.textContent;
  837. // We need to diff the text content of the header, because the MutationObserver callback
  838. // will fire even if the text content didn't change which is inefficient and is prone
  839. // to infinite loops if a poorly constructed expression is passed in (see #14249).
  840. if (textContent !== this._currentTextContent) {
  841. this._currentTextContent = textContent || '';
  842. // The content observer runs outside the `NgZone` by default, which
  843. // means that we need to bring the callback back in ourselves.
  844. this._ngZone.run(() => {
  845. this.updatePagination();
  846. this._alignInkBarToSelectedTab();
  847. this._changeDetectorRef.markForCheck();
  848. });
  849. }
  850. }
  851. /**
  852. * Updates the view whether pagination should be enabled or not.
  853. *
  854. * WARNING: Calling this method can be very costly in terms of performance. It should be called
  855. * as infrequently as possible from outside of the Tabs component as it causes a reflow of the
  856. * page.
  857. */
  858. updatePagination() {
  859. this._checkPaginationEnabled();
  860. this._checkScrollingControls();
  861. this._updateTabScrollPosition();
  862. }
  863. /** Tracks which element has focus; used for keyboard navigation */
  864. get focusIndex() {
  865. return this._keyManager ? this._keyManager.activeItemIndex : 0;
  866. }
  867. /** When the focus index is set, we must manually send focus to the correct label */
  868. set focusIndex(value) {
  869. if (!this._isValidIndex(value) || this.focusIndex === value || !this._keyManager) {
  870. return;
  871. }
  872. this._keyManager.setActiveItem(value);
  873. }
  874. /**
  875. * Determines if an index is valid. If the tabs are not ready yet, we assume that the user is
  876. * providing a valid index and return true.
  877. */
  878. _isValidIndex(index) {
  879. return this._items ? !!this._items.toArray()[index] : true;
  880. }
  881. /**
  882. * Sets focus on the HTML element for the label wrapper and scrolls it into the view if
  883. * scrolling is enabled.
  884. */
  885. _setTabFocus(tabIndex) {
  886. if (this._showPaginationControls) {
  887. this._scrollToLabel(tabIndex);
  888. }
  889. if (this._items && this._items.length) {
  890. this._items.toArray()[tabIndex].focus();
  891. // Do not let the browser manage scrolling to focus the element, this will be handled
  892. // by using translation. In LTR, the scroll left should be 0. In RTL, the scroll width
  893. // should be the full width minus the offset width.
  894. const containerEl = this._tabListContainer.nativeElement;
  895. const dir = this._getLayoutDirection();
  896. if (dir == 'ltr') {
  897. containerEl.scrollLeft = 0;
  898. }
  899. else {
  900. containerEl.scrollLeft = containerEl.scrollWidth - containerEl.offsetWidth;
  901. }
  902. }
  903. }
  904. /** The layout direction of the containing app. */
  905. _getLayoutDirection() {
  906. return this._dir && this._dir.value === 'rtl' ? 'rtl' : 'ltr';
  907. }
  908. /** Performs the CSS transformation on the tab list that will cause the list to scroll. */
  909. _updateTabScrollPosition() {
  910. if (this.disablePagination) {
  911. return;
  912. }
  913. const scrollDistance = this.scrollDistance;
  914. const translateX = this._getLayoutDirection() === 'ltr' ? -scrollDistance : scrollDistance;
  915. // Don't use `translate3d` here because we don't want to create a new layer. A new layer
  916. // seems to cause flickering and overflow in Internet Explorer. For example, the ink bar
  917. // and ripples will exceed the boundaries of the visible tab bar.
  918. // See: https://github.com/angular/components/issues/10276
  919. // We round the `transform` here, because transforms with sub-pixel precision cause some
  920. // browsers to blur the content of the element.
  921. this._tabList.nativeElement.style.transform = `translateX(${Math.round(translateX)}px)`;
  922. // Setting the `transform` on IE will change the scroll offset of the parent, causing the
  923. // position to be thrown off in some cases. We have to reset it ourselves to ensure that
  924. // it doesn't get thrown off. Note that we scope it only to IE and Edge, because messing
  925. // with the scroll position throws off Chrome 71+ in RTL mode (see #14689).
  926. if (this._platform.TRIDENT || this._platform.EDGE) {
  927. this._tabListContainer.nativeElement.scrollLeft = 0;
  928. }
  929. }
  930. /** Sets the distance in pixels that the tab header should be transformed in the X-axis. */
  931. get scrollDistance() {
  932. return this._scrollDistance;
  933. }
  934. set scrollDistance(value) {
  935. this._scrollTo(value);
  936. }
  937. /**
  938. * Moves the tab list in the 'before' or 'after' direction (towards the beginning of the list or
  939. * the end of the list, respectively). The distance to scroll is computed to be a third of the
  940. * length of the tab list view window.
  941. *
  942. * This is an expensive call that forces a layout reflow to compute box and scroll metrics and
  943. * should be called sparingly.
  944. */
  945. _scrollHeader(direction) {
  946. const viewLength = this._tabListContainer.nativeElement.offsetWidth;
  947. // Move the scroll distance one-third the length of the tab list's viewport.
  948. const scrollAmount = ((direction == 'before' ? -1 : 1) * viewLength) / 3;
  949. return this._scrollTo(this._scrollDistance + scrollAmount);
  950. }
  951. /** Handles click events on the pagination arrows. */
  952. _handlePaginatorClick(direction) {
  953. this._stopInterval();
  954. this._scrollHeader(direction);
  955. }
  956. /**
  957. * Moves the tab list such that the desired tab label (marked by index) is moved into view.
  958. *
  959. * This is an expensive call that forces a layout reflow to compute box and scroll metrics and
  960. * should be called sparingly.
  961. */
  962. _scrollToLabel(labelIndex) {
  963. if (this.disablePagination) {
  964. return;
  965. }
  966. const selectedLabel = this._items ? this._items.toArray()[labelIndex] : null;
  967. if (!selectedLabel) {
  968. return;
  969. }
  970. // The view length is the visible width of the tab labels.
  971. const viewLength = this._tabListContainer.nativeElement.offsetWidth;
  972. const { offsetLeft, offsetWidth } = selectedLabel.elementRef.nativeElement;
  973. let labelBeforePos, labelAfterPos;
  974. if (this._getLayoutDirection() == 'ltr') {
  975. labelBeforePos = offsetLeft;
  976. labelAfterPos = labelBeforePos + offsetWidth;
  977. }
  978. else {
  979. labelAfterPos = this._tabListInner.nativeElement.offsetWidth - offsetLeft;
  980. labelBeforePos = labelAfterPos - offsetWidth;
  981. }
  982. const beforeVisiblePos = this.scrollDistance;
  983. const afterVisiblePos = this.scrollDistance + viewLength;
  984. if (labelBeforePos < beforeVisiblePos) {
  985. // Scroll header to move label to the before direction
  986. this.scrollDistance -= beforeVisiblePos - labelBeforePos;
  987. }
  988. else if (labelAfterPos > afterVisiblePos) {
  989. // Scroll header to move label to the after direction
  990. this.scrollDistance += Math.min(labelAfterPos - afterVisiblePos, labelBeforePos - beforeVisiblePos);
  991. }
  992. }
  993. /**
  994. * Evaluate whether the pagination controls should be displayed. If the scroll width of the
  995. * tab list is wider than the size of the header container, then the pagination controls should
  996. * be shown.
  997. *
  998. * This is an expensive call that forces a layout reflow to compute box and scroll metrics and
  999. * should be called sparingly.
  1000. */
  1001. _checkPaginationEnabled() {
  1002. if (this.disablePagination) {
  1003. this._showPaginationControls = false;
  1004. }
  1005. else {
  1006. const isEnabled = this._tabListInner.nativeElement.scrollWidth > this._elementRef.nativeElement.offsetWidth;
  1007. if (!isEnabled) {
  1008. this.scrollDistance = 0;
  1009. }
  1010. if (isEnabled !== this._showPaginationControls) {
  1011. this._changeDetectorRef.markForCheck();
  1012. }
  1013. this._showPaginationControls = isEnabled;
  1014. }
  1015. }
  1016. /**
  1017. * Evaluate whether the before and after controls should be enabled or disabled.
  1018. * If the header is at the beginning of the list (scroll distance is equal to 0) then disable the
  1019. * before button. If the header is at the end of the list (scroll distance is equal to the
  1020. * maximum distance we can scroll), then disable the after button.
  1021. *
  1022. * This is an expensive call that forces a layout reflow to compute box and scroll metrics and
  1023. * should be called sparingly.
  1024. */
  1025. _checkScrollingControls() {
  1026. if (this.disablePagination) {
  1027. this._disableScrollAfter = this._disableScrollBefore = true;
  1028. }
  1029. else {
  1030. // Check if the pagination arrows should be activated.
  1031. this._disableScrollBefore = this.scrollDistance == 0;
  1032. this._disableScrollAfter = this.scrollDistance == this._getMaxScrollDistance();
  1033. this._changeDetectorRef.markForCheck();
  1034. }
  1035. }
  1036. /**
  1037. * Determines what is the maximum length in pixels that can be set for the scroll distance. This
  1038. * is equal to the difference in width between the tab list container and tab header container.
  1039. *
  1040. * This is an expensive call that forces a layout reflow to compute box and scroll metrics and
  1041. * should be called sparingly.
  1042. */
  1043. _getMaxScrollDistance() {
  1044. const lengthOfTabList = this._tabListInner.nativeElement.scrollWidth;
  1045. const viewLength = this._tabListContainer.nativeElement.offsetWidth;
  1046. return lengthOfTabList - viewLength || 0;
  1047. }
  1048. /** Tells the ink-bar to align itself to the current label wrapper */
  1049. _alignInkBarToSelectedTab() {
  1050. const selectedItem = this._items && this._items.length ? this._items.toArray()[this.selectedIndex] : null;
  1051. const selectedLabelWrapper = selectedItem ? selectedItem.elementRef.nativeElement : null;
  1052. if (selectedLabelWrapper) {
  1053. this._inkBar.alignToElement(selectedLabelWrapper);
  1054. }
  1055. else {
  1056. this._inkBar.hide();
  1057. }
  1058. }
  1059. /** Stops the currently-running paginator interval. */
  1060. _stopInterval() {
  1061. this._stopScrolling.next();
  1062. }
  1063. /**
  1064. * Handles the user pressing down on one of the paginators.
  1065. * Starts scrolling the header after a certain amount of time.
  1066. * @param direction In which direction the paginator should be scrolled.
  1067. */
  1068. _handlePaginatorPress(direction, mouseEvent) {
  1069. // Don't start auto scrolling for right mouse button clicks. Note that we shouldn't have to
  1070. // null check the `button`, but we do it so we don't break tests that use fake events.
  1071. if (mouseEvent && mouseEvent.button != null && mouseEvent.button !== 0) {
  1072. return;
  1073. }
  1074. // Avoid overlapping timers.
  1075. this._stopInterval();
  1076. // Start a timer after the delay and keep firing based on the interval.
  1077. timer(HEADER_SCROLL_DELAY, HEADER_SCROLL_INTERVAL)
  1078. // Keep the timer going until something tells it to stop or the component is destroyed.
  1079. .pipe(takeUntil(merge(this._stopScrolling, this._destroyed)))
  1080. .subscribe(() => {
  1081. const { maxScrollDistance, distance } = this._scrollHeader(direction);
  1082. // Stop the timer if we've reached the start or the end.
  1083. if (distance === 0 || distance >= maxScrollDistance) {
  1084. this._stopInterval();
  1085. }
  1086. });
  1087. }
  1088. /**
  1089. * Scrolls the header to a given position.
  1090. * @param position Position to which to scroll.
  1091. * @returns Information on the current scroll distance and the maximum.
  1092. */
  1093. _scrollTo(position) {
  1094. if (this.disablePagination) {
  1095. return { maxScrollDistance: 0, distance: 0 };
  1096. }
  1097. const maxScrollDistance = this._getMaxScrollDistance();
  1098. this._scrollDistance = Math.max(0, Math.min(maxScrollDistance, position));
  1099. // Mark that the scroll distance has changed so that after the view is checked, the CSS
  1100. // transformation can move the header.
  1101. this._scrollDistanceChanged = true;
  1102. this._checkScrollingControls();
  1103. return { maxScrollDistance, distance: this._scrollDistance };
  1104. }
  1105. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatPaginatedTabHeader, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1$1.ViewportRuler }, { token: i1.Directionality, optional: true }, { token: i0.NgZone }, { token: i3.Platform }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  1106. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: MatPaginatedTabHeader, inputs: { disablePagination: "disablePagination" }, ngImport: i0 }); }
  1107. }
  1108. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatPaginatedTabHeader, decorators: [{
  1109. type: Directive
  1110. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1$1.ViewportRuler }, { type: i1.Directionality, decorators: [{
  1111. type: Optional
  1112. }] }, { type: i0.NgZone }, { type: i3.Platform }, { type: undefined, decorators: [{
  1113. type: Optional
  1114. }, {
  1115. type: Inject,
  1116. args: [ANIMATION_MODULE_TYPE]
  1117. }] }]; }, propDecorators: { disablePagination: [{
  1118. type: Input
  1119. }] } });
  1120. /**
  1121. * Base class with all of the `MatTabHeader` functionality.
  1122. * @docs-private
  1123. */
  1124. class _MatTabHeaderBase extends MatPaginatedTabHeader {
  1125. /** Whether the ripple effect is disabled or not. */
  1126. get disableRipple() {
  1127. return this._disableRipple;
  1128. }
  1129. set disableRipple(value) {
  1130. this._disableRipple = coerceBooleanProperty(value);
  1131. }
  1132. constructor(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode) {
  1133. super(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode);
  1134. this._disableRipple = false;
  1135. }
  1136. _itemSelected(event) {
  1137. event.preventDefault();
  1138. }
  1139. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabHeaderBase, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1$1.ViewportRuler }, { token: i1.Directionality, optional: true }, { token: i0.NgZone }, { token: i3.Platform }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  1140. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabHeaderBase, inputs: { disableRipple: "disableRipple" }, usesInheritance: true, ngImport: i0 }); }
  1141. }
  1142. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabHeaderBase, decorators: [{
  1143. type: Directive
  1144. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1$1.ViewportRuler }, { type: i1.Directionality, decorators: [{
  1145. type: Optional
  1146. }] }, { type: i0.NgZone }, { type: i3.Platform }, { type: undefined, decorators: [{
  1147. type: Optional
  1148. }, {
  1149. type: Inject,
  1150. args: [ANIMATION_MODULE_TYPE]
  1151. }] }]; }, propDecorators: { disableRipple: [{
  1152. type: Input
  1153. }] } });
  1154. /**
  1155. * The header of the tab group which displays a list of all the tabs in the tab group. Includes
  1156. * an ink bar that follows the currently selected tab. When the tabs list's width exceeds the
  1157. * width of the header container, then arrows will be displayed to allow the user to scroll
  1158. * left and right across the header.
  1159. * @docs-private
  1160. */
  1161. class MatTabHeader extends _MatTabHeaderBase {
  1162. constructor(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode) {
  1163. super(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode);
  1164. }
  1165. ngAfterContentInit() {
  1166. this._inkBar = new MatInkBar(this._items);
  1167. super.ngAfterContentInit();
  1168. }
  1169. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabHeader, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1$1.ViewportRuler }, { token: i1.Directionality, optional: true }, { token: i0.NgZone }, { token: i3.Platform }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
  1170. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTabHeader, selector: "mat-tab-header", inputs: { selectedIndex: "selectedIndex" }, outputs: { selectFocusedIndex: "selectFocusedIndex", indexFocused: "indexFocused" }, host: { properties: { "class.mat-mdc-tab-header-pagination-controls-enabled": "_showPaginationControls", "class.mat-mdc-tab-header-rtl": "_getLayoutDirection() == 'rtl'" }, classAttribute: "mat-mdc-tab-header" }, queries: [{ propertyName: "_items", predicate: MatTabLabelWrapper }], viewQueries: [{ propertyName: "_tabListContainer", first: true, predicate: ["tabListContainer"], descendants: true, static: true }, { propertyName: "_tabList", first: true, predicate: ["tabList"], descendants: true, static: true }, { propertyName: "_tabListInner", first: true, predicate: ["tabListInner"], descendants: true, static: true }, { propertyName: "_nextPaginator", first: true, predicate: ["nextPaginator"], descendants: true }, { propertyName: "_previousPaginator", first: true, predicate: ["previousPaginator"], descendants: true }], usesInheritance: true, ngImport: i0, template: "<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-before\"\n #previousPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n tabindex=\"-1\"\n [matRippleDisabled]=\"_disableScrollBefore || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollBefore\"\n [disabled]=\"_disableScrollBefore || null\"\n (click)=\"_handlePaginatorClick('before')\"\n (mousedown)=\"_handlePaginatorPress('before', $event)\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n\n<div\n class=\"mat-mdc-tab-label-container\"\n #tabListContainer\n (keydown)=\"_handleKeydown($event)\"\n [class._mat-animation-noopable]=\"_animationMode === 'NoopAnimations'\">\n <div\n #tabList\n class=\"mat-mdc-tab-list\"\n role=\"tablist\"\n (cdkObserveContent)=\"_onContentChanges()\">\n <div class=\"mat-mdc-tab-labels\" #tabListInner>\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-after\"\n #nextPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n [matRippleDisabled]=\"_disableScrollAfter || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollAfter\"\n [disabled]=\"_disableScrollAfter || null\"\n tabindex=\"-1\"\n (mousedown)=\"_handlePaginatorPress('after', $event)\"\n (click)=\"_handlePaginatorClick('after')\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n", styles: [".mat-mdc-tab-header{display:flex;overflow:hidden;position:relative;flex-shrink:0;--mdc-tab-indicator-active-indicator-height:2px;--mdc-tab-indicator-active-indicator-shape:0;--mdc-secondary-navigation-tab-container-height:48px}.mat-mdc-tab-header-pagination{-webkit-user-select:none;user-select:none;position:relative;display:none;justify-content:center;align-items:center;min-width:32px;cursor:pointer;z-index:2;-webkit-tap-highlight-color:rgba(0,0,0,0);touch-action:none;box-sizing:content-box;background:none;border:none;outline:0;padding:0}.mat-mdc-tab-header-pagination::-moz-focus-inner{border:0}.mat-mdc-tab-header-pagination .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-header-pagination-controls-enabled .mat-mdc-tab-header-pagination{display:flex}.mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after{padding-left:4px}.mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(-135deg)}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-pagination-after{padding-right:4px}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(45deg)}.mat-mdc-tab-header-pagination-chevron{border-style:solid;border-width:2px 2px 0 0;height:8px;width:8px;border-color:var(--mat-tab-header-pagination-icon-color)}.mat-mdc-tab-header-pagination-disabled{box-shadow:none;cursor:default;pointer-events:none}.mat-mdc-tab-header-pagination-disabled .mat-mdc-tab-header-pagination-chevron{opacity:.4}.mat-mdc-tab-list{flex-grow:1;position:relative;transition:transform 500ms cubic-bezier(0.35, 0, 0.25, 1)}._mat-animation-noopable .mat-mdc-tab-list{transition:none}._mat-animation-noopable span.mdc-tab-indicator__content,._mat-animation-noopable span.mdc-tab__text-label{transition:none}.mat-mdc-tab-label-container{display:flex;flex-grow:1;overflow:hidden;z-index:1}.mat-mdc-tab-labels{display:flex;flex:1 0 auto}[mat-align-tabs=center]>.mat-mdc-tab-header .mat-mdc-tab-labels{justify-content:center}[mat-align-tabs=end]>.mat-mdc-tab-header .mat-mdc-tab-labels{justify-content:flex-end}.mat-mdc-tab::before{margin:5px}.cdk-high-contrast-active .mat-mdc-tab[aria-disabled=true]{color:GrayText}"], dependencies: [{ kind: "directive", type: i5.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "directive", type: i5$1.CdkObserveContent, selector: "[cdkObserveContent]", inputs: ["cdkObserveContentDisabled", "debounce"], outputs: ["cdkObserveContent"], exportAs: ["cdkObserveContent"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
  1171. }
  1172. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabHeader, decorators: [{
  1173. type: Component,
  1174. args: [{ selector: 'mat-tab-header', inputs: ['selectedIndex'], outputs: ['selectFocusedIndex', 'indexFocused'], encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, host: {
  1175. 'class': 'mat-mdc-tab-header',
  1176. '[class.mat-mdc-tab-header-pagination-controls-enabled]': '_showPaginationControls',
  1177. '[class.mat-mdc-tab-header-rtl]': "_getLayoutDirection() == 'rtl'",
  1178. }, template: "<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-before\"\n #previousPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n tabindex=\"-1\"\n [matRippleDisabled]=\"_disableScrollBefore || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollBefore\"\n [disabled]=\"_disableScrollBefore || null\"\n (click)=\"_handlePaginatorClick('before')\"\n (mousedown)=\"_handlePaginatorPress('before', $event)\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n\n<div\n class=\"mat-mdc-tab-label-container\"\n #tabListContainer\n (keydown)=\"_handleKeydown($event)\"\n [class._mat-animation-noopable]=\"_animationMode === 'NoopAnimations'\">\n <div\n #tabList\n class=\"mat-mdc-tab-list\"\n role=\"tablist\"\n (cdkObserveContent)=\"_onContentChanges()\">\n <div class=\"mat-mdc-tab-labels\" #tabListInner>\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-after\"\n #nextPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n [matRippleDisabled]=\"_disableScrollAfter || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollAfter\"\n [disabled]=\"_disableScrollAfter || null\"\n tabindex=\"-1\"\n (mousedown)=\"_handlePaginatorPress('after', $event)\"\n (click)=\"_handlePaginatorClick('after')\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n", styles: [".mat-mdc-tab-header{display:flex;overflow:hidden;position:relative;flex-shrink:0;--mdc-tab-indicator-active-indicator-height:2px;--mdc-tab-indicator-active-indicator-shape:0;--mdc-secondary-navigation-tab-container-height:48px}.mat-mdc-tab-header-pagination{-webkit-user-select:none;user-select:none;position:relative;display:none;justify-content:center;align-items:center;min-width:32px;cursor:pointer;z-index:2;-webkit-tap-highlight-color:rgba(0,0,0,0);touch-action:none;box-sizing:content-box;background:none;border:none;outline:0;padding:0}.mat-mdc-tab-header-pagination::-moz-focus-inner{border:0}.mat-mdc-tab-header-pagination .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-header-pagination-controls-enabled .mat-mdc-tab-header-pagination{display:flex}.mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after{padding-left:4px}.mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(-135deg)}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-pagination-after{padding-right:4px}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(45deg)}.mat-mdc-tab-header-pagination-chevron{border-style:solid;border-width:2px 2px 0 0;height:8px;width:8px;border-color:var(--mat-tab-header-pagination-icon-color)}.mat-mdc-tab-header-pagination-disabled{box-shadow:none;cursor:default;pointer-events:none}.mat-mdc-tab-header-pagination-disabled .mat-mdc-tab-header-pagination-chevron{opacity:.4}.mat-mdc-tab-list{flex-grow:1;position:relative;transition:transform 500ms cubic-bezier(0.35, 0, 0.25, 1)}._mat-animation-noopable .mat-mdc-tab-list{transition:none}._mat-animation-noopable span.mdc-tab-indicator__content,._mat-animation-noopable span.mdc-tab__text-label{transition:none}.mat-mdc-tab-label-container{display:flex;flex-grow:1;overflow:hidden;z-index:1}.mat-mdc-tab-labels{display:flex;flex:1 0 auto}[mat-align-tabs=center]>.mat-mdc-tab-header .mat-mdc-tab-labels{justify-content:center}[mat-align-tabs=end]>.mat-mdc-tab-header .mat-mdc-tab-labels{justify-content:flex-end}.mat-mdc-tab::before{margin:5px}.cdk-high-contrast-active .mat-mdc-tab[aria-disabled=true]{color:GrayText}"] }]
  1179. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1$1.ViewportRuler }, { type: i1.Directionality, decorators: [{
  1180. type: Optional
  1181. }] }, { type: i0.NgZone }, { type: i3.Platform }, { type: undefined, decorators: [{
  1182. type: Optional
  1183. }, {
  1184. type: Inject,
  1185. args: [ANIMATION_MODULE_TYPE]
  1186. }] }]; }, propDecorators: { _items: [{
  1187. type: ContentChildren,
  1188. args: [MatTabLabelWrapper, { descendants: false }]
  1189. }], _tabListContainer: [{
  1190. type: ViewChild,
  1191. args: ['tabListContainer', { static: true }]
  1192. }], _tabList: [{
  1193. type: ViewChild,
  1194. args: ['tabList', { static: true }]
  1195. }], _tabListInner: [{
  1196. type: ViewChild,
  1197. args: ['tabListInner', { static: true }]
  1198. }], _nextPaginator: [{
  1199. type: ViewChild,
  1200. args: ['nextPaginator']
  1201. }], _previousPaginator: [{
  1202. type: ViewChild,
  1203. args: ['previousPaginator']
  1204. }] } });
  1205. /** Injection token that can be used to provide the default options the tabs module. */
  1206. const MAT_TABS_CONFIG = new InjectionToken('MAT_TABS_CONFIG');
  1207. /** Used to generate unique ID's for each tab component */
  1208. let nextId = 0;
  1209. // Boilerplate for applying mixins to MatTabGroup.
  1210. /** @docs-private */
  1211. const _MatTabGroupMixinBase = mixinColor(mixinDisableRipple(class {
  1212. constructor(_elementRef) {
  1213. this._elementRef = _elementRef;
  1214. }
  1215. }), 'primary');
  1216. /**
  1217. * Base class with all of the `MatTabGroupBase` functionality.
  1218. * @docs-private
  1219. */
  1220. class _MatTabGroupBase extends _MatTabGroupMixinBase {
  1221. /** Whether the tab group should grow to the size of the active tab. */
  1222. get dynamicHeight() {
  1223. return this._dynamicHeight;
  1224. }
  1225. set dynamicHeight(value) {
  1226. this._dynamicHeight = coerceBooleanProperty(value);
  1227. }
  1228. /** The index of the active tab. */
  1229. get selectedIndex() {
  1230. return this._selectedIndex;
  1231. }
  1232. set selectedIndex(value) {
  1233. this._indexToSelect = coerceNumberProperty(value, null);
  1234. }
  1235. /** Duration for the tab animation. Will be normalized to milliseconds if no units are set. */
  1236. get animationDuration() {
  1237. return this._animationDuration;
  1238. }
  1239. set animationDuration(value) {
  1240. this._animationDuration = /^\d+$/.test(value + '') ? value + 'ms' : value;
  1241. }
  1242. /**
  1243. * `tabindex` to be set on the inner element that wraps the tab content. Can be used for improved
  1244. * accessibility when the tab does not have focusable elements or if it has scrollable content.
  1245. * The `tabindex` will be removed automatically for inactive tabs.
  1246. * Read more at https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-2/tabs.html
  1247. */
  1248. get contentTabIndex() {
  1249. return this._contentTabIndex;
  1250. }
  1251. set contentTabIndex(value) {
  1252. this._contentTabIndex = coerceNumberProperty(value, null);
  1253. }
  1254. /**
  1255. * Whether pagination should be disabled. This can be used to avoid unnecessary
  1256. * layout recalculations if it's known that pagination won't be required.
  1257. */
  1258. get disablePagination() {
  1259. return this._disablePagination;
  1260. }
  1261. set disablePagination(value) {
  1262. this._disablePagination = coerceBooleanProperty(value);
  1263. }
  1264. /**
  1265. * By default tabs remove their content from the DOM while it's off-screen.
  1266. * Setting this to `true` will keep it in the DOM which will prevent elements
  1267. * like iframes and videos from reloading next time it comes back into the view.
  1268. */
  1269. get preserveContent() {
  1270. return this._preserveContent;
  1271. }
  1272. set preserveContent(value) {
  1273. this._preserveContent = coerceBooleanProperty(value);
  1274. }
  1275. /** Background color of the tab group. */
  1276. get backgroundColor() {
  1277. return this._backgroundColor;
  1278. }
  1279. set backgroundColor(value) {
  1280. const classList = this._elementRef.nativeElement.classList;
  1281. classList.remove('mat-tabs-with-background', `mat-background-${this.backgroundColor}`);
  1282. if (value) {
  1283. classList.add('mat-tabs-with-background', `mat-background-${value}`);
  1284. }
  1285. this._backgroundColor = value;
  1286. }
  1287. constructor(elementRef, _changeDetectorRef, defaultConfig, _animationMode) {
  1288. super(elementRef);
  1289. this._changeDetectorRef = _changeDetectorRef;
  1290. this._animationMode = _animationMode;
  1291. /** All of the tabs that belong to the group. */
  1292. this._tabs = new QueryList();
  1293. /** The tab index that should be selected after the content has been checked. */
  1294. this._indexToSelect = 0;
  1295. /** Index of the tab that was focused last. */
  1296. this._lastFocusedTabIndex = null;
  1297. /** Snapshot of the height of the tab body wrapper before another tab is activated. */
  1298. this._tabBodyWrapperHeight = 0;
  1299. /** Subscription to tabs being added/removed. */
  1300. this._tabsSubscription = Subscription.EMPTY;
  1301. /** Subscription to changes in the tab labels. */
  1302. this._tabLabelSubscription = Subscription.EMPTY;
  1303. this._dynamicHeight = false;
  1304. this._selectedIndex = null;
  1305. /** Position of the tab header. */
  1306. this.headerPosition = 'above';
  1307. this._disablePagination = false;
  1308. this._preserveContent = false;
  1309. /** Output to enable support for two-way binding on `[(selectedIndex)]` */
  1310. this.selectedIndexChange = new EventEmitter();
  1311. /** Event emitted when focus has changed within a tab group. */
  1312. this.focusChange = new EventEmitter();
  1313. /** Event emitted when the body animation has completed */
  1314. this.animationDone = new EventEmitter();
  1315. /** Event emitted when the tab selection has changed. */
  1316. this.selectedTabChange = new EventEmitter(true);
  1317. this._groupId = nextId++;
  1318. this.animationDuration =
  1319. defaultConfig && defaultConfig.animationDuration ? defaultConfig.animationDuration : '500ms';
  1320. this.disablePagination =
  1321. defaultConfig && defaultConfig.disablePagination != null
  1322. ? defaultConfig.disablePagination
  1323. : false;
  1324. this.dynamicHeight =
  1325. defaultConfig && defaultConfig.dynamicHeight != null ? defaultConfig.dynamicHeight : false;
  1326. this.contentTabIndex = defaultConfig?.contentTabIndex ?? null;
  1327. this.preserveContent = !!defaultConfig?.preserveContent;
  1328. }
  1329. /**
  1330. * After the content is checked, this component knows what tabs have been defined
  1331. * and what the selected index should be. This is where we can know exactly what position
  1332. * each tab should be in according to the new selected index, and additionally we know how
  1333. * a new selected tab should transition in (from the left or right).
  1334. */
  1335. ngAfterContentChecked() {
  1336. // Don't clamp the `indexToSelect` immediately in the setter because it can happen that
  1337. // the amount of tabs changes before the actual change detection runs.
  1338. const indexToSelect = (this._indexToSelect = this._clampTabIndex(this._indexToSelect));
  1339. // If there is a change in selected index, emit a change event. Should not trigger if
  1340. // the selected index has not yet been initialized.
  1341. if (this._selectedIndex != indexToSelect) {
  1342. const isFirstRun = this._selectedIndex == null;
  1343. if (!isFirstRun) {
  1344. this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));
  1345. // Preserve the height so page doesn't scroll up during tab change.
  1346. // Fixes https://stackblitz.com/edit/mat-tabs-scroll-page-top-on-tab-change
  1347. const wrapper = this._tabBodyWrapper.nativeElement;
  1348. wrapper.style.minHeight = wrapper.clientHeight + 'px';
  1349. }
  1350. // Changing these values after change detection has run
  1351. // since the checked content may contain references to them.
  1352. Promise.resolve().then(() => {
  1353. this._tabs.forEach((tab, index) => (tab.isActive = index === indexToSelect));
  1354. if (!isFirstRun) {
  1355. this.selectedIndexChange.emit(indexToSelect);
  1356. // Clear the min-height, this was needed during tab change to avoid
  1357. // unnecessary scrolling.
  1358. this._tabBodyWrapper.nativeElement.style.minHeight = '';
  1359. }
  1360. });
  1361. }
  1362. // Setup the position for each tab and optionally setup an origin on the next selected tab.
  1363. this._tabs.forEach((tab, index) => {
  1364. tab.position = index - indexToSelect;
  1365. // If there is already a selected tab, then set up an origin for the next selected tab
  1366. // if it doesn't have one already.
  1367. if (this._selectedIndex != null && tab.position == 0 && !tab.origin) {
  1368. tab.origin = indexToSelect - this._selectedIndex;
  1369. }
  1370. });
  1371. if (this._selectedIndex !== indexToSelect) {
  1372. this._selectedIndex = indexToSelect;
  1373. this._lastFocusedTabIndex = null;
  1374. this._changeDetectorRef.markForCheck();
  1375. }
  1376. }
  1377. ngAfterContentInit() {
  1378. this._subscribeToAllTabChanges();
  1379. this._subscribeToTabLabels();
  1380. // Subscribe to changes in the amount of tabs, in order to be
  1381. // able to re-render the content as new tabs are added or removed.
  1382. this._tabsSubscription = this._tabs.changes.subscribe(() => {
  1383. const indexToSelect = this._clampTabIndex(this._indexToSelect);
  1384. // Maintain the previously-selected tab if a new tab is added or removed and there is no
  1385. // explicit change that selects a different tab.
  1386. if (indexToSelect === this._selectedIndex) {
  1387. const tabs = this._tabs.toArray();
  1388. let selectedTab;
  1389. for (let i = 0; i < tabs.length; i++) {
  1390. if (tabs[i].isActive) {
  1391. // Assign both to the `_indexToSelect` and `_selectedIndex` so we don't fire a changed
  1392. // event, otherwise the consumer may end up in an infinite loop in some edge cases like
  1393. // adding a tab within the `selectedIndexChange` event.
  1394. this._indexToSelect = this._selectedIndex = i;
  1395. this._lastFocusedTabIndex = null;
  1396. selectedTab = tabs[i];
  1397. break;
  1398. }
  1399. }
  1400. // If we haven't found an active tab and a tab exists at the selected index, it means
  1401. // that the active tab was swapped out. Since this won't be picked up by the rendering
  1402. // loop in `ngAfterContentChecked`, we need to sync it up manually.
  1403. if (!selectedTab && tabs[indexToSelect]) {
  1404. Promise.resolve().then(() => {
  1405. tabs[indexToSelect].isActive = true;
  1406. this.selectedTabChange.emit(this._createChangeEvent(indexToSelect));
  1407. });
  1408. }
  1409. }
  1410. this._changeDetectorRef.markForCheck();
  1411. });
  1412. }
  1413. /** Listens to changes in all of the tabs. */
  1414. _subscribeToAllTabChanges() {
  1415. // Since we use a query with `descendants: true` to pick up the tabs, we may end up catching
  1416. // some that are inside of nested tab groups. We filter them out manually by checking that
  1417. // the closest group to the tab is the current one.
  1418. this._allTabs.changes.pipe(startWith(this._allTabs)).subscribe((tabs) => {
  1419. this._tabs.reset(tabs.filter(tab => {
  1420. return tab._closestTabGroup === this || !tab._closestTabGroup;
  1421. }));
  1422. this._tabs.notifyOnChanges();
  1423. });
  1424. }
  1425. ngOnDestroy() {
  1426. this._tabs.destroy();
  1427. this._tabsSubscription.unsubscribe();
  1428. this._tabLabelSubscription.unsubscribe();
  1429. }
  1430. /** Re-aligns the ink bar to the selected tab element. */
  1431. realignInkBar() {
  1432. if (this._tabHeader) {
  1433. this._tabHeader._alignInkBarToSelectedTab();
  1434. }
  1435. }
  1436. /**
  1437. * Recalculates the tab group's pagination dimensions.
  1438. *
  1439. * WARNING: Calling this method can be very costly in terms of performance. It should be called
  1440. * as infrequently as possible from outside of the Tabs component as it causes a reflow of the
  1441. * page.
  1442. */
  1443. updatePagination() {
  1444. if (this._tabHeader) {
  1445. this._tabHeader.updatePagination();
  1446. }
  1447. }
  1448. /**
  1449. * Sets focus to a particular tab.
  1450. * @param index Index of the tab to be focused.
  1451. */
  1452. focusTab(index) {
  1453. const header = this._tabHeader;
  1454. if (header) {
  1455. header.focusIndex = index;
  1456. }
  1457. }
  1458. _focusChanged(index) {
  1459. this._lastFocusedTabIndex = index;
  1460. this.focusChange.emit(this._createChangeEvent(index));
  1461. }
  1462. _createChangeEvent(index) {
  1463. const event = new MatTabChangeEvent();
  1464. event.index = index;
  1465. if (this._tabs && this._tabs.length) {
  1466. event.tab = this._tabs.toArray()[index];
  1467. }
  1468. return event;
  1469. }
  1470. /**
  1471. * Subscribes to changes in the tab labels. This is needed, because the @Input for the label is
  1472. * on the MatTab component, whereas the data binding is inside the MatTabGroup. In order for the
  1473. * binding to be updated, we need to subscribe to changes in it and trigger change detection
  1474. * manually.
  1475. */
  1476. _subscribeToTabLabels() {
  1477. if (this._tabLabelSubscription) {
  1478. this._tabLabelSubscription.unsubscribe();
  1479. }
  1480. this._tabLabelSubscription = merge(...this._tabs.map(tab => tab._stateChanges)).subscribe(() => this._changeDetectorRef.markForCheck());
  1481. }
  1482. /** Clamps the given index to the bounds of 0 and the tabs length. */
  1483. _clampTabIndex(index) {
  1484. // Note the `|| 0`, which ensures that values like NaN can't get through
  1485. // and which would otherwise throw the component into an infinite loop
  1486. // (since Math.max(NaN, 0) === NaN).
  1487. return Math.min(this._tabs.length - 1, Math.max(index || 0, 0));
  1488. }
  1489. /** Returns a unique id for each tab label element */
  1490. _getTabLabelId(i) {
  1491. return `mat-tab-label-${this._groupId}-${i}`;
  1492. }
  1493. /** Returns a unique id for each tab content element */
  1494. _getTabContentId(i) {
  1495. return `mat-tab-content-${this._groupId}-${i}`;
  1496. }
  1497. /**
  1498. * Sets the height of the body wrapper to the height of the activating tab if dynamic
  1499. * height property is true.
  1500. */
  1501. _setTabBodyWrapperHeight(tabHeight) {
  1502. if (!this._dynamicHeight || !this._tabBodyWrapperHeight) {
  1503. return;
  1504. }
  1505. const wrapper = this._tabBodyWrapper.nativeElement;
  1506. wrapper.style.height = this._tabBodyWrapperHeight + 'px';
  1507. // This conditional forces the browser to paint the height so that
  1508. // the animation to the new height can have an origin.
  1509. if (this._tabBodyWrapper.nativeElement.offsetHeight) {
  1510. wrapper.style.height = tabHeight + 'px';
  1511. }
  1512. }
  1513. /** Removes the height of the tab body wrapper. */
  1514. _removeTabBodyWrapperHeight() {
  1515. const wrapper = this._tabBodyWrapper.nativeElement;
  1516. this._tabBodyWrapperHeight = wrapper.clientHeight;
  1517. wrapper.style.height = '';
  1518. this.animationDone.emit();
  1519. }
  1520. /** Handle click events, setting new selected index if appropriate. */
  1521. _handleClick(tab, tabHeader, index) {
  1522. tabHeader.focusIndex = index;
  1523. if (!tab.disabled) {
  1524. this.selectedIndex = index;
  1525. }
  1526. }
  1527. /** Retrieves the tabindex for the tab. */
  1528. _getTabIndex(index) {
  1529. const targetIndex = this._lastFocusedTabIndex ?? this.selectedIndex;
  1530. return index === targetIndex ? 0 : -1;
  1531. }
  1532. /** Callback for when the focused state of a tab has changed. */
  1533. _tabFocusChanged(focusOrigin, index) {
  1534. // Mouse/touch focus happens during the `mousedown`/`touchstart` phase which
  1535. // can cause the tab to be moved out from under the pointer, interrupting the
  1536. // click sequence (see #21898). We don't need to scroll the tab into view for
  1537. // such cases anyway, because it will be done when the tab becomes selected.
  1538. if (focusOrigin && focusOrigin !== 'mouse' && focusOrigin !== 'touch') {
  1539. this._tabHeader.focusIndex = index;
  1540. }
  1541. }
  1542. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabGroupBase, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: MAT_TABS_CONFIG, optional: true }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  1543. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabGroupBase, inputs: { dynamicHeight: "dynamicHeight", selectedIndex: "selectedIndex", headerPosition: "headerPosition", animationDuration: "animationDuration", contentTabIndex: "contentTabIndex", disablePagination: "disablePagination", preserveContent: "preserveContent", backgroundColor: "backgroundColor" }, outputs: { selectedIndexChange: "selectedIndexChange", focusChange: "focusChange", animationDone: "animationDone", selectedTabChange: "selectedTabChange" }, usesInheritance: true, ngImport: i0 }); }
  1544. }
  1545. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabGroupBase, decorators: [{
  1546. type: Directive
  1547. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
  1548. type: Inject,
  1549. args: [MAT_TABS_CONFIG]
  1550. }, {
  1551. type: Optional
  1552. }] }, { type: undefined, decorators: [{
  1553. type: Optional
  1554. }, {
  1555. type: Inject,
  1556. args: [ANIMATION_MODULE_TYPE]
  1557. }] }]; }, propDecorators: { dynamicHeight: [{
  1558. type: Input
  1559. }], selectedIndex: [{
  1560. type: Input
  1561. }], headerPosition: [{
  1562. type: Input
  1563. }], animationDuration: [{
  1564. type: Input
  1565. }], contentTabIndex: [{
  1566. type: Input
  1567. }], disablePagination: [{
  1568. type: Input
  1569. }], preserveContent: [{
  1570. type: Input
  1571. }], backgroundColor: [{
  1572. type: Input
  1573. }], selectedIndexChange: [{
  1574. type: Output
  1575. }], focusChange: [{
  1576. type: Output
  1577. }], animationDone: [{
  1578. type: Output
  1579. }], selectedTabChange: [{
  1580. type: Output
  1581. }] } });
  1582. /**
  1583. * Material design tab-group component. Supports basic tab pairs (label + content) and includes
  1584. * animated ink-bar, keyboard navigation, and screen reader.
  1585. * See: https://material.io/design/components/tabs.html
  1586. */
  1587. class MatTabGroup extends _MatTabGroupBase {
  1588. /** Whether the ink bar should fit its width to the size of the tab label content. */
  1589. get fitInkBarToContent() {
  1590. return this._fitInkBarToContent;
  1591. }
  1592. set fitInkBarToContent(v) {
  1593. this._fitInkBarToContent = coerceBooleanProperty(v);
  1594. this._changeDetectorRef.markForCheck();
  1595. }
  1596. /** Whether tabs should be stretched to fill the header. */
  1597. get stretchTabs() {
  1598. return this._stretchTabs;
  1599. }
  1600. set stretchTabs(v) {
  1601. this._stretchTabs = coerceBooleanProperty(v);
  1602. }
  1603. constructor(elementRef, changeDetectorRef, defaultConfig, animationMode) {
  1604. super(elementRef, changeDetectorRef, defaultConfig, animationMode);
  1605. this._fitInkBarToContent = false;
  1606. this._stretchTabs = true;
  1607. this.fitInkBarToContent =
  1608. defaultConfig && defaultConfig.fitInkBarToContent != null
  1609. ? defaultConfig.fitInkBarToContent
  1610. : false;
  1611. this.stretchTabs =
  1612. defaultConfig && defaultConfig.stretchTabs != null ? defaultConfig.stretchTabs : true;
  1613. }
  1614. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabGroup, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: MAT_TABS_CONFIG, optional: true }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
  1615. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTabGroup, selector: "mat-tab-group", inputs: { color: "color", disableRipple: "disableRipple", fitInkBarToContent: "fitInkBarToContent", stretchTabs: ["mat-stretch-tabs", "stretchTabs"] }, host: { attributes: { "ngSkipHydration": "" }, properties: { "class.mat-mdc-tab-group-dynamic-height": "dynamicHeight", "class.mat-mdc-tab-group-inverted-header": "headerPosition === \"below\"", "class.mat-mdc-tab-group-stretch-tabs": "stretchTabs" }, classAttribute: "mat-mdc-tab-group" }, providers: [
  1616. {
  1617. provide: MAT_TAB_GROUP,
  1618. useExisting: MatTabGroup,
  1619. },
  1620. ], queries: [{ propertyName: "_allTabs", predicate: MatTab, descendants: true }], viewQueries: [{ propertyName: "_tabBodyWrapper", first: true, predicate: ["tabBodyWrapper"], descendants: true }, { propertyName: "_tabHeader", first: true, predicate: ["tabHeader"], descendants: true }], exportAs: ["matTabGroup"], usesInheritance: true, ngImport: i0, template: "<mat-tab-header #tabHeader\n [selectedIndex]=\"selectedIndex || 0\"\n [disableRipple]=\"disableRipple\"\n [disablePagination]=\"disablePagination\"\n (indexFocused)=\"_focusChanged($event)\"\n (selectFocusedIndex)=\"selectedIndex = $event\">\n\n <div class=\"mdc-tab mat-mdc-tab mat-mdc-focus-indicator\"\n #tabNode\n role=\"tab\"\n matTabLabelWrapper\n cdkMonitorElementFocus\n *ngFor=\"let tab of _tabs; let i = index\"\n [id]=\"_getTabLabelId(i)\"\n [attr.tabIndex]=\"_getTabIndex(i)\"\n [attr.aria-posinset]=\"i + 1\"\n [attr.aria-setsize]=\"_tabs.length\"\n [attr.aria-controls]=\"_getTabContentId(i)\"\n [attr.aria-selected]=\"selectedIndex === i\"\n [attr.aria-label]=\"tab.ariaLabel || null\"\n [attr.aria-labelledby]=\"(!tab.ariaLabel && tab.ariaLabelledby) ? tab.ariaLabelledby : null\"\n [class.mdc-tab--active]=\"selectedIndex === i\"\n [ngClass]=\"tab.labelClass\"\n [disabled]=\"tab.disabled\"\n [fitInkBarToContent]=\"fitInkBarToContent\"\n (click)=\"_handleClick(tab, tabHeader, i)\"\n (cdkFocusChange)=\"_tabFocusChanged($event, i)\">\n <span class=\"mdc-tab__ripple\"></span>\n\n <!-- Needs to be a separate element, because we can't put\n `overflow: hidden` on tab due to the ink bar. -->\n <div\n class=\"mat-mdc-tab-ripple\"\n mat-ripple\n [matRippleTrigger]=\"tabNode\"\n [matRippleDisabled]=\"tab.disabled || disableRipple\"></div>\n\n <span class=\"mdc-tab__content\">\n <span class=\"mdc-tab__text-label\">\n <!-- If there is a label template, use it. -->\n <ng-template [ngIf]=\"tab.templateLabel\" [ngIfElse]=\"tabTextLabel\">\n <ng-template [cdkPortalOutlet]=\"tab.templateLabel\"></ng-template>\n </ng-template>\n\n <!-- If there is not a label template, fall back to the text label. -->\n <ng-template #tabTextLabel>{{tab.textLabel}}</ng-template>\n </span>\n </span>\n </div>\n</mat-tab-header>\n\n<div\n class=\"mat-mdc-tab-body-wrapper\"\n [class._mat-animation-noopable]=\"_animationMode === 'NoopAnimations'\"\n #tabBodyWrapper>\n <mat-tab-body role=\"tabpanel\"\n *ngFor=\"let tab of _tabs; let i = index\"\n [id]=\"_getTabContentId(i)\"\n [attr.tabindex]=\"(contentTabIndex != null && selectedIndex === i) ? contentTabIndex : null\"\n [attr.aria-labelledby]=\"_getTabLabelId(i)\"\n [class.mat-mdc-tab-body-active]=\"selectedIndex === i\"\n [ngClass]=\"tab.bodyClass\"\n [content]=\"tab.content!\"\n [position]=\"tab.position!\"\n [origin]=\"tab.origin\"\n [animationDuration]=\"animationDuration\"\n [preserveContent]=\"preserveContent\"\n (_onCentered)=\"_removeTabBodyWrapperHeight()\"\n (_onCentering)=\"_setTabBodyWrapperHeight($event)\">\n </mat-tab-body>\n</div>\n", styles: [".mdc-tab{min-width:90px;padding-right:24px;padding-left:24px;display:flex;flex:1 0 auto;justify-content:center;box-sizing:border-box;margin:0;padding-top:0;padding-bottom:0;border:none;outline:none;text-align:center;white-space:nowrap;cursor:pointer;-webkit-appearance:none;z-index:1}.mdc-tab::-moz-focus-inner{padding:0;border:0}.mdc-tab[hidden]{display:none}.mdc-tab--min-width{flex:0 1 auto}.mdc-tab__content{display:flex;align-items:center;justify-content:center;height:inherit;pointer-events:none}.mdc-tab__text-label{transition:150ms color linear;display:inline-block;line-height:1;z-index:2}.mdc-tab__icon{transition:150ms color linear;z-index:2}.mdc-tab--stacked .mdc-tab__content{flex-direction:column;align-items:center;justify-content:center}.mdc-tab--stacked .mdc-tab__text-label{padding-top:6px;padding-bottom:4px}.mdc-tab--active .mdc-tab__text-label,.mdc-tab--active .mdc-tab__icon{transition-delay:100ms}.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label{padding-left:8px;padding-right:0}[dir=rtl] .mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label,.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label[dir=rtl]{padding-left:0;padding-right:8px}.mdc-tab-indicator{display:flex;position:absolute;top:0;left:0;justify-content:center;width:100%;height:100%;pointer-events:none;z-index:1}.mdc-tab-indicator__content{transform-origin:left;opacity:0}.mdc-tab-indicator__content--underline{align-self:flex-end;box-sizing:border-box;width:100%;border-top-style:solid}.mdc-tab-indicator__content--icon{align-self:center;margin:0 auto}.mdc-tab-indicator--active .mdc-tab-indicator__content{opacity:1}.mdc-tab-indicator .mdc-tab-indicator__content{transition:250ms transform cubic-bezier(0.4, 0, 0.2, 1)}.mdc-tab-indicator--no-transition .mdc-tab-indicator__content{transition:none}.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition:150ms opacity linear}.mdc-tab-indicator--active.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition-delay:100ms}.mat-mdc-tab-ripple{position:absolute;top:0;left:0;bottom:0;right:0;pointer-events:none}.mat-mdc-tab{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none;background:none;font-family:var(--mat-tab-header-label-text-font);font-size:var(--mat-tab-header-label-text-size);letter-spacing:var(--mat-tab-header-label-text-letter-spacing);line-height:var(--mat-tab-header-label-text-line-height);font-weight:var(--mat-tab-header-label-text-weight)}.mat-mdc-tab .mdc-tab-indicator__content--underline{border-color:var(--mdc-tab-indicator-active-indicator-color)}.mat-mdc-tab .mdc-tab-indicator__content--underline{border-top-width:var(--mdc-tab-indicator-active-indicator-height)}.mat-mdc-tab .mdc-tab-indicator__content--underline{border-radius:var(--mdc-tab-indicator-active-indicator-shape)}.mat-mdc-tab:not(.mdc-tab--stacked){height:var(--mdc-secondary-navigation-tab-container-height)}.mat-mdc-tab:not(:disabled).mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):hover.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):focus.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):active.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:disabled.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):hover:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):focus:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):active:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:disabled:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab.mdc-tab{flex-grow:0}.mat-mdc-tab:hover .mdc-tab__text-label{color:var(--mat-tab-header-inactive-hover-label-text-color)}.mat-mdc-tab:focus .mdc-tab__text-label{color:var(--mat-tab-header-inactive-focus-label-text-color)}.mat-mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--mat-tab-header-active-label-text-color)}.mat-mdc-tab.mdc-tab--active .mdc-tab__ripple::before,.mat-mdc-tab.mdc-tab--active .mat-ripple-element{background-color:var(--mat-tab-header-active-ripple-color)}.mat-mdc-tab.mdc-tab--active:hover .mdc-tab__text-label{color:var(--mat-tab-header-active-hover-label-text-color)}.mat-mdc-tab.mdc-tab--active:hover .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-hover-indicator-color)}.mat-mdc-tab.mdc-tab--active:focus .mdc-tab__text-label{color:var(--mat-tab-header-active-focus-label-text-color)}.mat-mdc-tab.mdc-tab--active:focus .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-focus-indicator-color)}.mat-mdc-tab.mat-mdc-tab-disabled{opacity:.4;pointer-events:none}.mat-mdc-tab.mat-mdc-tab-disabled .mdc-tab__content{pointer-events:none}.mat-mdc-tab.mat-mdc-tab-disabled .mdc-tab__ripple::before,.mat-mdc-tab.mat-mdc-tab-disabled .mat-ripple-element{background-color:var(--mat-tab-header-disabled-ripple-color)}.mat-mdc-tab .mdc-tab__ripple::before{content:\"\";display:block;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;pointer-events:none;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab .mdc-tab__text-label{color:var(--mat-tab-header-inactive-label-text-color);display:inline-flex;align-items:center}.mat-mdc-tab .mdc-tab__content{position:relative;pointer-events:auto}.mat-mdc-tab:hover .mdc-tab__ripple::before{opacity:.04}.mat-mdc-tab.cdk-program-focused .mdc-tab__ripple::before,.mat-mdc-tab.cdk-keyboard-focused .mdc-tab__ripple::before{opacity:.12}.mat-mdc-tab .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-group.mat-mdc-tab-group-stretch-tabs>.mat-mdc-tab-header .mat-mdc-tab{flex-grow:1}.mat-mdc-tab-group{display:flex;flex-direction:column;max-width:100%}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination{background-color:var(--mat-tab-header-with-background-background-color)}.mat-mdc-tab-group.mat-tabs-with-background.mat-primary>.mat-mdc-tab-header .mat-mdc-tab .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background.mat-primary>.mat-mdc-tab-header .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-header .mat-mdc-tab:not(.mdc-tab--active) .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-header .mat-mdc-tab:not(.mdc-tab--active) .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-mdc-focus-indicator::before,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-focus-indicator::before{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-ripple-element,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mdc-tab__ripple::before,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-ripple-element,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mdc-tab__ripple::before{background-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-mdc-tab-group-inverted-header{flex-direction:column-reverse}.mat-mdc-tab-group.mat-mdc-tab-group-inverted-header .mdc-tab-indicator__content--underline{align-self:flex-start}.mat-mdc-tab-body-wrapper{position:relative;overflow:hidden;display:flex;transition:height 500ms cubic-bezier(0.35, 0, 0.25, 1)}.mat-mdc-tab-body-wrapper._mat-animation-noopable{transition:none !important;animation:none !important}"], dependencies: [{ kind: "directive", type: i1$2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1$2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1$2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.CdkPortalOutlet, selector: "[cdkPortalOutlet]", inputs: ["cdkPortalOutlet"], outputs: ["attached"], exportAs: ["cdkPortalOutlet"] }, { kind: "directive", type: i5.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "directive", type: i4.CdkMonitorFocus, selector: "[cdkMonitorElementFocus], [cdkMonitorSubtreeFocus]", outputs: ["cdkFocusChange"], exportAs: ["cdkMonitorFocus"] }, { kind: "component", type: MatTabBody, selector: "mat-tab-body" }, { kind: "directive", type: MatTabLabelWrapper, selector: "[matTabLabelWrapper]", inputs: ["disabled", "fitInkBarToContent"] }, { kind: "component", type: MatTabHeader, selector: "mat-tab-header", inputs: ["selectedIndex"], outputs: ["selectFocusedIndex", "indexFocused"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
  1621. }
  1622. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabGroup, decorators: [{
  1623. type: Component,
  1624. args: [{ selector: 'mat-tab-group', exportAs: 'matTabGroup', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, inputs: ['color', 'disableRipple'], providers: [
  1625. {
  1626. provide: MAT_TAB_GROUP,
  1627. useExisting: MatTabGroup,
  1628. },
  1629. ], host: {
  1630. 'ngSkipHydration': '',
  1631. 'class': 'mat-mdc-tab-group',
  1632. '[class.mat-mdc-tab-group-dynamic-height]': 'dynamicHeight',
  1633. '[class.mat-mdc-tab-group-inverted-header]': 'headerPosition === "below"',
  1634. '[class.mat-mdc-tab-group-stretch-tabs]': 'stretchTabs',
  1635. }, template: "<mat-tab-header #tabHeader\n [selectedIndex]=\"selectedIndex || 0\"\n [disableRipple]=\"disableRipple\"\n [disablePagination]=\"disablePagination\"\n (indexFocused)=\"_focusChanged($event)\"\n (selectFocusedIndex)=\"selectedIndex = $event\">\n\n <div class=\"mdc-tab mat-mdc-tab mat-mdc-focus-indicator\"\n #tabNode\n role=\"tab\"\n matTabLabelWrapper\n cdkMonitorElementFocus\n *ngFor=\"let tab of _tabs; let i = index\"\n [id]=\"_getTabLabelId(i)\"\n [attr.tabIndex]=\"_getTabIndex(i)\"\n [attr.aria-posinset]=\"i + 1\"\n [attr.aria-setsize]=\"_tabs.length\"\n [attr.aria-controls]=\"_getTabContentId(i)\"\n [attr.aria-selected]=\"selectedIndex === i\"\n [attr.aria-label]=\"tab.ariaLabel || null\"\n [attr.aria-labelledby]=\"(!tab.ariaLabel && tab.ariaLabelledby) ? tab.ariaLabelledby : null\"\n [class.mdc-tab--active]=\"selectedIndex === i\"\n [ngClass]=\"tab.labelClass\"\n [disabled]=\"tab.disabled\"\n [fitInkBarToContent]=\"fitInkBarToContent\"\n (click)=\"_handleClick(tab, tabHeader, i)\"\n (cdkFocusChange)=\"_tabFocusChanged($event, i)\">\n <span class=\"mdc-tab__ripple\"></span>\n\n <!-- Needs to be a separate element, because we can't put\n `overflow: hidden` on tab due to the ink bar. -->\n <div\n class=\"mat-mdc-tab-ripple\"\n mat-ripple\n [matRippleTrigger]=\"tabNode\"\n [matRippleDisabled]=\"tab.disabled || disableRipple\"></div>\n\n <span class=\"mdc-tab__content\">\n <span class=\"mdc-tab__text-label\">\n <!-- If there is a label template, use it. -->\n <ng-template [ngIf]=\"tab.templateLabel\" [ngIfElse]=\"tabTextLabel\">\n <ng-template [cdkPortalOutlet]=\"tab.templateLabel\"></ng-template>\n </ng-template>\n\n <!-- If there is not a label template, fall back to the text label. -->\n <ng-template #tabTextLabel>{{tab.textLabel}}</ng-template>\n </span>\n </span>\n </div>\n</mat-tab-header>\n\n<div\n class=\"mat-mdc-tab-body-wrapper\"\n [class._mat-animation-noopable]=\"_animationMode === 'NoopAnimations'\"\n #tabBodyWrapper>\n <mat-tab-body role=\"tabpanel\"\n *ngFor=\"let tab of _tabs; let i = index\"\n [id]=\"_getTabContentId(i)\"\n [attr.tabindex]=\"(contentTabIndex != null && selectedIndex === i) ? contentTabIndex : null\"\n [attr.aria-labelledby]=\"_getTabLabelId(i)\"\n [class.mat-mdc-tab-body-active]=\"selectedIndex === i\"\n [ngClass]=\"tab.bodyClass\"\n [content]=\"tab.content!\"\n [position]=\"tab.position!\"\n [origin]=\"tab.origin\"\n [animationDuration]=\"animationDuration\"\n [preserveContent]=\"preserveContent\"\n (_onCentered)=\"_removeTabBodyWrapperHeight()\"\n (_onCentering)=\"_setTabBodyWrapperHeight($event)\">\n </mat-tab-body>\n</div>\n", styles: [".mdc-tab{min-width:90px;padding-right:24px;padding-left:24px;display:flex;flex:1 0 auto;justify-content:center;box-sizing:border-box;margin:0;padding-top:0;padding-bottom:0;border:none;outline:none;text-align:center;white-space:nowrap;cursor:pointer;-webkit-appearance:none;z-index:1}.mdc-tab::-moz-focus-inner{padding:0;border:0}.mdc-tab[hidden]{display:none}.mdc-tab--min-width{flex:0 1 auto}.mdc-tab__content{display:flex;align-items:center;justify-content:center;height:inherit;pointer-events:none}.mdc-tab__text-label{transition:150ms color linear;display:inline-block;line-height:1;z-index:2}.mdc-tab__icon{transition:150ms color linear;z-index:2}.mdc-tab--stacked .mdc-tab__content{flex-direction:column;align-items:center;justify-content:center}.mdc-tab--stacked .mdc-tab__text-label{padding-top:6px;padding-bottom:4px}.mdc-tab--active .mdc-tab__text-label,.mdc-tab--active .mdc-tab__icon{transition-delay:100ms}.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label{padding-left:8px;padding-right:0}[dir=rtl] .mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label,.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label[dir=rtl]{padding-left:0;padding-right:8px}.mdc-tab-indicator{display:flex;position:absolute;top:0;left:0;justify-content:center;width:100%;height:100%;pointer-events:none;z-index:1}.mdc-tab-indicator__content{transform-origin:left;opacity:0}.mdc-tab-indicator__content--underline{align-self:flex-end;box-sizing:border-box;width:100%;border-top-style:solid}.mdc-tab-indicator__content--icon{align-self:center;margin:0 auto}.mdc-tab-indicator--active .mdc-tab-indicator__content{opacity:1}.mdc-tab-indicator .mdc-tab-indicator__content{transition:250ms transform cubic-bezier(0.4, 0, 0.2, 1)}.mdc-tab-indicator--no-transition .mdc-tab-indicator__content{transition:none}.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition:150ms opacity linear}.mdc-tab-indicator--active.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition-delay:100ms}.mat-mdc-tab-ripple{position:absolute;top:0;left:0;bottom:0;right:0;pointer-events:none}.mat-mdc-tab{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none;background:none;font-family:var(--mat-tab-header-label-text-font);font-size:var(--mat-tab-header-label-text-size);letter-spacing:var(--mat-tab-header-label-text-letter-spacing);line-height:var(--mat-tab-header-label-text-line-height);font-weight:var(--mat-tab-header-label-text-weight)}.mat-mdc-tab .mdc-tab-indicator__content--underline{border-color:var(--mdc-tab-indicator-active-indicator-color)}.mat-mdc-tab .mdc-tab-indicator__content--underline{border-top-width:var(--mdc-tab-indicator-active-indicator-height)}.mat-mdc-tab .mdc-tab-indicator__content--underline{border-radius:var(--mdc-tab-indicator-active-indicator-shape)}.mat-mdc-tab:not(.mdc-tab--stacked){height:var(--mdc-secondary-navigation-tab-container-height)}.mat-mdc-tab:not(:disabled).mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):hover.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):focus.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):active.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:disabled.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):hover:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):focus:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:not(:disabled):active:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab:disabled:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab.mdc-tab{flex-grow:0}.mat-mdc-tab:hover .mdc-tab__text-label{color:var(--mat-tab-header-inactive-hover-label-text-color)}.mat-mdc-tab:focus .mdc-tab__text-label{color:var(--mat-tab-header-inactive-focus-label-text-color)}.mat-mdc-tab.mdc-tab--active .mdc-tab__text-label{color:var(--mat-tab-header-active-label-text-color)}.mat-mdc-tab.mdc-tab--active .mdc-tab__ripple::before,.mat-mdc-tab.mdc-tab--active .mat-ripple-element{background-color:var(--mat-tab-header-active-ripple-color)}.mat-mdc-tab.mdc-tab--active:hover .mdc-tab__text-label{color:var(--mat-tab-header-active-hover-label-text-color)}.mat-mdc-tab.mdc-tab--active:hover .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-hover-indicator-color)}.mat-mdc-tab.mdc-tab--active:focus .mdc-tab__text-label{color:var(--mat-tab-header-active-focus-label-text-color)}.mat-mdc-tab.mdc-tab--active:focus .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-focus-indicator-color)}.mat-mdc-tab.mat-mdc-tab-disabled{opacity:.4;pointer-events:none}.mat-mdc-tab.mat-mdc-tab-disabled .mdc-tab__content{pointer-events:none}.mat-mdc-tab.mat-mdc-tab-disabled .mdc-tab__ripple::before,.mat-mdc-tab.mat-mdc-tab-disabled .mat-ripple-element{background-color:var(--mat-tab-header-disabled-ripple-color)}.mat-mdc-tab .mdc-tab__ripple::before{content:\"\";display:block;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;pointer-events:none;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab .mdc-tab__text-label{color:var(--mat-tab-header-inactive-label-text-color);display:inline-flex;align-items:center}.mat-mdc-tab .mdc-tab__content{position:relative;pointer-events:auto}.mat-mdc-tab:hover .mdc-tab__ripple::before{opacity:.04}.mat-mdc-tab.cdk-program-focused .mdc-tab__ripple::before,.mat-mdc-tab.cdk-keyboard-focused .mdc-tab__ripple::before{opacity:.12}.mat-mdc-tab .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-group.mat-mdc-tab-group-stretch-tabs>.mat-mdc-tab-header .mat-mdc-tab{flex-grow:1}.mat-mdc-tab-group{display:flex;flex-direction:column;max-width:100%}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination{background-color:var(--mat-tab-header-with-background-background-color)}.mat-mdc-tab-group.mat-tabs-with-background.mat-primary>.mat-mdc-tab-header .mat-mdc-tab .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background.mat-primary>.mat-mdc-tab-header .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-header .mat-mdc-tab:not(.mdc-tab--active) .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-header .mat-mdc-tab:not(.mdc-tab--active) .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-mdc-focus-indicator::before,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-focus-indicator::before{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-ripple-element,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mdc-tab__ripple::before,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-ripple-element,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mdc-tab__ripple::before{background-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-group.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-group.mat-mdc-tab-group-inverted-header{flex-direction:column-reverse}.mat-mdc-tab-group.mat-mdc-tab-group-inverted-header .mdc-tab-indicator__content--underline{align-self:flex-start}.mat-mdc-tab-body-wrapper{position:relative;overflow:hidden;display:flex;transition:height 500ms cubic-bezier(0.35, 0, 0.25, 1)}.mat-mdc-tab-body-wrapper._mat-animation-noopable{transition:none !important;animation:none !important}"] }]
  1636. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: undefined, decorators: [{
  1637. type: Inject,
  1638. args: [MAT_TABS_CONFIG]
  1639. }, {
  1640. type: Optional
  1641. }] }, { type: undefined, decorators: [{
  1642. type: Optional
  1643. }, {
  1644. type: Inject,
  1645. args: [ANIMATION_MODULE_TYPE]
  1646. }] }]; }, propDecorators: { _allTabs: [{
  1647. type: ContentChildren,
  1648. args: [MatTab, { descendants: true }]
  1649. }], _tabBodyWrapper: [{
  1650. type: ViewChild,
  1651. args: ['tabBodyWrapper']
  1652. }], _tabHeader: [{
  1653. type: ViewChild,
  1654. args: ['tabHeader']
  1655. }], fitInkBarToContent: [{
  1656. type: Input
  1657. }], stretchTabs: [{
  1658. type: Input,
  1659. args: ['mat-stretch-tabs']
  1660. }] } });
  1661. /** A simple change event emitted on focus or selection changes. */
  1662. class MatTabChangeEvent {
  1663. }
  1664. // Increasing integer for generating unique ids for tab nav components.
  1665. let nextUniqueId = 0;
  1666. /**
  1667. * Base class with all of the `MatTabNav` functionality.
  1668. * @docs-private
  1669. */
  1670. class _MatTabNavBase extends MatPaginatedTabHeader {
  1671. /** Background color of the tab nav. */
  1672. get backgroundColor() {
  1673. return this._backgroundColor;
  1674. }
  1675. set backgroundColor(value) {
  1676. const classList = this._elementRef.nativeElement.classList;
  1677. classList.remove('mat-tabs-with-background', `mat-background-${this.backgroundColor}`);
  1678. if (value) {
  1679. classList.add('mat-tabs-with-background', `mat-background-${value}`);
  1680. }
  1681. this._backgroundColor = value;
  1682. }
  1683. /** Whether the ripple effect is disabled or not. */
  1684. get disableRipple() {
  1685. return this._disableRipple;
  1686. }
  1687. set disableRipple(value) {
  1688. this._disableRipple = coerceBooleanProperty(value);
  1689. }
  1690. constructor(elementRef, dir, ngZone, changeDetectorRef, viewportRuler, platform, animationMode) {
  1691. super(elementRef, changeDetectorRef, viewportRuler, dir, ngZone, platform, animationMode);
  1692. this._disableRipple = false;
  1693. /** Theme color of the nav bar. */
  1694. this.color = 'primary';
  1695. }
  1696. _itemSelected() {
  1697. // noop
  1698. }
  1699. ngAfterContentInit() {
  1700. // We need this to run before the `changes` subscription in parent to ensure that the
  1701. // selectedIndex is up-to-date by the time the super class starts looking for it.
  1702. this._items.changes.pipe(startWith(null), takeUntil(this._destroyed)).subscribe(() => {
  1703. this.updateActiveLink();
  1704. });
  1705. super.ngAfterContentInit();
  1706. }
  1707. /** Notifies the component that the active link has been changed. */
  1708. updateActiveLink() {
  1709. if (!this._items) {
  1710. return;
  1711. }
  1712. const items = this._items.toArray();
  1713. for (let i = 0; i < items.length; i++) {
  1714. if (items[i].active) {
  1715. this.selectedIndex = i;
  1716. this._changeDetectorRef.markForCheck();
  1717. if (this.tabPanel) {
  1718. this.tabPanel._activeTabId = items[i].id;
  1719. }
  1720. return;
  1721. }
  1722. }
  1723. // The ink bar should hide itself if no items are active.
  1724. this.selectedIndex = -1;
  1725. this._inkBar.hide();
  1726. }
  1727. _getRole() {
  1728. return this.tabPanel ? 'tablist' : this._elementRef.nativeElement.getAttribute('role');
  1729. }
  1730. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabNavBase, deps: [{ token: i0.ElementRef }, { token: i1.Directionality, optional: true }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1$1.ViewportRuler }, { token: i3.Platform }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  1731. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabNavBase, inputs: { backgroundColor: "backgroundColor", disableRipple: "disableRipple", color: "color", tabPanel: "tabPanel" }, usesInheritance: true, ngImport: i0 }); }
  1732. }
  1733. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabNavBase, decorators: [{
  1734. type: Directive
  1735. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.Directionality, decorators: [{
  1736. type: Optional
  1737. }] }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1$1.ViewportRuler }, { type: i3.Platform }, { type: undefined, decorators: [{
  1738. type: Optional
  1739. }, {
  1740. type: Inject,
  1741. args: [ANIMATION_MODULE_TYPE]
  1742. }] }]; }, propDecorators: { backgroundColor: [{
  1743. type: Input
  1744. }], disableRipple: [{
  1745. type: Input
  1746. }], color: [{
  1747. type: Input
  1748. }], tabPanel: [{
  1749. type: Input
  1750. }] } });
  1751. // Boilerplate for applying mixins to MatTabLink.
  1752. const _MatTabLinkMixinBase = mixinTabIndex(mixinDisableRipple(mixinDisabled(class {
  1753. })));
  1754. /** Base class with all of the `MatTabLink` functionality. */
  1755. class _MatTabLinkBase extends _MatTabLinkMixinBase {
  1756. /** Whether the link is active. */
  1757. get active() {
  1758. return this._isActive;
  1759. }
  1760. set active(value) {
  1761. const newValue = coerceBooleanProperty(value);
  1762. if (newValue !== this._isActive) {
  1763. this._isActive = newValue;
  1764. this._tabNavBar.updateActiveLink();
  1765. }
  1766. }
  1767. /**
  1768. * Whether ripples are disabled on interaction.
  1769. * @docs-private
  1770. */
  1771. get rippleDisabled() {
  1772. return (this.disabled ||
  1773. this.disableRipple ||
  1774. this._tabNavBar.disableRipple ||
  1775. !!this.rippleConfig.disabled);
  1776. }
  1777. constructor(_tabNavBar,
  1778. /** @docs-private */ elementRef, globalRippleOptions, tabIndex, _focusMonitor, animationMode) {
  1779. super();
  1780. this._tabNavBar = _tabNavBar;
  1781. this.elementRef = elementRef;
  1782. this._focusMonitor = _focusMonitor;
  1783. /** Whether the tab link is active or not. */
  1784. this._isActive = false;
  1785. /** Unique id for the tab. */
  1786. this.id = `mat-tab-link-${nextUniqueId++}`;
  1787. this.rippleConfig = globalRippleOptions || {};
  1788. this.tabIndex = parseInt(tabIndex) || 0;
  1789. if (animationMode === 'NoopAnimations') {
  1790. this.rippleConfig.animation = { enterDuration: 0, exitDuration: 0 };
  1791. }
  1792. }
  1793. /** Focuses the tab link. */
  1794. focus() {
  1795. this.elementRef.nativeElement.focus();
  1796. }
  1797. ngAfterViewInit() {
  1798. this._focusMonitor.monitor(this.elementRef);
  1799. }
  1800. ngOnDestroy() {
  1801. this._focusMonitor.stopMonitoring(this.elementRef);
  1802. }
  1803. _handleFocus() {
  1804. // Since we allow navigation through tabbing in the nav bar, we
  1805. // have to update the focused index whenever the link receives focus.
  1806. this._tabNavBar.focusIndex = this._tabNavBar._items.toArray().indexOf(this);
  1807. }
  1808. _handleKeydown(event) {
  1809. if (this._tabNavBar.tabPanel && event.keyCode === SPACE) {
  1810. this.elementRef.nativeElement.click();
  1811. }
  1812. }
  1813. _getAriaControls() {
  1814. return this._tabNavBar.tabPanel
  1815. ? this._tabNavBar.tabPanel?.id
  1816. : this.elementRef.nativeElement.getAttribute('aria-controls');
  1817. }
  1818. _getAriaSelected() {
  1819. if (this._tabNavBar.tabPanel) {
  1820. return this.active ? 'true' : 'false';
  1821. }
  1822. else {
  1823. return this.elementRef.nativeElement.getAttribute('aria-selected');
  1824. }
  1825. }
  1826. _getAriaCurrent() {
  1827. return this.active && !this._tabNavBar.tabPanel ? 'page' : null;
  1828. }
  1829. _getRole() {
  1830. return this._tabNavBar.tabPanel ? 'tab' : this.elementRef.nativeElement.getAttribute('role');
  1831. }
  1832. _getTabIndex() {
  1833. if (this._tabNavBar.tabPanel) {
  1834. return this._isActive && !this.disabled ? 0 : -1;
  1835. }
  1836. else {
  1837. return this.tabIndex;
  1838. }
  1839. }
  1840. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabLinkBase, deps: [{ token: _MatTabNavBase }, { token: i0.ElementRef }, { token: MAT_RIPPLE_GLOBAL_OPTIONS, optional: true }, { token: 'tabindex', attribute: true }, { token: i4.FocusMonitor }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Directive }); }
  1841. static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "16.0.0", type: _MatTabLinkBase, inputs: { active: "active", id: "id" }, usesInheritance: true, ngImport: i0 }); }
  1842. }
  1843. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: _MatTabLinkBase, decorators: [{
  1844. type: Directive
  1845. }], ctorParameters: function () { return [{ type: _MatTabNavBase }, { type: i0.ElementRef }, { type: undefined, decorators: [{
  1846. type: Optional
  1847. }, {
  1848. type: Inject,
  1849. args: [MAT_RIPPLE_GLOBAL_OPTIONS]
  1850. }] }, { type: undefined, decorators: [{
  1851. type: Attribute,
  1852. args: ['tabindex']
  1853. }] }, { type: i4.FocusMonitor }, { type: undefined, decorators: [{
  1854. type: Optional
  1855. }, {
  1856. type: Inject,
  1857. args: [ANIMATION_MODULE_TYPE]
  1858. }] }]; }, propDecorators: { active: [{
  1859. type: Input
  1860. }], id: [{
  1861. type: Input
  1862. }] } });
  1863. const _MatTabLinkBaseWithInkBarItem = mixinInkBarItem(_MatTabLinkBase);
  1864. /**
  1865. * Navigation component matching the styles of the tab group header.
  1866. * Provides anchored navigation with animated ink bar.
  1867. */
  1868. class MatTabNav extends _MatTabNavBase {
  1869. /** Whether the ink bar should fit its width to the size of the tab label content. */
  1870. get fitInkBarToContent() {
  1871. return this._fitInkBarToContent.value;
  1872. }
  1873. set fitInkBarToContent(v) {
  1874. this._fitInkBarToContent.next(coerceBooleanProperty(v));
  1875. this._changeDetectorRef.markForCheck();
  1876. }
  1877. /** Whether tabs should be stretched to fill the header. */
  1878. get stretchTabs() {
  1879. return this._stretchTabs;
  1880. }
  1881. set stretchTabs(v) {
  1882. this._stretchTabs = coerceBooleanProperty(v);
  1883. }
  1884. constructor(elementRef, dir, ngZone, changeDetectorRef, viewportRuler, platform, animationMode, defaultConfig) {
  1885. super(elementRef, dir, ngZone, changeDetectorRef, viewportRuler, platform, animationMode);
  1886. this._fitInkBarToContent = new BehaviorSubject(false);
  1887. this._stretchTabs = true;
  1888. this.disablePagination =
  1889. defaultConfig && defaultConfig.disablePagination != null
  1890. ? defaultConfig.disablePagination
  1891. : false;
  1892. this.fitInkBarToContent =
  1893. defaultConfig && defaultConfig.fitInkBarToContent != null
  1894. ? defaultConfig.fitInkBarToContent
  1895. : false;
  1896. this.stretchTabs =
  1897. defaultConfig && defaultConfig.stretchTabs != null ? defaultConfig.stretchTabs : true;
  1898. }
  1899. ngAfterContentInit() {
  1900. this._inkBar = new MatInkBar(this._items);
  1901. super.ngAfterContentInit();
  1902. }
  1903. ngAfterViewInit() {
  1904. if (!this.tabPanel && (typeof ngDevMode === 'undefined' || ngDevMode)) {
  1905. throw new Error('A mat-tab-nav-panel must be specified via [tabPanel].');
  1906. }
  1907. super.ngAfterViewInit();
  1908. }
  1909. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabNav, deps: [{ token: i0.ElementRef }, { token: i1.Directionality, optional: true }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: i1$1.ViewportRuler }, { token: i3.Platform }, { token: ANIMATION_MODULE_TYPE, optional: true }, { token: MAT_TABS_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
  1910. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTabNav, selector: "[mat-tab-nav-bar]", inputs: { color: "color", fitInkBarToContent: "fitInkBarToContent", stretchTabs: ["mat-stretch-tabs", "stretchTabs"] }, host: { properties: { "attr.role": "_getRole()", "class.mat-mdc-tab-header-pagination-controls-enabled": "_showPaginationControls", "class.mat-mdc-tab-header-rtl": "_getLayoutDirection() == 'rtl'", "class.mat-mdc-tab-nav-bar-stretch-tabs": "stretchTabs", "class.mat-primary": "color !== \"warn\" && color !== \"accent\"", "class.mat-accent": "color === \"accent\"", "class.mat-warn": "color === \"warn\"", "class._mat-animation-noopable": "_animationMode === \"NoopAnimations\"" }, classAttribute: "mat-mdc-tab-nav-bar mat-mdc-tab-header" }, queries: [{ propertyName: "_items", predicate: i0.forwardRef(function () { return MatTabLink; }), descendants: true }], viewQueries: [{ propertyName: "_tabListContainer", first: true, predicate: ["tabListContainer"], descendants: true, static: true }, { propertyName: "_tabList", first: true, predicate: ["tabList"], descendants: true, static: true }, { propertyName: "_tabListInner", first: true, predicate: ["tabListInner"], descendants: true, static: true }, { propertyName: "_nextPaginator", first: true, predicate: ["nextPaginator"], descendants: true }, { propertyName: "_previousPaginator", first: true, predicate: ["previousPaginator"], descendants: true }], exportAs: ["matTabNavBar", "matTabNav"], usesInheritance: true, ngImport: i0, template: "<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-before\"\n #previousPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n tabindex=\"-1\"\n [matRippleDisabled]=\"_disableScrollBefore || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollBefore\"\n [disabled]=\"_disableScrollBefore || null\"\n (click)=\"_handlePaginatorClick('before')\"\n (mousedown)=\"_handlePaginatorPress('before', $event)\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n\n<div class=\"mat-mdc-tab-link-container\" #tabListContainer (keydown)=\"_handleKeydown($event)\">\n <div class=\"mat-mdc-tab-list\" #tabList (cdkObserveContent)=\"_onContentChanges()\">\n <div class=\"mat-mdc-tab-links\" #tabListInner>\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-after\"\n #nextPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n [matRippleDisabled]=\"_disableScrollAfter || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollAfter\"\n [disabled]=\"_disableScrollAfter || null\"\n tabindex=\"-1\"\n (mousedown)=\"_handlePaginatorPress('after', $event)\"\n (click)=\"_handlePaginatorClick('after')\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n", styles: [".mdc-tab{min-width:90px;padding-right:24px;padding-left:24px;display:flex;flex:1 0 auto;justify-content:center;box-sizing:border-box;margin:0;padding-top:0;padding-bottom:0;border:none;outline:none;text-align:center;white-space:nowrap;cursor:pointer;-webkit-appearance:none;z-index:1}.mdc-tab::-moz-focus-inner{padding:0;border:0}.mdc-tab[hidden]{display:none}.mdc-tab--min-width{flex:0 1 auto}.mdc-tab__content{display:flex;align-items:center;justify-content:center;height:inherit;pointer-events:none}.mdc-tab__text-label{transition:150ms color linear;display:inline-block;line-height:1;z-index:2}.mdc-tab__icon{transition:150ms color linear;z-index:2}.mdc-tab--stacked .mdc-tab__content{flex-direction:column;align-items:center;justify-content:center}.mdc-tab--stacked .mdc-tab__text-label{padding-top:6px;padding-bottom:4px}.mdc-tab--active .mdc-tab__text-label,.mdc-tab--active .mdc-tab__icon{transition-delay:100ms}.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label{padding-left:8px;padding-right:0}[dir=rtl] .mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label,.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label[dir=rtl]{padding-left:0;padding-right:8px}.mdc-tab-indicator{display:flex;position:absolute;top:0;left:0;justify-content:center;width:100%;height:100%;pointer-events:none;z-index:1}.mdc-tab-indicator__content{transform-origin:left;opacity:0}.mdc-tab-indicator__content--underline{align-self:flex-end;box-sizing:border-box;width:100%;border-top-style:solid}.mdc-tab-indicator__content--icon{align-self:center;margin:0 auto}.mdc-tab-indicator--active .mdc-tab-indicator__content{opacity:1}.mdc-tab-indicator .mdc-tab-indicator__content{transition:250ms transform cubic-bezier(0.4, 0, 0.2, 1)}.mdc-tab-indicator--no-transition .mdc-tab-indicator__content{transition:none}.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition:150ms opacity linear}.mdc-tab-indicator--active.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition-delay:100ms}.mat-mdc-tab-ripple{position:absolute;top:0;left:0;bottom:0;right:0;pointer-events:none}.mat-mdc-tab-header{display:flex;overflow:hidden;position:relative;flex-shrink:0;--mdc-tab-indicator-active-indicator-height:2px;--mdc-tab-indicator-active-indicator-shape:0;--mdc-secondary-navigation-tab-container-height:48px}.mat-mdc-tab-header-pagination{-webkit-user-select:none;user-select:none;position:relative;display:none;justify-content:center;align-items:center;min-width:32px;cursor:pointer;z-index:2;-webkit-tap-highlight-color:rgba(0,0,0,0);touch-action:none;box-sizing:content-box;background:none;border:none;outline:0;padding:0}.mat-mdc-tab-header-pagination::-moz-focus-inner{border:0}.mat-mdc-tab-header-pagination .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-header-pagination-controls-enabled .mat-mdc-tab-header-pagination{display:flex}.mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after{padding-left:4px}.mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(-135deg)}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-pagination-after{padding-right:4px}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(45deg)}.mat-mdc-tab-header-pagination-chevron{border-style:solid;border-width:2px 2px 0 0;height:8px;width:8px;border-color:var(--mat-tab-header-pagination-icon-color)}.mat-mdc-tab-header-pagination-disabled{box-shadow:none;cursor:default;pointer-events:none}.mat-mdc-tab-header-pagination-disabled .mat-mdc-tab-header-pagination-chevron{opacity:.4}.mat-mdc-tab-list{flex-grow:1;position:relative;transition:transform 500ms cubic-bezier(0.35, 0, 0.25, 1)}._mat-animation-noopable .mat-mdc-tab-list{transition:none}._mat-animation-noopable span.mdc-tab-indicator__content,._mat-animation-noopable span.mdc-tab__text-label{transition:none}.mat-mdc-tab-links{display:flex;flex:1 0 auto}[mat-align-tabs=center]>.mat-mdc-tab-link-container .mat-mdc-tab-links{justify-content:center}[mat-align-tabs=end]>.mat-mdc-tab-link-container .mat-mdc-tab-links{justify-content:flex-end}.mat-mdc-tab-link-container{display:flex;flex-grow:1;overflow:hidden;z-index:1}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination{background-color:var(--mat-tab-header-with-background-background-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background.mat-primary>.mat-mdc-tab-link-container .mat-mdc-tab-link .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background.mat-primary>.mat-mdc-tab-link-container .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-link-container .mat-mdc-tab-link:not(.mdc-tab--active) .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-link-container .mat-mdc-tab-link:not(.mdc-tab--active) .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-mdc-focus-indicator::before,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-focus-indicator::before{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-ripple-element,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mdc-tab__ripple::before,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-ripple-element,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mdc-tab__ripple::before{background-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron{color:var(--mat-tab-header-with-background-foreground-color)}"], dependencies: [{ kind: "directive", type: i5.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }, { kind: "directive", type: i5$1.CdkObserveContent, selector: "[cdkObserveContent]", inputs: ["cdkObserveContentDisabled", "debounce"], outputs: ["cdkObserveContent"], exportAs: ["cdkObserveContent"] }], changeDetection: i0.ChangeDetectionStrategy.Default, encapsulation: i0.ViewEncapsulation.None }); }
  1911. }
  1912. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabNav, decorators: [{
  1913. type: Component,
  1914. args: [{ selector: '[mat-tab-nav-bar]', exportAs: 'matTabNavBar, matTabNav', inputs: ['color'], host: {
  1915. '[attr.role]': '_getRole()',
  1916. 'class': 'mat-mdc-tab-nav-bar mat-mdc-tab-header',
  1917. '[class.mat-mdc-tab-header-pagination-controls-enabled]': '_showPaginationControls',
  1918. '[class.mat-mdc-tab-header-rtl]': "_getLayoutDirection() == 'rtl'",
  1919. '[class.mat-mdc-tab-nav-bar-stretch-tabs]': 'stretchTabs',
  1920. '[class.mat-primary]': 'color !== "warn" && color !== "accent"',
  1921. '[class.mat-accent]': 'color === "accent"',
  1922. '[class.mat-warn]': 'color === "warn"',
  1923. '[class._mat-animation-noopable]': '_animationMode === "NoopAnimations"',
  1924. }, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.Default, template: "<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-before\"\n #previousPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n tabindex=\"-1\"\n [matRippleDisabled]=\"_disableScrollBefore || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollBefore\"\n [disabled]=\"_disableScrollBefore || null\"\n (click)=\"_handlePaginatorClick('before')\"\n (mousedown)=\"_handlePaginatorPress('before', $event)\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n\n<div class=\"mat-mdc-tab-link-container\" #tabListContainer (keydown)=\"_handleKeydown($event)\">\n <div class=\"mat-mdc-tab-list\" #tabList (cdkObserveContent)=\"_onContentChanges()\">\n <div class=\"mat-mdc-tab-links\" #tabListInner>\n <ng-content></ng-content>\n </div>\n </div>\n</div>\n\n<!-- TODO: this also had `mat-elevation-z4`. Figure out what we should do with it. -->\n<button class=\"mat-mdc-tab-header-pagination mat-mdc-tab-header-pagination-after\"\n #nextPaginator\n aria-hidden=\"true\"\n type=\"button\"\n mat-ripple\n [matRippleDisabled]=\"_disableScrollAfter || disableRipple\"\n [class.mat-mdc-tab-header-pagination-disabled]=\"_disableScrollAfter\"\n [disabled]=\"_disableScrollAfter || null\"\n tabindex=\"-1\"\n (mousedown)=\"_handlePaginatorPress('after', $event)\"\n (click)=\"_handlePaginatorClick('after')\"\n (touchend)=\"_stopInterval()\">\n <div class=\"mat-mdc-tab-header-pagination-chevron\"></div>\n</button>\n", styles: [".mdc-tab{min-width:90px;padding-right:24px;padding-left:24px;display:flex;flex:1 0 auto;justify-content:center;box-sizing:border-box;margin:0;padding-top:0;padding-bottom:0;border:none;outline:none;text-align:center;white-space:nowrap;cursor:pointer;-webkit-appearance:none;z-index:1}.mdc-tab::-moz-focus-inner{padding:0;border:0}.mdc-tab[hidden]{display:none}.mdc-tab--min-width{flex:0 1 auto}.mdc-tab__content{display:flex;align-items:center;justify-content:center;height:inherit;pointer-events:none}.mdc-tab__text-label{transition:150ms color linear;display:inline-block;line-height:1;z-index:2}.mdc-tab__icon{transition:150ms color linear;z-index:2}.mdc-tab--stacked .mdc-tab__content{flex-direction:column;align-items:center;justify-content:center}.mdc-tab--stacked .mdc-tab__text-label{padding-top:6px;padding-bottom:4px}.mdc-tab--active .mdc-tab__text-label,.mdc-tab--active .mdc-tab__icon{transition-delay:100ms}.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label{padding-left:8px;padding-right:0}[dir=rtl] .mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label,.mdc-tab:not(.mdc-tab--stacked) .mdc-tab__icon+.mdc-tab__text-label[dir=rtl]{padding-left:0;padding-right:8px}.mdc-tab-indicator{display:flex;position:absolute;top:0;left:0;justify-content:center;width:100%;height:100%;pointer-events:none;z-index:1}.mdc-tab-indicator__content{transform-origin:left;opacity:0}.mdc-tab-indicator__content--underline{align-self:flex-end;box-sizing:border-box;width:100%;border-top-style:solid}.mdc-tab-indicator__content--icon{align-self:center;margin:0 auto}.mdc-tab-indicator--active .mdc-tab-indicator__content{opacity:1}.mdc-tab-indicator .mdc-tab-indicator__content{transition:250ms transform cubic-bezier(0.4, 0, 0.2, 1)}.mdc-tab-indicator--no-transition .mdc-tab-indicator__content{transition:none}.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition:150ms opacity linear}.mdc-tab-indicator--active.mdc-tab-indicator--fade .mdc-tab-indicator__content{transition-delay:100ms}.mat-mdc-tab-ripple{position:absolute;top:0;left:0;bottom:0;right:0;pointer-events:none}.mat-mdc-tab-header{display:flex;overflow:hidden;position:relative;flex-shrink:0;--mdc-tab-indicator-active-indicator-height:2px;--mdc-tab-indicator-active-indicator-shape:0;--mdc-secondary-navigation-tab-container-height:48px}.mat-mdc-tab-header-pagination{-webkit-user-select:none;user-select:none;position:relative;display:none;justify-content:center;align-items:center;min-width:32px;cursor:pointer;z-index:2;-webkit-tap-highlight-color:rgba(0,0,0,0);touch-action:none;box-sizing:content-box;background:none;border:none;outline:0;padding:0}.mat-mdc-tab-header-pagination::-moz-focus-inner{border:0}.mat-mdc-tab-header-pagination .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-header-pagination-controls-enabled .mat-mdc-tab-header-pagination{display:flex}.mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after{padding-left:4px}.mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(-135deg)}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before,.mat-mdc-tab-header-pagination-after{padding-right:4px}.mat-mdc-tab-header-rtl .mat-mdc-tab-header-pagination-before .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-header-pagination-after .mat-mdc-tab-header-pagination-chevron{transform:rotate(45deg)}.mat-mdc-tab-header-pagination-chevron{border-style:solid;border-width:2px 2px 0 0;height:8px;width:8px;border-color:var(--mat-tab-header-pagination-icon-color)}.mat-mdc-tab-header-pagination-disabled{box-shadow:none;cursor:default;pointer-events:none}.mat-mdc-tab-header-pagination-disabled .mat-mdc-tab-header-pagination-chevron{opacity:.4}.mat-mdc-tab-list{flex-grow:1;position:relative;transition:transform 500ms cubic-bezier(0.35, 0, 0.25, 1)}._mat-animation-noopable .mat-mdc-tab-list{transition:none}._mat-animation-noopable span.mdc-tab-indicator__content,._mat-animation-noopable span.mdc-tab__text-label{transition:none}.mat-mdc-tab-links{display:flex;flex:1 0 auto}[mat-align-tabs=center]>.mat-mdc-tab-link-container .mat-mdc-tab-links{justify-content:center}[mat-align-tabs=end]>.mat-mdc-tab-link-container .mat-mdc-tab-links{justify-content:flex-end}.mat-mdc-tab-link-container{display:flex;flex-grow:1;overflow:hidden;z-index:1}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination{background-color:var(--mat-tab-header-with-background-background-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background.mat-primary>.mat-mdc-tab-link-container .mat-mdc-tab-link .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background.mat-primary>.mat-mdc-tab-link-container .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-link-container .mat-mdc-tab-link:not(.mdc-tab--active) .mdc-tab__text-label{color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background:not(.mat-primary)>.mat-mdc-tab-link-container .mat-mdc-tab-link:not(.mdc-tab--active) .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-mdc-focus-indicator::before,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-focus-indicator::before{border-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-ripple-element,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mdc-tab__ripple::before,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-ripple-element,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mdc-tab__ripple::before{background-color:var(--mat-tab-header-with-background-foreground-color)}.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-link-container .mat-mdc-tab-header-pagination-chevron,.mat-mdc-tab-nav-bar.mat-tabs-with-background>.mat-mdc-tab-header-pagination .mat-mdc-tab-header-pagination-chevron{color:var(--mat-tab-header-with-background-foreground-color)}"] }]
  1925. }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i1.Directionality, decorators: [{
  1926. type: Optional
  1927. }] }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: i1$1.ViewportRuler }, { type: i3.Platform }, { type: undefined, decorators: [{
  1928. type: Optional
  1929. }, {
  1930. type: Inject,
  1931. args: [ANIMATION_MODULE_TYPE]
  1932. }] }, { type: undefined, decorators: [{
  1933. type: Optional
  1934. }, {
  1935. type: Inject,
  1936. args: [MAT_TABS_CONFIG]
  1937. }] }]; }, propDecorators: { fitInkBarToContent: [{
  1938. type: Input
  1939. }], stretchTabs: [{
  1940. type: Input,
  1941. args: ['mat-stretch-tabs']
  1942. }], _items: [{
  1943. type: ContentChildren,
  1944. args: [forwardRef(() => MatTabLink), { descendants: true }]
  1945. }], _tabListContainer: [{
  1946. type: ViewChild,
  1947. args: ['tabListContainer', { static: true }]
  1948. }], _tabList: [{
  1949. type: ViewChild,
  1950. args: ['tabList', { static: true }]
  1951. }], _tabListInner: [{
  1952. type: ViewChild,
  1953. args: ['tabListInner', { static: true }]
  1954. }], _nextPaginator: [{
  1955. type: ViewChild,
  1956. args: ['nextPaginator']
  1957. }], _previousPaginator: [{
  1958. type: ViewChild,
  1959. args: ['previousPaginator']
  1960. }] } });
  1961. /**
  1962. * Link inside of a `mat-tab-nav-bar`.
  1963. */
  1964. class MatTabLink extends _MatTabLinkBaseWithInkBarItem {
  1965. constructor(tabNavBar, elementRef, globalRippleOptions, tabIndex, focusMonitor, animationMode) {
  1966. super(tabNavBar, elementRef, globalRippleOptions, tabIndex, focusMonitor, animationMode);
  1967. this._destroyed = new Subject();
  1968. tabNavBar._fitInkBarToContent.pipe(takeUntil(this._destroyed)).subscribe(fitInkBarToContent => {
  1969. this.fitInkBarToContent = fitInkBarToContent;
  1970. });
  1971. }
  1972. ngOnDestroy() {
  1973. this._destroyed.next();
  1974. this._destroyed.complete();
  1975. super.ngOnDestroy();
  1976. }
  1977. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabLink, deps: [{ token: MatTabNav }, { token: i0.ElementRef }, { token: MAT_RIPPLE_GLOBAL_OPTIONS, optional: true }, { token: 'tabindex', attribute: true }, { token: i4.FocusMonitor }, { token: ANIMATION_MODULE_TYPE, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
  1978. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTabLink, selector: "[mat-tab-link], [matTabLink]", inputs: { disabled: "disabled", disableRipple: "disableRipple", tabIndex: "tabIndex", active: "active", id: "id" }, host: { listeners: { "focus": "_handleFocus()", "keydown": "_handleKeydown($event)" }, properties: { "attr.aria-controls": "_getAriaControls()", "attr.aria-current": "_getAriaCurrent()", "attr.aria-disabled": "disabled", "attr.aria-selected": "_getAriaSelected()", "attr.id": "id", "attr.tabIndex": "_getTabIndex()", "attr.role": "_getRole()", "class.mat-mdc-tab-disabled": "disabled", "class.mdc-tab--active": "active" }, classAttribute: "mdc-tab mat-mdc-tab-link mat-mdc-focus-indicator" }, exportAs: ["matTabLink"], usesInheritance: true, ngImport: i0, template: "<span class=\"mdc-tab__ripple\"></span>\n\n<div\n class=\"mat-mdc-tab-ripple\"\n mat-ripple\n [matRippleTrigger]=\"elementRef.nativeElement\"\n [matRippleDisabled]=\"rippleDisabled\"></div>\n\n<span class=\"mdc-tab__content\">\n <span class=\"mdc-tab__text-label\">\n <ng-content></ng-content>\n </span>\n</span>\n\n", styles: [".mat-mdc-tab-link{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none;background:none;font-family:var(--mat-tab-header-label-text-font);font-size:var(--mat-tab-header-label-text-size);letter-spacing:var(--mat-tab-header-label-text-letter-spacing);line-height:var(--mat-tab-header-label-text-line-height);font-weight:var(--mat-tab-header-label-text-weight)}.mat-mdc-tab-link .mdc-tab-indicator__content--underline{border-color:var(--mdc-tab-indicator-active-indicator-color)}.mat-mdc-tab-link .mdc-tab-indicator__content--underline{border-top-width:var(--mdc-tab-indicator-active-indicator-height)}.mat-mdc-tab-link .mdc-tab-indicator__content--underline{border-radius:var(--mdc-tab-indicator-active-indicator-shape)}.mat-mdc-tab-link:not(.mdc-tab--stacked){height:var(--mdc-secondary-navigation-tab-container-height)}.mat-mdc-tab-link:not(:disabled).mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):hover.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):focus.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):active.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:disabled.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):hover:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):focus:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):active:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:disabled:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link.mdc-tab{flex-grow:0}.mat-mdc-tab-link:hover .mdc-tab__text-label{color:var(--mat-tab-header-inactive-hover-label-text-color)}.mat-mdc-tab-link:focus .mdc-tab__text-label{color:var(--mat-tab-header-inactive-focus-label-text-color)}.mat-mdc-tab-link.mdc-tab--active .mdc-tab__text-label{color:var(--mat-tab-header-active-label-text-color)}.mat-mdc-tab-link.mdc-tab--active .mdc-tab__ripple::before,.mat-mdc-tab-link.mdc-tab--active .mat-ripple-element{background-color:var(--mat-tab-header-active-ripple-color)}.mat-mdc-tab-link.mdc-tab--active:hover .mdc-tab__text-label{color:var(--mat-tab-header-active-hover-label-text-color)}.mat-mdc-tab-link.mdc-tab--active:hover .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-hover-indicator-color)}.mat-mdc-tab-link.mdc-tab--active:focus .mdc-tab__text-label{color:var(--mat-tab-header-active-focus-label-text-color)}.mat-mdc-tab-link.mdc-tab--active:focus .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-focus-indicator-color)}.mat-mdc-tab-link.mat-mdc-tab-disabled{opacity:.4;pointer-events:none}.mat-mdc-tab-link.mat-mdc-tab-disabled .mdc-tab__content{pointer-events:none}.mat-mdc-tab-link.mat-mdc-tab-disabled .mdc-tab__ripple::before,.mat-mdc-tab-link.mat-mdc-tab-disabled .mat-ripple-element{background-color:var(--mat-tab-header-disabled-ripple-color)}.mat-mdc-tab-link .mdc-tab__ripple::before{content:\"\";display:block;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;pointer-events:none;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-link .mdc-tab__text-label{color:var(--mat-tab-header-inactive-label-text-color);display:inline-flex;align-items:center}.mat-mdc-tab-link .mdc-tab__content{position:relative;pointer-events:auto}.mat-mdc-tab-link:hover .mdc-tab__ripple::before{opacity:.04}.mat-mdc-tab-link.cdk-program-focused .mdc-tab__ripple::before,.mat-mdc-tab-link.cdk-keyboard-focused .mdc-tab__ripple::before{opacity:.12}.mat-mdc-tab-link .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-header.mat-mdc-tab-nav-bar-stretch-tabs .mat-mdc-tab-link{flex-grow:1}.mat-mdc-tab-link::before{margin:5px}@media(max-width: 599px){.mat-mdc-tab-link{min-width:72px}}"], dependencies: [{ kind: "directive", type: i5.MatRipple, selector: "[mat-ripple], [matRipple]", inputs: ["matRippleColor", "matRippleUnbounded", "matRippleCentered", "matRippleRadius", "matRippleAnimation", "matRippleDisabled", "matRippleTrigger"], exportAs: ["matRipple"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
  1979. }
  1980. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabLink, decorators: [{
  1981. type: Component,
  1982. args: [{ selector: '[mat-tab-link], [matTabLink]', exportAs: 'matTabLink', inputs: ['disabled', 'disableRipple', 'tabIndex', 'active', 'id'], changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
  1983. 'class': 'mdc-tab mat-mdc-tab-link mat-mdc-focus-indicator',
  1984. '[attr.aria-controls]': '_getAriaControls()',
  1985. '[attr.aria-current]': '_getAriaCurrent()',
  1986. '[attr.aria-disabled]': 'disabled',
  1987. '[attr.aria-selected]': '_getAriaSelected()',
  1988. '[attr.id]': 'id',
  1989. '[attr.tabIndex]': '_getTabIndex()',
  1990. '[attr.role]': '_getRole()',
  1991. '[class.mat-mdc-tab-disabled]': 'disabled',
  1992. '[class.mdc-tab--active]': 'active',
  1993. '(focus)': '_handleFocus()',
  1994. '(keydown)': '_handleKeydown($event)',
  1995. }, template: "<span class=\"mdc-tab__ripple\"></span>\n\n<div\n class=\"mat-mdc-tab-ripple\"\n mat-ripple\n [matRippleTrigger]=\"elementRef.nativeElement\"\n [matRippleDisabled]=\"rippleDisabled\"></div>\n\n<span class=\"mdc-tab__content\">\n <span class=\"mdc-tab__text-label\">\n <ng-content></ng-content>\n </span>\n</span>\n\n", styles: [".mat-mdc-tab-link{-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-decoration:none;background:none;font-family:var(--mat-tab-header-label-text-font);font-size:var(--mat-tab-header-label-text-size);letter-spacing:var(--mat-tab-header-label-text-letter-spacing);line-height:var(--mat-tab-header-label-text-line-height);font-weight:var(--mat-tab-header-label-text-weight)}.mat-mdc-tab-link .mdc-tab-indicator__content--underline{border-color:var(--mdc-tab-indicator-active-indicator-color)}.mat-mdc-tab-link .mdc-tab-indicator__content--underline{border-top-width:var(--mdc-tab-indicator-active-indicator-height)}.mat-mdc-tab-link .mdc-tab-indicator__content--underline{border-radius:var(--mdc-tab-indicator-active-indicator-shape)}.mat-mdc-tab-link:not(.mdc-tab--stacked){height:var(--mdc-secondary-navigation-tab-container-height)}.mat-mdc-tab-link:not(:disabled).mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):hover.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):focus.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):active.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:disabled.mdc-tab--active .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):hover:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):focus:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:not(:disabled):active:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link:disabled:not(.mdc-tab--active) .mdc-tab__icon{fill:currentColor}.mat-mdc-tab-link.mdc-tab{flex-grow:0}.mat-mdc-tab-link:hover .mdc-tab__text-label{color:var(--mat-tab-header-inactive-hover-label-text-color)}.mat-mdc-tab-link:focus .mdc-tab__text-label{color:var(--mat-tab-header-inactive-focus-label-text-color)}.mat-mdc-tab-link.mdc-tab--active .mdc-tab__text-label{color:var(--mat-tab-header-active-label-text-color)}.mat-mdc-tab-link.mdc-tab--active .mdc-tab__ripple::before,.mat-mdc-tab-link.mdc-tab--active .mat-ripple-element{background-color:var(--mat-tab-header-active-ripple-color)}.mat-mdc-tab-link.mdc-tab--active:hover .mdc-tab__text-label{color:var(--mat-tab-header-active-hover-label-text-color)}.mat-mdc-tab-link.mdc-tab--active:hover .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-hover-indicator-color)}.mat-mdc-tab-link.mdc-tab--active:focus .mdc-tab__text-label{color:var(--mat-tab-header-active-focus-label-text-color)}.mat-mdc-tab-link.mdc-tab--active:focus .mdc-tab-indicator__content--underline{border-color:var(--mat-tab-header-active-focus-indicator-color)}.mat-mdc-tab-link.mat-mdc-tab-disabled{opacity:.4;pointer-events:none}.mat-mdc-tab-link.mat-mdc-tab-disabled .mdc-tab__content{pointer-events:none}.mat-mdc-tab-link.mat-mdc-tab-disabled .mdc-tab__ripple::before,.mat-mdc-tab-link.mat-mdc-tab-disabled .mat-ripple-element{background-color:var(--mat-tab-header-disabled-ripple-color)}.mat-mdc-tab-link .mdc-tab__ripple::before{content:\"\";display:block;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;pointer-events:none;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-link .mdc-tab__text-label{color:var(--mat-tab-header-inactive-label-text-color);display:inline-flex;align-items:center}.mat-mdc-tab-link .mdc-tab__content{position:relative;pointer-events:auto}.mat-mdc-tab-link:hover .mdc-tab__ripple::before{opacity:.04}.mat-mdc-tab-link.cdk-program-focused .mdc-tab__ripple::before,.mat-mdc-tab-link.cdk-keyboard-focused .mdc-tab__ripple::before{opacity:.12}.mat-mdc-tab-link .mat-ripple-element{opacity:.12;background-color:var(--mat-tab-header-inactive-ripple-color)}.mat-mdc-tab-header.mat-mdc-tab-nav-bar-stretch-tabs .mat-mdc-tab-link{flex-grow:1}.mat-mdc-tab-link::before{margin:5px}@media(max-width: 599px){.mat-mdc-tab-link{min-width:72px}}"] }]
  1996. }], ctorParameters: function () { return [{ type: MatTabNav }, { type: i0.ElementRef }, { type: undefined, decorators: [{
  1997. type: Optional
  1998. }, {
  1999. type: Inject,
  2000. args: [MAT_RIPPLE_GLOBAL_OPTIONS]
  2001. }] }, { type: undefined, decorators: [{
  2002. type: Attribute,
  2003. args: ['tabindex']
  2004. }] }, { type: i4.FocusMonitor }, { type: undefined, decorators: [{
  2005. type: Optional
  2006. }, {
  2007. type: Inject,
  2008. args: [ANIMATION_MODULE_TYPE]
  2009. }] }]; } });
  2010. /**
  2011. * Tab panel component associated with MatTabNav.
  2012. */
  2013. class MatTabNavPanel {
  2014. constructor() {
  2015. /** Unique id for the tab panel. */
  2016. this.id = `mat-tab-nav-panel-${nextUniqueId++}`;
  2017. }
  2018. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabNavPanel, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
  2019. static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: MatTabNavPanel, selector: "mat-tab-nav-panel", inputs: { id: "id" }, host: { attributes: { "role": "tabpanel" }, properties: { "attr.aria-labelledby": "_activeTabId", "attr.id": "id" }, classAttribute: "mat-mdc-tab-nav-panel" }, exportAs: ["matTabNavPanel"], ngImport: i0, template: '<ng-content></ng-content>', isInline: true, changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
  2020. }
  2021. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabNavPanel, decorators: [{
  2022. type: Component,
  2023. args: [{
  2024. selector: 'mat-tab-nav-panel',
  2025. exportAs: 'matTabNavPanel',
  2026. template: '<ng-content></ng-content>',
  2027. host: {
  2028. '[attr.aria-labelledby]': '_activeTabId',
  2029. '[attr.id]': 'id',
  2030. 'class': 'mat-mdc-tab-nav-panel',
  2031. 'role': 'tabpanel',
  2032. },
  2033. encapsulation: ViewEncapsulation.None,
  2034. changeDetection: ChangeDetectionStrategy.OnPush,
  2035. }]
  2036. }], propDecorators: { id: [{
  2037. type: Input
  2038. }] } });
  2039. class MatTabsModule {
  2040. static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); }
  2041. static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.0", ngImport: i0, type: MatTabsModule, declarations: [MatTabContent,
  2042. MatTabLabel,
  2043. MatTab,
  2044. MatTabGroup,
  2045. MatTabNav,
  2046. MatTabNavPanel,
  2047. MatTabLink,
  2048. // Private directives, should not be exported.
  2049. MatTabBody,
  2050. MatTabBodyPortal,
  2051. MatTabLabelWrapper,
  2052. MatTabHeader], imports: [CommonModule,
  2053. MatCommonModule,
  2054. PortalModule,
  2055. MatRippleModule,
  2056. ObserversModule,
  2057. A11yModule], exports: [MatCommonModule,
  2058. MatTabContent,
  2059. MatTabLabel,
  2060. MatTab,
  2061. MatTabGroup,
  2062. MatTabNav,
  2063. MatTabNavPanel,
  2064. MatTabLink] }); }
  2065. static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabsModule, imports: [CommonModule,
  2066. MatCommonModule,
  2067. PortalModule,
  2068. MatRippleModule,
  2069. ObserversModule,
  2070. A11yModule, MatCommonModule] }); }
  2071. }
  2072. i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: MatTabsModule, decorators: [{
  2073. type: NgModule,
  2074. args: [{
  2075. imports: [
  2076. CommonModule,
  2077. MatCommonModule,
  2078. PortalModule,
  2079. MatRippleModule,
  2080. ObserversModule,
  2081. A11yModule,
  2082. ],
  2083. exports: [
  2084. MatCommonModule,
  2085. MatTabContent,
  2086. MatTabLabel,
  2087. MatTab,
  2088. MatTabGroup,
  2089. MatTabNav,
  2090. MatTabNavPanel,
  2091. MatTabLink,
  2092. ],
  2093. declarations: [
  2094. MatTabContent,
  2095. MatTabLabel,
  2096. MatTab,
  2097. MatTabGroup,
  2098. MatTabNav,
  2099. MatTabNavPanel,
  2100. MatTabLink,
  2101. // Private directives, should not be exported.
  2102. MatTabBody,
  2103. MatTabBodyPortal,
  2104. MatTabLabelWrapper,
  2105. MatTabHeader,
  2106. ],
  2107. }]
  2108. }] });
  2109. /**
  2110. * Generated bundle index. Do not edit.
  2111. */
  2112. export { MAT_TAB, MAT_TABS_CONFIG, MAT_TAB_CONTENT, MAT_TAB_GROUP, MAT_TAB_LABEL, MatInkBar, MatPaginatedTabHeader, MatTab, MatTabBody, MatTabBodyPortal, MatTabChangeEvent, MatTabContent, MatTabGroup, MatTabHeader, MatTabLabel, MatTabLabelWrapper, MatTabLink, MatTabNav, MatTabNavPanel, MatTabsModule, _MAT_INK_BAR_POSITIONER, _MAT_INK_BAR_POSITIONER_FACTORY, _MatTabBase, _MatTabBodyBase, _MatTabGroupBase, _MatTabHeaderBase, _MatTabLabelWrapperBase, _MatTabLinkBase, _MatTabNavBase, matTabsAnimations };
  2113. //# sourceMappingURL=tabs.mjs.map