|
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); |
|
} |
|
|
|
const unsubscribe = executeCallbacks(...callbacks); |
|
return { |
|
destroy() { |
|
unsubscribe(); |
|
}, |
|
}; |
|
}; |
|
|