@@ -21,7 +21,7 @@ import type {OverlayRef} from '../overlay-ref';
2121export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
2222 private _cursorOriginalValue : string ;
2323 private _cursorStyleIsSet = false ;
24- private _pointerDownEventTarget : EventTarget | null ;
24+ private _pointerDownEventTarget : HTMLElement | null ;
2525
2626 constructor (
2727 @Inject ( DOCUMENT ) document : any ,
@@ -89,12 +89,12 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
8989
9090 /** Store pointerdown event target to track origin of click. */
9191 private _pointerDownListener = ( event : PointerEvent ) => {
92- this . _pointerDownEventTarget = _getEventTarget ( event ) ;
92+ this . _pointerDownEventTarget = _getEventTarget < HTMLElement > ( event ) ;
9393 } ;
9494
9595 /** Click event listener that will be attached to the body propagate phase. */
9696 private _clickListener = ( event : MouseEvent ) => {
97- const target = _getEventTarget ( event ) ;
97+ const target = _getEventTarget < HTMLElement > ( event ) ;
9898 // In case of a click event, we want to check the origin of the click
9999 // (e.g. in case where a user starts a click inside the overlay and
100100 // releases the click outside of it).
@@ -128,8 +128,8 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
128128 // If it's an outside click (both origin and target of the click) dispatch the mouse event,
129129 // and proceed with the next overlay
130130 if (
131- overlayRef . overlayElement . contains ( target as Node ) ||
132- overlayRef . overlayElement . contains ( origin as Node )
131+ containsPierceShadowDom ( overlayRef . overlayElement , target ) ||
132+ containsPierceShadowDom ( overlayRef . overlayElement , origin )
133133 ) {
134134 break ;
135135 }
@@ -144,3 +144,20 @@ export class OverlayOutsideClickDispatcher extends BaseOverlayDispatcher {
144144 }
145145 } ;
146146}
147+
148+ /** Version of `Element.contains` that transcends shadow DOM boundaries. */
149+ function containsPierceShadowDom ( parent : HTMLElement , child : HTMLElement | null ) : boolean {
150+ const supportsShadowRoot = typeof ShadowRoot !== 'undefined' && ShadowRoot ;
151+ let current : Node | null = child ;
152+
153+ while ( current ) {
154+ if ( current === parent ) {
155+ return true ;
156+ }
157+
158+ current =
159+ supportsShadowRoot && current instanceof ShadowRoot ? current . host : current . parentNode ;
160+ }
161+
162+ return false ;
163+ }
0 commit comments