File size: 3,069 Bytes
bc20498
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
import { addEventListener } from '../../helpers/event.js';
import { isFunction, isHTMLElement, isReadable } from '../../helpers/is.js';
import { get, readable } from 'svelte/store';
import { effect, executeCallbacks, kbd, noop } from '../../helpers/index.js';
/**
 * Creates a readable store that tracks the latest Escape Keydown that occurred on the document.
 *
 * @returns A function to unsubscribe from the event listener and stop tracking keydown events.
 */
const documentEscapeKeyStore = readable(undefined, (set) => {
    /**
     * Event handler for keydown events on the document.
     * Updates the store's value with the latest Escape Keydown event and then resets it to undefined.
     */
    function keydown(event) {
        if (event && event.key === kbd.ESCAPE) {
            set(event);
        }
        // New subscriptions will not trigger immediately
        set(undefined);
    }
    // Adds a keydown event listener to the document, calling the keydown function when triggered.
    const unsubscribe = addEventListener(document, 'keydown', keydown, {
        passive: false,
    });
    // Returns a function to unsubscribe from the event listener and stop tracking keydown events.
    return unsubscribe;
});
export const useEscapeKeydown = (node, config = {}) => {
    let unsub = noop;
    function update(config = {}) {
        unsub();
        const options = { enabled: true, ...config };
        const enabled = (isReadable(options.enabled) ? options.enabled : readable(options.enabled));
        unsub = executeCallbacks(
        // Handle escape keydowns
        documentEscapeKeyStore.subscribe((e) => {
            if (!e || !get(enabled))
                return;
            const target = e.target;
            if (!isHTMLElement(target) || target.closest('[data-escapee]') !== node) {
                return;
            }
            e.preventDefault();
            // 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 && target === ignoreEl;
                        }))
                        return;
                }
            }
            // If none of the above conditions are met, call the handler
            options.handler?.(e);
        }), effect(enabled, ($enabled) => {
            if ($enabled) {
                node.dataset.escapee = '';
            }
            else {
                delete node.dataset.escapee;
            }
        }));
    }
    update(config);
    return {
        update,
        destroy() {
            node.removeAttribute('data-escapee');
            unsub();
        },
    };
};