dynamic-modal 1.1.14 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/input-upload/input-upload.js +4 -4
- package/dist/components/make-custom-upload/make-custom-upload.d.ts +4 -0
- package/dist/components/make-custom-upload/make-custom-upload.js +97 -0
- package/dist/components/make-watcher/make-watcher.d.ts +4 -0
- package/dist/components/make-watcher/make-watcher.js +62 -0
- package/dist/components/portal/portal.js +1 -1
- package/dist/interfaces/component-state.d.ts +2 -0
- package/dist/interfaces/custom-upload.d.ts +12 -0
- package/dist/interfaces/custom-upload.js +2 -0
- package/dist/interfaces/make-custom-upload.d.ts +7 -0
- package/dist/interfaces/make-custom-upload.js +2 -0
- package/dist/interfaces/make-watcher.d.ts +8 -0
- package/dist/interfaces/make-watcher.js +2 -0
- package/dist/interfaces/modal.d.ts +4 -1
- package/dist/interfaces/portal.d.ts +1 -0
- package/dist/modal.js +7 -3
- package/package.json +1 -1
- package/src/components/input-upload/input-upload.tsx +7 -4
- package/src/components/make-custom-upload/make-custom-upload.tsx +100 -0
- package/src/components/make-watcher/make-watcher.tsx +48 -0
- package/src/components/portal/portal.tsx +3 -1
- package/src/interfaces/component-state.ts +8 -0
- package/src/interfaces/custom-upload.ts +13 -0
- package/src/interfaces/make-custom-upload.ts +9 -0
- package/src/interfaces/make-watcher.ts +10 -0
- package/src/interfaces/modal.ts +5 -0
- package/src/interfaces/portal.ts +1 -0
- package/src/modal.tsx +28 -2
|
@@ -5,9 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
};
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
|
-
const InputUpload = ({ onChange, readAsArrayBuffer, ...props }) => {
|
|
8
|
+
const InputUpload = ({ onChange, readAsArrayBuffer, read, helpText, label, ...props }) => {
|
|
9
9
|
const onChangeHandler = (event) => {
|
|
10
|
-
if (
|
|
10
|
+
if (read && event.target.files) {
|
|
11
11
|
readFileBlob(event.target.files[0], false)
|
|
12
12
|
.then((result) => onChange(result))
|
|
13
13
|
.catch((err) => {
|
|
@@ -42,8 +42,8 @@ const InputUpload = ({ onChange, readAsArrayBuffer, ...props }) => {
|
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
44
|
return (react_1.default.createElement("div", { className: "flex flex-col w-full gap-1 text-center" },
|
|
45
|
-
|
|
45
|
+
label && (react_1.default.createElement("label", { className: "block mb-2 text-sm font-medium text-gray-900 dark:text-white", htmlFor: `file-input-${props.id}` }, label)),
|
|
46
46
|
react_1.default.createElement("input", { className: "file:transition-all file:delay-150 block w-full text-sm text-slate-500\r\n file:mr-4 file:py-2 file:px-4 file:rounded-md\r\n file:border-0 file:text-sm file:font-semibold\r\n file:bg-gray-100 file:text-blue-600\r\n hover:file:bg-blue-700 hover:file:text-white cursor-pointer disabled:cursor-not-allowed", "aria-describedby": `file-input-${props.id}-help`, id: `file-input-${props.id}`, type: "file", onChange: onChangeHandler, ...props }),
|
|
47
|
-
react_1.default.createElement("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-300 text-start", id: `file-input-${props.id}-help` },
|
|
47
|
+
react_1.default.createElement("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-300 text-start", id: `file-input-${props.id}-help` }, helpText?.toUpperCase())));
|
|
48
48
|
};
|
|
49
49
|
exports.default = InputUpload;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
37
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
38
|
+
};
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
const react_1 = __importStar(require("react"));
|
|
41
|
+
const react_hook_form_1 = require("react-hook-form");
|
|
42
|
+
const component_state_1 = require("../../context/component/component-state");
|
|
43
|
+
const use_enable_if_1 = __importDefault(require("../../hooks/use-enable-if"));
|
|
44
|
+
const use_render_if_1 = __importDefault(require("../../hooks/use-render-if"));
|
|
45
|
+
const MakeCustomUpload = ({ element, control, watch, unregister, }) => {
|
|
46
|
+
const { CustomUpload } = (0, react_1.useContext)(component_state_1.ComponentStateContext);
|
|
47
|
+
const { name: elementName, validation: { required, message, regex, ...otherValidation }, enableIf, renderIf, ...inputProps } = element;
|
|
48
|
+
const { checkEnable, enable, setEnable } = (0, use_enable_if_1.default)({
|
|
49
|
+
elementEnableIf: enableIf,
|
|
50
|
+
});
|
|
51
|
+
const { checkRender, render, setRender } = (0, use_render_if_1.default)({
|
|
52
|
+
elementRenderIf: renderIf,
|
|
53
|
+
});
|
|
54
|
+
const elementId = (0, react_1.useId)();
|
|
55
|
+
(0, react_1.useEffect)(() => {
|
|
56
|
+
const { unsubscribe } = watch((formData, { name, type }) => {
|
|
57
|
+
if (!name)
|
|
58
|
+
return;
|
|
59
|
+
if (enableIf) {
|
|
60
|
+
checkEnable(formData, { name, type }).then((enableStatus) => {
|
|
61
|
+
if (enableStatus === undefined || enableStatus === null)
|
|
62
|
+
return;
|
|
63
|
+
if (enable !== enableStatus)
|
|
64
|
+
setEnable(enableStatus);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
if (renderIf) {
|
|
68
|
+
checkRender(formData, { name, type }).then((renderStatus) => {
|
|
69
|
+
if (renderStatus === undefined || renderStatus === null)
|
|
70
|
+
return;
|
|
71
|
+
if (render !== renderStatus) {
|
|
72
|
+
if (render && !renderStatus)
|
|
73
|
+
unregister(elementName);
|
|
74
|
+
setRender(!!renderStatus);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
return () => unsubscribe();
|
|
80
|
+
}, [watch, render, enable]);
|
|
81
|
+
if (!render)
|
|
82
|
+
return null;
|
|
83
|
+
return (react_1.default.createElement(react_hook_form_1.Controller, { control: control, name: elementName, rules: {
|
|
84
|
+
required: {
|
|
85
|
+
value: required,
|
|
86
|
+
message: message ?? '',
|
|
87
|
+
},
|
|
88
|
+
pattern: regex
|
|
89
|
+
? {
|
|
90
|
+
value: regex,
|
|
91
|
+
message: message ?? '',
|
|
92
|
+
}
|
|
93
|
+
: undefined,
|
|
94
|
+
...otherValidation,
|
|
95
|
+
}, render: ({ field: { onChange, value }, fieldState: { invalid, error }, }) => (react_1.default.createElement(CustomUpload, { ...inputProps, name: elementName, id: elementId, onChange: onChange, value: value ?? '', invalid: invalid, error: error, disabled: element.disabled ?? !enable })) }));
|
|
96
|
+
};
|
|
97
|
+
exports.default = MakeCustomUpload;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
20
|
+
var ownKeys = function(o) {
|
|
21
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
22
|
+
var ar = [];
|
|
23
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
24
|
+
return ar;
|
|
25
|
+
};
|
|
26
|
+
return ownKeys(o);
|
|
27
|
+
};
|
|
28
|
+
return function (mod) {
|
|
29
|
+
if (mod && mod.__esModule) return mod;
|
|
30
|
+
var result = {};
|
|
31
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
32
|
+
__setModuleDefault(result, mod);
|
|
33
|
+
return result;
|
|
34
|
+
};
|
|
35
|
+
})();
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
38
|
+
const component_state_1 = require("../../context/component/component-state");
|
|
39
|
+
const MakeWatcher = ({ element, watch }) => {
|
|
40
|
+
const [value, setValue] = (0, react_1.useState)('');
|
|
41
|
+
const { Input } = (0, react_1.useContext)(component_state_1.ComponentStateContext);
|
|
42
|
+
const { watchList, style } = element;
|
|
43
|
+
const elementId = (0, react_1.useId)();
|
|
44
|
+
(0, react_1.useEffect)(() => {
|
|
45
|
+
const { unsubscribe } = watch((formData, { name }) => {
|
|
46
|
+
if (!name)
|
|
47
|
+
return;
|
|
48
|
+
if (watchList.includes(name)) {
|
|
49
|
+
const watchValue = [];
|
|
50
|
+
watchList.forEach((watchName) => {
|
|
51
|
+
const fragment = formData[watchName];
|
|
52
|
+
if (fragment)
|
|
53
|
+
watchValue.push(fragment);
|
|
54
|
+
});
|
|
55
|
+
setValue(watchValue.join(' '));
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
return () => unsubscribe();
|
|
59
|
+
}, [watch]);
|
|
60
|
+
return (react_1.default.createElement(Input, { name: `watcher-${elementId}`, id: elementId, value: value ?? '', onChange: () => { }, invalid: false, disabled: true, style: style }));
|
|
61
|
+
};
|
|
62
|
+
exports.default = MakeWatcher;
|
|
@@ -59,6 +59,6 @@ const Portal = (props) => {
|
|
|
59
59
|
}, [mounted, props.closeTime, props.portalOpen, props.portalTag]);
|
|
60
60
|
if (!mounted && !ref.current)
|
|
61
61
|
return null;
|
|
62
|
-
return (0, react_dom_1.createPortal)(react_1.default.createElement("div", { className:
|
|
62
|
+
return (0, react_dom_1.createPortal)(react_1.default.createElement("div", { className: `transition-all delay-100 fixed top-0 left-0 w-full h-full grid place-items-center bg-black bg-opacity-40 z-20 ${props.useBlur && 'backdrop-blur-xs'}` }, props.children), ref.current);
|
|
63
63
|
};
|
|
64
64
|
exports.Portal = Portal;
|
|
@@ -6,6 +6,7 @@ import { IMakeButton } from './make-button';
|
|
|
6
6
|
import { IMakeSelect } from './make-select';
|
|
7
7
|
import { IMakeTextarea } from './make-textarea';
|
|
8
8
|
import { IMakeToggle } from './make-toggle';
|
|
9
|
+
import { IMakeCustomUpload } from './make-custom-upload';
|
|
9
10
|
export interface IComponentAditionalProps {
|
|
10
11
|
onChange: (...event: any[]) => void;
|
|
11
12
|
value: any;
|
|
@@ -18,6 +19,7 @@ export interface IComponentState {
|
|
|
18
19
|
ModalButtonAction: FC<Omit<IMakeButton, 'elementType'>>;
|
|
19
20
|
Button: FC<Omit<IMakeButton, 'elementType'>>;
|
|
20
21
|
Input: FC<Omit<IMakeInput, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> & IComponentAditionalProps>;
|
|
22
|
+
CustomUpload: FC<Omit<IMakeCustomUpload, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> & IComponentAditionalProps>;
|
|
21
23
|
Select: FC<Omit<IMakeSelect, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> & IComponentAditionalProps & Record<'options', Array<IOption>>>;
|
|
22
24
|
Textarea: FC<Omit<IMakeTextarea, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> & IComponentAditionalProps>;
|
|
23
25
|
Toggle: FC<Omit<IMakeToggle, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> & IComponentAditionalProps>;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ChangeEvent, CSSProperties } from 'react';
|
|
2
|
+
export interface ICustomUpload {
|
|
3
|
+
id?: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
6
|
+
accept?: string;
|
|
7
|
+
label?: string;
|
|
8
|
+
helpText?: string;
|
|
9
|
+
style?: CSSProperties;
|
|
10
|
+
name: string;
|
|
11
|
+
disabled?: boolean;
|
|
12
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { IField, IFieldProps } from './field';
|
|
2
|
+
export interface IMakeWatcher extends Pick<IField, 'style'> {
|
|
3
|
+
elementType: 'watcher';
|
|
4
|
+
watchList: Array<string>;
|
|
5
|
+
}
|
|
6
|
+
export interface IMakeWatcherProps extends IFieldProps {
|
|
7
|
+
element: Omit<IMakeWatcher, 'elementType'>;
|
|
8
|
+
}
|
|
@@ -8,7 +8,9 @@ import { IMakeFieldGroup } from './make-field-group';
|
|
|
8
8
|
import { IMakeUpload } from './make-upload';
|
|
9
9
|
import { IOption } from './option';
|
|
10
10
|
import { IMakeButton } from './make-button';
|
|
11
|
-
|
|
11
|
+
import { IMakeCustomUpload } from './make-custom-upload';
|
|
12
|
+
import { IMakeWatcher } from './make-watcher';
|
|
13
|
+
export type IModalField = IMakeSelect | IMakeInput | IMakeFieldGroup | IMakeTextarea | IMakeToggle | IMakeDescription | IMakeUpload | IMakeCustomUpload | IMakeWatcher | IMakeButton;
|
|
12
14
|
export type IFormField = IMakeSelect | IMakeInput | IMakeTextarea | IMakeToggle;
|
|
13
15
|
export interface IModalRenderAction {
|
|
14
16
|
action: (data: string, ...args: any[]) => Promise<boolean>;
|
|
@@ -30,6 +32,7 @@ export interface IModalConfigProps {
|
|
|
30
32
|
overFlowBody?: string | number;
|
|
31
33
|
minHeightBody?: string | number;
|
|
32
34
|
useSubmit?: boolean;
|
|
35
|
+
useBlur?: boolean;
|
|
33
36
|
actions: {
|
|
34
37
|
containerStyle?: CSSProperties;
|
|
35
38
|
cancel?: Omit<IMakeButton, 'elementType'>;
|
package/dist/modal.js
CHANGED
|
@@ -49,13 +49,15 @@ const make_description_1 = __importDefault(require("./components/make-descriptio
|
|
|
49
49
|
const make_upload_1 = __importDefault(require("./components/make-upload/make-upload"));
|
|
50
50
|
const make_button_1 = __importDefault(require("./components/make-button/make-button"));
|
|
51
51
|
const component_state_1 = require("./context/component/component-state");
|
|
52
|
+
const make_custom_upload_1 = __importDefault(require("./components/make-custom-upload/make-custom-upload"));
|
|
53
|
+
const make_watcher_1 = __importDefault(require("./components/make-watcher/make-watcher"));
|
|
52
54
|
const Modal = ({ open, close, config }) => {
|
|
53
55
|
const { ModalButtonAction, ModalButtonCancel } = (0, react_1.useContext)(component_state_1.ComponentStateContext);
|
|
54
56
|
const [modalReady, setModalReady] = (0, react_1.useState)(undefined);
|
|
55
57
|
const [defaultLoaded, setDefaultLoaded] = (0, react_1.useState)(false);
|
|
56
58
|
const { control, handleSubmit, getValues, unregister, setValue, watch, trigger, reset, getFieldState, } = (0, react_hook_form_1.useForm)();
|
|
57
59
|
const formValueHandler = (element) => {
|
|
58
|
-
if (['group', 'upload', 'text'].includes(element.elementType))
|
|
60
|
+
if (['group', 'upload', 'custom-upload', 'text'].includes(element.elementType))
|
|
59
61
|
return;
|
|
60
62
|
if (!element.defaultValue && element.renderIf) {
|
|
61
63
|
unregister(element.name);
|
|
@@ -103,7 +105,7 @@ const Modal = ({ open, close, config }) => {
|
|
|
103
105
|
setValue,
|
|
104
106
|
unregister,
|
|
105
107
|
};
|
|
106
|
-
return elementType === 'input' ? (react_1.default.createElement(make_input_1.default, { ...props, key: `modal-input-${index}`, element: element })) : elementType === 'select' ? (react_1.default.createElement(make_select_1.default, { ...props, key: `modal-select-${index}`, element: element })) : elementType === 'textarea' ? (react_1.default.createElement(make_textarea_1.default, { ...props, key: `modal-textarea-${index}`, element: element })) : elementType === 'toggle' ? (react_1.default.createElement(make_toggle_1.default, { ...props, key: `modal-toggle-${index}`, element: element })) : elementType === 'text' ? (react_1.default.createElement(make_description_1.default, { ...props, key: `modal-text-${index}`, element: element })) : elementType === 'upload' ? (react_1.default.createElement(make_upload_1.default, { ...props, key: `modal-upload-${index}`, element: element })) : elementType === 'button' ? (react_1.default.createElement(make_button_1.default, { ...props, key: `modal-button-${index}`, element: element })) : null;
|
|
108
|
+
return elementType === 'input' ? (react_1.default.createElement(make_input_1.default, { ...props, key: `modal-input-${index}`, element: element })) : elementType === 'select' ? (react_1.default.createElement(make_select_1.default, { ...props, key: `modal-select-${index}`, element: element })) : elementType === 'textarea' ? (react_1.default.createElement(make_textarea_1.default, { ...props, key: `modal-textarea-${index}`, element: element })) : elementType === 'toggle' ? (react_1.default.createElement(make_toggle_1.default, { ...props, key: `modal-toggle-${index}`, element: element })) : elementType === 'text' ? (react_1.default.createElement(make_description_1.default, { ...props, key: `modal-text-${index}`, element: element })) : elementType === 'upload' ? (react_1.default.createElement(make_upload_1.default, { ...props, key: `modal-upload-${index}`, element: element })) : elementType === 'custom-upload' ? (react_1.default.createElement(make_custom_upload_1.default, { ...props, key: `modal-custom-upload-${index}`, element: element })) : elementType === 'watcher' ? (react_1.default.createElement(make_watcher_1.default, { ...props, key: `modal-watcher-${index}`, element: element })) : elementType === 'button' ? (react_1.default.createElement(make_button_1.default, { ...props, key: `modal-button-${index}`, element: element })) : null;
|
|
107
109
|
};
|
|
108
110
|
const closeHandler = () => {
|
|
109
111
|
if (modalReady?.onClose)
|
|
@@ -140,7 +142,7 @@ const Modal = ({ open, close, config }) => {
|
|
|
140
142
|
}, [config, modalReady, open]);
|
|
141
143
|
if (!modalReady)
|
|
142
144
|
return null;
|
|
143
|
-
return (react_1.default.createElement(portal_1.Portal, { closeTime: 200, portalOpen: open, portalTag: '#modal-portal' },
|
|
145
|
+
return (react_1.default.createElement(portal_1.Portal, { closeTime: 200, portalOpen: open, portalTag: '#modal-portal', useBlur: modalReady.useBlur },
|
|
144
146
|
react_1.default.createElement("div", { className: "rounded bg-white relative w-auto h-auto min-h-[200px] min-w-[500px]", style: modalReady.style },
|
|
145
147
|
react_1.default.createElement("form", { className: "flex flex-col p-4 gap-4", autoComplete: "off", onSubmit: handleSubmit(actionHandler) },
|
|
146
148
|
react_1.default.createElement("h2", { className: "text-bold text-center border-b pb-4 font-semibold" }, modalReady.title),
|
|
@@ -160,6 +162,8 @@ const Modal = ({ open, close, config }) => {
|
|
|
160
162
|
'toggle',
|
|
161
163
|
'multiselect',
|
|
162
164
|
'upload',
|
|
165
|
+
'custom-upload',
|
|
166
|
+
'watcher',
|
|
163
167
|
'button',
|
|
164
168
|
'autocomplete',
|
|
165
169
|
].includes(sub.elementType))
|
package/package.json
CHANGED
|
@@ -7,10 +7,13 @@ import { IFileResult, IInputUpload } from '../../interfaces/input-upload';
|
|
|
7
7
|
const InputUpload: FC<IInputUpload> = ({
|
|
8
8
|
onChange,
|
|
9
9
|
readAsArrayBuffer,
|
|
10
|
+
read,
|
|
11
|
+
helpText,
|
|
12
|
+
label,
|
|
10
13
|
...props
|
|
11
14
|
}: IInputUpload) => {
|
|
12
15
|
const onChangeHandler = (event: ChangeEvent<HTMLInputElement>) => {
|
|
13
|
-
if (
|
|
16
|
+
if (read && event.target.files) {
|
|
14
17
|
readFileBlob(event.target.files[0], false)
|
|
15
18
|
.then((result) => onChange(result))
|
|
16
19
|
.catch((err) => {
|
|
@@ -46,12 +49,12 @@ const InputUpload: FC<IInputUpload> = ({
|
|
|
46
49
|
|
|
47
50
|
return (
|
|
48
51
|
<div className="flex flex-col w-full gap-1 text-center">
|
|
49
|
-
{
|
|
52
|
+
{label && (
|
|
50
53
|
<label
|
|
51
54
|
className="block mb-2 text-sm font-medium text-gray-900 dark:text-white"
|
|
52
55
|
htmlFor={`file-input-${props.id}`}
|
|
53
56
|
>
|
|
54
|
-
{
|
|
57
|
+
{label}
|
|
55
58
|
</label>
|
|
56
59
|
)}
|
|
57
60
|
<input
|
|
@@ -70,7 +73,7 @@ const InputUpload: FC<IInputUpload> = ({
|
|
|
70
73
|
className="mt-1 text-sm text-gray-500 dark:text-gray-300 text-start"
|
|
71
74
|
id={`file-input-${props.id}-help`}
|
|
72
75
|
>
|
|
73
|
-
{
|
|
76
|
+
{helpText?.toUpperCase()}
|
|
74
77
|
</p>
|
|
75
78
|
</div>
|
|
76
79
|
);
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { FC, useContext, useEffect, useId } from 'react';
|
|
4
|
+
import { Controller } from 'react-hook-form';
|
|
5
|
+
|
|
6
|
+
import { ComponentStateContext } from '../../context/component/component-state';
|
|
7
|
+
import useEnableIf from '../../hooks/use-enable-if';
|
|
8
|
+
import useRenderIf from '../../hooks/use-render-if';
|
|
9
|
+
import { IMakeCustomUploadProps } from '../../interfaces/make-custom-upload';
|
|
10
|
+
|
|
11
|
+
const MakeCustomUpload: FC<IMakeCustomUploadProps> = ({
|
|
12
|
+
element,
|
|
13
|
+
control,
|
|
14
|
+
watch,
|
|
15
|
+
unregister,
|
|
16
|
+
}) => {
|
|
17
|
+
const { CustomUpload } = useContext(ComponentStateContext);
|
|
18
|
+
|
|
19
|
+
const {
|
|
20
|
+
name: elementName,
|
|
21
|
+
validation: { required, message, regex, ...otherValidation },
|
|
22
|
+
enableIf,
|
|
23
|
+
renderIf,
|
|
24
|
+
...inputProps
|
|
25
|
+
} = element;
|
|
26
|
+
|
|
27
|
+
const { checkEnable, enable, setEnable } = useEnableIf({
|
|
28
|
+
elementEnableIf: enableIf,
|
|
29
|
+
});
|
|
30
|
+
const { checkRender, render, setRender } = useRenderIf({
|
|
31
|
+
elementRenderIf: renderIf,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const elementId = useId();
|
|
35
|
+
|
|
36
|
+
useEffect(() => {
|
|
37
|
+
const { unsubscribe } = watch((formData, { name, type }) => {
|
|
38
|
+
if (!name) return;
|
|
39
|
+
|
|
40
|
+
if (enableIf) {
|
|
41
|
+
checkEnable(formData, { name, type }).then((enableStatus) => {
|
|
42
|
+
if (enableStatus === undefined || enableStatus === null) return;
|
|
43
|
+
if (enable !== enableStatus) setEnable(enableStatus);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (renderIf) {
|
|
48
|
+
checkRender(formData, { name, type }).then((renderStatus) => {
|
|
49
|
+
if (renderStatus === undefined || renderStatus === null) return;
|
|
50
|
+
|
|
51
|
+
if (render !== renderStatus) {
|
|
52
|
+
if (render && !renderStatus) unregister(elementName as string);
|
|
53
|
+
setRender(!!renderStatus);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return () => unsubscribe();
|
|
60
|
+
}, [watch, render, enable]);
|
|
61
|
+
|
|
62
|
+
if (!render) return null;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Controller
|
|
66
|
+
control={control}
|
|
67
|
+
name={elementName}
|
|
68
|
+
rules={{
|
|
69
|
+
required: {
|
|
70
|
+
value: required,
|
|
71
|
+
message: message ?? '',
|
|
72
|
+
},
|
|
73
|
+
pattern: regex
|
|
74
|
+
? {
|
|
75
|
+
value: regex,
|
|
76
|
+
message: message ?? '',
|
|
77
|
+
}
|
|
78
|
+
: undefined,
|
|
79
|
+
...otherValidation,
|
|
80
|
+
}}
|
|
81
|
+
render={({
|
|
82
|
+
field: { onChange, value },
|
|
83
|
+
fieldState: { invalid, error },
|
|
84
|
+
}) => (
|
|
85
|
+
<CustomUpload
|
|
86
|
+
{...inputProps}
|
|
87
|
+
name={elementName}
|
|
88
|
+
id={elementId}
|
|
89
|
+
onChange={onChange}
|
|
90
|
+
value={value ?? ''}
|
|
91
|
+
invalid={invalid}
|
|
92
|
+
error={error}
|
|
93
|
+
disabled={element.disabled ?? !enable}
|
|
94
|
+
/>
|
|
95
|
+
)}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export default MakeCustomUpload;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import React, { FC, useContext, useEffect, useId, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import { ComponentStateContext } from '../../context/component/component-state';
|
|
6
|
+
import { IMakeWatcherProps } from '../../interfaces/make-watcher';
|
|
7
|
+
|
|
8
|
+
const MakeWatcher: FC<IMakeWatcherProps> = ({ element, watch }) => {
|
|
9
|
+
const [value, setValue] = useState<string>('');
|
|
10
|
+
const { Input } = useContext(ComponentStateContext);
|
|
11
|
+
|
|
12
|
+
const { watchList, style } = element;
|
|
13
|
+
|
|
14
|
+
const elementId = useId();
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
const { unsubscribe } = watch((formData, { name }) => {
|
|
18
|
+
if (!name) return;
|
|
19
|
+
|
|
20
|
+
if (watchList.includes(name)) {
|
|
21
|
+
const watchValue: Array<string> = [];
|
|
22
|
+
|
|
23
|
+
watchList.forEach((watchName) => {
|
|
24
|
+
const fragment: string = formData[watchName];
|
|
25
|
+
if (fragment) watchValue.push(fragment);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
setValue(watchValue.join(' '));
|
|
29
|
+
}
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
return () => unsubscribe();
|
|
33
|
+
}, [watch]);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<Input
|
|
37
|
+
name={`watcher-${elementId}`}
|
|
38
|
+
id={elementId}
|
|
39
|
+
value={value ?? ''}
|
|
40
|
+
onChange={() => {}}
|
|
41
|
+
invalid={false}
|
|
42
|
+
disabled={true}
|
|
43
|
+
style={style}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export default MakeWatcher;
|
|
@@ -31,7 +31,9 @@ export const Portal: FC<IPortal> = (props) => {
|
|
|
31
31
|
if (!mounted && !ref.current) return null;
|
|
32
32
|
|
|
33
33
|
return createPortal(
|
|
34
|
-
<div
|
|
34
|
+
<div
|
|
35
|
+
className={`transition-all delay-100 fixed top-0 left-0 w-full h-full grid place-items-center bg-black bg-opacity-40 z-20 ${props.useBlur && 'backdrop-blur-xs'}`}
|
|
36
|
+
>
|
|
35
37
|
{props.children}
|
|
36
38
|
</div>,
|
|
37
39
|
ref.current!,
|
|
@@ -7,6 +7,7 @@ import { IMakeButton } from './make-button';
|
|
|
7
7
|
import { IMakeSelect } from './make-select';
|
|
8
8
|
import { IMakeTextarea } from './make-textarea';
|
|
9
9
|
import { IMakeToggle } from './make-toggle';
|
|
10
|
+
import { IMakeCustomUpload } from './make-custom-upload';
|
|
10
11
|
|
|
11
12
|
export interface IComponentAditionalProps {
|
|
12
13
|
onChange: (...event: any[]) => void;
|
|
@@ -25,6 +26,13 @@ export interface IComponentState {
|
|
|
25
26
|
Omit<IMakeInput, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> &
|
|
26
27
|
IComponentAditionalProps
|
|
27
28
|
>;
|
|
29
|
+
CustomUpload: FC<
|
|
30
|
+
Omit<
|
|
31
|
+
IMakeCustomUpload,
|
|
32
|
+
'elementType' | 'validation' | 'renderIf' | 'enableIf'
|
|
33
|
+
> &
|
|
34
|
+
IComponentAditionalProps
|
|
35
|
+
>;
|
|
28
36
|
Select: FC<
|
|
29
37
|
Omit<IMakeSelect, 'elementType' | 'validation' | 'renderIf' | 'enableIf'> &
|
|
30
38
|
IComponentAditionalProps &
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ChangeEvent, CSSProperties } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ICustomUpload {
|
|
4
|
+
id?: string;
|
|
5
|
+
value?: string;
|
|
6
|
+
onChange: (event: ChangeEvent<HTMLInputElement>) => void;
|
|
7
|
+
accept?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
helpText?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
name: string;
|
|
12
|
+
disabled?: boolean;
|
|
13
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { IField, IFieldProps } from './field';
|
|
2
|
+
|
|
3
|
+
export interface IMakeWatcher extends Pick<IField, 'style'> {
|
|
4
|
+
elementType: 'watcher';
|
|
5
|
+
watchList: Array<string>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export interface IMakeWatcherProps extends IFieldProps {
|
|
9
|
+
element: Omit<IMakeWatcher, 'elementType'>;
|
|
10
|
+
}
|
package/src/interfaces/modal.ts
CHANGED
|
@@ -9,6 +9,8 @@ import { IMakeFieldGroup } from './make-field-group';
|
|
|
9
9
|
import { IMakeUpload } from './make-upload';
|
|
10
10
|
import { IOption } from './option';
|
|
11
11
|
import { IMakeButton } from './make-button';
|
|
12
|
+
import { IMakeCustomUpload } from './make-custom-upload';
|
|
13
|
+
import { IMakeWatcher } from './make-watcher';
|
|
12
14
|
|
|
13
15
|
export type IModalField =
|
|
14
16
|
| IMakeSelect
|
|
@@ -18,6 +20,8 @@ export type IModalField =
|
|
|
18
20
|
| IMakeToggle
|
|
19
21
|
| IMakeDescription
|
|
20
22
|
| IMakeUpload
|
|
23
|
+
| IMakeCustomUpload
|
|
24
|
+
| IMakeWatcher
|
|
21
25
|
| IMakeButton;
|
|
22
26
|
|
|
23
27
|
export type IFormField = IMakeSelect | IMakeInput | IMakeTextarea | IMakeToggle;
|
|
@@ -49,6 +53,7 @@ export interface IModalConfigProps {
|
|
|
49
53
|
overFlowBody?: string | number;
|
|
50
54
|
minHeightBody?: string | number;
|
|
51
55
|
useSubmit?: boolean;
|
|
56
|
+
useBlur?: boolean;
|
|
52
57
|
actions: {
|
|
53
58
|
containerStyle?: CSSProperties;
|
|
54
59
|
cancel?: Omit<IMakeButton, 'elementType'>;
|
package/src/interfaces/portal.ts
CHANGED
package/src/modal.tsx
CHANGED
|
@@ -26,6 +26,10 @@ import { IMakeDescription } from './interfaces/make-description';
|
|
|
26
26
|
import { IMakeUpload } from './interfaces/make-upload';
|
|
27
27
|
import { IMakeButton } from './interfaces/make-button';
|
|
28
28
|
import { ComponentStateContext } from './context/component/component-state';
|
|
29
|
+
import MakeCustomUpload from './components/make-custom-upload/make-custom-upload';
|
|
30
|
+
import { IMakeCustomUpload } from './interfaces/make-custom-upload';
|
|
31
|
+
import MakeWatcher from './components/make-watcher/make-watcher';
|
|
32
|
+
import { IMakeWatcher } from './interfaces/make-watcher';
|
|
29
33
|
|
|
30
34
|
export const Modal = ({ open, close, config }: IModal) => {
|
|
31
35
|
const { ModalButtonAction, ModalButtonCancel } = useContext(
|
|
@@ -49,7 +53,10 @@ export const Modal = ({ open, close, config }: IModal) => {
|
|
|
49
53
|
} = useForm();
|
|
50
54
|
|
|
51
55
|
const formValueHandler = (element: IFormField) => {
|
|
52
|
-
if (
|
|
56
|
+
if (
|
|
57
|
+
['group', 'upload', 'custom-upload', 'text'].includes(element.elementType)
|
|
58
|
+
)
|
|
59
|
+
return;
|
|
53
60
|
if (!element.defaultValue && element.renderIf) {
|
|
54
61
|
unregister(element.name);
|
|
55
62
|
return;
|
|
@@ -149,6 +156,18 @@ export const Modal = ({ open, close, config }: IModal) => {
|
|
|
149
156
|
key={`modal-upload-${index}`}
|
|
150
157
|
element={element as IMakeUpload}
|
|
151
158
|
/>
|
|
159
|
+
) : elementType === 'custom-upload' ? (
|
|
160
|
+
<MakeCustomUpload
|
|
161
|
+
{...props}
|
|
162
|
+
key={`modal-custom-upload-${index}`}
|
|
163
|
+
element={element as IMakeCustomUpload}
|
|
164
|
+
/>
|
|
165
|
+
) : elementType === 'watcher' ? (
|
|
166
|
+
<MakeWatcher
|
|
167
|
+
{...props}
|
|
168
|
+
key={`modal-watcher-${index}`}
|
|
169
|
+
element={element as IMakeWatcher}
|
|
170
|
+
/>
|
|
152
171
|
) : elementType === 'button' ? (
|
|
153
172
|
<MakeButton
|
|
154
173
|
{...props}
|
|
@@ -203,7 +222,12 @@ export const Modal = ({ open, close, config }: IModal) => {
|
|
|
203
222
|
if (!modalReady) return null;
|
|
204
223
|
|
|
205
224
|
return (
|
|
206
|
-
<Portal
|
|
225
|
+
<Portal
|
|
226
|
+
closeTime={200}
|
|
227
|
+
portalOpen={open}
|
|
228
|
+
portalTag={'#modal-portal'}
|
|
229
|
+
useBlur={modalReady.useBlur}
|
|
230
|
+
>
|
|
207
231
|
<div
|
|
208
232
|
className="rounded bg-white relative w-auto h-auto min-h-[200px] min-w-[500px]"
|
|
209
233
|
style={modalReady.style}
|
|
@@ -252,6 +276,8 @@ export const Modal = ({ open, close, config }: IModal) => {
|
|
|
252
276
|
'toggle',
|
|
253
277
|
'multiselect',
|
|
254
278
|
'upload',
|
|
279
|
+
'custom-upload',
|
|
280
|
+
'watcher',
|
|
255
281
|
'button',
|
|
256
282
|
'autocomplete',
|
|
257
283
|
].includes(sub.elementType),
|