/** code from https://github.com/angular/material2 */ import { AfterContentChecked, AfterViewInit, Component, ContentChild, ElementRef, EventEmitter, Input, OnInit, Output, Renderer2, TemplateRef, ViewChild, ViewEncapsulation, } from '@angular/core'; import { Observable } from 'rxjs/Observable'; import { map } from 'rxjs/operators/map'; import { YztTabComponent } from './yzt-tab.component'; import { YztTabsNavComponent } from './yzt-tabs-nav.component'; export interface NzAnimatedInterface { inkBar: boolean; tabPane: boolean; } export class NzTabChangeEvent { index: number; tab: YztTabComponent; } export type NzTabPosition = 'top' | 'bottom' | 'left' | 'right'; export type NzTabPositionMode = 'horizontal' | 'vertical'; export type NzTabType = 'line' | 'card'; @Component({ selector: 'yzt-tabset', encapsulation: ViewEncapsulation.None, template: `
`, styleUrls: [ './style/index.less', './style/patch.less' ] }) export class YztTabSetComponent implements AfterContentChecked, OnInit, AfterViewInit { _el; _classMap; _prefixCls = 'yzt-tabs'; _width; _tabPosition: NzTabPosition = 'top'; _tabPositionMode: NzTabPositionMode = 'horizontal'; _indexToSelect: number | null = 0; _selectedIndex: number | null = null; _isViewInit = false; _tabs: YztTabComponent[] = []; @Input() nzTabBarExtraTemplate: TemplateRef; @ContentChild('nzTabBarExtraContent') nzTabBarExtraContent: TemplateRef; @ViewChild('tabNav') _tabNav: YztTabsNavComponent; @ViewChild('tabContent') _tabContent: ElementRef; @ViewChild('hostContent') _hostContent: ElementRef; @Input() nzAnimated: NzAnimatedInterface | boolean = true; @Input() nzShowPagination = true; @Input() nzHide = false; @Input() set nzSelectedIndex(value: number | null) { this._indexToSelect = value; } get nzSelectedIndex(): number | null { return this._selectedIndex; } @Output() get nzSelectedIndexChange(): Observable { return this.nzSelectChange.pipe(map(event => event.index)); } @Output() nzSelectChange: EventEmitter = new EventEmitter(true); @Input() nzSize = 'default'; _type: NzTabType = 'line'; tabs: YztTabComponent[] = []; @Input() set nzTabPosition(value: NzTabPosition) { if (this._tabPosition === value) { return; } this._tabPosition = value; if ((this._tabPosition === 'top') || (this._tabPosition === 'bottom')) { this._tabPositionMode = 'horizontal'; } else { this._tabPositionMode = 'vertical'; } this._setPosition(value); this._setClassMap(); } get nzTabPosition(): NzTabPosition { return this._tabPosition; } @Input() set nzType(value: NzTabType) { if (this._type === value) { return; } this._type = value; if (this._type === 'card') { this.nzAnimated = false; } this._setClassMap(); } get nzType(): NzTabType { return this._type; } _setPosition(value: NzTabPosition): void { if (this._isViewInit) { if (value === 'bottom') { this._renderer.insertBefore(this._hostContent.nativeElement, this._tabContent.nativeElement, this._tabNav._elementRef.nativeElement); } else { this._renderer.insertBefore(this._hostContent.nativeElement, this._tabNav._elementRef.nativeElement, this._tabContent.nativeElement); } } } _setClassMap(): void { this._classMap = { [this._prefixCls]: true, [`${this._prefixCls}-vertical`]: (this._tabPosition === 'left') || (this._tabPosition === 'right'), [`${this._prefixCls}-${this._tabPosition}`]: this._tabPosition, [`${this._prefixCls}-no-animation`]: (this.nzAnimated === false) || ((this.nzAnimated as NzAnimatedInterface).tabPane === false), [`${this._prefixCls}-${this._type}`]: this._type, [`${this._prefixCls}-mini`]: (this.nzSize === 'small') }; } clickLabel(index: number): void { this.nzSelectedIndex = index; this._tabs[index].nzClick.emit(); } ngOnInit(): void { this._setClassMap(); } ngAfterContentChecked(): void { // Clamp the next selected index to the bounds of 0 and the tabs length. Note the `|| 0`, which // ensures that values like NaN can't get through and which would otherwise throw the // component into an infinite loop (since Math.max(NaN, 0) === NaN). const indexToSelect = this._indexToSelect = Math.min(this._tabs.length - 1, Math.max(this._indexToSelect || 0, 0)); // If there is a change in selected index, emit a change event. Should not trigger if // the selected index has not yet been initialized. if (this._selectedIndex !== indexToSelect && this._selectedIndex != null) { this.nzSelectChange.emit(this._createChangeEvent(indexToSelect)); } // Setup the position for each tab and optionally setup an origin on the next selected tab. this._tabs.forEach((tab: YztTabComponent, index: number) => { tab.position = index - indexToSelect; // If there is already a selected tab, then set up an origin for the next selected tab // if it doesn't have one already. if (this._selectedIndex != null && tab.position === 0 && !tab.origin) { tab.origin = indexToSelect - this._selectedIndex; } }); this._selectedIndex = indexToSelect; } ngAfterViewInit(): void { this._isViewInit = true; this._setPosition(this._tabPosition); } private _createChangeEvent(index: number): NzTabChangeEvent { const event = new NzTabChangeEvent(); event.index = index; if (this._tabs && this._tabs.length) { event.tab = this._tabs[index]; this._tabs.forEach((item, i) => { if (i !== index) { item.nzDeselect.emit(); } }); event.tab.nzSelect.emit(); } return event; } get inkBarAnimated(): boolean { return (this.nzAnimated === true) || ((this.nzAnimated as NzAnimatedInterface).inkBar === true); } get tabPaneAnimated(): boolean { return (this.nzAnimated === true) || ((this.nzAnimated as NzAnimatedInterface).tabPane === true); } constructor(private _renderer: Renderer2) { } }