import { Component , Input , HostBinding , ContentChildren , QueryList , AfterContentInit , OnChanges , OnDestroy , OnInit , SimpleChanges , SimpleChange , ChangeDetectorRef , ViewEncapsulation , ChangeDetectionStrategy } from '@angular/core' ; import { takeUntil } from 'rxjs/operators' ; import { ThyTimelineItemComponent } from './timeline-item.component' ; import { ThyTimelineService } from './timeline.service' ; import { Subject } from 'rxjs' ; export type ThyTimeMode = 'left' | 'right' | 'center' ; export enum ThyTimeModes { left = 'left' , right = 'right' , center = 'center' } export type ThyTimeDirection = 'horizontal' | 'vertical' ; @ Component ( { changeDetection : ChangeDetectionStrategy . OnPush , encapsulation : ViewEncapsulation . None , selector : 'thy-timeline' , providers : [ ThyTimelineService ] , template : `
        <ng-container>
            <ng-container *ngFor="let item of timelineItems">
                <ng-template [ngTemplateOutlet]="item.template"></ng-template>
            </ng-container>
            <ng-content></ng-content>
        </ng-container>
    ` } ) export class ThyTimelineComponent implements OnInit , AfterContentInit , OnChanges , OnDestroy { @ Input ( ) thyReverse : Boolean ; @ Input ( ) thyMode : ThyTimeMode ; @ Input ( ) thyDirection : ThyTimeDirection = 'vertical' ; public timelineItems : ThyTimelineItemComponent [ ] = [ ] ; private destroy$ = new Subject < void > ( ) ; @ HostBinding ( `class.thy-timeline` ) isTimeline = true ; @ HostBinding ( `class.thy-timeline-right` ) rightTimeline = false ; @ HostBinding ( `class.thy-timeline-center` ) centerTimeline = false ; @ HostBinding ( `class.thy-timeline-template` ) templateTimeline = false ; @ HostBinding ( `class.thy-timeline-horizontal` ) horizontal = false ; @ ContentChildren ( ThyTimelineItemComponent ) listOfItems : QueryList < ThyTimelineItemComponent > ; constructor ( private cdr , private timelineService ) { } ngOnChanges ( changes ) { const { thyMode , thyReverse } = changes ; if ( thyMode && ! this . horizontal ) { if ( thyMode . currentValue === 'right' ) { this . rightTimeline = ! this . templateTimeline ; this . centerTimeline = false ; } else if ( thyMode . currentValue === 'center' ) { this . centerTimeline = true ; this . rightTimeline = false ; } else { this . rightTimeline = false ; this . centerTimeline = false ; } } if ( ( simpleChangeActivated ( thyMode ) && ! this . horizontal ) || simpleChangeActivated ( thyReverse ) ) { this . updateChildren ( ) ; } } ngOnInit ( ) { this . horizontal = this . thyDirection === 'horizontal' ? true : false ; this . timelineService . check$ . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => { this . cdr . markForCheck ( ) ; } ) ; } ngAfterContentInit ( ) { this . updateChildren ( ) ; this . listOfItems . changes . subscribe ( ( ) => { this . updateChildren ( ) ; } ) ; } ngOnDestroy ( ) { this . destroy$ . next ( ) ; this . destroy$ . complete ( ) ; } private updateChildren ( ) { if ( this . listOfItems && this . listOfItems . length ) { const length = this . listOfItems . length ; this . listOfItems . forEach ( ( item , index ) => { item . isLast = ! this . thyReverse ? index === length - 1 : index === 0 ; item . isFirst = this . thyReverse ? index === length - 1 : index === 0 ; item . reverse = this . thyReverse ; if ( ! this . horizontal ) { item . position = getTimelineItemPosition ( index , this . thyMode ) ; } if ( item . description || ( item . thyPosition && ! this . horizontal ) ) { this . templateTimeline = true ; } item . detectChanges ( ) ; } ) ; this . timelineItems = this . thyReverse ? this . listOfItems . toArray ( ) . reverse ( ) : this . listOfItems . toArray ( ) ; } this . cdr . markForCheck ( ) ; } } function simpleChangeActivated ( simpleChange ? ) { return ! ! ( simpleChange && ( simpleChange . previousValue !== simpleChange . currentValue || simpleChange . isFirstChange ( ) ) ) ; } function getTimelineItemPosition ( index , mode ) { return mode === 'left' ? 'left' : mode === 'right' ? 'right' : mode === 'center' && index % 2 === 0 ? 'left' : 'right' ; }