// Unique ID applied to modals created using the showWindowModal function export const WINDOW_MODAL_ID = 'window-modal'; // We only import these modules if a user actually triggers a modal. Here we cache them so they are only imported once. let preactImport; let modalImports; const getPreactImport = () => { if (!preactImport) { preactImport = import('preact'); } return preactImport; }; const getModalImports = () => { if (!modalImports) { modalImports = [import('@crayons/Modal'), getPreactImport()]; } return Promise.all(modalImports); }; /** * This helper function presents content inside a Preact modal. * * The modal content may be passed either as: * - the actual HTML (using modalContent prop), which will be dropped straight into the modal * - a CSS selector (using contentSelector prop), which will be used to locate the HTML content on the current page before dropping it into the modal * * Only one modal will be presented at any given time. All additional props will be passed directly to the Modal component. * * @param {Object} args * @param {HTMLElement} args.modalContent The HTML to display inside of the modal * @param {string} args.contentSelector The CSS query to locate the HTML to be presented in the modal, as an alternative to passing the actual HTML (e.g. '#my-modal-content') * @param {Function} args.onOpen A callback function to run when the modal opens. This can be useful, for example, to attach any event listeners to items inside the modal. * @param {Object} args.document Allows us to specify which "document" is relevant; e.g. use within iframes. */ export const showWindowModal = async ({ modalContent, contentSelector, onOpen, document = window.document, ...modalProps }) => { const [{ Modal }, { render, h }] = await getModalImports(); // Guard against two modals being opened at once let currentModalContainer = document.getElementById(WINDOW_MODAL_ID); if (currentModalContainer) { render(null, currentModalContainer); } else { currentModalContainer = document.createElement('div'); currentModalContainer.setAttribute('id', WINDOW_MODAL_ID); document.body.appendChild(currentModalContainer); } render( { render(null, currentModalContainer); }} focusTrapSelector={`#${WINDOW_MODAL_ID}`} document={document} {...modalProps} >
, currentModalContainer, ); onOpen?.(); }; /** * This helper function closes any currently open window modal. This can be useful, for example, if your modal contains a "cancel" button. */ export const closeWindowModal = async (document = window.document) => { const currentModalContainer = document.getElementById(WINDOW_MODAL_ID); if (currentModalContainer) { const { render } = await getPreactImport(); render(null, currentModalContainer); } };