From a1dd8c76e22608056f2f0540f9c5584626321993 Mon Sep 17 00:00:00 2001 From: sibbng Date: Mon, 14 Nov 2022 01:27:24 +0300 Subject: [PATCH] feat(onClickOutside): allow selector strings for ignore list --- packages/core/onClickOutside/index.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/packages/core/onClickOutside/index.ts b/packages/core/onClickOutside/index.ts index bf8933eb311..560b0eddd12 100644 --- a/packages/core/onClickOutside/index.ts +++ b/packages/core/onClickOutside/index.ts @@ -9,7 +9,7 @@ export interface OnClickOutsideOptions extends ConfigurableWindow { /** * List of elements that should not trigger the event. */ - ignore?: MaybeElementRef[] + ignore?: (MaybeElementRef | string)[] /** * Use capturing phase for internal event listener. * @default true @@ -37,7 +37,7 @@ export function onClickOutside( handler: OnClickOutsideHandler<{ detectIframe: T['detectIframe'] }>, options: T = {} as T, ) { - const { window = defaultWindow, ignore, capture = true, detectIframe = false } = options + const { window = defaultWindow, ignore = [], capture = true, detectIframe = false } = options if (!window) return @@ -46,6 +46,19 @@ export function onClickOutside( let fallback: number + const shouldIgnore = (event: PointerEvent) => { + return ignore.some((target) => { + if (typeof target === 'string') { + return Array.from(window.document.querySelectorAll(target)) + .some(el => el === event.target || event.composedPath().includes(el)) + } + else { + const el = unrefElement(target) + return el && (event.target === el || event.composedPath().includes(el)) + } + }) + } + const listener = (event: PointerEvent) => { window.clearTimeout(fallback) @@ -54,6 +67,9 @@ export function onClickOutside( if (!el || el === event.target || event.composedPath().includes(el)) return + if (event.detail === 0) + shouldListen = !shouldIgnore(event) + if (!shouldListen) { shouldListen = true return @@ -62,13 +78,6 @@ export function onClickOutside( handler(event) } - const shouldIgnore = (event: PointerEvent) => { - return ignore && ignore.some((target) => { - const el = unrefElement(target) - return el && (event.target === el || event.composedPath().includes(el)) - }) - } - const cleanup = [ useEventListener(window, 'click', listener, { passive: true, capture }), useEventListener(window, 'pointerdown', (e) => {