Skip to content

Commit

Permalink
refactor(onClickOutside)!: listen click event, remove event option (v…
Browse files Browse the repository at this point in the history
  • Loading branch information
sibbng committed Nov 20, 2021
1 parent 09f8b51 commit 2ff6ca9
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 17 deletions.
1 change: 0 additions & 1 deletion packages/core/onClickOutside/demo.vue
Expand Up @@ -22,7 +22,6 @@ onClickOutside(
console.log(event)
dropdown.value = false
},
{ event: 'mousedown' },
)
</script>

Expand Down
4 changes: 2 additions & 2 deletions packages/core/onClickOutside/directive.ts
@@ -1,9 +1,9 @@
import { FunctionDirective } from 'vue-demi'
import { onClickOutside, OnClickOutsideEvents } from '.'
import { onClickOutside } from '.'

/**
* TODO: Test that this actually works
*/
export const VOnClickOutside: FunctionDirective<any, (evt: OnClickOutsideEvents['pointerdown']) => void> = (el, binding) => {
export const VOnClickOutside: FunctionDirective<any, (evt: PointerEvent) => void> = (el, binding) => {
onClickOutside(el, binding.value)
}
34 changes: 20 additions & 14 deletions packages/core/onClickOutside/index.ts
@@ -1,12 +1,8 @@
import { ref } from 'vue-demi'
import { MaybeElementRef, unrefElement } from '../unrefElement'
import { useEventListener } from '../useEventListener'
import { ConfigurableWindow, defaultWindow } from '../_configurable'

export type OnClickOutsideEvents = Pick<WindowEventMap, 'click' | 'mousedown' | 'mouseup' | 'touchstart' | 'touchend' | 'pointerdown' | 'pointerup'>
export interface OnClickOutsideOptions<E extends keyof OnClickOutsideEvents> extends ConfigurableWindow {
event?: E
}

/**
* Listen for clicks outside of an element.
*
Expand All @@ -15,26 +11,36 @@ export interface OnClickOutsideOptions<E extends keyof OnClickOutsideEvents> ext
* @param handler
* @param options
*/
export function onClickOutside<E extends keyof OnClickOutsideEvents = 'pointerdown'>(
export function onClickOutside(
target: MaybeElementRef,
handler: (evt: OnClickOutsideEvents[E]) => void,
options: OnClickOutsideOptions<E> = {},
handler: (evt: PointerEvent) => void,
options: ConfigurableWindow = {},
) {
const { window = defaultWindow, event = 'pointerdown' } = options
const { window = defaultWindow } = options

if (!window)
return

const listener = (event: OnClickOutsideEvents[E]) => {
const shouldListen = ref(true)

const listener = (event: PointerEvent) => {
const el = unrefElement(target)
if (!el)
return

if (el === event.target || event.composedPath().includes(el))
if (!el || el === event.target || event.composedPath().includes(el) || !shouldListen.value)
return

handler(event)
}

return useEventListener(window, event, listener, { passive: true })
const cleanup = [
useEventListener(window, 'click', listener, { passive: true, capture: true }),
useEventListener(window, 'pointerdown', (e) => {
const el = unrefElement(target)
shouldListen.value = !!el && !e.composedPath().includes(el)
}, { passive: true }),
]

const stop = () => cleanup.forEach(fn => fn())

return stop
}

0 comments on commit 2ff6ca9

Please sign in to comment.