react-form-manage 1.0.8-beta.9 → 1.0.8

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +173 -4
  2. package/README.md +8 -4
  3. package/dist/components/Form/FormCleanUp.js +3 -3
  4. package/dist/components/Form/FormItem.d.ts +10 -4
  5. package/dist/components/Form/FormItem.js +52 -14
  6. package/dist/components/Form/FormList.d.ts +2 -2
  7. package/dist/components/Form/FormList.js +2 -2
  8. package/dist/constants/form.d.ts +1 -1
  9. package/dist/hooks/useFormItemControl.d.ts +8 -3
  10. package/dist/hooks/useFormItemControl.js +64 -28
  11. package/dist/hooks/useFormListControl.d.ts +2 -1
  12. package/dist/hooks/useFormListControl.js +85 -19
  13. package/dist/index.cjs.d.ts +1 -0
  14. package/dist/index.d.ts +4 -3
  15. package/dist/index.esm.d.ts +1 -0
  16. package/dist/index.js +4 -2
  17. package/dist/providers/Form.d.ts +15 -2
  18. package/dist/providers/Form.js +197 -22
  19. package/dist/stores/formStore.d.ts +44 -4
  20. package/dist/stores/formStore.js +42 -7
  21. package/dist/test/CommonTest.d.ts +3 -0
  22. package/dist/test/CommonTest.js +49 -0
  23. package/dist/test/TestDialog.d.ts +3 -0
  24. package/dist/test/TestDialog.js +21 -0
  25. package/dist/test/TestListener.d.ts +3 -0
  26. package/dist/test/TestListener.js +17 -0
  27. package/dist/test/TestNotFormWrapper.d.ts +3 -0
  28. package/dist/test/TestNotFormWrapper.js +15 -0
  29. package/dist/test/TestSelect.d.ts +6 -0
  30. package/dist/test/TestSelect.js +24 -0
  31. package/dist/test/TestWatchNormalize.d.ts +3 -0
  32. package/dist/test/TestWatchNormalize.js +23 -0
  33. package/dist/test/TestWrapperFormItem.d.ts +3 -0
  34. package/dist/test/TestWrapperFormItem.js +13 -0
  35. package/dist/test/testSetValue/TestCase10_SetFieldValues_ComplexNested.d.ts +21 -0
  36. package/dist/test/testSetValue/TestCase10_SetFieldValues_ComplexNested.js +61 -0
  37. package/dist/test/testSetValue/TestCase1_PlainObjectToPrimitives.d.ts +16 -0
  38. package/dist/test/testSetValue/TestCase1_PlainObjectToPrimitives.js +18 -0
  39. package/dist/test/testSetValue/TestCase2_PlainObjectToFormList.d.ts +21 -0
  40. package/dist/test/testSetValue/TestCase2_PlainObjectToFormList.js +33 -0
  41. package/dist/test/testSetValue/TestCase3_ArrayNonListenerToPrimitives.d.ts +21 -0
  42. package/dist/test/testSetValue/TestCase3_ArrayNonListenerToPrimitives.js +26 -0
  43. package/dist/test/testSetValue/TestCase4_PlainObjectRemovedFields.d.ts +20 -0
  44. package/dist/test/testSetValue/TestCase4_PlainObjectRemovedFields.js +32 -0
  45. package/dist/test/testSetValue/TestCase5_FormListRemovedItems.d.ts +22 -0
  46. package/dist/test/testSetValue/TestCase5_FormListRemovedItems.js +29 -0
  47. package/dist/test/testSetValue/TestCase6_NestedFormListRemoved.d.ts +28 -0
  48. package/dist/test/testSetValue/TestCase6_NestedFormListRemoved.js +36 -0
  49. package/dist/test/testSetValue/TestCase7_SetFieldValues_MixedStructure.d.ts +17 -0
  50. package/dist/test/testSetValue/TestCase7_SetFieldValues_MixedStructure.js +33 -0
  51. package/dist/test/testSetValue/TestCase8_SetFieldValues_NestedObject.d.ts +27 -0
  52. package/dist/test/testSetValue/TestCase8_SetFieldValues_NestedObject.js +57 -0
  53. package/dist/test/testSetValue/TestCase9_SetFieldValues_MultipleArrays.d.ts +25 -0
  54. package/dist/test/testSetValue/TestCase9_SetFieldValues_MultipleArrays.js +46 -0
  55. package/dist/test/testSetValue/index.d.ts +2 -0
  56. package/dist/test/testSetValue/index.js +28 -0
  57. package/dist/types/index.d.ts +1 -1
  58. package/dist/types/public.d.ts +1 -1
  59. package/dist/utils/obj.util.d.ts +29 -1
  60. package/dist/utils/obj.util.js +59 -5
  61. package/package.json +2 -1
  62. package/src/App.tsx +38 -163
  63. package/src/DEEP_TRIGGER_LOGIC.md +573 -0
  64. package/src/components/Form/FormCleanUp.tsx +4 -8
  65. package/src/components/Form/FormItem.tsx +174 -57
  66. package/src/components/Form/FormList.tsx +17 -4
  67. package/src/constants/form.ts +1 -1
  68. package/src/hooks/useFormItemControl.ts +78 -32
  69. package/src/hooks/useFormListControl.ts +133 -43
  70. package/src/index.ts +25 -13
  71. package/src/main.tsx +6 -1
  72. package/src/providers/Form.tsx +451 -23
  73. package/src/stores/formStore.ts +363 -283
  74. package/src/test/CommonTest.tsx +177 -0
  75. package/src/test/TestDialog.tsx +52 -0
  76. package/src/test/TestListener.tsx +21 -0
  77. package/src/test/TestNotFormWrapper.tsx +43 -0
  78. package/src/test/TestSelect.tsx +38 -0
  79. package/src/test/TestWatchNormalize.tsx +32 -0
  80. package/src/test/TestWrapperFormItem.tsx +34 -0
  81. package/src/test/testSetValue/TestCase10_SetFieldValues_ComplexNested.tsx +203 -0
  82. package/src/test/testSetValue/TestCase1_PlainObjectToPrimitives.tsx +72 -0
  83. package/src/test/testSetValue/TestCase2_PlainObjectToFormList.tsx +114 -0
  84. package/src/test/testSetValue/TestCase3_ArrayNonListenerToPrimitives.tsx +99 -0
  85. package/src/test/testSetValue/TestCase4_PlainObjectRemovedFields.tsx +112 -0
  86. package/src/test/testSetValue/TestCase5_FormListRemovedItems.tsx +119 -0
  87. package/src/test/testSetValue/TestCase6_NestedFormListRemoved.tsx +185 -0
  88. package/src/test/testSetValue/TestCase7_SetFieldValues_MixedStructure.tsx +110 -0
  89. package/src/test/testSetValue/TestCase8_SetFieldValues_NestedObject.tsx +162 -0
  90. package/src/test/testSetValue/TestCase9_SetFieldValues_MultipleArrays.tsx +169 -0
  91. package/src/test/testSetValue/index.tsx +100 -0
  92. package/src/types/index.ts +1 -1
  93. package/src/types/public.ts +1 -1
  94. package/src/utils/obj.util.ts +153 -13
@@ -3,18 +3,22 @@ import { useEffect, useState } from "react";
3
3
  import { v4 } from "uuid";
4
4
  import { useShallow } from "zustand/react/shallow";
5
5
  import { useFormContext } from "../providers/Form";
6
- import { useFormCleanUp, useFormStore } from "../stores/formStore";
6
+ import { useFormStore } from "../stores/formStore";
7
7
  function useFormListControl({ name, form, initialValues, formName }) {
8
+ const [formItemId] = useState(v4());
8
9
  const contextForm = useFormContext();
9
10
  const getFormValues = useFormStore((state) => state.getFormValues);
10
11
  const [listFormInitValues, setListFormInitValues] = useState(void 0);
11
- const { clearCacheData, setCacheData } = useFormStore(useShallow((state) => ({
12
+ const { clearCacheData, setCacheData, setListener, getListener, clearArrItems } = useFormStore(useShallow((state) => ({
13
+ // Cache
12
14
  cacheData: state.cacheData,
13
15
  clearCacheData: state.clearCacheData,
14
- setCacheData: state.setCacheData
15
- })));
16
- const { setCleanUpStack } = useFormCleanUp(useShallow((state) => ({
17
- setCleanUpStack: state.setCleanUpStack
16
+ setCacheData: state.setCacheData,
17
+ // Listener
18
+ setListener: state.setListener,
19
+ getListener: state.getListener,
20
+ // Clear Arr Items
21
+ clearArrItems: state.clearArrItems
18
22
  })));
19
23
  const { initValue: internalInitValue, formState } = useFormStore(useShallow((state) => {
20
24
  return {
@@ -37,29 +41,33 @@ function useFormListControl({ name, form, initialValues, formName }) {
37
41
  value: d
38
42
  };
39
43
  }).filter(Boolean);
40
- const mapCurWithKey = cur.map((c) => mapPrevWithKey.find((m) => m.key === c.key) || c);
44
+ const mapCurWithKey = cur.map((c) => {
45
+ const find = mapPrevWithKey.find((m) => m.key === c.key);
46
+ if (find) {
47
+ return {
48
+ key: find.key,
49
+ value: isNil(c.value) ? find.value : c.value
50
+ };
51
+ }
52
+ return c;
53
+ });
41
54
  const getNewValueCache = mapCurWithKey.filter(Boolean).map((c) => c.value);
42
55
  const startRemoveIndex = formDataBeforeChange.length - getNewValueCache.length;
43
56
  if (startRemoveIndex > 0) {
44
- Array.from(Array(startRemoveIndex)).map((_, index) => {
45
- return getNewValueCache.length + index;
46
- }).forEach((index) => {
47
- setCleanUpStack({
57
+ const clearItems = Array.from(Array(startRemoveIndex)).map((_, index) => {
58
+ const clearIndex = getNewValueCache.length + index;
59
+ return {
48
60
  formName: formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName),
49
- name: `${name}.${index}`,
50
- type: "array"
51
- });
61
+ name: `${name}.${clearIndex}`
62
+ };
52
63
  });
64
+ clearArrItems(clearItems);
53
65
  }
54
66
  setCacheData(formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName), name, getNewValueCache);
55
67
  };
56
68
  const add = (index) => {
57
69
  setListFields((prev) => {
58
- if (index > prev.length)
59
- return prev;
60
- if (index < 0)
61
- return prev;
62
- if (index === prev.length) {
70
+ if (isNil(index) || index === prev.length) {
63
71
  const newName = `${name}.${prev.length}`;
64
72
  const newKey = v4();
65
73
  const result2 = [
@@ -71,6 +79,10 @@ function useFormListControl({ name, form, initialValues, formName }) {
71
79
  ];
72
80
  return result2;
73
81
  }
82
+ if (index > prev.length)
83
+ return prev;
84
+ if (index < 0)
85
+ return prev;
74
86
  const clonePrev = [...prev];
75
87
  const result = clonePrev.reduce((prev2, cur, curIndex) => {
76
88
  const newKey = v4();
@@ -180,6 +192,12 @@ function useFormListControl({ name, form, initialValues, formName }) {
180
192
  });
181
193
  setListFields(result);
182
194
  setCacheData(formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName), name, listFormInitValues);
195
+ if (getListener(formItemId)) {
196
+ setListener({
197
+ formItemId,
198
+ isInitied: true
199
+ });
200
+ }
183
201
  return;
184
202
  }
185
203
  if (Array.isArray(internalInitValue)) {
@@ -193,6 +211,12 @@ function useFormListControl({ name, form, initialValues, formName }) {
193
211
  });
194
212
  setListFields(result);
195
213
  setListFormInitValues(internalInitValue);
214
+ if (getListener(formItemId)) {
215
+ setListener({
216
+ formItemId,
217
+ isInitied: true
218
+ });
219
+ }
196
220
  return;
197
221
  }
198
222
  if (Array.isArray(initialValues)) {
@@ -209,6 +233,12 @@ function useFormListControl({ name, form, initialValues, formName }) {
209
233
  }
210
234
  setListFields(result);
211
235
  setListFormInitValues(initialValues);
236
+ if (getListener(formItemId)) {
237
+ setListener({
238
+ formItemId,
239
+ isInitied: true
240
+ });
241
+ }
212
242
  return;
213
243
  }
214
244
  }
@@ -218,6 +248,42 @@ function useFormListControl({ name, form, initialValues, formName }) {
218
248
  clearCacheData();
219
249
  };
220
250
  }, [listFields]);
251
+ useEffect(() => {
252
+ if (!getListener(formItemId)) {
253
+ setListener({
254
+ formName: formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName),
255
+ name: name || "",
256
+ formItemId,
257
+ type: "array",
258
+ onArrayChange: (newArr) => {
259
+ setListFields((prev) => {
260
+ const result = newArr.map((_, i) => {
261
+ const itemName = `${name}.${i}`;
262
+ const existingItem = prev[i];
263
+ return {
264
+ key: existingItem ? existingItem.key : v4(),
265
+ name: itemName
266
+ };
267
+ });
268
+ handleCacheListField(prev, result.map((r, i) => {
269
+ return { ...r, value: newArr[i] };
270
+ }));
271
+ return result;
272
+ });
273
+ }
274
+ });
275
+ }
276
+ return () => {
277
+ if (getListener(formItemId)) {
278
+ setListener({
279
+ formName: formName || (form == null ? void 0 : form.formName) || (contextForm == null ? void 0 : contextForm.formName),
280
+ name: name || "",
281
+ formItemId,
282
+ onArrayChange: void 0
283
+ });
284
+ }
285
+ };
286
+ }, []);
221
287
  return { listFields, move, add, remove };
222
288
  }
223
289
  export {
@@ -0,0 +1 @@
1
+ export * from "./index";
package/dist/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
- import Form, { useForm, useWatch, useSubmitDataWatch, useFormStateWatch, type FormProps, type ValidationRule, type FormFieldError, type SubmitState, type UseFormItemStateWatchReturn } from "./providers/Form";
2
1
  import { SUBMIT_STATE } from "./constants/form";
2
+ import Form, { useForm, useFormStateWatch, useSubmitDataWatch, useWatch, type FormFieldError, type FormProps, type SubmitState, type UseFormItemStateWatchReturn, type ValidationRule } from "./providers/Form";
3
3
  import FormItem, { type FormItemProps } from "./components/Form/FormItem";
4
4
  import FormList, { type FormListProps } from "./components/Form/FormList";
5
- import Input from "./components/Input";
6
5
  import InputWrapper, { type InputWrapperProps } from "./components/Form/InputWrapper";
6
+ import Input from "./components/Input";
7
7
  import useFormItemControl from "./hooks/useFormItemControl";
8
8
  import useFormListControl from "./hooks/useFormListControl";
9
- export { Form, FormItem, FormList, Input, InputWrapper, useFormItemControl, useFormListControl, useForm, useWatch, useSubmitDataWatch, useFormStateWatch, type FormProps, type FormItemProps, type FormListProps, type InputWrapperProps, type ValidationRule, type FormFieldError, type SubmitState, type UseFormItemStateWatchReturn, SUBMIT_STATE, };
9
+ import { useFormStore, type CleanUpItem, type FormInstance, type ListenerItem } from "./stores/formStore";
10
+ export { Form, FormItem, FormList, Input, InputWrapper, SUBMIT_STATE, useForm, useFormItemControl, useFormListControl, useFormStateWatch, useFormStore, useSubmitDataWatch, useWatch, type CleanUpItem, type FormFieldError, type FormInstance, type FormItemProps, type FormListProps, type FormProps, type InputWrapperProps, type ListenerItem, type SubmitState, type UseFormItemStateWatchReturn, type ValidationRule, };
10
11
  export default Form;
@@ -0,0 +1 @@
1
+ export * from "./index";
package/dist/index.js CHANGED
@@ -1,11 +1,12 @@
1
- import Form, { useForm, useWatch, useSubmitDataWatch, useFormStateWatch } from "./providers/Form";
2
1
  import { SUBMIT_STATE } from "./constants/form";
2
+ import Form, { useForm, useFormStateWatch, useSubmitDataWatch, useWatch } from "./providers/Form";
3
3
  import FormItem from "./components/Form/FormItem";
4
4
  import FormList from "./components/Form/FormList";
5
- import Input from "./components/Input";
6
5
  import InputWrapper from "./components/Form/InputWrapper";
6
+ import Input from "./components/Input";
7
7
  import useFormItemControl from "./hooks/useFormItemControl";
8
8
  import useFormListControl from "./hooks/useFormListControl";
9
+ import { useFormStore } from "./stores/formStore";
9
10
  var stdin_default = Form;
10
11
  export {
11
12
  Form,
@@ -19,6 +20,7 @@ export {
19
20
  useFormItemControl,
20
21
  useFormListControl,
21
22
  useFormStateWatch,
23
+ useFormStore,
22
24
  useSubmitDataWatch,
23
25
  useWatch
24
26
  };
@@ -1,8 +1,14 @@
1
1
  import type { ComponentType, FormHTMLAttributes, ReactNode } from "react";
2
+ import FormItem from "../components/Form/FormItem";
3
+ import { OnChangeOptions } from "../hooks/useFormItemControl";
2
4
  import type { PublicFormInstance, UseFormItemStateWatchReturn } from "../types/public";
3
- export type { FormFieldError, SubmitState, UseFormItemStateWatchReturn, ValidationRule, } from "../types/public";
5
+ export type { FormFieldError, SubmitState, UseFormItemStateWatchReturn, ValidationRule } from "../types/public";
4
6
  export declare const FormContext: import("react").Context<any>;
7
+ export interface SetFieldValueOptions extends OnChangeOptions {
8
+ deepTrigger?: boolean;
9
+ }
5
10
  export interface FormProps<T = any> extends Omit<FormHTMLAttributes<HTMLFormElement>, "onSubmit"> {
11
+ collectHiddenFields?: boolean;
6
12
  children: ReactNode;
7
13
  formName: string;
8
14
  initialValues?: T;
@@ -15,10 +21,12 @@ export interface FormProps<T = any> extends Omit<FormHTMLAttributes<HTMLFormElem
15
21
  }) => void | Promise<void>;
16
22
  FormElement?: ComponentType<any>;
17
23
  }
18
- declare function Form<T = any>({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, ...props }: FormProps<T>): import("react/jsx-runtime").JSX.Element;
24
+ declare function Form<T = any>({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, collectHiddenFields: formCollectHiddenFields, ...props }: FormProps<T>): import("react/jsx-runtime").JSX.Element;
19
25
  declare namespace Form {
20
26
  var useForm: typeof import("./Form").useForm;
27
+ var Item: typeof FormItem;
21
28
  var useWatch: typeof import("./Form").useWatch;
29
+ var useWatchNormalized: typeof import("./Form").useWatchNormalized;
22
30
  var useSubmitDataWatch: typeof import("./Form").useSubmitDataWatch;
23
31
  var useFormStateWatch: <T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>) => any;
24
32
  var useFormItemStateWatch: <T = any>(nameOrFormItemId: string, formNameOrFormInstance?: string | PublicFormInstance<T>) => UseFormItemStateWatchReturn;
@@ -27,6 +35,11 @@ export default Form;
27
35
  export declare function useFormContext(): any;
28
36
  export declare function useForm<T = any>(formNameOrFormInstance?: string | PublicFormInstance<T>): PublicFormInstance<T>[];
29
37
  export declare function useWatch<T = any>(name: keyof T & string, formNameOrFormInstance?: string | PublicFormInstance<T>): T[keyof T] | undefined;
38
+ export declare function useWatchNormalized<T, TFn extends (v: any) => any>({ name, normalizeFn, formNameOrFormInstance, }: {
39
+ name: keyof T & string;
40
+ normalizeFn: TFn;
41
+ formNameOrFormInstance?: string | PublicFormInstance<T>;
42
+ }): ReturnType<TFn>;
30
43
  export declare function useSubmitDataWatch<T = any>({ formNameOrFormInstance, triggerWhenChange, mapFn, }: {
31
44
  formNameOrFormInstance?: string | PublicFormInstance<T>;
32
45
  triggerWhenChange?: boolean;
@@ -1,15 +1,15 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { cloneDeep, get, isEqual, last, set, uniq } from "lodash";
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cloneDeep, filter, get, isArray, isEqual, isNil, isPlainObject, last, set, uniqBy } from "lodash";
3
3
  import { useTask } from "minh-custom-hooks-release";
4
- import { createContext, useContext, useEffect, useState } from "react";
4
+ import { createContext, useContext, useEffect, useMemo, useState } from "react";
5
5
  import { flushSync } from "react-dom";
6
6
  import { useShallow } from "zustand/react/shallow";
7
- import FormCleanUp from "../components/Form/FormCleanUp";
7
+ import FormItem from "../components/Form/FormItem";
8
8
  import { SUBMIT_STATE } from "../constants/form";
9
- import { useFormListeners, useFormStore } from "../stores/formStore";
10
- import { getAllNoneObjStringPath } from "../utils/obj.util";
9
+ import { useFormStore } from "../stores/formStore";
10
+ import { getAllNoneObjStringPath, getAllPathsIncludingContainers, getAllPathsStopAtArray } from "../utils/obj.util";
11
11
  const FormContext = createContext(null);
12
- function Form({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, ...props }) {
12
+ function Form({ children, formName, initialValues, onFinish, onReject, onFinally, FormElement, collectHiddenFields: formCollectHiddenFields = true, ...props }) {
13
13
  const {
14
14
  // appInitValue,
15
15
  getFormItemValue,
@@ -39,12 +39,12 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
39
39
  // Test, nhớ xóa sau khi xong
40
40
  // formStates: state.formStates?.[formName],
41
41
  })));
42
- const { getListeners } = useFormListeners(useShallow((state) => {
42
+ const { getListeners } = useFormStore(useShallow((state) => {
43
43
  return {
44
44
  getListeners: state.getListeners
45
45
  };
46
46
  }));
47
- const setFieldValue = (name, value, options) => {
47
+ const handlePrimitiveValue = (name, value, options) => {
48
48
  const listener = getListeners().find((l) => l.name === name && l.formName === formName);
49
49
  if (listener) {
50
50
  listener.onChange(value, options);
@@ -52,20 +52,170 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
52
52
  setData(formName, name, value);
53
53
  }
54
54
  };
55
+ const handleArrayListener = (name, value, options, coreRecursive) => {
56
+ const listener = getListeners().find((l) => l.name === name && l.formName === formName);
57
+ if (!listener)
58
+ return;
59
+ const currentValue = getFormItemValue(formName, name);
60
+ if (!isEqual(currentValue, value)) {
61
+ listener.onArrayChange(value, options);
62
+ value.forEach((item, index) => {
63
+ const itemName = `${name}.${index}`;
64
+ const itemListener = getListeners().find((l) => l.name === itemName && l.formName === formName);
65
+ if (itemListener) {
66
+ itemListener.onChange(item, options);
67
+ }
68
+ const nestedPaths = getAllPathsIncludingContainers(item);
69
+ nestedPaths.forEach((p) => {
70
+ if (coreRecursive) {
71
+ coreRecursive(`${itemName}.${p}`, get(item, p), options);
72
+ }
73
+ });
74
+ });
75
+ if (isArray(currentValue) && currentValue.length > value.length) {
76
+ for (let index = value.length; index < currentValue.length; index++) {
77
+ const itemName = `${name}.${index}`;
78
+ if (coreRecursive) {
79
+ coreRecursive(itemName, void 0, options);
80
+ }
81
+ }
82
+ }
83
+ }
84
+ };
85
+ const handlePlainObject = (name, value, options, coreRecursive) => {
86
+ const listener = getListeners().find((l) => l.name === name && l.formName === formName);
87
+ if (listener && listener.type !== "array") {
88
+ listener.onChange(value, options);
89
+ }
90
+ const allPaths = getAllPathsIncludingContainers(value);
91
+ allPaths.forEach((p) => {
92
+ if (coreRecursive) {
93
+ const fullPath = `${name}.${p}`;
94
+ coreRecursive(fullPath, get(value, p), options);
95
+ }
96
+ });
97
+ const previousValue = getFieldValue(name);
98
+ if (isPlainObject(previousValue)) {
99
+ const previousKeys = Object.keys(previousValue);
100
+ const newKeys = Object.keys(value);
101
+ const removedKeys = previousKeys.filter((k) => !newKeys.includes(k));
102
+ removedKeys.forEach((key) => {
103
+ if (coreRecursive) {
104
+ coreRecursive(`${name}.${key}`, void 0, options);
105
+ }
106
+ });
107
+ }
108
+ };
109
+ const handleNonListenerArray = (name, value, options, coreRecursive) => {
110
+ const previousValues = getFieldValue(name);
111
+ if (isArray(previousValues)) {
112
+ if (previousValues.length !== value.length || !isEqual(previousValues, value)) {
113
+ setData(formName, name, value);
114
+ }
115
+ value.forEach((item, index) => {
116
+ if (!isEqual(previousValues[index], item)) {
117
+ const itemName = `${name}.${index}`;
118
+ const itemListener = getListeners().find((l) => l.name === itemName && l.formName === formName);
119
+ if (itemListener) {
120
+ itemListener.onChange(item, options);
121
+ }
122
+ const nestedPaths = getAllPathsIncludingContainers(item);
123
+ nestedPaths.forEach((p) => {
124
+ if (coreRecursive) {
125
+ coreRecursive(`${itemName}.${p}`, get(item, p), options);
126
+ }
127
+ });
128
+ }
129
+ });
130
+ if (previousValues.length > value.length) {
131
+ for (let index = value.length; index < previousValues.length; index++) {
132
+ const itemName = `${name}.${index}`;
133
+ const removedItem = previousValues[index];
134
+ const nestedPaths = getAllPathsIncludingContainers(removedItem);
135
+ nestedPaths.forEach((p) => {
136
+ if (coreRecursive) {
137
+ coreRecursive(`${itemName}.${p}`, void 0, options);
138
+ }
139
+ });
140
+ if (coreRecursive) {
141
+ coreRecursive(itemName, void 0, options);
142
+ }
143
+ }
144
+ }
145
+ }
146
+ };
147
+ const deepTriggerSetCore = (name, value, options) => {
148
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean" || value === null || value === void 0) {
149
+ handlePrimitiveValue(name, value, options);
150
+ return;
151
+ }
152
+ if (isPlainObject(value)) {
153
+ const listener = getListeners().find((l) => l.name === name && l.formName === formName);
154
+ handlePlainObject(name, value, options, deepTriggerSetCore);
155
+ return;
156
+ }
157
+ if (Array.isArray(value)) {
158
+ const listener = getListeners().find((l) => l.name === name && l.formName === formName);
159
+ if (listener && listener.type === "array") {
160
+ handleArrayListener(name, value, options, deepTriggerSetCore);
161
+ } else if (!listener) {
162
+ handleNonListenerArray(name, value, options, deepTriggerSetCore);
163
+ } else {
164
+ handlePlainObject(name, value, options, deepTriggerSetCore);
165
+ }
166
+ return;
167
+ }
168
+ handlePrimitiveValue(name, value, options);
169
+ };
170
+ const handleDeepTriggerSet = (name, value, options) => {
171
+ deepTriggerSetCore(name, value, options);
172
+ };
173
+ const setFieldValue = (name, value, options) => {
174
+ if (options == null ? void 0 : options.deepTrigger) {
175
+ handleDeepTriggerSet(name, value, options);
176
+ return;
177
+ }
178
+ const listener = getListeners().find((l) => l.name === name && l.formName === formName);
179
+ if (listener) {
180
+ if (listener.type === "array") {
181
+ if (!isEqual(getFormItemValue(formName, name), value)) {
182
+ listener.onArrayChange(value, options);
183
+ const allStringPath = getAllNoneObjStringPath(value);
184
+ allStringPath.forEach((p) => {
185
+ const findListener = getListeners().find((l) => l.name === `${name}.${p}` && l.formName === formName);
186
+ if (findListener) {
187
+ findListener.onChange(get(value, p), options);
188
+ } else {
189
+ setData(formName, `${name}.${p}`, get(value, p));
190
+ }
191
+ });
192
+ }
193
+ } else {
194
+ listener.onChange(value, options);
195
+ }
196
+ } else {
197
+ setData(formName, name, value);
198
+ }
199
+ };
55
200
  const setFieldValues = (values, options = { notTriggerDirty: false }) => {
56
- const allStringPath = getAllNoneObjStringPath(values);
57
- allStringPath.forEach((p) => {
58
- const listener = getListeners().find((l) => l.name === p && l.formName === formName);
201
+ const allPaths = getAllPathsStopAtArray(values);
202
+ allPaths.forEach((path) => {
203
+ const pathValue = get(values, path);
204
+ if (Array.isArray(pathValue)) {
205
+ handleDeepTriggerSet(path, pathValue, options);
206
+ return;
207
+ }
208
+ const listener = getListeners().find((l) => l.name === path && l.formName === formName);
59
209
  if (listener) {
60
- listener.onChange(get(values, listener.name), options);
210
+ listener.onChange(pathValue, options);
61
211
  } else {
62
- setData(formName, p, get(values, p));
212
+ setData(formName, path, pathValue);
63
213
  }
64
214
  });
65
215
  };
66
- const getFieldValue = (name) => {
216
+ function getFieldValue(name) {
67
217
  return getFormItemValue(formName, name);
68
- };
218
+ }
69
219
  const getFieldValues = (names = []) => {
70
220
  return names.map((name) => ({
71
221
  name,
@@ -106,7 +256,17 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
106
256
  const formValues = getFormValues(formName);
107
257
  const resultValues = cloneDeep(formValues);
108
258
  const cleanValues = {};
109
- uniq(listeners, (l) => l.name).forEach((l) => {
259
+ uniqBy(filter(listeners, (l) => {
260
+ if (!l.hidden)
261
+ return true;
262
+ if (isNil(props2 == null ? void 0 : props2.collectHiddenFields)) {
263
+ if (isNil(l.collectOnHidden)) {
264
+ return formCollectHiddenFields;
265
+ }
266
+ return Boolean(l.collectOnHidden);
267
+ }
268
+ return props2.collectHiddenFields;
269
+ }), (l) => l.name).forEach((l) => {
110
270
  set(cleanValues, l.name, get(resultValues, l.name));
111
271
  });
112
272
  const handleIsolateCase = async () => {
@@ -245,9 +405,9 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
245
405
  clearFormState(formName);
246
406
  };
247
407
  }, []);
248
- return _jsxs(FormContext.Provider, { value: {
408
+ return _jsx(FormContext.Provider, { value: {
249
409
  formName
250
- }, children: [FormElement ? _jsx(FormElement, { onSubmit: (e) => {
410
+ }, children: FormElement ? _jsx(FormElement, { onSubmit: (e) => {
251
411
  e.preventDefault();
252
412
  e.stopPropagation();
253
413
  runSubmit(void 0);
@@ -255,7 +415,7 @@ function Form({ children, formName, initialValues, onFinish, onReject, onFinally
255
415
  e.preventDefault();
256
416
  e.stopPropagation();
257
417
  runSubmit(void 0);
258
- }, ...props, children }), _jsx(FormCleanUp, {})] });
418
+ }, ...props, children }) });
259
419
  }
260
420
  function useFormContext() {
261
421
  const c = useContext(FormContext);
@@ -264,7 +424,8 @@ function useFormContext() {
264
424
  return c;
265
425
  }
266
426
  function useForm(formNameOrFormInstance) {
267
- const targetFormName = typeof formNameOrFormInstance === "object" && formNameOrFormInstance !== null ? formNameOrFormInstance.formName : formNameOrFormInstance;
427
+ const formContext = useContext(FormContext);
428
+ const targetFormName = isNil(formNameOrFormInstance) ? formContext == null ? void 0 : formContext.formName : typeof formNameOrFormInstance === "object" && formNameOrFormInstance !== null ? formNameOrFormInstance.formName : formNameOrFormInstance;
268
429
  const formInstance = useFormStore((state) => {
269
430
  return state.formInstances.find((i) => i.formName === targetFormName);
270
431
  });
@@ -278,6 +439,17 @@ function useWatch(name, formNameOrFormInstance) {
278
439
  });
279
440
  return value;
280
441
  }
442
+ function useWatchNormalized({ name, normalizeFn, formNameOrFormInstance }) {
443
+ const [formInstance] = useForm(formNameOrFormInstance);
444
+ const rawValue = useFormStore((state) => {
445
+ var _a;
446
+ return state.getFormItemValue((_a = formInstance == null ? void 0 : formInstance.formName) != null ? _a : formNameOrFormInstance, name);
447
+ });
448
+ const normalizedValue = useMemo(() => {
449
+ return normalizeFn(rawValue);
450
+ }, [rawValue, normalizeFn]);
451
+ return normalizedValue;
452
+ }
281
453
  function useSubmitDataWatch({ formNameOrFormInstance, triggerWhenChange = false, mapFn }) {
282
454
  const [formInstance] = useForm(formNameOrFormInstance);
283
455
  const value = useFormStore((state) => {
@@ -311,7 +483,9 @@ const useFormItemStateWatch = (nameOrFormItemId, formNameOrFormInstance) => {
311
483
  };
312
484
  };
313
485
  Form.useForm = useForm;
486
+ Form.Item = FormItem;
314
487
  Form.useWatch = useWatch;
488
+ Form.useWatchNormalized = useWatchNormalized;
315
489
  Form.useSubmitDataWatch = useSubmitDataWatch;
316
490
  Form.useFormStateWatch = useFormStateWatch;
317
491
  Form.useFormItemStateWatch = useFormItemStateWatch;
@@ -323,5 +497,6 @@ export {
323
497
  useFormItemStateWatch,
324
498
  useFormStateWatch,
325
499
  useSubmitDataWatch,
326
- useWatch
500
+ useWatch,
501
+ useWatchNormalized
327
502
  };
@@ -1,7 +1,21 @@
1
- export interface FormInstance {
1
+ type ListenerFormItemType = "normal" | "array";
2
+ export interface SubmitProps<T = any> {
3
+ externalFinishCallback?: (values: T, allValues?: any) => void | Promise<void>;
4
+ externalRejectCallback?: (errorFields: any[]) => void | Promise<void>;
5
+ externalFinallyCallback?: (result: {
6
+ errorsField: any[];
7
+ values: T;
8
+ withUnRegisteredValues: any;
9
+ }) => void | Promise<void>;
10
+ callBothFinish?: boolean;
11
+ callBothReject?: boolean;
12
+ callBothFinally?: boolean;
13
+ collectHiddenFields?: boolean;
14
+ }
15
+ export interface FormInstance<T = any> {
2
16
  formName: string;
3
17
  resetFields: (values?: any) => void;
4
- submit: (values?: any) => void;
18
+ submit: (props?: SubmitProps<T>) => void;
5
19
  submitAsync: (values?: any) => Promise<any>;
6
20
  setFieldValue: (name: string, value: any, options?: any) => void;
7
21
  setFieldValues: (values: Record<string, any>, options?: any) => void;
@@ -13,6 +27,30 @@ export interface FormInstance {
13
27
  getFieldErrors: () => Record<string, any>;
14
28
  setFieldFocus: (name: string) => void;
15
29
  }
30
+ export interface ListenerItem {
31
+ name?: string;
32
+ formName?: string;
33
+ isTouched?: boolean;
34
+ isDirty?: boolean;
35
+ formItemId?: string;
36
+ internalErrors?: any;
37
+ onArrayChange?: any;
38
+ onChange?: any;
39
+ onReset?: any;
40
+ onFocus?: any;
41
+ emitFocus?: any;
42
+ isInitied?: boolean;
43
+ type?: ListenerFormItemType;
44
+ hidden?: boolean;
45
+ collectOnHidden?: boolean;
46
+ }
47
+ export interface CleanUpItem {
48
+ name?: string;
49
+ type?: string;
50
+ key: string;
51
+ itemKey?: string;
52
+ formName?: string;
53
+ }
16
54
  interface FormStoreState {
17
55
  forms: Record<string, any>;
18
56
  initialValues: Record<string, any>;
@@ -20,9 +58,11 @@ interface FormStoreState {
20
58
  cacheData: Record<string, any>;
21
59
  formInstances: FormInstance[];
22
60
  submitHistory: Record<string, any[]>;
61
+ listeners: ListenerItem[];
62
+ cleanUpStack: CleanUpItem[];
23
63
  [key: string]: any;
24
64
  }
25
65
  export declare const useFormStore: import("zustand").UseBoundStore<import("zustand").StoreApi<FormStoreState>>;
26
- export declare const useFormListeners: import("zustand").UseBoundStore<import("zustand").StoreApi<any>>;
27
- export declare const useFormCleanUp: import("zustand").UseBoundStore<import("zustand").StoreApi<any>>;
66
+ export declare const useFormListeners: import("zustand").UseBoundStore<import("zustand").StoreApi<FormStoreState>>;
67
+ export declare const useFormCleanUp: import("zustand").UseBoundStore<import("zustand").StoreApi<FormStoreState>>;
28
68
  export {};