react-form-manage 1.0.6-beta.0 → 1.0.6-beta.2

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 (54) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/components/Form/FormCleanUp.js +46 -0
  3. package/dist/components/Form/FormItem.d.ts +11 -17
  4. package/dist/components/Form/FormItem.js +46 -0
  5. package/dist/components/Form/FormList.d.ts +23 -7
  6. package/dist/components/Form/FormList.js +11 -0
  7. package/dist/components/Form/InputWrapper.d.ts +10 -5
  8. package/dist/components/Form/InputWrapper.js +7 -0
  9. package/dist/components/Input.d.ts +4 -5
  10. package/dist/components/Input.js +8 -0
  11. package/dist/constants/validation.js +33 -0
  12. package/dist/contexts/FormContext.js +2 -0
  13. package/dist/hooks/useFormItemControl.js +390 -0
  14. package/dist/hooks/useFormListControl.js +280 -0
  15. package/dist/index.d.ts +8 -185
  16. package/dist/index.js +9 -0
  17. package/dist/providers/Form.d.ts +15 -10
  18. package/dist/providers/Form.js +322 -0
  19. package/dist/stores/formStore.js +304 -0
  20. package/dist/types/index.d.ts +1 -0
  21. package/dist/types/index.js +1 -0
  22. package/dist/types/public.d.ts +51 -0
  23. package/dist/utils/obj.util.js +24 -0
  24. package/package.json +30 -45
  25. package/src/App.css +49 -0
  26. package/src/App.tsx +36 -0
  27. package/src/assets/react.svg +1 -0
  28. package/src/components/Form/FormCleanUp.tsx +57 -0
  29. package/src/components/Form/FormItem.tsx +72 -0
  30. package/src/components/Form/FormList.tsx +22 -0
  31. package/src/components/Form/InputWrapper.tsx +24 -0
  32. package/src/components/Input.jsx +13 -0
  33. package/src/components/Input.tsx +21 -0
  34. package/src/constants/validation.ts +63 -0
  35. package/src/contexts/FormContext.ts +3 -0
  36. package/src/hooks/useFormItemControl.ts +558 -0
  37. package/src/hooks/useFormListControl.ts +378 -0
  38. package/src/index.css +68 -0
  39. package/src/index.ts +35 -0
  40. package/src/main.tsx +10 -0
  41. package/src/providers/Form.tsx +440 -0
  42. package/src/stores/formStore.ts +477 -0
  43. package/src/types/index.ts +1 -0
  44. package/src/types/public.ts +50 -0
  45. package/src/utils/obj.util.ts +42 -0
  46. package/dist/App.d.ts +0 -2
  47. package/dist/index.cjs +0 -2
  48. package/dist/index.cjs.d.ts +0 -1
  49. package/dist/index.cjs.map +0 -1
  50. package/dist/index.esm.d.ts +0 -1
  51. package/dist/index.esm.js +0 -2
  52. package/dist/index.esm.js.map +0 -1
  53. package/src/types/components.d.ts +0 -135
  54. /package/dist/{main.d.ts → types/public.js} +0 -0
@@ -0,0 +1,390 @@
1
+ import { get, isNil } from "lodash";
2
+ import { useTaskEffect } from "minh-custom-hooks-release";
3
+ import { useEffect, useMemo } from "react";
4
+ import { useShallow } from "zustand/react/shallow"; // Import useShallow
5
+ import { IS_ALPHABET_STRING_AND_NUMBER_REGEX, IS_EMAIL_REGEX, IS_NAME_REGEX, IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_REGEX, IS_NO_SPACE_ALPHABET_STRING_REGEX, IS_NOSPACE_STRING_AND_NUMBER_REGEX, IS_PASSWORD_REGEX, IS_POSITIVE_INTEGER_STRING_NUMBER_REGEX, IS_POSITIVE_STRING_NUMBER_REGEX, IS_STRING_AND_NUMBER_REGEX, IS_STRING_NUMBER_REGEX, IS_USERNAME_REGEX, IS_VIETNAMESE_PHONE_NUMBER_REGEX, } from "../constants/validation";
6
+ import { useFormContext } from "../providers/Form";
7
+ import { useFormCleanUp, useFormListeners, useFormStore, } from "../stores/formStore";
8
+ const VALID_PREMITIVE_TYPE = ["string", "number", "undefined"];
9
+ export default function useFormItemControl({ formName, form, name, initialValue, formItemId, rules, elementRef, }) {
10
+ const contextForm = useFormContext();
11
+ const { value, setData, getCacheData, getFormValues } = useFormStore(useShallow((state) => {
12
+ return {
13
+ value: get(state.forms, `${formName || form?.formName || contextForm?.formName}.${name}`),
14
+ setData: state.setData,
15
+ getCacheData: state.getCacheData,
16
+ getFormValues: state.getFormValues,
17
+ };
18
+ }));
19
+ const { setCleanUpStack } = useFormCleanUp(useShallow((state) => ({
20
+ setCleanUpStack: state.setCleanUpStack,
21
+ })));
22
+ const { initValue: internalInitValue, setInitData, getInitData, } = useFormStore(useShallow((state) => {
23
+ // console.log(
24
+ // "Shallow get initValue: ",
25
+ // formName || form?.formName || contextForm?.formName,
26
+ // name,
27
+ // get(
28
+ // state.initialValues,
29
+ // `${formName || form?.formName || contextForm?.formName}.${name}`
30
+ // )
31
+ // );
32
+ return {
33
+ initValue: get(state.initialValues, `${formName || form?.formName || contextForm?.formName}.${name}`),
34
+ setInitData: state.setInitData,
35
+ getInitData: state.getInitData,
36
+ };
37
+ }));
38
+ const { listener, setListener } = useFormListeners(useShallow((state) => {
39
+ // console.log(
40
+ // "Get listener from store: ",
41
+ // state.listeners.find((l) => l.formItemId === formItemId)
42
+ // );
43
+ return {
44
+ listener: state.listeners.find((l) => l.formItemId === formItemId),
45
+ setListener: state.setListener,
46
+ };
47
+ }));
48
+ const onInitData = (value) => {
49
+ // console.log(
50
+ // "Init:",
51
+ // formName || form?.formName || contextForm?.formName,
52
+ // name,
53
+ // value
54
+ // );
55
+ setInitData(formName || form?.formName || contextForm?.formName, name, value);
56
+ };
57
+ const onFocus = () => {
58
+ setListener({
59
+ formItemId,
60
+ isTouched: true,
61
+ isDirty: listener?.isDirty,
62
+ });
63
+ };
64
+ const emitFocus = () => {
65
+ if (elementRef?.current) {
66
+ elementRef.current.focus();
67
+ }
68
+ };
69
+ const onChange = (value, options) => {
70
+ if (options?.notTriggerDirty !== true) {
71
+ setListener({
72
+ formItemId,
73
+ isDirty: true,
74
+ isTouched: listener?.isTouched,
75
+ });
76
+ }
77
+ setData(formName || form?.formName || contextForm?.formName, name, value);
78
+ };
79
+ const onReset = (value) => {
80
+ console.log("Reset", value, getInitData(formName || form?.formName || contextForm?.formName, name));
81
+ onChange(isNil(value)
82
+ ? getInitData(formName || form?.formName || contextForm?.formName, name)
83
+ : value);
84
+ };
85
+ // validate field rules
86
+ const internalRules = useMemo(() => {
87
+ return rules || [];
88
+ }, [rules]);
89
+ const { data: errors, state } = useTaskEffect({
90
+ async task() {
91
+ const listErrors = [];
92
+ const formValues = getFormValues(formName || form?.formName || contextForm?.formName);
93
+ const ruleToTask = internalRules?.map((r, index) => async () => {
94
+ const ruleName = r?.name || index;
95
+ const fieldValue = value?.toString?.();
96
+ if (typeof r.handler === "function") {
97
+ if (!(await r.handler(value, formValues))) {
98
+ listErrors.push({
99
+ ruleName,
100
+ message: r.message,
101
+ });
102
+ return;
103
+ }
104
+ }
105
+ if (VALID_PREMITIVE_TYPE.includes(typeof value)) {
106
+ // REQUIRE
107
+ if (r.required && !(fieldValue?.toString()?.trim()?.length > 0)) {
108
+ // tempMessage.push("This field is required!");
109
+ listErrors.push({
110
+ ruleName,
111
+ message: r.message,
112
+ });
113
+ return;
114
+ }
115
+ // Min Max
116
+ if (!isNil(r.min) || !isNil(r.max)) {
117
+ if (isNil(value)) {
118
+ listErrors.push({
119
+ ruleName,
120
+ message: r.message,
121
+ });
122
+ return;
123
+ }
124
+ if ((r.min ?? Number.MIN_SAFE_INTEGER) <=
125
+ (r.max ?? Number.MAX_SAFE_INTEGER)) {
126
+ if (!isNil(r.min)) {
127
+ if (!isNaN(Number(fieldValue)) && Number(fieldValue) <= r.min) {
128
+ // tempMessage.push(MIN_INVALID_MESSAGE);
129
+ listErrors.push({
130
+ ruleName,
131
+ message: r.message,
132
+ });
133
+ return;
134
+ }
135
+ }
136
+ if (!isNil(r.max)) {
137
+ if (!isNaN(Number(fieldValue)) && Number(fieldValue) >= r.max) {
138
+ // tempMessage.push(MAX_INVALID_MESSAGE);
139
+ listErrors.push({
140
+ ruleName,
141
+ message: r.message,
142
+ });
143
+ return;
144
+ }
145
+ }
146
+ }
147
+ }
148
+ // MIN LENGTH MAX LENGTH
149
+ if (!isNil(r.minLength) || !isNil(r.maxLength)) {
150
+ if ((r.minLength ?? Number.MIN_SAFE_INTEGER) <=
151
+ (r.maxLength ?? Number.MAX_SAFE_INTEGER)) {
152
+ if (!isNil(r.minLength)) {
153
+ if (fieldValue?.length <= r.minLength) {
154
+ // tempMessage.push(MIN_INVALID_LENGTH_MESSAGE);
155
+ listErrors.push({
156
+ ruleName,
157
+ message: r.message,
158
+ });
159
+ return;
160
+ }
161
+ }
162
+ if (!isNil(r.maxLength)) {
163
+ if (fieldValue?.length >= r.maxLength) {
164
+ // tempMessage.push(MAX_INVALID_LENGTH_MESSAGE);
165
+ listErrors.push({
166
+ ruleName,
167
+ message: r.message,
168
+ });
169
+ return;
170
+ }
171
+ }
172
+ }
173
+ }
174
+ // Password
175
+ if (r.isPassword && !IS_PASSWORD_REGEX.test(fieldValue)) {
176
+ // tempMessage.push(IS_PASSWORD_INVALID_MESSAGE);
177
+ listErrors.push({
178
+ ruleName,
179
+ message: r.message,
180
+ });
181
+ return;
182
+ }
183
+ // Username
184
+ if (r.isUsername && !IS_USERNAME_REGEX.test(fieldValue)) {
185
+ // tempMessage.push(IS_USERNAME_INVALID_MESSAGE);
186
+ listErrors.push({
187
+ ruleName,
188
+ message: r.message,
189
+ });
190
+ return;
191
+ }
192
+ // Is Vietnamese Phone number
193
+ if (r.isPhoneNumber &&
194
+ !IS_VIETNAMESE_PHONE_NUMBER_REGEX.test(fieldValue)) {
195
+ // tempMessage.push(IS_VIETNAMESE_PHONE_NUMBER_INVALID_MESSAGE);
196
+ listErrors.push({
197
+ ruleName,
198
+ message: r.message,
199
+ });
200
+ return;
201
+ }
202
+ // String number
203
+ if (r.isStringNumber && !IS_STRING_NUMBER_REGEX.test(fieldValue)) {
204
+ // tempMessage.push(IS_STRING_NUMBER_INVALID_MESSAGE);
205
+ listErrors.push({
206
+ ruleName,
207
+ message: r.message,
208
+ });
209
+ return;
210
+ }
211
+ // String positive number
212
+ if (r.isPositiveStringNumber &&
213
+ !IS_POSITIVE_STRING_NUMBER_REGEX.test(fieldValue)) {
214
+ // tempMessage.push(IS_POSITIVE_STRING_NUMBER_INVALID_MESSAGE);
215
+ listErrors.push({
216
+ ruleName,
217
+ message: r.message,
218
+ });
219
+ return;
220
+ }
221
+ // String positive integer number
222
+ if (r.isPositiveIntegerStringNumber &&
223
+ !IS_POSITIVE_INTEGER_STRING_NUMBER_REGEX.test(fieldValue)) {
224
+ // tempMessage.push(
225
+ listErrors.push({
226
+ ruleName,
227
+ message: r.message,
228
+ });
229
+ return;
230
+ // IS_POSITIVE_INTEGER_STRING_NUMBER_INVALID_MESSAGE
231
+ // );
232
+ }
233
+ // Email
234
+ if (r.isEmail && !IS_EMAIL_REGEX.test(fieldValue)) {
235
+ // tempMessage.push(IS_EMAIL_INVALID_MESSAGE);
236
+ listErrors.push({
237
+ ruleName,
238
+ message: r.message,
239
+ });
240
+ return;
241
+ }
242
+ // Vietnamese Name
243
+ if (r.isVietnameseName && !IS_NAME_REGEX.test(fieldValue)) {
244
+ // tempMessage.push(IS_NAME_INVALID_MESSAGE);
245
+ listErrors.push({
246
+ ruleName,
247
+ message: r.message,
248
+ });
249
+ return;
250
+ }
251
+ // String and number without whitespace
252
+ if (r.isNoSpaceStringAndNumber &&
253
+ !IS_NOSPACE_STRING_AND_NUMBER_REGEX.test(fieldValue)) {
254
+ // tempMessage.push(IS_NOSPACE_STRING_AND_NUMBER_MESSAGE);
255
+ listErrors.push({
256
+ ruleName,
257
+ message: r.message,
258
+ });
259
+ return;
260
+ }
261
+ // String and number with
262
+ if (r.isStringAndNumber &&
263
+ !IS_STRING_AND_NUMBER_REGEX.test(fieldValue)) {
264
+ // tempMessage.push(IS_STRING_AND_NUMBER_MESSAGE);
265
+ listErrors.push({
266
+ ruleName,
267
+ message: r.message,
268
+ });
269
+ return;
270
+ }
271
+ if (r.isNoSpaceOnlyAlphabetStringAndNumber &&
272
+ !IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_REGEX.test(fieldValue)) {
273
+ // tempMessage.push(IS_NO_SPACE_ALPHABET_STRING_AND_NUMBER_MESSAGE);
274
+ listErrors.push({
275
+ ruleName,
276
+ message: r.message,
277
+ });
278
+ return;
279
+ }
280
+ if (r.isOnlyAlphabetStringAndNumber &&
281
+ !IS_ALPHABET_STRING_AND_NUMBER_REGEX.test(fieldValue)) {
282
+ // tempMessage.push(IS_ALPHABET_STRING_AND_NUMBER_MESSAGE);
283
+ listErrors.push({
284
+ ruleName,
285
+ message: r.message,
286
+ });
287
+ return;
288
+ }
289
+ if (r.isNoSpaceAlphabetString &&
290
+ !IS_NO_SPACE_ALPHABET_STRING_REGEX.test(fieldValue)) {
291
+ // tempMessage.push(IS_NO_SPACE_ALPHABET_STRING_MESSAGE);
292
+ listErrors.push({
293
+ ruleName,
294
+ message: r.message,
295
+ });
296
+ return;
297
+ }
298
+ }
299
+ });
300
+ // console.log("Trigger validate: ", listErrors);
301
+ for (const rAsync of ruleToTask) {
302
+ await rAsync();
303
+ }
304
+ setListener({ formItemId, internalErrors: listErrors });
305
+ return listErrors;
306
+ },
307
+ deps: [internalRules, value],
308
+ onError(err) {
309
+ console.log(err);
310
+ },
311
+ });
312
+ // useEffect(() => {
313
+ // console.log({ name, errors });
314
+ // }, [errors]);
315
+ // useEffect(() => {
316
+ // console.log({ name, listener });
317
+ // }, [listener]);
318
+ useEffect(() => {
319
+ // console.log({ internalInitValue, value, initialValue });
320
+ // console.log("Init item value: ", name, value, internalInitValue);
321
+ // console.log("internalInitValue: ", internalInitValue);
322
+ if (!value) {
323
+ if (!internalInitValue) {
324
+ if (!isNil(initialValue)) {
325
+ console.log("On init data", initialValue);
326
+ onInitData(initialValue);
327
+ }
328
+ }
329
+ else {
330
+ onChange(internalInitValue);
331
+ }
332
+ }
333
+ }, [internalInitValue]);
334
+ useEffect(() => {
335
+ if (!listener) {
336
+ setListener({
337
+ onChange,
338
+ emitFocus,
339
+ isTouched: false,
340
+ isDirty: false,
341
+ name,
342
+ formName: formName || form?.formName || contextForm?.formName,
343
+ formItemId,
344
+ onReset,
345
+ });
346
+ }
347
+ // return () => {
348
+ // console.log("Revoke listener", listener);
349
+ // };
350
+ }, []);
351
+ useEffect(() => {
352
+ if (listener) {
353
+ setListener({
354
+ formItemId,
355
+ onChange,
356
+ name,
357
+ formName: formName || form?.formName || contextForm?.formName,
358
+ onReset,
359
+ isTouched: listener?.isTouched,
360
+ isDirty: listener?.isDirty,
361
+ });
362
+ }
363
+ const cacheData = getCacheData(formName || form?.formName || contextForm?.formName);
364
+ // console.log("Get cache Data after list change: ", cacheData);
365
+ if (cacheData) {
366
+ const getNewDataFromCache = get(cacheData, name);
367
+ // console.log("Init data when change form ite: ", name, cacheData);
368
+ if (!getNewDataFromCache) {
369
+ onChange(initialValue);
370
+ }
371
+ else
372
+ onChange(getNewDataFromCache);
373
+ }
374
+ }, [name, formName || form?.formName || contextForm?.formName]);
375
+ useEffect(() => {
376
+ return () => {
377
+ setCleanUpStack({
378
+ itemKey: formItemId,
379
+ });
380
+ };
381
+ }, []);
382
+ return {
383
+ value: value,
384
+ onChange,
385
+ state,
386
+ errors,
387
+ onFocus,
388
+ isDirty: listener?.isDirty,
389
+ };
390
+ }
@@ -0,0 +1,280 @@
1
+ import { cloneDeep, get, isNil } from "lodash";
2
+ import { useEffect, useState } from "react";
3
+ import { v4 } from "uuid";
4
+ import { useShallow } from "zustand/react/shallow";
5
+ import { useFormContext } from "../providers/Form";
6
+ import { useFormCleanUp, useFormStore } from "../stores/formStore";
7
+ export default function useFormListControl({ name, form, initialValues, formName, }) {
8
+ const contextForm = useFormContext();
9
+ const getFormValues = useFormStore((state) => state.getFormValues);
10
+ const [listFormInitValues, setListFormInitValues] = useState(undefined);
11
+ const { clearCacheData, setCacheData } = useFormStore(useShallow((state) => ({
12
+ cacheData: state.cacheData,
13
+ clearCacheData: state.clearCacheData,
14
+ setCacheData: state.setCacheData,
15
+ })));
16
+ const { setCleanUpStack } = useFormCleanUp(useShallow((state) => ({
17
+ setCleanUpStack: state.setCleanUpStack,
18
+ })));
19
+ const { initValue: internalInitValue, formState } = useFormStore(useShallow((state) => {
20
+ // console.log(
21
+ // "Shallow get initValue: ",
22
+ // formName || form?.formName || contextForm?.formName,
23
+ // name,
24
+ // get(
25
+ // state.initialValues,
26
+ // `${formName || form?.formName || contextForm?.formName}.${name}`
27
+ // )
28
+ // );
29
+ return {
30
+ initValue: get(state.initialValues, `${formName || form?.formName || contextForm?.formName}.${name}`),
31
+ formState: get(state.formStates, formName || form?.formName || contextForm?.formName),
32
+ setInitData: state.setInitData,
33
+ getFormState: state.getFormState,
34
+ };
35
+ }));
36
+ const [listFields, setListFields] = useState([]);
37
+ const handleCacheListField = (prev, cur) => {
38
+ const currentFormValues = cloneDeep(getFormValues(formName || form?.formName || contextForm?.formName));
39
+ const formDataBeforeChange = get(currentFormValues, name);
40
+ const mapPrevWithKey = formDataBeforeChange
41
+ .map((d, index) => {
42
+ const findPrev = prev.find((p, pIndex) => pIndex === index);
43
+ if (!findPrev)
44
+ return undefined;
45
+ return {
46
+ key: findPrev.key,
47
+ value: d,
48
+ };
49
+ })
50
+ .filter(Boolean);
51
+ const mapCurWithKey = cur.map((c) => mapPrevWithKey.find((m) => m.key === c.key) || c);
52
+ const getNewValueCache = mapCurWithKey.filter(Boolean).map((c) => c.value);
53
+ const startRemoveIndex = formDataBeforeChange.length - getNewValueCache.length;
54
+ // console.log("Before list fields: ", prev);
55
+ // console.log("After list fields: ", cur);
56
+ // console.log("Before change arr value: ", formDataBeforeChange);
57
+ // console.log("Mapping prev value with prev fields: ", mapPrevWithKey);
58
+ // console.log("Mapping Cur value with prev fields: ", mapCurWithKey);
59
+ // console.log("After change arr value: ", getNewValueCache);
60
+ // Nếu số phần tử trước khi thay đổi mảng lớn hơn thì đẩy 2 phần tử còn lại vào clean up stack để clear
61
+ if (startRemoveIndex > 0) {
62
+ Array.from(Array(startRemoveIndex))
63
+ .map((_, index) => {
64
+ return getNewValueCache.length + index;
65
+ })
66
+ .forEach((index) => {
67
+ // console.log("Data for cleanup arr element: ", {
68
+ // formName: formName || form?.formName || contextForm?.formName,
69
+ // name: `${name}.${index}`,
70
+ // type: "array",
71
+ // });
72
+ setCleanUpStack({
73
+ formName: formName || form?.formName || contextForm?.formName,
74
+ name: `${name}.${index}`,
75
+ type: "array",
76
+ });
77
+ });
78
+ }
79
+ // console.log({ getNewValueCache });
80
+ setCacheData(formName || form?.formName || contextForm?.formName, name, getNewValueCache);
81
+ };
82
+ const add = (index) => {
83
+ setListFields((prev) => {
84
+ if (index > prev.length)
85
+ return prev;
86
+ if (index < 0)
87
+ return prev;
88
+ if (index === prev.length) {
89
+ const newName = `${name}.${prev.length}`;
90
+ const newKey = v4();
91
+ const result = [
92
+ ...prev,
93
+ {
94
+ name: newName,
95
+ key: newKey,
96
+ },
97
+ ];
98
+ return result;
99
+ }
100
+ const clonePrev = [...prev];
101
+ const result = clonePrev
102
+ .reduce((prev, cur, curIndex) => {
103
+ const newKey = v4();
104
+ if (curIndex === index)
105
+ return [
106
+ ...prev,
107
+ {
108
+ key: newKey,
109
+ },
110
+ cur,
111
+ ];
112
+ return [...prev, cur];
113
+ }, [])
114
+ .map((r, index) => ({
115
+ name: `${name}.${index}`,
116
+ key: r.key,
117
+ }));
118
+ handleCacheListField(prev, result);
119
+ return result;
120
+ });
121
+ };
122
+ const remove = ({ index, key }) => {
123
+ setListFields((prev) => {
124
+ if (!isNil(key)) {
125
+ const clonePrev = [...prev];
126
+ const removedItem = clonePrev.filter((d) => d.key !== key);
127
+ console.log("Remove data: ", removedItem);
128
+ const result = removedItem.map((r, index) => ({
129
+ name: `${name}.${index}`,
130
+ key: r.key,
131
+ }));
132
+ handleCacheListField(prev, result);
133
+ return result;
134
+ }
135
+ if (!isNil(index)) {
136
+ if (index > prev.length - 1 || index < 0)
137
+ return prev;
138
+ const clonePrev = [...prev];
139
+ clonePrev.splice(index, 1);
140
+ const result = clonePrev.map((r, index) => ({
141
+ name: `${name}.${index}`,
142
+ key: r.key,
143
+ }));
144
+ handleCacheListField(prev, result);
145
+ return result;
146
+ }
147
+ return prev;
148
+ });
149
+ };
150
+ const move = ({ from, fromKey, to }) => {
151
+ setListFields((prev) => {
152
+ console.log("move list item: ", { from, to });
153
+ if (from >= listFields.length ||
154
+ from < 0 ||
155
+ to >= listFields.length ||
156
+ to < 0 ||
157
+ from === to)
158
+ return prev;
159
+ console.log("Trigger move item: ");
160
+ if (!isNil(fromKey)) {
161
+ const findItemIndex = prev.findIndex((p) => p.key === fromKey);
162
+ if (findItemIndex < 0)
163
+ return prev;
164
+ const moveItem = cloneDeep(listFields[findItemIndex]);
165
+ const result = prev
166
+ .reduce((prev, cur, curIndex) => {
167
+ if (findItemIndex === curIndex)
168
+ return [...prev];
169
+ if (to === curIndex) {
170
+ if (findItemIndex > to)
171
+ return [...prev, moveItem, cur];
172
+ else
173
+ return [...prev, cur, moveItem];
174
+ }
175
+ else {
176
+ return [...prev, cur];
177
+ }
178
+ }, [])
179
+ .map((i, index) => ({
180
+ key: i.key,
181
+ name: `${name}.${index}`,
182
+ }));
183
+ handleCacheListField(prev, result);
184
+ return result;
185
+ }
186
+ else if (!isNil(from)) {
187
+ console.log("Trigger from index: ");
188
+ const moveItem = cloneDeep(listFields[from]);
189
+ const result = prev
190
+ .reduce((prev, cur, curIndex) => {
191
+ if (from === curIndex)
192
+ return [...prev];
193
+ if (to === curIndex) {
194
+ if (from > to)
195
+ return [...prev, moveItem, cur];
196
+ else
197
+ return [...prev, cur, moveItem];
198
+ }
199
+ else {
200
+ return [...prev, cur];
201
+ }
202
+ }, [])
203
+ .map((i, index) => ({
204
+ key: i.key,
205
+ name: `${name}.${index}`,
206
+ }));
207
+ console.log({ result });
208
+ handleCacheListField(prev, result);
209
+ return result;
210
+ }
211
+ return prev;
212
+ });
213
+ };
214
+ useEffect(() => {
215
+ console.log("Trigger init", formState?.isInitied, internalInitValue);
216
+ if (formState?.isInitied) {
217
+ if (Array.isArray(listFormInitValues)) {
218
+ const result = listFormInitValues?.map((_, i) => {
219
+ const itemName = `${name}.${i}`;
220
+ const key = v4();
221
+ return {
222
+ key,
223
+ name: itemName,
224
+ };
225
+ });
226
+ console.log("Get local init values: ", listFormInitValues, result);
227
+ setListFields(result);
228
+ setCacheData(formName || form?.formName || contextForm?.formName, name, listFormInitValues);
229
+ return;
230
+ }
231
+ if (Array.isArray(internalInitValue)) {
232
+ const result = internalInitValue.map((_, i) => {
233
+ const itemName = `${name}.${i}`;
234
+ const key = v4();
235
+ return {
236
+ key,
237
+ name: itemName,
238
+ };
239
+ });
240
+ // console.log("Get form init values: ", internalInitValue, result);
241
+ setListFields(result);
242
+ setListFormInitValues(internalInitValue);
243
+ return;
244
+ }
245
+ // console.log({ initialValues });
246
+ // console.log("After init: ", { result: cloneDeep(result) });
247
+ if (Array.isArray(initialValues)) {
248
+ const result = initialValues.map((_, i) => {
249
+ const itemName = `${name}.${i}`;
250
+ const key = v4();
251
+ return {
252
+ key,
253
+ name: itemName,
254
+ };
255
+ });
256
+ if (initialValues) {
257
+ setCacheData(formName || form?.formName || contextForm?.formName, name, initialValues);
258
+ }
259
+ setListFields(result);
260
+ setListFormInitValues(initialValues);
261
+ // console.log("Get form init values: ", internalInitValue, result);
262
+ return;
263
+ }
264
+ }
265
+ }, [formState?.isInitied]);
266
+ // useEffect(() => {
267
+ // console.log("Show form list init values: ", { internalInitValue });
268
+ // }, [internalInitValue]);
269
+ // useEffect(() => {
270
+ // console.log("List fields update: ", listFields);
271
+ // }, [listFields]);
272
+ useEffect(() => {
273
+ // console.log({ listFields });
274
+ return () => {
275
+ // console.log("Cleanup listfield change");
276
+ clearCacheData();
277
+ };
278
+ }, [listFields]);
279
+ return { listFields, move, add, remove };
280
+ }