react-simpler-modal
Version:
a lightweight, hook-based modal management library for React. It leverages React Context and custom hooks to offer an intuitive, type-safe API for handling multiple modals—making it easy to show, hide, update, and persist modal state across your app.
87 lines (86 loc) • 3.29 kB
JavaScript
// src/lib/simpler-modal.tsx
import { createContext, useContext, useReducer } from "react";
import { jsx } from "react/jsx-runtime";
var modalReducer = (state, action) => {
switch (action.type) {
case "SHOW_MODAL": {
const { mergeData } = action.options || {};
const currentData = state[action.modalType]?.data;
const newData = mergeData && typeof currentData === "object" && typeof action.data === "object" ? { ...currentData, ...action.data } : action.data;
return {
...state,
[action.modalType]: { isShowing: true, data: newData }
};
}
case "HIDE_MODAL": {
const { persistData } = action.options || {};
return {
...state,
[action.modalType]: {
isShowing: false,
data: persistData ? state[action.modalType]?.data : void 0
}
};
}
case "TOGGLE_MODAL": {
const isCurrentlyShowing = state[action.modalType]?.isShowing || false;
const { mergeData } = action.options || {};
const currentData = state[action.modalType]?.data;
const newData = !isCurrentlyShowing && mergeData && typeof currentData === "object" && typeof action.data === "object" ? { ...currentData, ...action.data } : !isCurrentlyShowing ? action.data : void 0;
return {
...state,
[action.modalType]: {
isShowing: !isCurrentlyShowing,
data: newData
}
};
}
case "UPDATE_MODAL_DATA": {
const { mergeData } = action.options || {};
const currentData = state[action.modalType]?.data;
const newData = mergeData && typeof currentData === "object" && typeof action.data === "object" ? { ...currentData, ...action.data } : action.data;
return {
...state,
[action.modalType]: {
isShowing: state[action.modalType]?.isShowing || false,
data: newData
}
};
}
default:
return state;
}
};
function simplerModalFactory(initialState) {
const ModalContext = createContext(null);
const ModalProvider = ({ children }) => {
const [state, dispatch] = useReducer(modalReducer, initialState);
return /* @__PURE__ */ jsx(ModalContext.Provider, { value: { state, dispatch }, children });
};
const useModal = () => {
const context = useContext(ModalContext);
if (!context) {
throw new Error("useModal must be used within its corresponding ModalProvider");
}
const { state, dispatch } = context;
const showModal = (modalType, data, options) => {
dispatch({ type: "SHOW_MODAL", modalType, data, options });
};
const hideModal = (modalType, options) => {
dispatch({ type: "HIDE_MODAL", modalType, options });
};
const toggleModal = (modalType, data, options) => {
dispatch({ type: "TOGGLE_MODAL", modalType, data, options });
};
const updateModalData = (modalType, data, options) => {
dispatch({ type: "UPDATE_MODAL_DATA", modalType, data, options });
};
const isModalOpen = (modalType) => !!state[modalType]?.isShowing;
const getModalData = (modalType) => state[modalType]?.data;
return { showModal, hideModal, toggleModal, updateModalData, isModalOpen, getModalData };
};
return { ModalProvider, useModal };
}
export {
simplerModalFactory
};