move showModal helper into its own pack file (#17266)
This commit is contained in:
parent
240893401d
commit
64ed2c6dec
2 changed files with 84 additions and 51 deletions
|
|
@ -5,11 +5,9 @@ import {
|
|||
initializeMemberMenu,
|
||||
} from '../topNavigation/utilities';
|
||||
import { waitOnBaseData } from '../utilities/waitOnBaseData';
|
||||
import { showWindowModal, closeWindowModal } from '@utilities/showModal';
|
||||
import * as Runtime from '@utilities/runtime';
|
||||
|
||||
// Unique ID applied to modals created using window.Forem.showModal
|
||||
const WINDOW_MODAL_ID = 'window-modal';
|
||||
|
||||
// Namespace for functions which need to be accessed in plain JS initializers
|
||||
window.Forem = {
|
||||
preactImport: undefined,
|
||||
|
|
@ -53,54 +51,8 @@ window.Forem = {
|
|||
originalTextArea,
|
||||
);
|
||||
},
|
||||
modalImports: undefined,
|
||||
getModalImports() {
|
||||
if (!this.modalImports) {
|
||||
this.modalImports = [import('@crayons/Modal'), this.getPreactImport()];
|
||||
}
|
||||
return Promise.all(this.modalImports);
|
||||
},
|
||||
showModal: async ({ title, contentSelector, size = 'small', onOpen }) => {
|
||||
const [{ Modal }, { render, h }] = await window.Forem.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(
|
||||
<Modal
|
||||
title={title}
|
||||
onClose={() => {
|
||||
render(null, currentModalContainer);
|
||||
}}
|
||||
size={size}
|
||||
focusTrapSelector={`#${WINDOW_MODAL_ID}`}
|
||||
>
|
||||
<div
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: document.querySelector(contentSelector).innerHTML,
|
||||
}}
|
||||
/>
|
||||
</Modal>,
|
||||
currentModalContainer,
|
||||
);
|
||||
|
||||
onOpen?.();
|
||||
},
|
||||
closeModal: async () => {
|
||||
const currentModalContainer = document.getElementById(WINDOW_MODAL_ID);
|
||||
if (currentModalContainer) {
|
||||
const { render } = await window.Forem.getPreactImport();
|
||||
render(null, currentModalContainer);
|
||||
}
|
||||
},
|
||||
showModal: showWindowModal,
|
||||
closeModal: closeWindowModal,
|
||||
Runtime,
|
||||
};
|
||||
|
||||
|
|
|
|||
81
app/javascript/utilities/showModal.jsx
Normal file
81
app/javascript/utilities/showModal.jsx
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Unique ID applied to modals created using the showWindowModal function
|
||||
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 finds the HTML with the given contentSelector, and presents it inside a Preact modal.
|
||||
* Only one modal will be presented at any given time.
|
||||
*
|
||||
* @param {Object} args
|
||||
* @param {string} args.title The title of the modal (presented at the top of the modal dialog)
|
||||
* @param {string} args.contentSelector The CSS query to locate the HTML to be presented in the modal (e.g. '#my-modal-content')
|
||||
* @param {string} args.size The size prop for the modal ('small', 'medium', or 'large')
|
||||
* @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.
|
||||
*/
|
||||
export const showWindowModal = async ({
|
||||
title,
|
||||
contentSelector,
|
||||
size = 'small',
|
||||
onOpen,
|
||||
}) => {
|
||||
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(
|
||||
<Modal
|
||||
title={title}
|
||||
onClose={() => {
|
||||
render(null, currentModalContainer);
|
||||
}}
|
||||
size={size}
|
||||
focusTrapSelector={`#${WINDOW_MODAL_ID}`}
|
||||
>
|
||||
<div
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: document.querySelector(contentSelector).innerHTML,
|
||||
}}
|
||||
/>
|
||||
</Modal>,
|
||||
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 () => {
|
||||
const currentModalContainer = document.getElementById(WINDOW_MODAL_ID);
|
||||
if (currentModalContainer) {
|
||||
const { render } = await getPreactImport();
|
||||
render(null, currentModalContainer);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Reference in a new issue