@@ -32,7 +32,14 @@ import {
32
32
ViewChildren ,
33
33
ViewEncapsulation ,
34
34
} from '@angular/core' ;
35
- import { CanColorCtor , mixinColor } from '@angular/material/core' ;
35
+ import {
36
+ CanColorCtor ,
37
+ MatRipple ,
38
+ mixinColor ,
39
+ RippleAnimationConfig ,
40
+ RippleRef ,
41
+ RippleState ,
42
+ } from '@angular/material/core' ;
36
43
import { SpecificEventListener , EventType } from '@material/base' ;
37
44
import { MDCSliderAdapter , MDCSliderFoundation , Thumb , TickMark } from '@material/slider' ;
38
45
@@ -48,6 +55,173 @@ export interface MatSliderDragEvent {
48
55
value : number ;
49
56
}
50
57
58
+ /**
59
+ * The visual slider thumb.
60
+ *
61
+ * Handles the slider thumb ripple states (hover, focus, and active),
62
+ * and displaying the value tooltip on discrete sliders.
63
+ */
64
+ @Component ( {
65
+ selector : 'mat-slider-visual-start-thumb, mat-slider-visual-end-thumb' ,
66
+ templateUrl : './slider-thumb.html' ,
67
+ host : {
68
+ 'class' : 'mdc-slider__thumb' ,
69
+ '(mouseenter)' : '_onMouseEnter()' ,
70
+ '(mouseleave)' : '_onMouseLeave()' ,
71
+ } ,
72
+ changeDetection : ChangeDetectionStrategy . OnPush ,
73
+ encapsulation : ViewEncapsulation . None ,
74
+ } )
75
+ export class MatSliderVisualThumb implements AfterViewInit {
76
+ /** Whether the slider displays a numeric value label upon pressing the thumb. */
77
+ @Input ( ) _discrete : boolean ;
78
+
79
+ /** The display value of the slider thumb. */
80
+ @Input ( ) _valueIndicatorText : string ;
81
+
82
+ /** The MatRipple for this slider thumb. */
83
+ @ViewChild ( MatRipple ) private readonly _ripple : MatRipple ;
84
+
85
+ /** The slider thumb knob */
86
+ @ViewChild ( 'knob' ) _knob : ElementRef < HTMLElement > ;
87
+
88
+ /** Indicates which slider thumb this input corresponds to. */
89
+ _thumbPosition : Thumb =
90
+ this . _elementRef . nativeElement . tagName . toLowerCase ( )
91
+ === 'mat-slider-visual-start-thumb' . toLowerCase ( )
92
+ ? Thumb . START
93
+ : Thumb . END ;
94
+
95
+ /** The slider input corresponding to this slider thumb. */
96
+ private _sliderInput : MatSliderThumb ;
97
+
98
+ /** The RippleRef for the slider thumbs hover state. */
99
+ private _hoverRippleRef : RippleRef ;
100
+
101
+ /** The RippleRef for the slider thumbs focus state. */
102
+ private _focusRippleRef : RippleRef ;
103
+
104
+ /** The RippleRef for the slider thumbs active state. */
105
+ private _activeRippleRef : RippleRef ;
106
+
107
+ /** Whether the slider thumb is currently being pressed. */
108
+ private _isActive : boolean = false ;
109
+
110
+ /** Whether the slider thumb is currently being hovered. */
111
+ private _isHovered : boolean = false ;
112
+
113
+ constructor (
114
+ private readonly _slider : MatSlider ,
115
+ private readonly _elementRef : ElementRef < HTMLElement > ) { }
116
+
117
+ ngAfterViewInit ( ) {
118
+ this . _ripple . radius = 24 ;
119
+ this . _sliderInput = this . _slider . _getInput ( this . _thumbPosition ) ;
120
+
121
+ this . _sliderInput . dragStart . subscribe ( ( e : MatSliderDragEvent ) => this . _onDragStart ( e ) ) ;
122
+ this . _sliderInput . dragEnd . subscribe ( ( e : MatSliderDragEvent ) => this . _onDragEnd ( e ) ) ;
123
+
124
+ this . _sliderInput . _focus . subscribe ( ( ) => this . _onFocus ( ) ) ;
125
+ this . _sliderInput . _blur . subscribe ( ( ) => this . _onBlur ( ) ) ;
126
+ }
127
+
128
+ _onMouseEnter ( ) : void {
129
+ this . _isHovered = true ;
130
+ // We don't want to show the hover ripple on top of the focus ripple.
131
+ // This can happen if the user tabs to a thumb and then the user moves their cursor over it.
132
+ if ( ! this . _isShowingRipple ( this . _focusRippleRef ) ) {
133
+ this . _showHoverRipple ( ) ;
134
+ }
135
+ }
136
+
137
+ _onMouseLeave ( ) : void {
138
+ this . _isHovered = false ;
139
+ this . _hoverRippleRef ?. fadeOut ( ) ;
140
+ }
141
+
142
+ private _onFocus ( ) : void {
143
+ // We don't want to show the hover ripple on top of the focus ripple.
144
+ // Happen when the users cursor is over a thumb and then the user tabs to it.
145
+ this . _hoverRippleRef ?. fadeOut ( ) ;
146
+ this . _showFocusRipple ( ) ;
147
+ }
148
+
149
+ private _onBlur ( ) : void {
150
+ // Happens when the user tabs away while still dragging a thumb.
151
+ if ( ! this . _isActive ) {
152
+ this . _focusRippleRef ?. fadeOut ( ) ;
153
+ }
154
+ // Happens when the user tabs away from a thumb but their cursor is still over it.
155
+ if ( this . _isHovered ) {
156
+ this . _showHoverRipple ( ) ;
157
+ }
158
+ }
159
+
160
+ private _onDragStart ( event : MatSliderDragEvent ) : void {
161
+ if ( event . source . _thumbPosition === this . _thumbPosition ) {
162
+ this . _isActive = true ;
163
+ this . _showActiveRipple ( ) ;
164
+ }
165
+ }
166
+
167
+ private _onDragEnd ( event : MatSliderDragEvent ) : void {
168
+ if ( event . source . _thumbPosition === this . _thumbPosition ) {
169
+ this . _isActive = false ;
170
+ this . _activeRippleRef ?. fadeOut ( ) ;
171
+ // Happens when the user starts dragging a thumb, tabs away, and then stops dragging.
172
+ if ( ! this . _sliderInput . _isFocused ( ) ) {
173
+ this . _focusRippleRef ?. fadeOut ( ) ;
174
+ }
175
+ }
176
+ }
177
+
178
+ /** Handles displaying the hover ripple. */
179
+ private _showHoverRipple ( ) : void {
180
+ if ( ! this . _isShowingRipple ( this . _hoverRippleRef ) ) {
181
+ this . _hoverRippleRef = this . _showRipple ( { enterDuration : 0 , exitDuration : 0 } ) ;
182
+ this . _hoverRippleRef . element . classList . add ( 'mdc-slider-hover-ripple' ) ;
183
+ }
184
+ }
185
+
186
+ /** Handles displaying the focus ripple. */
187
+ private _showFocusRipple ( ) : void {
188
+ if ( ! this . _isShowingRipple ( this . _focusRippleRef ) ) {
189
+ this . _focusRippleRef = this . _showRipple ( { enterDuration : 0 , exitDuration : 0 } ) ;
190
+ this . _focusRippleRef . element . classList . add ( 'mdc-slider-focus-ripple' ) ;
191
+ }
192
+ }
193
+
194
+ /** Handles displaying the active ripple. */
195
+ private _showActiveRipple ( ) : void {
196
+ if ( ! this . _isShowingRipple ( this . _activeRippleRef ) ) {
197
+ this . _activeRippleRef = this . _showRipple ( { enterDuration : 225 , exitDuration : 400 } ) ;
198
+ this . _activeRippleRef . element . classList . add ( 'mdc-slider-active-ripple' ) ;
199
+ }
200
+ }
201
+
202
+ /** Whether the given rippleRef is currently fading in or visible. */
203
+ private _isShowingRipple ( rippleRef ?: RippleRef ) : boolean {
204
+ return rippleRef ?. state === RippleState . FADING_IN || rippleRef ?. state === RippleState . VISIBLE ;
205
+ }
206
+
207
+ /** Manually launches the slider thumb ripple using the specified ripple animation config. */
208
+ private _showRipple ( animation : RippleAnimationConfig ) : RippleRef {
209
+ return this . _ripple . launch (
210
+ { animation, centered : true , persistent : true } ,
211
+ ) ;
212
+ }
213
+
214
+ /** Gets the hosts native HTML element. */
215
+ _getHostElement ( ) : HTMLElement {
216
+ return this . _elementRef . nativeElement ;
217
+ }
218
+
219
+ /** Gets the native HTML element of the slider thumb knob. */
220
+ _getKnob ( ) : HTMLElement {
221
+ return this . _knob . nativeElement ;
222
+ }
223
+ }
224
+
51
225
/**
52
226
* Directive that adds slider-specific behaviors to an input element inside `<mat-slider>`.
53
227
* Up to two may be placed inside of a `<mat-slider>`.
@@ -111,7 +285,7 @@ export class MatSliderThumb implements AfterViewInit {
111
285
@Output ( ) readonly _focus : EventEmitter < void > = new EventEmitter < void > ( ) ;
112
286
113
287
/** Indicates which slider thumb this input corresponds to. */
114
- private _thumbPosition : Thumb = this . _elementRef . nativeElement . hasAttribute ( 'matSliderStartThumb' )
288
+ _thumbPosition : Thumb = this . _elementRef . nativeElement . hasAttribute ( 'matSliderStartThumb' )
115
289
? Thumb . START
116
290
: Thumb . END ;
117
291
@@ -235,14 +409,7 @@ const _MatSliderMixinBase:
235
409
} )
236
410
export class MatSlider extends _MatSliderMixinBase implements AfterViewInit , OnDestroy {
237
411
/** The slider thumb(s). */
238
- @ViewChildren ( 'thumb' ) _thumbs : QueryList < ElementRef < HTMLElement > > ;
239
-
240
- /** The slider thumb knob(s) */
241
- @ViewChildren ( 'knob' ) _knobs : QueryList < ElementRef < HTMLElement > > ;
242
-
243
- /** The span containing the slider thumb value indicator text */
244
- @ViewChildren ( 'valueIndicatorTextElement' )
245
- _valueIndicatorTextElements : QueryList < ElementRef < HTMLElement > > ;
412
+ @ViewChildren ( MatSliderVisualThumb ) _thumbs : QueryList < MatSliderVisualThumb > ;
246
413
247
414
/** The active section of the slider track. */
248
415
@ViewChild ( 'trackActive' ) _trackActive : ElementRef < HTMLElement > ;
@@ -322,10 +489,10 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, OnD
322
489
_tickMarks : TickMark [ ] ;
323
490
324
491
/** The display value of the start thumb. */
325
- private _startValueIndicatorText : string ;
492
+ _startValueIndicatorText : string ;
326
493
327
494
/** The display value of the end thumb. */
328
- private _endValueIndicatorText : string ;
495
+ _endValueIndicatorText : string ;
329
496
330
497
constructor (
331
498
readonly _cdr : ChangeDetectorRef ,
@@ -383,30 +550,26 @@ export class MatSlider extends _MatSliderMixinBase implements AfterViewInit, OnD
383
550
384
551
/** Gets the slider thumb input of the given thumb position. */
385
552
_getInput ( thumbPosition : Thumb ) : MatSliderThumb {
386
- return thumbPosition === Thumb . END ? this . _inputs . last ! : this . _inputs . first ! ;
553
+ return thumbPosition === Thumb . END ? this . _inputs . last : this . _inputs . first ;
387
554
}
388
555
389
556
/** Gets the slider thumb HTML input element of the given thumb position. */
390
557
_getInputElement ( thumbPosition : Thumb ) : HTMLInputElement {
391
558
return this . _getInput ( thumbPosition ) . _hostElement ;
392
559
}
393
560
561
+ private _getThumb ( thumbPosition : Thumb ) : MatSliderVisualThumb {
562
+ return thumbPosition === Thumb . END ? this . _thumbs . last : this . _thumbs . first ;
563
+ }
564
+
394
565
/** Gets the slider thumb HTML element of the given thumb position. */
395
566
_getThumbElement ( thumbPosition : Thumb ) : HTMLElement {
396
- const thumbElementRef = thumbPosition === Thumb . END ? this . _thumbs . last : this . _thumbs . first ;
397
- return thumbElementRef . nativeElement ;
567
+ return this . _getThumb ( thumbPosition ) . _getHostElement ( ) ;
398
568
}
399
569
400
570
/** Gets the slider knob HTML element of the given thumb position. */
401
571
_getKnobElement ( thumbPosition : Thumb ) : HTMLElement {
402
- const knobElementRef = thumbPosition === Thumb . END ? this . _knobs . last : this . _knobs . first ;
403
- return knobElementRef . nativeElement ;
404
- }
405
-
406
- _getValueIndicatorText ( thumbPosition : Thumb ) {
407
- return thumbPosition === Thumb . START
408
- ? this . _startValueIndicatorText
409
- : this . _endValueIndicatorText ;
572
+ return this . _getThumb ( thumbPosition ) . _getKnob ( ) ;
410
573
}
411
574
412
575
/**
0 commit comments