113 lines
2.7 KiB
JavaScript
113 lines
2.7 KiB
JavaScript
import React, {
|
|
createContext,
|
|
useContext,
|
|
useState,
|
|
useEffect,
|
|
useRef,
|
|
} from "react";
|
|
|
|
const ModalContext = createContext();
|
|
|
|
export const useModal = () => useContext(ModalContext);
|
|
|
|
// ModalProvider to manage modal state and expose functionality to the rest of the app
|
|
export const ModalProvider = ({ children }) => {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [modalContent, setModalContent] = useState(null);
|
|
const [onSubmit, setOnSubmit] = useState(null);
|
|
const [modalSize, setModalSize] = useState("lg");
|
|
|
|
// Ref to track the modal content element
|
|
const modalRef = useRef(null);
|
|
|
|
const openModal = (content, onSubmitCallback, size = "lg") => {
|
|
setModalContent(content); // Set modal content dynamically
|
|
setOnSubmit(() => onSubmitCallback); // Set the submit handler dynamically
|
|
setIsOpen(true); // Open the modal
|
|
setModalSize(size); // Set the modal size
|
|
};
|
|
|
|
// Function to close the modal
|
|
const closeModal = () => {
|
|
setIsOpen(false); // Close the modal
|
|
setModalContent(null); // Clear modal content
|
|
setOnSubmit(null); // Clear the submit callback
|
|
setModalSize("lg"); // Reset modal size
|
|
};
|
|
|
|
useEffect(() => {
|
|
const handleEscape = (event) => {
|
|
if (event.key === "Escape") {
|
|
closeModal();
|
|
}
|
|
};
|
|
document.addEventListener("keydown", handleEscape);
|
|
return () => {
|
|
document.removeEventListener("keydown", handleEscape);
|
|
};
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const handleClickOutside = (event) => {
|
|
if (modalRef.current && !modalRef.current.contains(event.target)) {
|
|
closeModal();
|
|
}
|
|
};
|
|
document.addEventListener("mousedown", handleClickOutside);
|
|
return () => {
|
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
};
|
|
}, []);
|
|
|
|
return (
|
|
<ModalContext.Provider
|
|
value={{
|
|
isOpen,
|
|
openModal,
|
|
closeModal,
|
|
modalContent,
|
|
modalSize,
|
|
onSubmit,
|
|
}}
|
|
>
|
|
{children}
|
|
|
|
{isOpen && (
|
|
<div style={overlayStyles}>
|
|
<div
|
|
ref={modalRef}
|
|
style={{
|
|
...modalStyles,
|
|
maxWidth: modalSize === "sm" ? "400px" : "800px",
|
|
}}
|
|
>
|
|
<div>{modalContent}</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</ModalContext.Provider>
|
|
);
|
|
};
|
|
|
|
const overlayStyles = {
|
|
position: "fixed",
|
|
top: 0,
|
|
left: 0,
|
|
right: 0,
|
|
bottom: 0,
|
|
backgroundColor: "rgba(0, 0, 0, 0.5)",
|
|
display: "flex",
|
|
justifyContent: "center",
|
|
alignItems: "center",
|
|
zIndex: 1050,
|
|
};
|
|
|
|
const modalStyles = {
|
|
backgroundColor: "white",
|
|
padding: "20px",
|
|
borderRadius: "5px",
|
|
boxShadow: "0 4px 6px rgba(0, 0, 0, 0.1)",
|
|
width: "90%",
|
|
maxWidth: "800px",
|
|
};
|