11import { CommonModule , DOCUMENT } from '@angular/common' ;
2- import { Component , ElementRef , inject , Inject , OnDestroy , OnInit , ViewChild , ViewEncapsulation } from '@angular/core' ;
2+ import {
3+ Component ,
4+ ElementRef ,
5+ EventEmitter ,
6+ inject ,
7+ OnDestroy ,
8+ OnInit ,
9+ ViewChild ,
10+ ViewEncapsulation ,
11+ } from '@angular/core' ;
312import { fromEvent , merge , Subject } from 'rxjs' ;
413import { filter , takeUntil } from 'rxjs/operators' ;
514import { InternalDialogRef } from './dialog-ref' ;
615import { DialogService } from './dialog.service' ;
716import { coerceCssPixelValue } from './dialog.utils' ;
817import { DialogDraggableDirective , DragOffset } from './draggable.directive' ;
918import { DIALOG_CONFIG , NODES_TO_INSERT } from './providers' ;
19+ import { DialogConfig } from '@ngneat/dialog' ;
20+ import { animate , animateChild , group , keyframes , query , state , style , transition , trigger } from '@angular/animations' ;
21+
22+ export const _defaultParams = {
23+ params : { enterAnimationDuration : '150ms' , exitAnimationDuration : '75ms' } ,
24+ } ;
1025
1126@Component ( {
1227 selector : 'ngneat-dialog' ,
1328 standalone : true ,
1429 imports : [ DialogDraggableDirective , CommonModule ] ,
30+ animations : [
31+ trigger ( 'dialogContent' , [
32+ // Note: The `enter` animation transitions to `transform: none`, because for some reason
33+ // specifying the transform explicitly, causes IE both to blur the dialog content and
34+ // decimate the animation performance. Leaving it as `none` solves both issues.
35+ state ( 'void, exit' , style ( { opacity : 0 , transform : 'scale(0.7)' } ) ) ,
36+ state ( 'enter' , style ( { transform : 'none' } ) ) ,
37+ transition (
38+ '* => enter' ,
39+ group ( [
40+ animate (
41+ '0.4s cubic-bezier(0.25, 0.8, 0.25, 1)' ,
42+ keyframes ( [ style ( { opacity : 0 , transform : 'translateX(50px)' } ) , style ( { opacity : 1 , transform : 'none' } ) ] )
43+ ) ,
44+ query ( '@*' , animateChild ( ) , { optional : true } ) ,
45+ ] ) ,
46+ _defaultParams
47+ ) ,
48+ transition (
49+ '* => void, * => exit' ,
50+ group ( [
51+ animate ( '0.4s cubic-bezier(0.4, 0.0, 0.2, 1)' , style ( { opacity : 0 } ) ) ,
52+ query ( '@*' , animateChild ( ) , { optional : true } ) ,
53+ ] ) ,
54+ _defaultParams
55+ ) ,
56+ ] ) ,
57+ trigger ( 'dialogContainer' , [
58+ transition (
59+ '* => void, * => exit' ,
60+ group ( [
61+ animate ( '0.4s cubic-bezier(0.4, 0.0, 0.2, 1)' , style ( { opacity : 0 } ) ) ,
62+ query ( '@*' , animateChild ( ) , { optional : true } ) ,
63+ ] ) ,
64+ _defaultParams
65+ ) ,
66+ ] ) ,
67+ ] ,
68+ host : {
69+ '[@dialogContainer]' : `this.dialogRef._getAnimationState()` ,
70+ '(@dialogContainer.start)' : '_onAnimationStart($event)' ,
71+ '(@dialogContainer.done)' : '_onAnimationDone($event)' ,
72+ } ,
1573 template : `
1674 <div
1775 #backdrop
@@ -21,6 +79,9 @@ import { DIALOG_CONFIG, NODES_TO_INSERT } from './providers';
2179 >
2280 <div
2381 #dialog
82+ [@dialogContent]="this.dialogRef._getAnimationState()"
83+ (@dialogContent.start)="_onAnimationStart($event)"
84+ (@dialogContent.done)="_onAnimationDone($event)"
2485 class="ngneat-dialog-content"
2586 [class.ngneat-dialog-resizable]="config.resizable"
2687 [ngStyle]="styles"
@@ -49,6 +110,7 @@ import { DIALOG_CONFIG, NODES_TO_INSERT } from './providers';
49110 encapsulation : ViewEncapsulation . None ,
50111} )
51112export class DialogComponent implements OnInit , OnDestroy {
113+ _animationStateChanged = new EventEmitter < { state : string ; totalTime : number } > ( ) ;
52114 config = inject ( DIALOG_CONFIG ) ;
53115 dialogRef = inject ( InternalDialogRef ) ;
54116
@@ -96,6 +158,16 @@ export class DialogComponent implements OnInit, OnDestroy {
96158 }
97159
98160 ngOnInit ( ) {
161+ const dialogElement = this . dialogElement . nativeElement ;
162+ this . evaluateConfigBasedFields ( ) ;
163+
164+ // `dialogElement` is resolved at this point
165+ // And here is where dialog finally will be placed
166+ this . nodes . forEach ( ( node ) => dialogElement . appendChild ( node ) ) ;
167+ this . dialogRef . _state = 'enter' ;
168+ }
169+
170+ private evaluateConfigBasedFields ( ) : void {
99171 const backdrop = this . config . backdrop ? this . backdrop . nativeElement : this . document . body ;
100172 const dialogElement = this . dialogElement . nativeElement ;
101173
@@ -133,6 +205,22 @@ export class DialogComponent implements OnInit, OnDestroy {
133205 }
134206 }
135207
208+ _onAnimationStart ( event ) : any {
209+ if ( event . toState === 'enter' ) {
210+ this . _animationStateChanged . next ( { state : 'opening' , totalTime : event . totalTime } ) ;
211+ } else if ( event . toState === 'exit' || event . toState === 'void' ) {
212+ this . _animationStateChanged . next ( { state : 'closing' , totalTime : event . totalTime } ) ;
213+ }
214+ }
215+
216+ _onAnimationDone ( event ) {
217+ if ( event . toState === 'enter' ) {
218+ // this._openAnimationDone(totalTime);
219+ } else if ( event . toState === 'exit' ) {
220+ this . _animationStateChanged . next ( { state : 'closed' , totalTime : event . totalTime } ) ;
221+ }
222+ }
223+
136224 reset ( offset ?: DragOffset ) : void {
137225 if ( this . config . draggable ) {
138226 this . draggable . reset ( offset ) ;
0 commit comments