@@ -17,7 +17,6 @@ import {
17
17
import { ESCAPE , hasModifierKey } from '@angular/cdk/keycodes' ;
18
18
import { BreakpointObserver , Breakpoints , BreakpointState } from '@angular/cdk/layout' ;
19
19
import {
20
- ConnectedPosition ,
21
20
FlexibleConnectedPositionStrategy ,
22
21
HorizontalConnectionPos ,
23
22
OriginConnectionPosition ,
@@ -27,6 +26,7 @@ import {
27
26
ScrollStrategy ,
28
27
VerticalConnectionPos ,
29
28
ConnectionPositionPair ,
29
+ ConnectedPosition ,
30
30
} from '@angular/cdk/overlay' ;
31
31
import { Platform , normalizePassiveListenerOptions } from '@angular/cdk/platform' ;
32
32
import { ComponentPortal , ComponentType } from '@angular/cdk/portal' ;
@@ -207,6 +207,10 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
207
207
}
208
208
set hideDelay ( value : NumberInput ) {
209
209
this . _hideDelay = coerceNumberProperty ( value ) ;
210
+
211
+ if ( this . _tooltipInstance ) {
212
+ this . _tooltipInstance . _mouseLeaveHideDelay = this . _hideDelay ;
213
+ }
210
214
}
211
215
private _hideDelay = this . _defaultOptions . hideDelay ;
212
216
@@ -376,14 +380,16 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
376
380
this . _detach ( ) ;
377
381
this . _portal =
378
382
this . _portal || new ComponentPortal ( this . _tooltipComponent , this . _viewContainerRef ) ;
379
- this . _tooltipInstance = overlayRef . attach ( this . _portal ) . instance ;
380
- this . _tooltipInstance
383
+ const instance = ( this . _tooltipInstance = overlayRef . attach ( this . _portal ) . instance ) ;
384
+ instance . _triggerElement = this . _elementRef . nativeElement ;
385
+ instance . _mouseLeaveHideDelay = this . _hideDelay ;
386
+ instance
381
387
. afterHidden ( )
382
388
. pipe ( takeUntil ( this . _destroyed ) )
383
389
. subscribe ( ( ) => this . _detach ( ) ) ;
384
390
this . _setTooltipClass ( this . _tooltipClass ) ;
385
391
this . _updateTooltipMessage ( ) ;
386
- this . _tooltipInstance ! . show ( delay ) ;
392
+ instance . show ( delay ) ;
387
393
}
388
394
389
395
/** Hides the tooltip after the delay in ms, defaults to tooltip-delay-hide or 0ms if no input */
@@ -687,7 +693,15 @@ export abstract class _MatTooltipBase<T extends _TooltipComponentBase>
687
693
const exitListeners : ( readonly [ string , EventListenerOrEventListenerObject ] ) [ ] = [ ] ;
688
694
if ( this . _platformSupportsMouseEvents ( ) ) {
689
695
exitListeners . push (
690
- [ 'mouseleave' , ( ) => this . hide ( ) ] ,
696
+ [
697
+ 'mouseleave' ,
698
+ event => {
699
+ const newTarget = ( event as MouseEvent ) . relatedTarget as Node | null ;
700
+ if ( ! newTarget || ! this . _overlayRef ?. overlayElement . contains ( newTarget ) ) {
701
+ this . hide ( ) ;
702
+ }
703
+ } ,
704
+ ] ,
691
705
[ 'wheel' , event => this . _wheelListener ( event as WheelEvent ) ] ,
692
706
) ;
693
707
} else if ( this . touchGestures !== 'off' ) {
@@ -824,6 +838,12 @@ export abstract class _TooltipComponentBase implements OnDestroy {
824
838
/** Property watched by the animation framework to show or hide the tooltip */
825
839
_visibility : TooltipVisibility = 'initial' ;
826
840
841
+ /** Element that caused the tooltip to open. */
842
+ _triggerElement : HTMLElement ;
843
+
844
+ /** Amount of milliseconds to delay the closing sequence. */
845
+ _mouseLeaveHideDelay : number ;
846
+
827
847
/** Whether interactions on the page should close the tooltip */
828
848
private _closeOnInteraction : boolean = false ;
829
849
@@ -885,6 +905,7 @@ export abstract class _TooltipComponentBase implements OnDestroy {
885
905
clearTimeout ( this . _showTimeoutId ) ;
886
906
clearTimeout ( this . _hideTimeoutId ) ;
887
907
this . _onHide . complete ( ) ;
908
+ this . _triggerElement = null ! ;
888
909
}
889
910
890
911
_animationStart ( ) {
@@ -923,6 +944,12 @@ export abstract class _TooltipComponentBase implements OnDestroy {
923
944
this . _changeDetectorRef . markForCheck ( ) ;
924
945
}
925
946
947
+ _handleMouseLeave ( { relatedTarget} : MouseEvent ) {
948
+ if ( ! relatedTarget || ! this . _triggerElement . contains ( relatedTarget as Node ) ) {
949
+ this . hide ( this . _mouseLeaveHideDelay ) ;
950
+ }
951
+ }
952
+
926
953
/**
927
954
* Callback for when the timeout in this.show() gets completed.
928
955
* This method is only needed by the mdc-tooltip, and so it is only implemented
@@ -946,6 +973,7 @@ export abstract class _TooltipComponentBase implements OnDestroy {
946
973
// Forces the element to have a layout in IE and Edge. This fixes issues where the element
947
974
// won't be rendered if the animations are disabled or there is no web animations polyfill.
948
975
'[style.zoom]' : '_visibility === "visible" ? 1 : null' ,
976
+ '(mouseleave)' : '_handleMouseLeave($event)' ,
949
977
'aria-hidden' : 'true' ,
950
978
} ,
951
979
} )
0 commit comments