import { ThyPlacement } from 'ngx-tethys/core' ; import { ThyPopover , ThyPopoverConfig } from 'ngx-tethys/popover' ; import { coerceBooleanProperty , FunctionProp , warnDeprecation } from 'ngx-tethys/util' ; import { fromEvent , Observable , Subject } from 'rxjs' ; import { debounceTime , mapTo , takeUntil , tap } from 'rxjs/operators' ; import { coerceArray } from '@angular/cdk/coercion' ; import { AfterViewInit , ChangeDetectorRef , Directive , ElementRef , EventEmitter , Input , OnChanges , OnDestroy , OnInit , Output , SimpleChange , TemplateRef } from '@angular/core' ; import { AbstractPickerComponent } from './abstract-picker.component' ; import { DatePopupComponent } from './lib/popups/date-popup.component' ; import { CompatibleValue , PanelMode } from './standard-types' ; @ Directive ( ) export abstract class PickerDirective extends AbstractPickerComponent implements OnInit , AfterViewInit , OnDestroy , OnChanges { showWeek = false ; @ Input ( ) thyDateRender : FunctionProp < TemplateRef < Date > | string > ; @ Input ( ) thyMode : PanelMode = 'date' ; panelMode : PanelMode | PanelMode [ ] ; @ Output ( ) readonly thyOnPanelChange = new EventEmitter < PanelMode | PanelMode [ ] > ( ) ; @ Output ( ) readonly thyOnCalendarChange = new EventEmitter < Date [ ] > ( ) ; private _showTime : object | boolean ; @ Input ( ) get thyShowTime ( ) : object | boolean { return this . _showTime ; } set thyShowTime ( value ) { this . _showTime = typeof value === 'object' ? value : coerceBooleanProperty ( value ) ; } @ Input ( ) thyMustShowTime = false ; @ Input ( ) thyPlacement : ThyPlacement = 'bottom' ; private offset = 4 ; @ Input ( ) set thyOffset ( value ) { warnDeprecation ( `thyOffset parameter will be deprecated, please use thyPopoverOptions instead.` ) ; this . offset = value ; } private hasBackdrop = true ; @ Input ( ) set thyHasBackdrop ( value ) { warnDeprecation ( `thyHasBackdrop parameter will be deprecated, please use thyPopoverOptions instead.` ) ; this . hasBackdrop = value ; } @ Input ( ) thyPopoverOptions : ThyPopoverConfig ; @ Input ( ) thyStopPropagation = true ; private destroy$ = new Subject ( ) ; private el : HTMLElement = this . elementRef . nativeElement ; readonly $click : Observable < boolean > = fromEvent ( this . el , 'click' ) . pipe ( tap ( e => { if ( this . thyStopPropagation ) { e . stopPropagation ( ) ; } } ) , mapTo ( true ) ) ; ngOnInit ( ) { this . thyMode = this . thyMode || 'date' ; this . panelMode = this . isRange ? [ this . thyMode , this . thyMode ] : this . thyMode ; } private openOverlay ( ) { const popoverRef = this . thyPopover . open ( DatePopupComponent , Object . assign ( { origin : this . el , hasBackdrop : this . hasBackdrop , backdropClass : 'thy-overlay-transparent-backdrop' , offset : this . offset , initialState : { isRange : this . isRange , panelMode : this . panelMode , showWeek : this . showWeek , value : this . thyValue , showTime : this . thyShowTime , mustShowTime : this . withTime , format : this . thyFormat , dateRender : this . thyDateRender , disabledDate : this . thyDisabledDate , placeholder : this . thyPlaceHolder , className : this . thyPanelClassName , defaultPickerValue : this . thyDefaultPickerValue , minDate : this . thyMinDate , maxDate : this . thyMaxDate } , placement : this . thyPlacement } , this . thyPopoverOptions ) ) ; if ( popoverRef ) { const componentInstance = popoverRef . componentInstance ; componentInstance . valueChange . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( event ) => this . onValueChange ( event ) ) ; componentInstance . calendarChange . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( event ) => { const rangeValue = coerceArray ( event ) . map ( x => x . nativeDate ) ; this . thyOnCalendarChange . emit ( rangeValue ) ; } ) ; componentInstance . showTimePickerChange . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( event ) => this . onShowTimePickerChange ( event ) ) ; componentInstance . ngOnChanges ( { value : { } as SimpleChange } ) ; popoverRef . afterOpened ( ) . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => this . thyOpenChange . emit ( true ) ) ; popoverRef . afterClosed ( ) . pipe ( takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => this . thyOpenChange . emit ( false ) ) ; } } closeOverlay ( ) { this . thyPopover . close ( ) ; } initActionSubscribe ( ) { this . $click . pipe ( debounceTime ( 50 ) , takeUntil ( this . destroy$ ) ) . subscribe ( ( ) => { if ( ! this . thyDisabled && ! this . thyReadonly ) { this . openOverlay ( ) ; } } ) ; } constructor ( public elementRef , public cdr , private thyPopover ) { super ( cdr ) ; } ngAfterViewInit ( ) { this . setDefaultTimePickerState ( ) ; this . initActionSubscribe ( ) ; } ngOnDestroy ( ) { this . destroy$ . next ( ) ; this . destroy$ . complete ( ) ; } onValueChange ( value ) { this . restoreTimePickerState ( value ) ; super . onValueChange ( value ) ; this . closeOverlay ( ) ; } setDefaultTimePickerState ( ) { this . withTime = this . thyMustShowTime ; } restoreTimePickerState ( value ) { if ( ! value ) { this . withTime = this . thyMustShowTime || this . originWithTime ; } } onShowTimePickerChange ( show ) { this . withTime = show ; } }