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();
},
};
};
|