UNPKG

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
// 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 };