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.
@@ -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, index) => (_jsx("span", { style: fragment.style, children: fragment.text }, `desc-fragment-${index}`))) }))] }));
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, useEffect, useId } from 'react';
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
- useEffect(() => {
19
- const { unsubscribe } = watch((formData, { name, type }) => {
20
- if (!name)
21
- return;
22
- if (enableIf) {
23
- checkEnable(formData, { name, type }).then((enableStatus) => {
24
- if (enableStatus === undefined || enableStatus === null)
25
- return;
26
- if (enable !== enableStatus)
27
- setEnable(enableStatus);
28
- });
29
- }
30
- if (renderIf) {
31
- checkRender(formData, { name, type }).then((renderStatus) => {
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, useEffect, useId, useState } from 'react';
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
- useEffect(() => {
24
- const { unsubscribe } = watch((formData, { name, type }) => {
25
- if (!name)
26
- return;
27
- if (enableIf) {
28
- checkEnable(formData, { name, type }).then((enableStatus) => {
29
- if (enableStatus === undefined || enableStatus === null)
30
- return;
31
- if (enable !== enableStatus)
32
- setEnable(enableStatus);
33
- });
34
- }
35
- if (renderIf) {
36
- checkRender(formData, { name, type }).then((renderStatus) => {
37
- if (renderStatus === undefined || renderStatus === null)
38
- return;
39
- if (render !== renderStatus) {
40
- if (render && !renderStatus)
41
- unregister(elementName);
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, useEffect, useMemo, useState } from 'react';
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
- const MakeTable = ({ element, watch, control, setValue }) => {
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 { Button } = useContext(ComponentStateContext);
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
- const addToTable = useCallback((selected) => {
22
- if (selected === '')
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((e) => e[selectValueName] === selected);
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(selected, elementSelected);
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, setRowSelected, setSelected]);
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
- if (action)
42
- action(row);
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((e) => {
76
- const id = e[selectValueName];
77
- const name = e[selectTitleName];
78
- return {
79
- id,
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((e) => e.title);
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
- 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: (selected) => {
91
- setSelected(selected);
92
- } }), _jsx(Button, { style: buttonStyle, text: selectActionName, onClick: () => addToTable(selected) })] }), _jsxs("table", { className: "text-[11px] w-full shadow-md sm:rounded-lg", children: [_jsx("thead", { className: "sticky top-0 text-gray-700 bg-gray-50 text-center z-10", children: _jsx("tr", { children: keyColumns.map((title) => (_jsx("th", { scope: 'col', className: 'px-6 py-3', children: title }))) }) }), _jsx("tbody", { children: tableData.map((row, index) => {
93
- return (_jsx("tr", { className: "bg-white border-b hover:bg-gray-50 text-center", children: columns.map(({ Icon, isButton, action, isDeleteAction, style, ...column }) => {
94
- if (!isButton)
95
- return (_jsx("td", { className: 'px-6 py-4', style: style, children: row[column.key] ?? '' }));
96
- return (_jsx("td", { children: _jsx("button", { className: 'p-2 rounded-md text-lg', onClick: () => { tableButtonAction(row, isDeleteAction, action); }, style: style, children: Icon && _jsx(Icon, {}) }) }));
97
- }) }, `row-${row[selectValueName]}-i-${index}`));
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, useEffect, useId } from 'react';
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
- useEffect(() => {
19
- const { unsubscribe } = watch((formData, { name, type }) => {
20
- if (!name)
21
- return;
22
- if (enableIf) {
23
- checkEnable(formData, { name, type }).then((enableStatus) => {
24
- if (enableStatus === undefined || enableStatus === null)
25
- return;
26
- if (enable !== enableStatus)
27
- setEnable(enableStatus);
28
- });
29
- }
30
- if (renderIf) {
31
- checkRender(formData, { name, type }).then((renderStatus) => {
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, useEffect, useId } from 'react';
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
- useEffect(() => {
19
- const { unsubscribe } = watch((formData, { name, type }) => {
20
- if (!name)
21
- return;
22
- if (enableIf) {
23
- checkEnable(formData, { name, type }).then((enableStatus) => {
24
- if (enableStatus === undefined || enableStatus === null)
25
- return;
26
- if (enable !== enableStatus)
27
- setEnable(enableStatus);
28
- });
29
- }
30
- if (renderIf) {
31
- checkRender(formData, { name, type }).then((renderStatus) => {
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 { useRef, useEffect, useState } from 'react';
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 ref = useRef(null);
7
- const [mounted, setMounted] = useState(false);
21
+ const [{ mounted, node }, dispatch] = useReducer(portalReducer, initialState);
8
22
  useEffect(() => {
9
- if (mounted && !props.portalOpen && props.closeTime > 0) {
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
- setMounted(false);
12
- ref.current = null;
30
+ dispatch({ type: 'CLOSE' });
13
31
  }, props.closeTime);
14
32
  return () => clearTimeout(timeoutId);
15
33
  }
16
- else if (mounted && !props.portalOpen) {
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 && !ref.current)
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 }), ref.current);
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;