7
7
*/
8
8
9
9
import { DOCUMENT } from '@angular/common' ;
10
+ import { ANIMATION_MODULE_TYPE , Injectable , NgZone , OnDestroy , inject } from '@angular/core' ;
10
11
import {
11
- ANIMATION_MODULE_TYPE ,
12
- ElementRef ,
13
- Injectable ,
14
- NgZone ,
15
- OnDestroy ,
16
- inject ,
17
- } from '@angular/core' ;
18
- import { MAT_RIPPLE_GLOBAL_OPTIONS , MatRipple } from '../ripple' ;
12
+ MAT_RIPPLE_GLOBAL_OPTIONS ,
13
+ RippleRenderer ,
14
+ RippleTarget ,
15
+ defaultRippleAnimationConfig ,
16
+ } from '../ripple' ;
19
17
import { Platform , _getEventTarget } from '@angular/cdk/platform' ;
20
18
21
19
/** The options for the MatRippleLoader's event listeners. */
@@ -55,7 +53,10 @@ export class MatRippleLoader implements OnDestroy {
55
53
private _globalRippleOptions = inject ( MAT_RIPPLE_GLOBAL_OPTIONS , { optional : true } ) ;
56
54
private _platform = inject ( Platform ) ;
57
55
private _ngZone = inject ( NgZone ) ;
58
- private _hosts = new Map < HTMLElement , MatRipple > ( ) ;
56
+ private _hosts = new Map <
57
+ HTMLElement ,
58
+ { renderer : RippleRenderer ; target : RippleTarget ; hasSetUpEvents : boolean }
59
+ > ( ) ;
59
60
60
61
constructor ( ) {
61
62
this . _ngZone . runOutsideAngular ( ( ) => {
@@ -65,7 +66,7 @@ export class MatRippleLoader implements OnDestroy {
65
66
} ) ;
66
67
}
67
68
68
- ngOnDestroy ( ) {
69
+ ngOnDestroy ( ) : void {
69
70
const hosts = this . _hosts . keys ( ) ;
70
71
71
72
for ( const host of hosts ) {
@@ -115,13 +116,15 @@ export class MatRippleLoader implements OnDestroy {
115
116
116
117
// If the ripple has already been instantiated, just disable it.
117
118
if ( ripple ) {
118
- ripple . disabled = disabled ;
119
- return ;
120
- }
119
+ ripple . target . rippleDisabled = disabled ;
121
120
122
- // Otherwise, set an attribute so we know what the
123
- // disabled state should be when the ripple is initialized.
124
- if ( disabled ) {
121
+ if ( ! disabled && ! ripple . hasSetUpEvents ) {
122
+ ripple . hasSetUpEvents = true ;
123
+ ripple . renderer . setupTriggerEvents ( host ) ;
124
+ }
125
+ } else if ( disabled ) {
126
+ // Otherwise, set an attribute so we know what the
127
+ // disabled state should be when the ripple is initialized.
125
128
host . setAttribute ( matRippleDisabled , '' ) ;
126
129
} else {
127
130
host . removeAttribute ( matRippleDisabled ) ;
@@ -148,50 +151,59 @@ export class MatRippleLoader implements OnDestroy {
148
151
} ;
149
152
150
153
/** Creates a MatRipple and appends it to the given element. */
151
- private _createRipple ( host : HTMLElement ) : MatRipple | undefined {
152
- if ( ! this . _document ) {
154
+ private _createRipple ( host : HTMLElement ) : void {
155
+ if ( ! this . _document || this . _hosts . has ( host ) ) {
153
156
return ;
154
157
}
155
158
156
- const existingRipple = this . _hosts . get ( host ) ;
157
- if ( existingRipple ) {
158
- return existingRipple ;
159
- }
160
-
161
159
// Create the ripple element.
162
160
host . querySelector ( '.mat-ripple' ) ?. remove ( ) ;
163
161
const rippleEl = this . _document . createElement ( 'span' ) ;
164
162
rippleEl . classList . add ( 'mat-ripple' , host . getAttribute ( matRippleClassName ) ! ) ;
165
163
host . append ( rippleEl ) ;
166
164
167
- // Create the MatRipple.
168
- const ripple = new MatRipple (
169
- new ElementRef ( rippleEl ) ,
170
- this . _ngZone ,
171
- this . _platform ,
172
- this . _globalRippleOptions ? this . _globalRippleOptions : undefined ,
173
- this . _animationMode ? this . _animationMode : undefined ,
174
- ) ;
175
- ripple . _isInitialized = true ;
176
- ripple . trigger = host ;
177
- ripple . centered = host . hasAttribute ( matRippleCentered ) ;
178
- ripple . disabled = host . hasAttribute ( matRippleDisabled ) ;
179
- this . attachRipple ( host , ripple ) ;
180
- return ripple ;
181
- }
165
+ const isNoopAnimations = this . _animationMode === 'NoopAnimations' ;
166
+ const globalOptions = this . _globalRippleOptions ;
167
+ const enterDuration = isNoopAnimations
168
+ ? 0
169
+ : globalOptions ?. animation ?. enterDuration ?? defaultRippleAnimationConfig . enterDuration ;
170
+ const exitDuration = isNoopAnimations
171
+ ? 0
172
+ : globalOptions ?. animation ?. exitDuration ?? defaultRippleAnimationConfig . exitDuration ;
173
+ const target : RippleTarget = {
174
+ rippleDisabled :
175
+ isNoopAnimations || globalOptions ?. disabled || host . hasAttribute ( matRippleDisabled ) ,
176
+ rippleConfig : {
177
+ centered : host . hasAttribute ( matRippleCentered ) ,
178
+ terminateOnPointerUp : globalOptions ?. terminateOnPointerUp ,
179
+ animation : {
180
+ enterDuration,
181
+ exitDuration,
182
+ } ,
183
+ } ,
184
+ } ;
185
+
186
+ const renderer = new RippleRenderer ( target , this . _ngZone , rippleEl , this . _platform ) ;
187
+ const hasSetUpEvents = ! target . rippleDisabled ;
188
+
189
+ if ( hasSetUpEvents ) {
190
+ renderer . setupTriggerEvents ( host ) ;
191
+ }
192
+
193
+ this . _hosts . set ( host , {
194
+ target,
195
+ renderer,
196
+ hasSetUpEvents,
197
+ } ) ;
182
198
183
- attachRipple ( host : HTMLElement , ripple : MatRipple ) : void {
184
199
host . removeAttribute ( matRippleUninitialized ) ;
185
- this . _hosts . set ( host , ripple ) ;
186
200
}
187
201
188
- destroyRipple ( host : HTMLElement ) {
202
+ destroyRipple ( host : HTMLElement ) : void {
189
203
const ripple = this . _hosts . get ( host ) ;
190
204
191
205
if ( ripple ) {
192
- // Since this directive is created manually, it needs to be destroyed manually too.
193
- // tslint:disable-next-line:no-lifecycle-invocation
194
- ripple . ngOnDestroy ( ) ;
206
+ ripple . renderer . _removeTriggerEvents ( ) ;
195
207
this . _hosts . delete ( host ) ;
196
208
}
197
209
}
0 commit comments