From 2df53627331b7908ebf85782d59f44948fbf7c8a Mon Sep 17 00:00:00 2001 From: Valerii Sidorenko Date: Wed, 1 Mar 2023 16:05:31 +0100 Subject: [PATCH] fix(LayerManager): check click outside event on the same layer where the mousedown event happened (#549) --- src/components/utils/LayerManager.ts | 34 +++++++++++++++++++++------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/components/utils/LayerManager.ts b/src/components/utils/LayerManager.ts index c69be4b91..c2e9f10ab 100644 --- a/src/components/utils/LayerManager.ts +++ b/src/components/utils/LayerManager.ts @@ -22,7 +22,7 @@ export interface LayerConfig extends LayerExtendableProps { class LayerManager { private stack: LayerConfig[] = []; - private mouseDownTarget: HTMLElement | null = null; + private mouseDownLayerTarget?: {layer: LayerConfig; target: HTMLElement}; add(config: LayerConfig) { this.stack.push(config); @@ -70,23 +70,41 @@ class LayerManager { }; private handleDocumentClick = (event: MouseEvent) => { - const topLayer = this.getTopLayer(); + let layer: LayerConfig; + let mouseDownTarget: HTMLElement | null = null; + if (this.mouseDownLayerTarget) { + layer = this.mouseDownLayerTarget.layer; + mouseDownTarget = this.mouseDownLayerTarget.target; + this.mouseDownLayerTarget = undefined; + if (!this.stack.includes(layer)) { + return; + } + } else { + layer = this.getTopLayer(); + } - if (!topLayer.disableOutsideClick && this.isOutsideClick(topLayer, event)) { - topLayer.onOutsideClick?.(event); - topLayer.onClose?.(event, 'outsideClick'); + if (!layer.disableOutsideClick && this.isOutsideClick(layer, event, mouseDownTarget)) { + layer.onOutsideClick?.(event); + layer.onClose?.(event, 'outsideClick'); } }; private handleDocumentMouseDown = (event: MouseEvent) => { - this.mouseDownTarget = event.target as HTMLElement; + const layer = this.getTopLayer(); + if (layer) { + this.mouseDownLayerTarget = {layer, target: event.target as HTMLElement}; + } }; private getTopLayer() { return this.stack[this.stack.length - 1]; } - private isOutsideClick(layer: LayerConfig, event: MouseEvent) { + private isOutsideClick( + layer: LayerConfig, + event: MouseEvent, + mouseDownTarget: HTMLElement | null = null, + ) { const contentElements = layer.contentRefs || []; const {target} = event; const composedPath = typeof event.composedPath === 'function' ? event.composedPath() : []; @@ -95,7 +113,7 @@ class LayerManager { const isClickOnContentElements = contentElements.some( (el) => el?.current?.contains?.(target as Element) || - el?.current?.contains?.(this.mouseDownTarget) || + el?.current?.contains?.(mouseDownTarget) || composedPath.includes(el?.current as EventTarget), );