2022-11-01 22:05:08 +00:00
|
|
|
import { onCleanup, onMount } from 'solid-js'
|
|
|
|
|
|
|
|
type Options = {
|
|
|
|
containerRef: { current: HTMLElement }
|
2023-05-12 13:45:31 +00:00
|
|
|
handler: (e: MouseEvent & { target: Element }) => void
|
2023-05-03 16:13:48 +00:00
|
|
|
// if predicate is present
|
|
|
|
// handler is called only if predicate function returns true
|
2023-05-12 13:45:31 +00:00
|
|
|
predicate?: (e: MouseEvent & { target: Element }) => boolean
|
2022-11-01 22:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export const useOutsideClickHandler = (options: Options) => {
|
|
|
|
const { predicate, containerRef, handler } = options
|
2023-05-12 13:45:31 +00:00
|
|
|
const handleClickOutside = (e: MouseEvent & { target: Element }) => {
|
|
|
|
if (predicate && !predicate(e)) {
|
2022-11-01 22:05:08 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-12 13:45:31 +00:00
|
|
|
if (e.target === containerRef.current || containerRef.current?.contains(e.target)) {
|
2022-11-01 22:05:08 +00:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2023-05-12 13:45:31 +00:00
|
|
|
handler(e)
|
2022-11-01 22:05:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
onMount(() => {
|
|
|
|
document.addEventListener('click', handleClickOutside, { capture: true })
|
|
|
|
onCleanup(() => document.removeEventListener('click', handleClickOutside, { capture: true }))
|
|
|
|
})
|
|
|
|
}
|