UNPKG

@sv-use/core

Version:

A collection of Svelte 5 utilities.

62 lines (61 loc) 2.28 kB
import { handleEventListener } from '../handle-event-listener/index.svelte.js'; import { toArray } from '../__internal__/utils.svelte.js'; import { defaultWindow } from '../__internal__/configurable.js'; import { onDestroy } from 'svelte'; /** * Runs a callback when a click occurs outside the element or its ignore list. * @param element The main element on which not to trigger a click. * @param callback The callback to run when an outside click is valid. * @param options Additional options to customize the behavior. * @see https://svelte-librarian.github.io/sv-use/docs/core/on-click-outside */ export function onClickOutside(element, callback, options = {}) { const { autoCleanup = false, capture = true, ignore = [], window = defaultWindow } = options; let shouldListen = true; let isProcessingClick = false; const cleanups = []; if (window) { cleanups.push(handleEventListener(window, 'click', (event) => { if (!isProcessingClick) { isProcessingClick = true; setTimeout(() => { isProcessingClick = false; }, 0); handleClick(event); } }, { passive: true, capture }), handleEventListener(window, 'pointerdown', (e) => { const el = element(); shouldListen = !shouldIgnoreClick(e) && !!(el && !e.composedPath().includes(el)); }, { passive: true })); } if (autoCleanup) { onDestroy(() => { cleanup(); }); } function handleClick(event) { const el = element(); if (!event.target) return; if (!el || el === event.target || event.composedPath().includes(el)) return; if (event.detail === 0) { shouldListen = !shouldIgnoreClick(event); } if (!shouldListen) { shouldListen = true; return; } callback(event); } function shouldIgnoreClick(event) { return toArray(ignore).some((target) => { const el = target(); return el && (event.target === el || event.composedPath().includes(el)); }); } function cleanup() { cleanups.forEach((fn) => fn()); } return cleanup; }