@@ -5,30 +5,51 @@ import {
55 ViewEncapsulation ,
66 NgZone ,
77 OnDestroy ,
8+ animate ,
9+ state ,
10+ style ,
11+ transition ,
12+ trigger ,
13+ AnimationTransitionEvent ,
14+ EventEmitter ,
815} from '@angular/core' ;
916import { BasePortalHost , ComponentPortal , PortalHostDirective , TemplatePortal } from '../core' ;
1017import { MdDialogConfig } from './dialog-config' ;
11- import { MdDialogRef } from './dialog-ref' ;
1218import { MdDialogContentAlreadyAttachedError } from './dialog-errors' ;
1319import { FocusTrap } from '../core/a11y/focus-trap' ;
1420import 'rxjs/add/operator/first' ;
1521
1622
23+ /** Possible states for the dialog container animation. */
24+ export type MdDialogContainerAnimationState = 'void' | 'enter' | 'exit' | 'exit-start' ;
25+
26+
1727/**
1828 * Internal component that wraps user-provided dialog content.
29+ * Animation is based on https://material.io/guidelines/motion/choreography.html.
1930 * @docs -private
2031 */
2132@Component ( {
2233 moduleId : module . id ,
2334 selector : 'md-dialog-container, mat-dialog-container' ,
2435 templateUrl : 'dialog-container.html' ,
2536 styleUrls : [ 'dialog.css' ] ,
37+ encapsulation : ViewEncapsulation . None ,
38+ animations : [
39+ trigger ( 'slideDialog' , [
40+ state ( 'void' , style ( { transform : 'translateY(25%) scale(0.9)' , opacity : 0 } ) ) ,
41+ state ( 'enter' , style ( { transform : 'translateY(0%) scale(1)' , opacity : 1 } ) ) ,
42+ state ( 'exit' , style ( { transform : 'translateY(25%)' , opacity : 0 } ) ) ,
43+ transition ( '* => *' , animate ( '400ms cubic-bezier(0.25, 0.8, 0.25, 1)' ) ) ,
44+ ] )
45+ ] ,
2646 host : {
2747 'class' : 'md-dialog-container' ,
2848 '[attr.role]' : 'dialogConfig?.role' ,
29- '(keydown.escape)' : 'handleEscapeKey()' ,
49+ '(keydown.escape)' : '_handleEscapeKey()' ,
50+ '[@slideDialog]' : '_state' ,
51+ '(@slideDialog.done)' : '_onAnimationDone($event)' ,
3052 } ,
31- encapsulation : ViewEncapsulation . None ,
3253} )
3354export class MdDialogContainer extends BasePortalHost implements OnDestroy {
3455 /** The portal host inside of this container into which the dialog content will be loaded. */
@@ -43,8 +64,11 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
4364 /** The dialog configuration. */
4465 dialogConfig : MdDialogConfig ;
4566
46- /** Reference to the open dialog. */
47- dialogRef : MdDialogRef < any > ;
67+ /** State of the dialog animation. */
68+ _state : MdDialogContainerAnimationState = 'enter' ;
69+
70+ /** Emits the current animation state whenever it changes. */
71+ _onAnimationStateChange = new EventEmitter < MdDialogContainerAnimationState > ( ) ;
4872
4973 constructor ( private _ngZone : NgZone ) {
5074 super ( ) ;
@@ -77,22 +101,40 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
77101 throw Error ( 'Not yet implemented' ) ;
78102 }
79103
104+ ngOnDestroy ( ) {
105+ // When the dialog is destroyed, return focus to the element that originally had it before
106+ // the dialog was opened. Wait for the DOM to finish settling before changing the focus so
107+ // that it doesn't end up back on the <body>.
108+ this . _ngZone . onMicrotaskEmpty . first ( ) . subscribe ( ( ) => {
109+ ( this . _elementFocusedBeforeDialogWasOpened as HTMLElement ) . focus ( ) ;
110+ this . _onAnimationStateChange . complete ( ) ;
111+ } ) ;
112+ }
113+
80114 /**
81115 * Handles the user pressing the Escape key.
82116 * @docs -private
83117 */
84- handleEscapeKey ( ) {
118+ _handleEscapeKey ( ) {
85119 if ( ! this . dialogConfig . disableClose ) {
86- this . dialogRef . close ( ) ;
120+ this . _exit ( ) ;
87121 }
88122 }
89123
90- ngOnDestroy ( ) {
91- // When the dialog is destroyed, return focus to the element that originally had it before
92- // the dialog was opened. Wait for the DOM to finish settling before changing the focus so
93- // that it doesn't end up back on the <body>.
94- this . _ngZone . onMicrotaskEmpty . first ( ) . subscribe ( ( ) => {
95- ( this . _elementFocusedBeforeDialogWasOpened as HTMLElement ) . focus ( ) ;
96- } ) ;
124+ /**
125+ * Kicks off the leave animation.
126+ * @docs -private
127+ */
128+ _exit ( ) : void {
129+ this . _state = 'exit' ;
130+ this . _onAnimationStateChange . emit ( 'exit-start' ) ;
131+ }
132+
133+ /**
134+ * Callback, invoked whenever an animation on the host completes.
135+ * @docs -private
136+ */
137+ _onAnimationDone ( event : AnimationTransitionEvent ) {
138+ this . _onAnimationStateChange . emit ( event . toState as MdDialogContainerAnimationState ) ;
97139 }
98140}
0 commit comments