@@ -475,6 +475,9 @@ export class MatSlider extends _MatSliderMixinBase
475475 return ( this . _dir && this . _dir . value == 'rtl' ) ? 'rtl' : 'ltr' ;
476476 }
477477
478+ /** Keeps track of the last pointer event that was captured by the slider. */
479+ private _lastPointerEvent : MouseEvent | TouchEvent | null ;
480+
478481 constructor ( elementRef : ElementRef ,
479482 private _focusMonitor : FocusMonitor ,
480483 private _changeDetectorRef : ChangeDetectorRef ,
@@ -513,6 +516,7 @@ export class MatSlider extends _MatSliderMixinBase
513516 const element = this . _elementRef . nativeElement ;
514517 element . removeEventListener ( 'mousedown' , this . _pointerDown , activeEventOptions ) ;
515518 element . removeEventListener ( 'touchstart' , this . _pointerDown , activeEventOptions ) ;
519+ this . _lastPointerEvent = null ;
516520 this . _removeGlobalEvents ( ) ;
517521 this . _focusMonitor . stopMonitoring ( this . _elementRef ) ;
518522 this . _dirChangeSubscription . unsubscribe ( ) ;
@@ -611,6 +615,7 @@ export class MatSlider extends _MatSliderMixinBase
611615 const oldValue = this . value ;
612616 const pointerPosition = getPointerPositionOnPage ( event ) ;
613617 this . _isSliding = true ;
618+ this . _lastPointerEvent = event ;
614619 event . preventDefault ( ) ;
615620 this . _focusHostElement ( ) ;
616621 this . _onMouseenter ( ) ; // Simulate mouseenter in case this is a mobile device.
@@ -637,6 +642,7 @@ export class MatSlider extends _MatSliderMixinBase
637642 // Prevent the slide from selecting anything else.
638643 event . preventDefault ( ) ;
639644 const oldValue = this . value ;
645+ this . _lastPointerEvent = event ;
640646 this . _updateValueFromPosition ( getPointerPositionOnPage ( event ) ) ;
641647
642648 // Native range elements always emit `input` events when the value changed while sliding.
@@ -654,7 +660,7 @@ export class MatSlider extends _MatSliderMixinBase
654660
655661 event . preventDefault ( ) ;
656662 this . _removeGlobalEvents ( ) ;
657- this . _valueOnSlideStart = this . _pointerPositionOnStart = null ;
663+ this . _valueOnSlideStart = this . _pointerPositionOnStart = this . _lastPointerEvent = null ;
658664 this . _isSliding = false ;
659665
660666 if ( this . _valueOnSlideStart != this . value && ! this . disabled &&
@@ -665,6 +671,15 @@ export class MatSlider extends _MatSliderMixinBase
665671 }
666672 }
667673
674+ /** Called when the window has lost focus. */
675+ private _windowBlur = ( ) => {
676+ // If the window is blurred while dragging we need to stop dragging because the
677+ // browser won't dispatch the `mouseup` and `touchend` events anymore.
678+ if ( this . _lastPointerEvent ) {
679+ this . _pointerUp ( this . _lastPointerEvent ) ;
680+ }
681+ }
682+
668683 /**
669684 * Binds our global move and end events. They're bound at the document level and only while
670685 * dragging so that the user doesn't have to keep their pointer exactly over the slider
@@ -683,6 +698,9 @@ export class MatSlider extends _MatSliderMixinBase
683698 body . addEventListener ( 'touchcancel' , this . _pointerUp , activeEventOptions ) ;
684699 }
685700 }
701+ if ( typeof window !== 'undefined' && window ) {
702+ window . addEventListener ( 'blur' , this . _windowBlur ) ;
703+ }
686704 }
687705
688706 /** Removes any global event listeners that we may have added. */
@@ -695,6 +713,9 @@ export class MatSlider extends _MatSliderMixinBase
695713 body . removeEventListener ( 'touchend' , this . _pointerUp , activeEventOptions ) ;
696714 body . removeEventListener ( 'touchcancel' , this . _pointerUp , activeEventOptions ) ;
697715 }
716+ if ( typeof window !== 'undefined' && window ) {
717+ window . removeEventListener ( 'blur' , this . _windowBlur ) ;
718+ }
698719 }
699720
700721 /** Increments the slider by the given number of steps (negative number decrements). */
0 commit comments