Skip to content

Commit 2f972c6

Browse files
committed
Use ripple renderer without MatRipple
1 parent 3274e49 commit 2f972c6

File tree

4 files changed

+61
-37
lines changed

4 files changed

+61
-37
lines changed

src/lib/core/ripple/index.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ import {PlatformModule} from '@angular/cdk/platform';
1111
import {MatCommonModule} from '../common-behaviors/common-module';
1212
import {MatRipple} from './ripple';
1313

14-
export {MatRipple, RippleGlobalOptions, MAT_RIPPLE_GLOBAL_OPTIONS} from './ripple';
15-
export {RippleRef, RippleState} from './ripple-ref';
16-
export {RippleConfig, RIPPLE_FADE_IN_DURATION, RIPPLE_FADE_OUT_DURATION} from './ripple-renderer';
14+
export * from './ripple';
15+
export * from './ripple-ref';
16+
export * from './ripple-renderer';
1717

1818
@NgModule({
1919
imports: [MatCommonModule, PlatformModule],

src/lib/core/ripple/ripple-renderer.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import {ElementRef, NgZone} from '@angular/core';
1010
import {Platform} from '@angular/cdk/platform';
11-
import {MatRipple} from './ripple';
1211
import {RippleRef, RippleState} from './ripple-ref';
1312

1413
/** Fade-in duration for the ripples. Can be modified with the speedFactor option. */
@@ -31,6 +30,19 @@ export type RippleConfig = {
3130
persistent?: boolean;
3231
};
3332

33+
/**
34+
* Interface that describes the target for launching ripples.
35+
* It defines the ripple configuration and disabled state for interaction ripples.
36+
* @docs-private
37+
*/
38+
export interface RippleTarget {
39+
/** Configuration for ripples that are launched on pointer down. */
40+
rippleConfig: RippleConfig;
41+
42+
/** Whether ripples on pointer down should be disabled. */
43+
rippleDisabled: boolean;
44+
}
45+
3446
/**
3547
* Helper service that performs DOM manipulations. Not intended to be used outside this module.
3648
* The constructor takes a reference to the ripple directive's host element and a map of DOM
@@ -58,7 +70,7 @@ export class RippleRenderer {
5870
/** Time in milliseconds when the last touchstart event happened. */
5971
private _lastTouchStartEvent: number;
6072

61-
constructor(private _ripple: MatRipple,
73+
constructor(private _target: RippleTarget,
6274
private _ngZone: NgZone,
6375
elementRef: ElementRef,
6476
platform: Platform) {
@@ -170,7 +182,7 @@ export class RippleRenderer {
170182
}
171183

172184
// Remove all previously registered event listeners from the trigger element.
173-
this._removeTriggerListeners();
185+
this._removeTriggerEvents();
174186

175187
this._ngZone.runOutsideAngular(() => {
176188
this._triggerEvents.forEach((fn, type) => element.addEventListener(type, fn));
@@ -184,23 +196,23 @@ export class RippleRenderer {
184196
const isSyntheticEvent = this._lastTouchStartEvent &&
185197
Date.now() < this._lastTouchStartEvent + IGNORE_MOUSE_EVENTS_TIMEOUT;
186198

187-
if (!this._ripple.disabled && !isSyntheticEvent) {
199+
if (!this._target.rippleDisabled && !isSyntheticEvent) {
188200
this._isPointerDown = true;
189-
this.fadeInRipple(event.clientX, event.clientY, this._ripple.rippleConfig);
201+
this.fadeInRipple(event.clientX, event.clientY, this._target.rippleConfig);
190202
}
191203
}
192204

193205
/** Function being called whenever the trigger is being pressed using touch. */
194206
private onTouchStart(event: TouchEvent) {
195-
if (!this._ripple.disabled) {
207+
if (!this._target.rippleDisabled) {
196208
// Some browsers fire mouse events after a `touchstart` event. Those synthetic mouse
197209
// events will launch a second ripple if we don't ignore mouse events for a specific
198210
// time after a touchstart event.
199211
this._lastTouchStartEvent = Date.now();
200212
this._isPointerDown = true;
201213

202214
this.fadeInRipple(
203-
event.touches[0].clientX, event.touches[0].clientY, this._ripple.rippleConfig);
215+
event.touches[0].clientX, event.touches[0].clientY, this._target.rippleConfig);
204216
}
205217
}
206218

@@ -226,7 +238,7 @@ export class RippleRenderer {
226238
}
227239

228240
/** Removes previously registered event listeners from the trigger element. */
229-
_removeTriggerListeners() {
241+
_removeTriggerEvents() {
230242
if (this._triggerElement) {
231243
this._triggerEvents.forEach((fn, type) => {
232244
this._triggerElement!.removeEventListener(type, fn);

src/lib/core/ripple/ripple.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
Optional,
2020
} from '@angular/core';
2121
import {RippleRef} from './ripple-ref';
22-
import {RippleConfig, RippleRenderer} from './ripple-renderer';
22+
import {RippleConfig, RippleRenderer, RippleTarget} from './ripple-renderer';
2323

2424
/** Configurable options for `matRipple`. */
2525
export interface RippleGlobalOptions {
@@ -49,7 +49,7 @@ export const MAT_RIPPLE_GLOBAL_OPTIONS =
4949
'[class.mat-ripple-unbounded]': 'unbounded'
5050
}
5151
})
52-
export class MatRipple implements OnInit, OnDestroy {
52+
export class MatRipple implements OnInit, OnDestroy, RippleTarget {
5353

5454
/** Custom color for all ripples. */
5555
@Input('matRippleColor') color: string;
@@ -82,7 +82,7 @@ export class MatRipple implements OnInit, OnDestroy {
8282
* by using the `launch()` method.
8383
*/
8484
@Input('matRippleDisabled')
85-
get disabled() { return this._disabled || !!this._globalOptions.disabled; }
85+
get disabled() { return this._disabled; }
8686
set disabled(value: boolean) {
8787
this._disabled = value;
8888
this._setupTriggerEventsIfEnabled();
@@ -125,7 +125,7 @@ export class MatRipple implements OnInit, OnDestroy {
125125
}
126126

127127
ngOnDestroy() {
128-
this._rippleRenderer._removeTriggerListeners();
128+
this._rippleRenderer._removeTriggerEvents();
129129
}
130130

131131
/** Launches a manual ripple at the specified position. */
@@ -148,6 +148,11 @@ export class MatRipple implements OnInit, OnDestroy {
148148
};
149149
}
150150

151+
/** Whether ripples on pointer-down are disabled or not. */
152+
get rippleDisabled(): boolean {
153+
return this.disabled || !!this._globalOptions.disabled;
154+
}
155+
151156
/** Sets up the the trigger event listeners if ripples are enabled. */
152157
private _setupTriggerEventsIfEnabled() {
153158
if (!this.disabled && this._isInitialized) {

src/lib/tabs/tab-nav-bar/tab-nav-bar.ts

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import {Directionality} from '@angular/cdk/bidi';
99
import {coerceBooleanProperty} from '@angular/cdk/coercion';
1010
import {Platform} from '@angular/cdk/platform';
11-
import {takeUntil} from 'rxjs/operators/takeUntil';
1211
import {ViewportRuler} from '@angular/cdk/scrolling';
1312
import {
1413
AfterContentInit,
@@ -39,12 +38,15 @@ import {
3938
mixinColor,
4039
mixinDisabled,
4140
mixinDisableRipple,
42-
mixinTabIndex,
41+
mixinTabIndex, RippleConfig,
4342
RippleGlobalOptions,
43+
RippleRenderer,
44+
RippleTarget,
4445
ThemePalette,
4546
} from '@angular/material/core';
4647
import {merge} from 'rxjs/observable/merge';
4748
import {of as observableOf} from 'rxjs/observable/of';
49+
import {takeUntil} from 'rxjs/operators/takeUntil';
4850
import {Subject} from 'rxjs/Subject';
4951
import {MatInkBar} from '../ink-bar';
5052

@@ -171,15 +173,16 @@ export class MatTabNav extends _MatTabNavMixinBase implements AfterContentInit,
171173

172174
// Boilerplate for applying mixins to MatTabLink.
173175
export class MatTabLinkBase {}
174-
export const _MatTabLinkMixinBase = mixinTabIndex(mixinDisabled(MatTabLinkBase));
176+
export const _MatTabLinkMixinBase =
177+
mixinTabIndex(mixinDisableRipple(mixinDisabled(MatTabLinkBase)));
175178

176179
/**
177180
* Link inside of a `mat-tab-nav-bar`.
178181
*/
179182
@Directive({
180183
selector: '[mat-tab-link], [matTabLink]',
181184
exportAs: 'matTabLink',
182-
inputs: ['disabled', 'tabIndex'],
185+
inputs: ['disabled', 'disableRipple', 'tabIndex'],
183186
host: {
184187
'class': 'mat-tab-link',
185188
'[attr.aria-disabled]': 'disabled.toString()',
@@ -189,16 +192,13 @@ export const _MatTabLinkMixinBase = mixinTabIndex(mixinDisabled(MatTabLinkBase))
189192
}
190193
})
191194
export class MatTabLink extends _MatTabLinkMixinBase
192-
implements OnDestroy, CanDisable, HasTabIndex {
195+
implements OnDestroy, CanDisable, CanDisableRipple, HasTabIndex, RippleTarget {
193196

194197
/** Whether the tab link is active or not. */
195198
private _isActive: boolean = false;
196199

197-
/** Whether the ripples for this tab should be disabled or not. */
198-
private _disableRipple: boolean = false;
199-
200-
/** Reference to the instance of the ripple for the tab link. */
201-
private _tabLinkRipple: MatRipple;
200+
/** Reference to the RippleRenderer for the tab-link. */
201+
private _tabLinkRipple: RippleRenderer;
202202

203203
/** Whether the link is active. */
204204
@Input()
@@ -210,11 +210,18 @@ export class MatTabLink extends _MatTabLinkMixinBase
210210
}
211211
}
212212

213-
/** Whether ripples should be disabled or not. */
214-
get disableRipple(): boolean { return this.disabled || this._disableRipple; }
215-
set disableRipple(value: boolean) {
216-
this._disableRipple = value;
217-
this._tabLinkRipple.disabled = this.disableRipple;
213+
/**
214+
* Ripple configuration for ripples that are launched on pointer down.
215+
* @docs-private
216+
*/
217+
rippleConfig: RippleConfig = {};
218+
219+
/**
220+
* Whether ripples are disabled on interaction
221+
* @docs-private
222+
*/
223+
get rippleDisabled(): boolean {
224+
return this.disabled || this.disableRipple;
218225
}
219226

220227
constructor(private _tabNavBar: MatTabNav,
@@ -225,17 +232,17 @@ export class MatTabLink extends _MatTabLinkMixinBase
225232
@Attribute('tabindex') tabIndex: string) {
226233
super();
227234

228-
// Manually create a ripple instance that uses the tab link element as trigger element.
229-
// Notice that the lifecycle hooks for the ripple config won't be called anymore.
230-
this._tabLinkRipple = new MatRipple(_elementRef, ngZone, platform, globalOptions);
231-
this._tabLinkRipple.ngOnInit();
235+
this._tabLinkRipple = new RippleRenderer(this, ngZone, _elementRef, platform);
236+
this._tabLinkRipple.setupTriggerEvents(_elementRef.nativeElement);
232237

233238
this.tabIndex = parseInt(tabIndex) || 0;
239+
240+
if (globalOptions) {
241+
this.rippleConfig = {speedFactor: globalOptions.baseSpeedFactor};
242+
}
234243
}
235244

236245
ngOnDestroy() {
237-
// Manually call the ngOnDestroy lifecycle hook of the ripple instance because it won't be
238-
// called automatically since its instance is not created by Angular.
239-
this._tabLinkRipple.ngOnDestroy();
246+
this._tabLinkRipple._removeTriggerEvents();
240247
}
241248
}

0 commit comments

Comments
 (0)