@mantine/modals
Version:
Modals manager based on Mantine components
200 lines (199 loc) • 4.89 kB
JavaScript
"use client";
import { ModalsContext } from "./context.mjs";
import { ConfirmModal } from "./ConfirmModal.mjs";
import { useModalsEvents } from "./events.mjs";
import { handleCloseModal, modalsReducer } from "./reducer.mjs";
import { useCallback, useReducer, useRef } from "react";
import { Modal, getDefaultZIndex } from "@mantine/core";
import { randomId } from "@mantine/hooks";
import { jsx, jsxs } from "react/jsx-runtime";
//#region packages/@mantine/modals/src/ModalsProvider.tsx
function separateConfirmModalProps(props) {
if (!props) return {
confirmProps: {},
modalProps: {}
};
const { id, children, onCancel, onConfirm, closeOnConfirm, closeOnCancel, cancelProps, confirmProps, groupProps, labels, ...others } = props;
return {
confirmProps: {
id,
children,
onCancel,
onConfirm,
closeOnConfirm,
closeOnCancel,
cancelProps,
confirmProps,
groupProps,
labels
},
modalProps: {
id,
...others
}
};
}
function ModalsProvider({ children, modalProps, labels, modals }) {
const [state, dispatch] = useReducer(modalsReducer, {
modals: [],
current: null
});
const stateRef = useRef(state);
stateRef.current = state;
const closingRef = useRef(false);
const closeAll = useCallback((canceled) => {
if (!closingRef.current) {
closingRef.current = true;
stateRef.current.modals.concat().reverse().forEach((modal) => {
handleCloseModal(modal, canceled);
});
closingRef.current = false;
}
dispatch({
type: "CLOSE_ALL",
canceled
});
}, [stateRef, dispatch]);
const openModal = useCallback(({ modalId, ...props }) => {
const id = modalId || randomId();
dispatch({
type: "OPEN",
modal: {
id,
type: "content",
props
}
});
return id;
}, [dispatch]);
const openConfirmModal = useCallback(({ modalId, ...props }) => {
const id = modalId || randomId();
dispatch({
type: "OPEN",
modal: {
id,
type: "confirm",
props
}
});
return id;
}, [dispatch]);
const openContextModal = useCallback((modal, { modalId, ...props }) => {
const id = modalId || randomId();
dispatch({
type: "OPEN",
modal: {
id,
type: "context",
props,
ctx: modal
}
});
return id;
}, [dispatch]);
const closeModal = useCallback((id, canceled) => {
if (!closingRef.current) {
const modal = stateRef.current.modals.find((m) => m.id === id);
if (modal) {
closingRef.current = true;
handleCloseModal(modal, canceled);
closingRef.current = false;
}
}
dispatch({
type: "CLOSE",
modalId: id,
canceled
});
}, [stateRef, dispatch]);
const updateModal = useCallback(({ modalId, ...newProps }) => {
dispatch({
type: "UPDATE",
modalId,
newProps
});
}, [dispatch]);
const updateContextModal = useCallback(({ modalId, ...newProps }) => {
dispatch({
type: "UPDATE",
modalId,
newProps
});
}, [dispatch]);
useModalsEvents({
openModal,
openConfirmModal,
openContextModal: ({ modal, ...payload }) => openContextModal(modal, payload),
closeModal,
closeContextModal: closeModal,
closeAllModals: closeAll,
updateModal,
updateContextModal
});
const ctx = {
modalProps: modalProps || {},
modals: state.modals,
openModal,
openConfirmModal,
openContextModal,
closeModal,
closeContextModal: closeModal,
closeAll,
updateModal,
updateContextModal
};
const getCurrentModal = () => {
const currentModal = stateRef.current.current;
switch (currentModal?.type) {
case "context": {
const { innerProps, ...rest } = currentModal.props;
const ContextModal = modals[currentModal.ctx];
return {
modalProps: rest,
content: /* @__PURE__ */ jsx(ContextModal, {
innerProps,
context: ctx,
id: currentModal.id
})
};
}
case "confirm": {
const { modalProps: separatedModalProps, confirmProps: separatedConfirmProps } = separateConfirmModalProps(currentModal.props);
return {
modalProps: separatedModalProps,
content: /* @__PURE__ */ jsx(ConfirmModal, {
...separatedConfirmProps,
id: currentModal.id,
labels: currentModal.props.labels || labels
})
};
}
case "content": {
const { children: currentModalChildren, ...rest } = currentModal.props;
return {
modalProps: rest,
content: currentModalChildren
};
}
default: return {
modalProps: {},
content: null
};
}
};
const { modalProps: currentModalProps, content } = getCurrentModal();
return /* @__PURE__ */ jsxs(ModalsContext, {
value: ctx,
children: [/* @__PURE__ */ jsx(Modal, {
zIndex: getDefaultZIndex("modal") + 1,
...modalProps,
...currentModalProps,
opened: state.modals.length > 0,
onClose: () => closeModal(state.current?.id),
children: content
}), children]
});
}
//#endregion
export { ModalsProvider };
//# sourceMappingURL=ModalsProvider.mjs.map