UNPKG

dynamic-modal

Version:

The dynamic-modal is a solution of creation different modals into project using a json configuration file

143 lines (142 loc) 9.13 kB
'use client'; "use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Modal = void 0; const jsx_runtime_1 = require("react/jsx-runtime"); const react_1 = require("react"); const react_2 = require("react"); const react_hook_form_1 = require("react-hook-form"); const portal_1 = require("./components/portal/portal"); const make_toggle_1 = __importDefault(require("./components/make-toggle/make-toggle")); const make_input_1 = __importDefault(require("./components/make-input/make-input")); const make_select_1 = __importDefault(require("./components/make-select/make-select")); const make_textarea_1 = __importDefault(require("./components/make-textarea/make-textarea")); const make_description_1 = __importDefault(require("./components/make-description/make-description")); const make_upload_1 = __importDefault(require("./components/make-upload/make-upload")); const make_button_1 = __importDefault(require("./components/make-button/make-button")); const component_state_1 = require("./context/component/component-state"); const make_custom_upload_1 = __importDefault(require("./components/make-custom-upload/make-custom-upload")); const make_watcher_1 = __importDefault(require("./components/make-watcher/make-watcher")); const make_table_1 = __importDefault(require("./components/make-table/make-table")); const Modal = ({ open, close, config }) => { const { ModalButtonAction, ModalButtonCancel } = (0, react_2.useContext)(component_state_1.ComponentStateContext); const [modalReady, setModalReady] = (0, react_2.useState)(undefined); const [defaultLoaded, setDefaultLoaded] = (0, react_2.useState)(false); const { control, handleSubmit, getValues, unregister, setValue, watch, trigger, reset, getFieldState, } = (0, react_hook_form_1.useForm)(); const formValueHandler = (element) => { if ([ 'group', 'upload', 'custom-upload', 'text', 'description', 'watcher', 'table', ].includes(element.elementType)) return; if (!element.defaultValue && element.renderIf) { unregister(element.name); return; } const defaultValue = element.defaultValue ?? ''; const parsedValue = defaultValue === 'true' ? true : defaultValue === 'false' ? false : defaultValue; setValue(element.name, parsedValue ?? ''); }; const autoLoadGroup = (groupFields) => { groupFields.forEach((element) => { formValueHandler(element); }); }; const autoLoadField = (modalFields) => { if (defaultLoaded) return; modalFields.forEach((element) => { if (element.elementType === 'group') { autoLoadGroup(element.groups); return; } formValueHandler(element); }); setDefaultLoaded(true); }; const getUseSubmit = (modalConfig) => { const useSubmit = modalConfig.useSubmit === undefined ? true : modalConfig.useSubmit === false ? false : true; return useSubmit; }; const getRender = ({ elementType, ...element }, index, isEndOfRender = false) => { if (isEndOfRender && modalReady) setTimeout(() => autoLoadField(modalReady.fields), 200); const props = { control, watch, setValue, unregister, }; return elementType === 'input' ? ((0, react_1.createElement)(make_input_1.default, { ...props, key: `modal-input-${index}`, element: element })) : elementType === 'select' ? ((0, react_1.createElement)(make_select_1.default, { ...props, key: `modal-select-${index}`, element: element })) : elementType === 'textarea' ? ((0, react_1.createElement)(make_textarea_1.default, { ...props, key: `modal-textarea-${index}`, element: element })) : elementType === 'toggle' ? ((0, react_1.createElement)(make_toggle_1.default, { ...props, key: `modal-toggle-${index}`, element: element })) : elementType === 'text' ? ((0, react_1.createElement)(make_description_1.default, { ...props, key: `modal-text-${index}`, element: element })) : elementType === 'upload' ? ((0, react_1.createElement)(make_upload_1.default, { ...props, key: `modal-upload-${index}`, element: element })) : elementType === 'custom-upload' ? ((0, react_1.createElement)(make_custom_upload_1.default, { ...props, key: `modal-custom-upload-${index}`, element: element })) : elementType === 'watcher' ? ((0, react_1.createElement)(make_watcher_1.default, { ...props, key: `modal-watcher-${index}`, element: element })) : elementType === 'button' ? ((0, react_1.createElement)(make_button_1.default, { ...props, key: `modal-button-${index}`, element: element, getValues: getValues })) : elementType === 'table' ? ((0, react_1.createElement)(make_table_1.default, { ...props, key: `modal-table-${index}`, element: element })) : null; }; const closeHandler = () => { if (modalReady?.onClose) modalReady.onClose(); setTimeout(() => { setModalReady(undefined); setDefaultLoaded(false); reset(); close(); }, 200); }; const manualSubmit = async () => { const form = getValues(); const fields = Object.keys(form); await trigger(fields); const validations = fields.map((field) => { const { invalid } = getFieldState(field); return invalid; }); const result = validations.some((isInvalid) => isInvalid) ? undefined : form; if (!result) return; actionHandler({ ...(modalReady?.reservedData ?? {}), ...form }); }; const actionHandler = (data) => { modalReady?.out({ ...(modalReady?.reservedData ?? {}), ...data }); closeHandler(); }; (0, react_2.useEffect)(() => { if (open && !modalReady) setModalReady(config); }, [config, modalReady, open]); if (!modalReady) return null; return ((0, jsx_runtime_1.jsx)(portal_1.Portal, { closeTime: 200, portalOpen: open, portalTag: '#modal-portal', useBlur: modalReady.useBlur, children: (0, jsx_runtime_1.jsx)("div", { className: `rounded bg-white relative w-auto h-auto min-h-[200px] min-w-[500px] ${modalReady.useBlur && 'shadow-md border border-gray-200'}`, style: modalReady.style, children: (0, jsx_runtime_1.jsxs)("form", { className: "flex flex-col p-4 gap-4", autoComplete: "off", onSubmit: handleSubmit(actionHandler), children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-bold text-center border-b pb-4 font-semibold", children: modalReady.title }), (0, jsx_runtime_1.jsx)("div", { className: "flex flex-col gap-4 py-4", style: { overflowY: modalReady.overFlowBody ? 'auto' : undefined, height: modalReady.overFlowBody, minHeight: modalReady.minHeightBody, }, children: modalReady.fields.map((element, index) => { const isEndOfRender = index + 1 === modalReady.fields.length; if (element.elementType === 'group') { const groupElements = element.groups .filter((sub) => !['group', 'watcher', 'table'].includes(sub.elementType)) .map((sub, subIndex) => getRender(sub, index + subIndex, isEndOfRender)); const hideDiv = groupElements.filter((render) => render).length === 0; return ((0, jsx_runtime_1.jsxs)("div", { className: `flex flex-col w-full gap-2 ${hideDiv && 'hidden'}`, children: [element.title && ((0, jsx_runtime_1.jsx)("h3", { className: "font-bold border-b-2 pb-2 mb-2", children: element.title })), (0, jsx_runtime_1.jsx)("div", { className: "flex gap-4 w-full", style: element.style, children: groupElements.map((component) => component) })] }, `modal-group-${index}`)); } else { return getRender(element, index, isEndOfRender); } }) }), (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-4 items-center justify-center border-t p-2", style: modalReady?.actions.containerStyle, children: [modalReady.actions.cancel && ((0, jsx_runtime_1.jsx)(ModalButtonCancel, { ...modalReady.actions.cancel, onClick: closeHandler })), getUseSubmit(modalReady) ? ((0, jsx_runtime_1.jsx)(ModalButtonAction, { ...modalReady.actions.action, type: "submit" })) : ((0, jsx_runtime_1.jsx)(ModalButtonAction, { ...modalReady.actions.action, onClick: manualSubmit, type: "button" }))] })] }) }) })); }; exports.Modal = Modal; exports.default = exports.Modal;