DuyTa's picture
Upload folder using huggingface_hub
bc20498 verified
// Modified from Grail UI v0.9.6 (2023-06-10)
// Source: https://github.com/grail-ui/grail-ui
// https://github.com/grail-ui/grail-ui/tree/master/packages/grail-ui/src/clickOutside/clickOutside.ts
import { readable } from 'svelte/store';
import { addEventListener } from '../../helpers/event.js';
import { get } from 'svelte/store';
import { isFunction } from '../../helpers/is.js';
/**
* Creates a readable store that tracks the latest PointerEvent that occurred on the document.
*
* @returns A function to unsubscribe from the event listener and stop tracking pointer events.
*/
const documentClickStore = readable(undefined, (set) => {
/**
* Event handler for pointerdown events on the document.
* Updates the store's value with the latest PointerEvent and then resets it to undefined.
*/
function clicked(event) {
set(event);
// New subscriptions will not trigger immediately
set(undefined);
}
// Adds a pointerdown event listener to the document, calling the clicked function when triggered.
const unsubscribe = addEventListener(document, 'pointerup', clicked, {
passive: false,
capture: true,
});
// Returns a function to unsubscribe from the event listener and stop tracking pointer events.
return unsubscribe;
});
export const useClickOutside = (node, config = {}) => {
let options = { enabled: true, ...config };
// Returns true if the click outside handler is enabled
function isEnabled() {
return typeof options.enabled === 'boolean' ? options.enabled : get(options.enabled);
}
// Handle document clicks
const unsubscribe = documentClickStore.subscribe((e) => {
// If the click outside handler is disabled, or if the event is null or the node itself, return early
if (!isEnabled() || !e || e.target === node) {
return;
}
const composedPath = e.composedPath();
// If the target is in the node, return early
if (composedPath.includes(node))
return;
// If an ignore function is passed, check if it returns true
if (options.ignore) {
if (isFunction(options.ignore)) {
if (options.ignore(e))
return;
}
// If an ignore array is passed, check if any elements in the array match the target
else if (Array.isArray(options.ignore)) {
if (options.ignore.length > 0 &&
options.ignore.some((ignoreEl) => {
return ignoreEl && (e.target === ignoreEl || composedPath.includes(ignoreEl));
}))
return;
}
}
// If none of the above conditions are met, call the handler
options.handler?.(e);
});
return {
update(params) {
options = { ...options, ...params };
},
destroy() {
unsubscribe();
},
};
};