File size: 2,513 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
import { createFocusTrap, useEscapeKeydown, useFloating, usePortal, } from '../index.js';
import { executeCallbacks, noop, isHTMLElement, } from '../../helpers/index.js';
import { useModal } from '../modal/action.js';
const defaultConfig = {
    floating: {},
    focusTrap: {},
    modal: {},
    escapeKeydown: {},
    portal: 'body',
};
export const usePopper = (popperElement, args) => {
    popperElement.dataset.escapee = '';
    const { anchorElement, open, options } = args;
    if (!anchorElement || !open || !options) {
        return { destroy: noop };
    }
    const opts = { ...defaultConfig, ...options };
    const callbacks = [];
    if (opts.portal !== null) {
        const portal = usePortal(popperElement, opts.portal);
        if (portal?.destroy) {
            callbacks.push(portal.destroy);
        }
    }
    callbacks.push(useFloating(anchorElement, popperElement, opts.floating).destroy);
    if (opts.focusTrap !== null) {
        const { useFocusTrap } = createFocusTrap({
            immediate: true,
            escapeDeactivates: false,
            allowOutsideClick: true,
            returnFocusOnDeactivate: false,
            fallbackFocus: popperElement,
            ...opts.focusTrap,
        });
        const usedFocusTrap = useFocusTrap(popperElement);
        if (usedFocusTrap?.destroy) {
            callbacks.push(usedFocusTrap.destroy);
        }
    }
    if (opts.modal !== null) {
        callbacks.push(useModal(popperElement, {
            onClose: () => {
                if (isHTMLElement(anchorElement)) {
                    open.set(false);
                    anchorElement.focus();
                }
            },
            shouldCloseOnInteractOutside: (e) => {
                if (e.defaultPrevented)
                    return false;
                if (isHTMLElement(anchorElement) && anchorElement.contains(e.target)) {
                    return false;
                }
                return true;
            },
            ...opts.modal,
        }).destroy);
    }
    if (opts.escapeKeydown !== null) {
        callbacks.push(useEscapeKeydown(popperElement, {
            enabled: open,
            handler: () => {
                open.set(false);
            },
            ...opts.escapeKeydown,
        }).destroy);
    }
    // @ts-expect-error - This works and is correct, but TS doesn't like it
    const unsubscribe = executeCallbacks(...callbacks);
    return {
        destroy() {
            unsubscribe();
        },
    };
};