Click outside of the dropdown to close it.
diff --git a/packages/core/onClickOutside/directive.ts b/packages/core/onClickOutside/directive.ts
index fe41f7a28cb..2acd1fd697e 100644
--- a/packages/core/onClickOutside/directive.ts
+++ b/packages/core/onClickOutside/directive.ts
@@ -1,19 +1,26 @@
-import type { FunctionDirective } from 'vue-demi'
+import { directiveHooks } from '@vueuse/shared'
+import type { ObjectDirective } from 'vue-demi'
import { onClickOutside } from '.'
+import type { OnClickOutsideHandler, OnClickOutsideOptions } from '.'
-const handler = (): FunctionDirective
(evt: E) => void> => {
- let stop = null as unknown as ReturnType
- return (el, binding) => {
- if (stop) {
- stop()
- stop = onClickOutside(el, binding.value)
- return
+export const vOnClickOutside: ObjectDirective<
+HTMLElement,
+OnClickOutsideHandler | [(evt: any) => void, OnClickOutsideOptions]
+> = {
+ [directiveHooks.mounted](el, binding) {
+ const capture = !binding.modifiers.bubble
+ if (typeof binding.value === 'function') {
+ (el as any).__onClickOutside_stop = onClickOutside(el, binding.value, { capture })
}
- stop = onClickOutside(el, binding.value)
- }
+ else {
+ const [handler, options] = binding.value
+ ;(el as any).__onClickOutside_stop = onClickOutside(el, handler, Object.assign({ capture }, options))
+ }
+ },
+ [directiveHooks.unmounted](el) {
+ (el as any).__onClickOutside_stop()
+ },
}
-export const vOnClickOutside = handler()
-
// alias
export { vOnClickOutside as VOnClickOutside }
diff --git a/packages/core/onClickOutside/index.ts b/packages/core/onClickOutside/index.ts
index 7da5e51f683..81bd6e512d7 100644
--- a/packages/core/onClickOutside/index.ts
+++ b/packages/core/onClickOutside/index.ts
@@ -23,6 +23,8 @@ export interface OnClickOutsideOptions extends ConfigurableWindow {
detectIframe?: boolean
}
+export type OnClickOutsideHandler = (evt: T['detectIframe'] extends true ? PointerEvent | FocusEvent : PointerEvent) => void
+
/**
* Listen for clicks outside of an element.
*
@@ -33,7 +35,7 @@ export interface OnClickOutsideOptions extends ConfigurableWindow {
*/
export function onClickOutside(
target: MaybeElementRef,
- handler: (evt: T['detectIframe'] extends true ? PointerEvent | FocusEvent : PointerEvent) => void,
+ handler: OnClickOutsideHandler<{ detectIframe: T['detectIframe'] }>,
options: T = {} as T,
) {
const { window = defaultWindow, ignore, capture = true, detectIframe = false } = options