6
6
* found in the LICENSE file at https://angular.dev/license
7
7
*/
8
8
9
- import { AnimationEvent } from '@angular/animations' ;
10
9
import { CdkDialogContainer } from '@angular/cdk/dialog' ;
11
10
import { BreakpointObserver , Breakpoints } from '@angular/cdk/layout' ;
12
11
import {
12
+ ANIMATION_MODULE_TYPE ,
13
13
ChangeDetectionStrategy ,
14
14
Component ,
15
15
EventEmitter ,
@@ -18,9 +18,11 @@ import {
18
18
inject ,
19
19
} from '@angular/core' ;
20
20
import { Subscription } from 'rxjs' ;
21
- import { matBottomSheetAnimations } from './bottom-sheet-animations' ;
22
21
import { CdkPortalOutlet } from '@angular/cdk/portal' ;
23
22
23
+ const ENTER_ANIMATION = '_mat-bottom-sheet-enter' ;
24
+ const EXIT_ANIMATION = '_mat-bottom-sheet-exit' ;
25
+
24
26
/**
25
27
* Internal component that wraps user-provided bottom sheet content.
26
28
* @docs -private
@@ -35,27 +37,34 @@ import {CdkPortalOutlet} from '@angular/cdk/portal';
35
37
// tslint:disable-next-line:validate-decorators
36
38
changeDetection : ChangeDetectionStrategy . Default ,
37
39
encapsulation : ViewEncapsulation . None ,
38
- animations : [ matBottomSheetAnimations . bottomSheetState ] ,
39
40
host : {
40
41
'class' : 'mat-bottom-sheet-container' ,
42
+ '[class.mat-bottom-sheet-container-animations-enabled]' : '!_animationsDisabled' ,
43
+ '[class.mat-bottom-sheet-container-enter]' : '_animationState === "visible"' ,
44
+ '[class.mat-bottom-sheet-container-exit]' : '_animationState === "hidden"' ,
41
45
'tabindex' : '-1' ,
42
46
'[attr.role]' : '_config.role' ,
43
47
'[attr.aria-modal]' : '_config.ariaModal' ,
44
48
'[attr.aria-label]' : '_config.ariaLabel' ,
45
- '[@state] ' : '_animationState ' ,
46
- '(@state.start )' : '_onAnimationStart( $event)' ,
47
- '(@state.done )' : '_onAnimationDone( $event)' ,
49
+ '(animationstart) ' : '_handleAnimationEvent(true, $event.animationName) ' ,
50
+ '(animationend )' : '_handleAnimationEvent(false, $event.animationName )' ,
51
+ '(animationcancel )' : '_handleAnimationEvent(false, $event.animationName )' ,
48
52
} ,
49
53
imports : [ CdkPortalOutlet ] ,
50
54
} )
51
55
export class MatBottomSheetContainer extends CdkDialogContainer implements OnDestroy {
52
56
private _breakpointSubscription : Subscription ;
57
+ protected _animationsDisabled =
58
+ inject ( ANIMATION_MODULE_TYPE , { optional : true } ) === 'NoopAnimations' ;
53
59
54
60
/** The state of the bottom sheet animations. */
55
61
_animationState : 'void' | 'visible' | 'hidden' = 'void' ;
56
62
57
63
/** Emits whenever the state of the animation changes. */
58
- _animationStateChanged = new EventEmitter < AnimationEvent > ( ) ;
64
+ _animationStateChanged = new EventEmitter < {
65
+ toState : 'visible' | 'hidden' ;
66
+ phase : 'start' | 'done' ;
67
+ } > ( ) ;
59
68
60
69
/** Whether the component has been destroyed. */
61
70
private _destroyed : boolean ;
@@ -93,14 +102,21 @@ export class MatBottomSheetContainer extends CdkDialogContainer implements OnDes
93
102
this . _animationState = 'visible' ;
94
103
this . _changeDetectorRef . markForCheck ( ) ;
95
104
this . _changeDetectorRef . detectChanges ( ) ;
105
+ if ( this . _animationsDisabled ) {
106
+ this . _simulateAnimation ( ENTER_ANIMATION ) ;
107
+ }
96
108
}
97
109
}
98
110
99
111
/** Begin animation of the bottom sheet exiting from view. */
100
112
exit ( ) : void {
101
113
if ( ! this . _destroyed ) {
114
+ this . _elementRef . nativeElement . setAttribute ( 'mat-exit' , '' ) ;
102
115
this . _animationState = 'hidden' ;
103
116
this . _changeDetectorRef . markForCheck ( ) ;
117
+ if ( this . _animationsDisabled ) {
118
+ this . _simulateAnimation ( EXIT_ANIMATION ) ;
119
+ }
104
120
}
105
121
}
106
122
@@ -110,16 +126,27 @@ export class MatBottomSheetContainer extends CdkDialogContainer implements OnDes
110
126
this . _destroyed = true ;
111
127
}
112
128
113
- _onAnimationDone ( event : AnimationEvent ) {
114
- if ( event . toState === 'visible' ) {
129
+ private _simulateAnimation ( name : typeof ENTER_ANIMATION | typeof EXIT_ANIMATION ) {
130
+ this . _ngZone . run ( ( ) => {
131
+ this . _handleAnimationEvent ( true , name ) ;
132
+ setTimeout ( ( ) => this . _handleAnimationEvent ( false , name ) ) ;
133
+ } ) ;
134
+ }
135
+
136
+ protected _handleAnimationEvent ( isStart : boolean , animationName : string ) {
137
+ const isEnter = animationName === ENTER_ANIMATION ;
138
+ const isExit = animationName === EXIT_ANIMATION ;
139
+
140
+ if ( isEnter ) {
115
141
this . _trapFocus ( ) ;
116
142
}
117
143
118
- this . _animationStateChanged . emit ( event ) ;
119
- }
120
-
121
- _onAnimationStart ( event : AnimationEvent ) {
122
- this . _animationStateChanged . emit ( event ) ;
144
+ if ( isEnter || isExit ) {
145
+ this . _animationStateChanged . emit ( {
146
+ toState : isEnter ? 'visible' : 'hidden' ,
147
+ phase : isStart ? 'start' : 'done' ,
148
+ } ) ;
149
+ }
123
150
}
124
151
125
152
protected override _captureInitialFocus ( ) : void { }
0 commit comments