dynamic-modal 1.1.22 → 1.1.24
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/README.md +574 -142
- package/dist/src/components/make-description/make-description.js +1 -1
- package/dist/src/components/make-input/make-input.js +16 -27
- package/dist/src/components/make-select/make-select.js +21 -40
- package/dist/src/components/make-table/make-table.js +48 -62
- package/dist/src/components/make-textarea/make-textarea.js +16 -27
- package/dist/src/components/make-toggle/make-toggle.js +16 -27
- package/dist/src/components/portal/portal.js +27 -16
- package/dist/src/hooks/use-conditional-field.d.ts +28 -0
- package/dist/src/hooks/use-conditional-field.js +61 -0
- package/dist/src/modal.js +57 -39
- package/dist/src/util/general/general.util.js +8 -4
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
const MakeDescription = ({ element: { text, Icon, containerStyle, textStyle, elements }, }) => {
|
|
4
|
-
return (_jsxs("div", { className: "flex gap-4 w-full h-auto text-xs text-center p-2 border-1 rounded-md", style: containerStyle, children: [Icon && _jsx(Icon, {}), text && !elements && _jsx("p", { style: textStyle, children: text }), !text && elements && (_jsx("p", { style: textStyle, children: elements.map((fragment
|
|
4
|
+
return (_jsxs("div", { className: "flex gap-4 w-full h-auto text-xs text-center p-2 border-1 rounded-md", style: containerStyle, children: [Icon && _jsx(Icon, {}), text && !elements && _jsx("p", { style: textStyle, children: text }), !text && elements && (_jsx("p", { style: textStyle, children: elements.map((fragment) => (_jsx("span", { style: fragment.style, children: fragment.text }, `desc-fragment-${fragment.text}`))) }))] }));
|
|
5
5
|
};
|
|
6
6
|
export default MakeDescription;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useContext,
|
|
3
|
+
import { useContext, useId } from 'react';
|
|
4
4
|
import { Controller } from 'react-hook-form';
|
|
5
5
|
import { ComponentStateContext } from '../../context/component/component-state';
|
|
6
6
|
import useEnableIf from '../../hooks/use-enable-if';
|
|
7
7
|
import useRenderIf from '../../hooks/use-render-if';
|
|
8
|
+
import useConditionalField from '../../hooks/use-conditional-field';
|
|
8
9
|
const MakeInput = ({ element, control, watch, unregister, }) => {
|
|
9
10
|
const { Input } = useContext(ComponentStateContext);
|
|
10
11
|
const { name: elementName, validation: { required, message, regex, ...otherValidation }, enableIf, renderIf, ...inputProps } = element;
|
|
@@ -15,32 +16,20 @@ const MakeInput = ({ element, control, watch, unregister, }) => {
|
|
|
15
16
|
elementRenderIf: renderIf,
|
|
16
17
|
});
|
|
17
18
|
const elementId = useId();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (renderStatus === undefined || renderStatus === null)
|
|
33
|
-
return;
|
|
34
|
-
if (render !== renderStatus) {
|
|
35
|
-
if (render && !renderStatus)
|
|
36
|
-
unregister(elementName);
|
|
37
|
-
setRender(!!renderStatus);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return () => unsubscribe();
|
|
43
|
-
}, [watch, render, enable]);
|
|
19
|
+
useConditionalField({
|
|
20
|
+
watch,
|
|
21
|
+
elementName,
|
|
22
|
+
renderIf,
|
|
23
|
+
enableIf,
|
|
24
|
+
render,
|
|
25
|
+
enable,
|
|
26
|
+
checkRender,
|
|
27
|
+
checkEnable,
|
|
28
|
+
checkLiveData: async () => null,
|
|
29
|
+
setRender,
|
|
30
|
+
setEnable,
|
|
31
|
+
unregister,
|
|
32
|
+
});
|
|
44
33
|
if (!render)
|
|
45
34
|
return null;
|
|
46
35
|
return (_jsx(Controller, { control: control, name: elementName, rules: {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useContext,
|
|
3
|
+
import { useContext, useId, useState } from 'react';
|
|
4
4
|
import { Controller } from 'react-hook-form';
|
|
5
5
|
import { ComponentStateContext } from '../../context/component/component-state';
|
|
6
6
|
import useEnableIf from '../../hooks/use-enable-if';
|
|
7
7
|
import useRenderIf from '../../hooks/use-render-if';
|
|
8
8
|
import useLiveData from '../../hooks/use-live-data';
|
|
9
|
+
import useConditionalField from '../../hooks/use-conditional-field';
|
|
9
10
|
const MakeSelect = ({ element, control, watch, setValue, unregister, }) => {
|
|
10
11
|
const { Select } = useContext(ComponentStateContext);
|
|
11
12
|
const { name: elementName, validation: { required, message, regex, ...otherValidation }, enableIf, renderIf, liveData: elementLiveData, ...inputProps } = element;
|
|
@@ -20,45 +21,25 @@ const MakeSelect = ({ element, control, watch, setValue, unregister, }) => {
|
|
|
20
21
|
elementRenderIf: renderIf,
|
|
21
22
|
});
|
|
22
23
|
const elementId = useId();
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
setRender(!!renderStatus);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
if (elementLiveData) {
|
|
47
|
-
setLiveSearching(true);
|
|
48
|
-
checkLiveData(formData, { name, type })
|
|
49
|
-
.then((options) => {
|
|
50
|
-
if (options === undefined || options === null)
|
|
51
|
-
return;
|
|
52
|
-
setLiveData(options);
|
|
53
|
-
setValue(elementName, options);
|
|
54
|
-
})
|
|
55
|
-
.finally(() => {
|
|
56
|
-
setLiveSearching(false);
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
|
-
return () => unsubscribe();
|
|
61
|
-
}, [watch, render, enable, liveData]);
|
|
24
|
+
useConditionalField({
|
|
25
|
+
watch,
|
|
26
|
+
elementName,
|
|
27
|
+
renderIf,
|
|
28
|
+
enableIf,
|
|
29
|
+
liveDataConfig: elementLiveData,
|
|
30
|
+
render,
|
|
31
|
+
enable,
|
|
32
|
+
checkRender,
|
|
33
|
+
checkEnable,
|
|
34
|
+
checkLiveData,
|
|
35
|
+
setRender,
|
|
36
|
+
setEnable,
|
|
37
|
+
setLiveData,
|
|
38
|
+
setLiveSearching,
|
|
39
|
+
unregister,
|
|
40
|
+
setValue,
|
|
41
|
+
liveDataResetValue: inputProps.defaultValue ?? [],
|
|
42
|
+
});
|
|
62
43
|
if (!render)
|
|
63
44
|
return null;
|
|
64
45
|
return (_jsx(Controller, { control: control, name: elementName, rules: {
|
|
@@ -1,100 +1,86 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
-
import { useCallback, useContext,
|
|
3
|
+
import { useCallback, useContext, useMemo, useState } from 'react';
|
|
4
4
|
import useRenderIf from '../../hooks/use-render-if';
|
|
5
5
|
import { ComponentStateContext } from '../../context/component/component-state';
|
|
6
6
|
import useLiveData from '../../hooks/use-live-data';
|
|
7
7
|
import { Controller } from 'react-hook-form';
|
|
8
|
-
|
|
8
|
+
import useConditionalField from '../../hooks/use-conditional-field';
|
|
9
|
+
const MakeTable = ({ element, watch, control, setValue, }) => {
|
|
9
10
|
const [liveSearching, setLiveSearching] = useState(false);
|
|
10
11
|
const [selected, setSelected] = useState('');
|
|
11
12
|
const [rowSelected, setRowSelected] = useState(new Map());
|
|
12
|
-
const { Select } = useContext(ComponentStateContext);
|
|
13
|
-
const {
|
|
14
|
-
const { selectTitleName, selectValueName, selectActionName, selectPlaceholder, renderIf, columns, name: elementName, data, liveData: elementLiveData, style, buttonStyle } = element;
|
|
13
|
+
const { Select, Button } = useContext(ComponentStateContext);
|
|
14
|
+
const { selectTitleName, selectValueName, selectActionName, selectPlaceholder, renderIf, columns, name: elementName, data, liveData: elementLiveData, style, buttonStyle, } = element;
|
|
15
15
|
const { checkLiveData, liveData, setLiveData } = useLiveData({
|
|
16
16
|
elementLiveData,
|
|
17
17
|
});
|
|
18
18
|
const { checkRender, render, setRender } = useRenderIf({
|
|
19
19
|
elementRenderIf: renderIf,
|
|
20
20
|
});
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
useConditionalField({
|
|
22
|
+
watch,
|
|
23
|
+
elementName,
|
|
24
|
+
renderIf,
|
|
25
|
+
liveDataConfig: elementLiveData,
|
|
26
|
+
render,
|
|
27
|
+
enable: true,
|
|
28
|
+
checkRender,
|
|
29
|
+
checkEnable: async () => null,
|
|
30
|
+
checkLiveData,
|
|
31
|
+
setRender,
|
|
32
|
+
setEnable: () => { },
|
|
33
|
+
setLiveData,
|
|
34
|
+
setLiveSearching,
|
|
35
|
+
});
|
|
36
|
+
const addToTable = useCallback((selectedValue) => {
|
|
37
|
+
if (selectedValue === '')
|
|
23
38
|
return;
|
|
24
|
-
const elementSelected = data.find((
|
|
39
|
+
const elementSelected = data.find((item) => String(item[selectValueName]) === selectedValue);
|
|
25
40
|
if (elementSelected) {
|
|
26
41
|
const currentElements = new Map(rowSelected.entries());
|
|
27
|
-
currentElements.set(
|
|
42
|
+
currentElements.set(selectedValue, elementSelected);
|
|
28
43
|
setValue(elementName, Array.from(currentElements.values()));
|
|
29
44
|
setRowSelected(currentElements);
|
|
30
45
|
setSelected('');
|
|
31
46
|
}
|
|
32
|
-
}, [data, rowSelected,
|
|
47
|
+
}, [data, elementName, rowSelected, selectValueName, setValue]);
|
|
33
48
|
const tableButtonAction = useCallback((row, isDeleteAction, action) => {
|
|
34
|
-
const id = row[selectValueName];
|
|
49
|
+
const id = String(row[selectValueName]);
|
|
35
50
|
if (isDeleteAction) {
|
|
36
51
|
const currentElements = new Map(rowSelected.entries());
|
|
37
52
|
currentElements.delete(id);
|
|
38
53
|
setRowSelected(currentElements);
|
|
54
|
+
setValue(elementName, Array.from(currentElements.values()));
|
|
39
55
|
return;
|
|
40
56
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}, [rowSelected, setRowSelected]);
|
|
44
|
-
useEffect(() => {
|
|
45
|
-
const { unsubscribe } = watch((formData, { name, type }) => {
|
|
46
|
-
if (!name)
|
|
47
|
-
return;
|
|
48
|
-
if (renderIf) {
|
|
49
|
-
checkRender(formData, { name, type }).then((renderStatus) => {
|
|
50
|
-
if (renderStatus === undefined || renderStatus === null)
|
|
51
|
-
return;
|
|
52
|
-
if (render !== renderStatus) {
|
|
53
|
-
setRender(!!renderStatus);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
if (elementLiveData) {
|
|
58
|
-
setLiveSearching(true);
|
|
59
|
-
checkLiveData(formData, { name, type })
|
|
60
|
-
.then((options) => {
|
|
61
|
-
if (options === undefined || options === null)
|
|
62
|
-
return;
|
|
63
|
-
setLiveData(options);
|
|
64
|
-
})
|
|
65
|
-
.finally(() => {
|
|
66
|
-
setLiveSearching(false);
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
return () => unsubscribe();
|
|
71
|
-
}, [watch, render, liveData]);
|
|
72
|
-
if (!render)
|
|
73
|
-
return null;
|
|
57
|
+
action?.(row);
|
|
58
|
+
}, [elementName, rowSelected, selectValueName, setValue]);
|
|
74
59
|
const selectOptions = useMemo(() => {
|
|
75
|
-
return data.map((
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
name
|
|
81
|
-
};
|
|
82
|
-
});
|
|
83
|
-
}, [data]);
|
|
60
|
+
return data.map((item) => ({
|
|
61
|
+
id: String(item[selectValueName]),
|
|
62
|
+
name: String(item[selectTitleName]),
|
|
63
|
+
}));
|
|
64
|
+
}, [data, selectTitleName, selectValueName]);
|
|
84
65
|
const keyColumns = useMemo(() => {
|
|
85
|
-
return columns.map((
|
|
66
|
+
return columns.map((column) => column.title);
|
|
86
67
|
}, [columns]);
|
|
87
68
|
const tableData = useMemo(() => {
|
|
88
69
|
return Array.from(rowSelected.values());
|
|
89
70
|
}, [rowSelected]);
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
71
|
+
if (!render)
|
|
72
|
+
return null;
|
|
73
|
+
return (_jsxs("div", { className: "flex flex-col gap-2", style: style, children: [_jsxs("div", { className: "flex w-full justify-between gap-4", children: [_jsx(Controller, { control: control, name: elementName, defaultValue: [], render: ({ field: { value } }) => (_jsx("input", { type: "hidden", value: value })) }), _jsx(Select, { name: "table-select-field", placeholder: selectPlaceholder, isSearch: true, value: selected, invalid: false, options: liveData || selectOptions, liveSearching: liveSearching, onChange: (value) => {
|
|
74
|
+
setSelected(value);
|
|
75
|
+
} }), _jsx(Button, { style: buttonStyle, text: selectActionName, onClick: () => addToTable(selected) })] }), _jsxs("table", { className: "w-full text-[11px] shadow-md sm:rounded-lg", children: [_jsx("thead", { className: "sticky top-0 z-10 bg-gray-50 text-center text-gray-700", children: _jsx("tr", { children: keyColumns.map((title) => (_jsx("th", { scope: "col", className: "px-6 py-3", children: title }, `column-${title}`))) }) }), _jsx("tbody", { children: tableData.map((row) => {
|
|
76
|
+
return (_jsx("tr", { className: "border-b bg-white text-center hover:bg-gray-50", children: columns.map(({ Icon, isButton, action, isDeleteAction, style: columnStyle, ...column }) => {
|
|
77
|
+
if (!isButton) {
|
|
78
|
+
return (_jsx("td", { className: "px-6 py-4", style: columnStyle, children: row[column.key] ?? '' }, `${String(row[selectValueName])}-${column.title}`));
|
|
79
|
+
}
|
|
80
|
+
return (_jsx("td", { children: _jsx("button", { type: "button", className: "rounded-md p-2 text-lg", onClick: () => {
|
|
81
|
+
tableButtonAction(row, isDeleteAction, action);
|
|
82
|
+
}, style: columnStyle, children: Icon && _jsx(Icon, {}) }) }, `${String(row[selectValueName])}-${column.title}`));
|
|
83
|
+
}) }, `row-${String(row[selectValueName])}`));
|
|
98
84
|
}) })] })] }));
|
|
99
85
|
};
|
|
100
86
|
export default MakeTable;
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useContext,
|
|
3
|
+
import { useContext, useId } from 'react';
|
|
4
4
|
import { Controller } from 'react-hook-form';
|
|
5
5
|
import { ComponentStateContext } from '../../context/component/component-state';
|
|
6
6
|
import useEnableIf from '../../hooks/use-enable-if';
|
|
7
7
|
import useRenderIf from '../../hooks/use-render-if';
|
|
8
|
+
import useConditionalField from '../../hooks/use-conditional-field';
|
|
8
9
|
const MakeTextarea = ({ element, control, watch, unregister, }) => {
|
|
9
10
|
const { Textarea } = useContext(ComponentStateContext);
|
|
10
11
|
const { name: elementName, validation: { required, message, regex, ...otherValidation }, enableIf, renderIf, ...inputProps } = element;
|
|
@@ -15,32 +16,20 @@ const MakeTextarea = ({ element, control, watch, unregister, }) => {
|
|
|
15
16
|
elementRenderIf: renderIf,
|
|
16
17
|
});
|
|
17
18
|
const elementId = useId();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (renderStatus === undefined || renderStatus === null)
|
|
33
|
-
return;
|
|
34
|
-
if (render !== renderStatus) {
|
|
35
|
-
if (render && !renderStatus)
|
|
36
|
-
unregister(elementName);
|
|
37
|
-
setRender(!!renderStatus);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return () => unsubscribe();
|
|
43
|
-
}, [watch, render, enable]);
|
|
19
|
+
useConditionalField({
|
|
20
|
+
watch,
|
|
21
|
+
elementName,
|
|
22
|
+
renderIf,
|
|
23
|
+
enableIf,
|
|
24
|
+
render,
|
|
25
|
+
enable,
|
|
26
|
+
checkRender,
|
|
27
|
+
checkEnable,
|
|
28
|
+
checkLiveData: async () => null,
|
|
29
|
+
setRender,
|
|
30
|
+
setEnable,
|
|
31
|
+
unregister,
|
|
32
|
+
});
|
|
44
33
|
if (!render)
|
|
45
34
|
return null;
|
|
46
35
|
return (_jsx(Controller, { name: elementName, control: control, rules: {
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import { useContext,
|
|
3
|
+
import { useContext, useId } from 'react';
|
|
4
4
|
import { Controller } from 'react-hook-form';
|
|
5
5
|
import { ComponentStateContext } from '../../context/component/component-state';
|
|
6
6
|
import useEnableIf from '../../hooks/use-enable-if';
|
|
7
7
|
import useRenderIf from '../../hooks/use-render-if';
|
|
8
|
+
import useConditionalField from '../../hooks/use-conditional-field';
|
|
8
9
|
const MakeToggle = ({ element, control, watch, unregister, }) => {
|
|
9
10
|
const { Toggle } = useContext(ComponentStateContext);
|
|
10
11
|
const { name: elementName, validation: { required, message, regex, ...otherValidation }, enableIf, renderIf, ...inputProps } = element;
|
|
@@ -15,32 +16,20 @@ const MakeToggle = ({ element, control, watch, unregister, }) => {
|
|
|
15
16
|
elementRenderIf: renderIf,
|
|
16
17
|
});
|
|
17
18
|
const elementId = useId();
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
if (renderStatus === undefined || renderStatus === null)
|
|
33
|
-
return;
|
|
34
|
-
if (render !== renderStatus) {
|
|
35
|
-
if (render && !renderStatus)
|
|
36
|
-
unregister(elementName);
|
|
37
|
-
setRender(!!renderStatus);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
return () => unsubscribe();
|
|
43
|
-
}, [watch, render, enable]);
|
|
19
|
+
useConditionalField({
|
|
20
|
+
watch,
|
|
21
|
+
elementName,
|
|
22
|
+
renderIf,
|
|
23
|
+
enableIf,
|
|
24
|
+
render,
|
|
25
|
+
enable,
|
|
26
|
+
checkRender,
|
|
27
|
+
checkEnable,
|
|
28
|
+
checkLiveData: async () => null,
|
|
29
|
+
setRender,
|
|
30
|
+
setEnable,
|
|
31
|
+
unregister,
|
|
32
|
+
});
|
|
44
33
|
if (!render)
|
|
45
34
|
return null;
|
|
46
35
|
return (_jsx(Controller, { control: control, name: elementName, rules: {
|
|
@@ -1,28 +1,39 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useEffect, useReducer } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
|
+
const initialState = {
|
|
6
|
+
mounted: false,
|
|
7
|
+
node: null,
|
|
8
|
+
};
|
|
9
|
+
const portalReducer = (state, action) => {
|
|
10
|
+
if (action.type === 'OPEN') {
|
|
11
|
+
return {
|
|
12
|
+
mounted: !!action.node,
|
|
13
|
+
node: action.node,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
if (!state.mounted && !state.node)
|
|
17
|
+
return state;
|
|
18
|
+
return initialState;
|
|
19
|
+
};
|
|
5
20
|
export const Portal = (props) => {
|
|
6
|
-
const
|
|
7
|
-
const [mounted, setMounted] = useState(false);
|
|
21
|
+
const [{ mounted, node }, dispatch] = useReducer(portalReducer, initialState);
|
|
8
22
|
useEffect(() => {
|
|
9
|
-
if (
|
|
23
|
+
if (props.portalOpen) {
|
|
24
|
+
const portalNode = document.querySelector(props.portalTag ?? '#portal');
|
|
25
|
+
dispatch({ type: 'OPEN', node: portalNode });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (mounted && props.closeTime > 0) {
|
|
10
29
|
const timeoutId = setTimeout(() => {
|
|
11
|
-
|
|
12
|
-
ref.current = null;
|
|
30
|
+
dispatch({ type: 'CLOSE' });
|
|
13
31
|
}, props.closeTime);
|
|
14
32
|
return () => clearTimeout(timeoutId);
|
|
15
33
|
}
|
|
16
|
-
|
|
17
|
-
setMounted(false);
|
|
18
|
-
ref.current = null;
|
|
19
|
-
}
|
|
20
|
-
else if (!mounted && props.portalOpen) {
|
|
21
|
-
ref.current = document.querySelector(props.portalTag ?? '#portal');
|
|
22
|
-
setMounted(true);
|
|
23
|
-
}
|
|
34
|
+
dispatch({ type: 'CLOSE' });
|
|
24
35
|
}, [mounted, props.closeTime, props.portalOpen, props.portalTag]);
|
|
25
|
-
if (!mounted
|
|
36
|
+
if (!mounted || !node)
|
|
26
37
|
return null;
|
|
27
|
-
return createPortal(_jsx("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-sm'}`, children: props.children }),
|
|
38
|
+
return createPortal(_jsx("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-sm'}`, children: props.children }), node);
|
|
28
39
|
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { FieldValues, UseFormSetValue, UseFormUnregister, UseFormWatch } from 'react-hook-form';
|
|
2
|
+
import { IOption } from '../interfaces/option';
|
|
3
|
+
import { IModalLiveDataCondition, IModalRenderCondition } from '../interfaces/modal';
|
|
4
|
+
type WatchMeta = {
|
|
5
|
+
name: string;
|
|
6
|
+
type: string | undefined;
|
|
7
|
+
};
|
|
8
|
+
interface IUseConditionalFieldProps {
|
|
9
|
+
watch: UseFormWatch<FieldValues>;
|
|
10
|
+
elementName: string;
|
|
11
|
+
renderIf?: IModalRenderCondition;
|
|
12
|
+
enableIf?: IModalRenderCondition;
|
|
13
|
+
liveDataConfig?: IModalLiveDataCondition;
|
|
14
|
+
render: boolean;
|
|
15
|
+
enable: boolean;
|
|
16
|
+
checkRender: (formData: Record<string, unknown>, meta: WatchMeta) => Promise<boolean | undefined | null>;
|
|
17
|
+
checkEnable: (formData: Record<string, unknown>, meta: WatchMeta) => Promise<boolean | undefined | null>;
|
|
18
|
+
checkLiveData: (formData: Record<string, unknown>, meta: WatchMeta) => Promise<Array<IOption> | undefined | null>;
|
|
19
|
+
setRender: (value: boolean) => void;
|
|
20
|
+
setEnable: (value: boolean) => void;
|
|
21
|
+
setLiveData?: (value: Array<IOption>) => void;
|
|
22
|
+
setLiveSearching?: (value: boolean) => void;
|
|
23
|
+
unregister?: UseFormUnregister<FieldValues>;
|
|
24
|
+
setValue?: UseFormSetValue<FieldValues>;
|
|
25
|
+
liveDataResetValue?: string | Array<string>;
|
|
26
|
+
}
|
|
27
|
+
declare const useConditionalField: ({ watch, elementName, renderIf, enableIf, liveDataConfig, render, enable, checkRender, checkEnable, checkLiveData, setRender, setEnable, setLiveData, setLiveSearching, unregister, setValue, liveDataResetValue, }: IUseConditionalFieldProps) => void;
|
|
28
|
+
export default useConditionalField;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { useEffect, useEffectEvent, useRef } from 'react';
|
|
3
|
+
const useConditionalField = ({ watch, elementName, renderIf, enableIf, liveDataConfig, render, enable, checkRender, checkEnable, checkLiveData, setRender, setEnable, setLiveData, setLiveSearching, unregister, setValue, liveDataResetValue, }) => {
|
|
4
|
+
const liveRequestId = useRef(0);
|
|
5
|
+
const handleWatchChange = useEffectEvent(async (formData, meta) => {
|
|
6
|
+
if (enableIf) {
|
|
7
|
+
const enableStatus = await checkEnable(formData, meta);
|
|
8
|
+
if (enableStatus !== undefined &&
|
|
9
|
+
enableStatus !== null &&
|
|
10
|
+
enable !== enableStatus) {
|
|
11
|
+
setEnable(enableStatus);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (renderIf) {
|
|
15
|
+
const renderStatus = await checkRender(formData, meta);
|
|
16
|
+
if (renderStatus !== undefined &&
|
|
17
|
+
renderStatus !== null &&
|
|
18
|
+
render !== renderStatus) {
|
|
19
|
+
if (render && !renderStatus)
|
|
20
|
+
unregister?.(elementName);
|
|
21
|
+
setRender(renderStatus);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (liveDataConfig && setLiveData) {
|
|
25
|
+
const requestId = ++liveRequestId.current;
|
|
26
|
+
setLiveSearching?.(true);
|
|
27
|
+
try {
|
|
28
|
+
const options = await checkLiveData(formData, meta);
|
|
29
|
+
if (requestId !== liveRequestId.current ||
|
|
30
|
+
options === undefined ||
|
|
31
|
+
options === null) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
setLiveData(options);
|
|
35
|
+
if (setValue) {
|
|
36
|
+
setValue(elementName, liveDataResetValue ?? []);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (requestId === liveRequestId.current) {
|
|
41
|
+
setLiveSearching?.(false);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const { unsubscribe } = watch((formData, meta) => {
|
|
48
|
+
if (!meta.name)
|
|
49
|
+
return;
|
|
50
|
+
void handleWatchChange(formData, {
|
|
51
|
+
name: meta.name,
|
|
52
|
+
type: meta.type,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
return () => {
|
|
56
|
+
liveRequestId.current += 1;
|
|
57
|
+
unsubscribe();
|
|
58
|
+
};
|
|
59
|
+
}, [watch]);
|
|
60
|
+
};
|
|
61
|
+
export default useConditionalField;
|