@juantroconisf/lib 5.3.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -43,46 +43,27 @@ type ValidatorErrorMessage = {
43
43
  * @template O The state type.
44
44
  * @template K The key of the array in the state.
45
45
  */
46
- type ArrayRules<O extends StateType, K extends keyof O = keyof O> = {
47
- [F in FieldPaths<ArrayElement<O[K]>>]?: ValidatorParams | ((item: ArrayElement<O[K]>, index: number) => ValidatorParams);
48
- };
49
- /**
50
- * Custom error messages for individual fields in an array item.
51
- * @template O The state type.
52
- * @template K The key of the array in the state.
53
- */
54
- type ArrayMessages<O extends StateType, K extends keyof O = keyof O> = {
55
- [F in FieldPaths<ArrayElement<O[K]>>]?: ValidatorErrorMessage;
56
- };
46
+ type ValidatorRule<item = any> = ValidatorParams | ((item: item, ...args: any[]) => ValidatorParams);
47
+ type RulePath<T> = T extends object ? {
48
+ [K in keyof T & string]: NonNullable<T[K]> extends (infer E)[] ? K | (E extends object ? `${K}.${RulePath<E>}` : never) : NonNullable<T[K]> extends object ? NonNullable<T[K]> extends Date ? K : K | `${K}.${RulePath<NonNullable<T[K]>>}` : K;
49
+ }[keyof T & string] : never;
57
50
  /**
58
51
  * Options for the useForm hook.
59
52
  * @template O The state type.
60
53
  */
61
54
  interface FormOptions<O extends StateType> {
62
55
  /** Validation rules for top-level fields. */
63
- rules?: {
64
- [key in keyof O]?: ValidatorParams;
65
- };
56
+ rules?: Partial<Record<RulePath<O>, ValidatorRule>>;
66
57
  /** Custom error messages for top-level fields. */
67
- messages?: {
68
- [key in keyof O]?: ValidatorErrorMessage;
69
- };
70
- /** Validation rules for items within arrays. */
71
- arrayRules?: {
72
- [K in ArrayKeys<O>]?: ArrayRules<O, K>;
73
- };
74
- /** Custom error messages for items within arrays. */
75
- arrayMessages?: {
76
- [K in ArrayKeys<O>]?: ArrayMessages<O, K>;
77
- };
58
+ messages?: Partial<Record<RulePath<O>, ValidatorErrorMessage>>;
78
59
  /**
79
60
  * Custom property names used as unique identifiers for items in specific arrays.
80
61
  * Default is "id".
81
62
  */
82
63
  arrayIdentifiers?: Partial<Record<ArrayKeys<O>, string>>;
83
64
  }
84
- type TouchedType<O extends StateType> = Record<keyof O, boolean>;
85
- type ErrorsType<O extends StateType> = Record<keyof O, NextUIError>;
65
+ type TouchedType = Map<string, boolean>;
66
+ type ErrorsType = Map<string, NextUIError>;
86
67
  type ValueChangeFunc<O extends StateType, K extends keyof O> = (id: K, value: O[K]) => void;
87
68
  type BlurFunc<O extends StateType> = (id: keyof O) => void;
88
69
  interface ComponentInputProps<O extends StateType> {
@@ -181,8 +162,8 @@ interface UseFormResponse<O extends StateType> {
181
162
  onSelectionChange: ValueChangeFunc<O, keyof O>;
182
163
  state: O;
183
164
  setState: React.Dispatch<React.SetStateAction<O>>;
184
- touched: TouchedType<O>;
185
- errors: ErrorsType<O>;
165
+ touched: TouchedType;
166
+ errors: ErrorsType;
186
167
  /** Main object to bind form elements to the state. */
187
168
  on: OnMethods<O>;
188
169
  /** Array manipulation helpers. */
@@ -196,6 +177,6 @@ interface UseFormResponse<O extends StateType> {
196
177
  resetTouched: (preservedKeys?: (keyof O)[]) => void;
197
178
  }
198
179
 
199
- declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayRules, arrayMessages, arrayIdentifiers, }?: FormOptions<O>): UseFormResponse<O>;
180
+ declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayIdentifiers }?: FormOptions<O>): UseFormResponse<O>;
200
181
 
201
- export { type ArrayMessages, type ArrayRules, type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UXProps, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorTypes, type ValueChangeFunc, useForm };
182
+ export { type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UXProps, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorRule, type ValidatorTypes, type ValueChangeFunc, useForm };
package/dist/index.d.ts CHANGED
@@ -43,46 +43,27 @@ type ValidatorErrorMessage = {
43
43
  * @template O The state type.
44
44
  * @template K The key of the array in the state.
45
45
  */
46
- type ArrayRules<O extends StateType, K extends keyof O = keyof O> = {
47
- [F in FieldPaths<ArrayElement<O[K]>>]?: ValidatorParams | ((item: ArrayElement<O[K]>, index: number) => ValidatorParams);
48
- };
49
- /**
50
- * Custom error messages for individual fields in an array item.
51
- * @template O The state type.
52
- * @template K The key of the array in the state.
53
- */
54
- type ArrayMessages<O extends StateType, K extends keyof O = keyof O> = {
55
- [F in FieldPaths<ArrayElement<O[K]>>]?: ValidatorErrorMessage;
56
- };
46
+ type ValidatorRule<item = any> = ValidatorParams | ((item: item, ...args: any[]) => ValidatorParams);
47
+ type RulePath<T> = T extends object ? {
48
+ [K in keyof T & string]: NonNullable<T[K]> extends (infer E)[] ? K | (E extends object ? `${K}.${RulePath<E>}` : never) : NonNullable<T[K]> extends object ? NonNullable<T[K]> extends Date ? K : K | `${K}.${RulePath<NonNullable<T[K]>>}` : K;
49
+ }[keyof T & string] : never;
57
50
  /**
58
51
  * Options for the useForm hook.
59
52
  * @template O The state type.
60
53
  */
61
54
  interface FormOptions<O extends StateType> {
62
55
  /** Validation rules for top-level fields. */
63
- rules?: {
64
- [key in keyof O]?: ValidatorParams;
65
- };
56
+ rules?: Partial<Record<RulePath<O>, ValidatorRule>>;
66
57
  /** Custom error messages for top-level fields. */
67
- messages?: {
68
- [key in keyof O]?: ValidatorErrorMessage;
69
- };
70
- /** Validation rules for items within arrays. */
71
- arrayRules?: {
72
- [K in ArrayKeys<O>]?: ArrayRules<O, K>;
73
- };
74
- /** Custom error messages for items within arrays. */
75
- arrayMessages?: {
76
- [K in ArrayKeys<O>]?: ArrayMessages<O, K>;
77
- };
58
+ messages?: Partial<Record<RulePath<O>, ValidatorErrorMessage>>;
78
59
  /**
79
60
  * Custom property names used as unique identifiers for items in specific arrays.
80
61
  * Default is "id".
81
62
  */
82
63
  arrayIdentifiers?: Partial<Record<ArrayKeys<O>, string>>;
83
64
  }
84
- type TouchedType<O extends StateType> = Record<keyof O, boolean>;
85
- type ErrorsType<O extends StateType> = Record<keyof O, NextUIError>;
65
+ type TouchedType = Map<string, boolean>;
66
+ type ErrorsType = Map<string, NextUIError>;
86
67
  type ValueChangeFunc<O extends StateType, K extends keyof O> = (id: K, value: O[K]) => void;
87
68
  type BlurFunc<O extends StateType> = (id: keyof O) => void;
88
69
  interface ComponentInputProps<O extends StateType> {
@@ -181,8 +162,8 @@ interface UseFormResponse<O extends StateType> {
181
162
  onSelectionChange: ValueChangeFunc<O, keyof O>;
182
163
  state: O;
183
164
  setState: React.Dispatch<React.SetStateAction<O>>;
184
- touched: TouchedType<O>;
185
- errors: ErrorsType<O>;
165
+ touched: TouchedType;
166
+ errors: ErrorsType;
186
167
  /** Main object to bind form elements to the state. */
187
168
  on: OnMethods<O>;
188
169
  /** Array manipulation helpers. */
@@ -196,6 +177,6 @@ interface UseFormResponse<O extends StateType> {
196
177
  resetTouched: (preservedKeys?: (keyof O)[]) => void;
197
178
  }
198
179
 
199
- declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayRules, arrayMessages, arrayIdentifiers, }?: FormOptions<O>): UseFormResponse<O>;
180
+ declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayIdentifiers }?: FormOptions<O>): UseFormResponse<O>;
200
181
 
201
- export { type ArrayMessages, type ArrayRules, type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UXProps, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorTypes, type ValueChangeFunc, useForm };
182
+ export { type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UXProps, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorRule, type ValidatorTypes, type ValueChangeFunc, useForm };
package/dist/index.js CHANGED
@@ -82,10 +82,10 @@ function getNestedValue(obj, path) {
82
82
  return path.split(".").reduce((acc, key) => acc?.[key], obj);
83
83
  }
84
84
  function removeCompositeKeysByPrefix(map2, prefix) {
85
- const result = {};
86
- for (const [key, value] of Object.entries(map2)) {
87
- if (!key.startsWith(prefix)) {
88
- result[key] = value;
85
+ const result = new Map(map2);
86
+ for (const key of map2.keys()) {
87
+ if (key.startsWith(prefix)) {
88
+ result.delete(key);
89
89
  }
90
90
  }
91
91
  return result;
@@ -101,13 +101,6 @@ function setNestedValue(state, dotPath, value) {
101
101
  current[keys[keys.length - 1]] = value;
102
102
  return copy;
103
103
  }
104
- var allToValue = (obj, value) => Object.keys(obj).reduce(
105
- (acc, key) => {
106
- acc[key] = value;
107
- return acc;
108
- },
109
- {}
110
- );
111
104
  var regex = {
112
105
  email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
113
106
  password: /^(?!.*\s)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~`!@#$%^&*()--+={}[\]|:;"'<>,.?/_₹]).{8,24}$/
@@ -226,21 +219,8 @@ function useValidate() {
226
219
  }
227
220
 
228
221
  // src/hooks/useForm.tsx
229
- function useForm(initialState, {
230
- rules,
231
- messages,
232
- arrayRules,
233
- arrayMessages,
234
- arrayIdentifiers
235
- } = {}) {
236
- const initial = {
237
- touched: allToValue(initialState, false),
238
- errors: allToValue(initialState, {
239
- isInvalid: false,
240
- errorMessage: ""
241
- })
242
- };
243
- const [state, setState] = (0, import_react.useState)(initialState), [touched, setTouched] = (0, import_react.useState)(initial.touched), [errors2, setErrors] = (0, import_react.useState)(initial.errors), [itemTouched, setItemTouched] = (0, import_react.useState)({}), [itemErrors, setItemErrors] = (0, import_react.useState)({}), [nestedTouched, setNestedTouched] = (0, import_react.useState)({}), [nestedErrors, setNestedErrors] = (0, import_react.useState)({}), { performValidations } = useValidate();
222
+ function useForm(initialState, { rules, messages, arrayIdentifiers } = {}) {
223
+ const [state, setState] = (0, import_react.useState)(initialState), [touched, setTouched] = (0, import_react.useState)(/* @__PURE__ */ new Map()), [errors2, setErrors] = (0, import_react.useState)(/* @__PURE__ */ new Map()), { performValidations } = useValidate();
244
224
  const indexMap = (0, import_react.useMemo)(() => {
245
225
  const map2 = /* @__PURE__ */ new Map();
246
226
  for (const key in state) {
@@ -266,39 +246,43 @@ function useForm(initialState, {
266
246
  },
267
247
  [indexMap]
268
248
  );
269
- const validateInput = (id, value) => setErrors(
270
- (prev) => handleNestedChange({
271
- state: prev,
272
- id,
273
- value: performValidations(value, rules?.[id], messages?.[id])
274
- })
275
- );
249
+ const getRule = (path) => {
250
+ if (rules?.[path]) return rules[path];
251
+ const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
252
+ return rules?.[genericPath];
253
+ };
254
+ const getMessage = (path) => {
255
+ if (messages?.[path]) return messages[path];
256
+ const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
257
+ return messages?.[genericPath];
258
+ };
259
+ const validateInput = (compositeKey, value, ruleKey) => {
260
+ const ruleDef = getRule(ruleKey);
261
+ const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
262
+ const message = getMessage(ruleKey);
263
+ const error = performValidations(value, rule, message);
264
+ setErrors((prev) => new Map(prev).set(compositeKey, error));
265
+ };
276
266
  const getUXProps = (0, import_react.useCallback)(
277
- (id) => {
278
- const inputError = errors2[id] || nestedErrors[id];
279
- const isTouched = touched[id] || nestedTouched[id];
267
+ (compositeKey) => {
268
+ const inputError = errors2.get(compositeKey);
269
+ const isTouched = touched.get(compositeKey);
280
270
  return {
281
271
  isInvalid: Boolean(isTouched && inputError?.isInvalid),
282
272
  errorMessage: isTouched ? inputError?.errorMessage || "" : ""
283
273
  };
284
274
  },
285
- [errors2, touched, nestedErrors, nestedTouched]
275
+ [errors2, touched]
286
276
  );
287
277
  const onBlur = (id) => {
288
- validateInput(id, state[id]);
289
- if (touched[id]) return;
290
- setTouched(
291
- (prev) => handleNestedChange({
292
- state: prev,
293
- id,
294
- value: true
295
- })
296
- );
278
+ validateInput(String(id), state[id], String(id));
279
+ if (touched.get(String(id))) return;
280
+ setTouched((prev) => new Map(prev).set(String(id), true));
297
281
  }, onValueChange = ((...args) => {
298
282
  if (args.length === 2) {
299
283
  const [id, value] = args;
300
284
  setState((prev) => handleNestedChange({ state: prev, id, value }));
301
- validateInput(id, value);
285
+ validateInput(String(id), value, String(id));
302
286
  return;
303
287
  }
304
288
  if (args.length === 3) {
@@ -344,7 +328,7 @@ function useForm(initialState, {
344
328
  value: fixedValue
345
329
  })
346
330
  );
347
- validateInput(id, fixedValue);
331
+ validateInput(String(id), fixedValue, String(id));
348
332
  };
349
333
  const getItemCompositeKey = (arrayKey, itemId, field) => `${arrayKey}.${itemId}.${field}`;
350
334
  const getPrimitiveCompositeKey = (arrayKey, index) => `${arrayKey}.@${index}`;
@@ -352,27 +336,33 @@ function useForm(initialState, {
352
336
  const validateItemInput = (arrayKey, itemId, field, value) => {
353
337
  const index = getIndex(String(arrayKey), itemId);
354
338
  if (index === void 0) return;
355
- const arrayRuleDef = arrayRules?.[arrayKey]?.[field];
356
339
  const item = state[arrayKey][index];
357
- const fieldRules = typeof arrayRuleDef === "function" ? arrayRuleDef(item, index) : arrayRuleDef;
358
- const fieldMessages = arrayMessages?.[arrayKey]?.[field];
359
340
  const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
360
- setItemErrors((prev) => ({
361
- ...prev,
362
- [compositeKey]: performValidations(value, fieldRules, fieldMessages)
363
- }));
341
+ let genericField = field.replace(/\.@\d+/, "");
342
+ if (genericField === "")
343
+ genericField = String(arrayKey);
344
+ else genericField = `${String(arrayKey)}.${genericField}`;
345
+ let effectivePath = `${String(arrayKey)}.${field}`;
346
+ if (field === "") effectivePath = String(arrayKey);
347
+ effectivePath = effectivePath.replace(/\.@\d+/g, "").replace(/\.@\d+$/, "");
348
+ const ruleDef = getRule(effectivePath);
349
+ const rule = typeof ruleDef === "function" ? ruleDef(value, state, item, index) : ruleDef;
350
+ const message = getMessage(effectivePath);
351
+ setErrors(
352
+ (prev) => new Map(prev).set(compositeKey, performValidations(value, rule, message))
353
+ );
364
354
  };
365
355
  const getItemUXProps = (0, import_react.useCallback)(
366
356
  (arrayKey, itemId, field) => {
367
357
  const compositeKey = getItemCompositeKey(arrayKey, itemId, field);
368
- const inputError = itemErrors[compositeKey];
369
- const isTouched = itemTouched[compositeKey];
358
+ const inputError = errors2.get(compositeKey);
359
+ const isTouched = touched.get(compositeKey);
370
360
  return {
371
361
  isInvalid: Boolean(isTouched && inputError?.isInvalid),
372
362
  errorMessage: isTouched ? inputError?.errorMessage || "" : ""
373
363
  };
374
364
  },
375
- [itemErrors, itemTouched]
365
+ [errors2, touched]
376
366
  );
377
367
  const onItemBlur = (arrayKey, itemId, field) => {
378
368
  const index = getIndex(String(arrayKey), itemId);
@@ -381,8 +371,8 @@ function useForm(initialState, {
381
371
  const value = getNestedValue(arr[index], field);
382
372
  validateItemInput(arrayKey, itemId, field, value);
383
373
  const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
384
- if (itemTouched[compositeKey]) return;
385
- setItemTouched((prev) => ({ ...prev, [compositeKey]: true }));
374
+ if (touched.get(compositeKey)) return;
375
+ setTouched((prev) => new Map(prev).set(compositeKey, true));
386
376
  };
387
377
  const onItemValueChange = (arrayKey, itemId, field, value) => {
388
378
  const index = getIndex(String(arrayKey), itemId);
@@ -411,17 +401,18 @@ function useForm(initialState, {
411
401
  validateItemInput(arrayKey, itemId, field, fixedValue);
412
402
  };
413
403
  const validateNestedInput = (dotPath, value) => {
414
- const topKey = dotPath.split(".")[0];
415
- setNestedErrors((prev) => ({
416
- ...prev,
417
- [dotPath]: performValidations(value, rules?.[topKey], messages?.[topKey])
418
- }));
404
+ const ruleDef = getRule(dotPath);
405
+ const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
406
+ const message = getMessage(dotPath);
407
+ setErrors(
408
+ (prev) => new Map(prev).set(dotPath, performValidations(value, rule, message))
409
+ );
419
410
  };
420
411
  const onNestedBlur = (dotPath) => {
421
412
  const value = getNestedValue(state, dotPath);
422
413
  validateNestedInput(dotPath, value);
423
- if (nestedTouched[dotPath]) return;
424
- setNestedTouched((prev) => ({ ...prev, [dotPath]: true }));
414
+ if (touched.get(dotPath)) return;
415
+ setTouched((prev) => new Map(prev).set(dotPath, true));
425
416
  };
426
417
  const onNestedValueChange = (dotPath, value) => {
427
418
  setState((prev) => setNestedValue(prev, dotPath, value));
@@ -466,12 +457,8 @@ function useForm(initialState, {
466
457
  ...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
467
458
  id: compositeKey2,
468
459
  onBlur: () => {
469
- const compositeKey3 = getPrimitiveCompositeKey(
470
- String(arrayKey2),
471
- index2
472
- );
473
- if (itemTouched[compositeKey3]) return;
474
- setItemTouched((prev) => ({ ...prev, [compositeKey3]: true }));
460
+ if (touched.get(compositeKey2)) return;
461
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
475
462
  },
476
463
  onValueChange: (v) => {
477
464
  setState((prev) => {
@@ -479,6 +466,7 @@ function useForm(initialState, {
479
466
  arr3[index2] = v;
480
467
  return { ...prev, [arrayKey2]: arr3 };
481
468
  });
469
+ validateItemInput(arrayKey2, `@${index2}`, "", v);
482
470
  },
483
471
  value: value2
484
472
  };
@@ -499,8 +487,8 @@ function useForm(initialState, {
499
487
  ...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
500
488
  id: compositeKey2,
501
489
  onBlur: () => {
502
- if (itemTouched[compositeKey2]) return;
503
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
490
+ if (touched.get(compositeKey2)) return;
491
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
504
492
  },
505
493
  onValueChange: (v) => {
506
494
  if (parentIndex === void 0) return;
@@ -512,6 +500,8 @@ function useForm(initialState, {
512
500
  parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
513
501
  return { ...prev, [parentKey]: parentArr };
514
502
  });
503
+ const fieldPath = `${field2}.@${index2}`;
504
+ validateItemInput(parentKey, parentId, fieldPath, v);
515
505
  },
516
506
  value: value2
517
507
  };
@@ -566,8 +556,8 @@ function useForm(initialState, {
566
556
  ...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
567
557
  id: compositeKey2,
568
558
  onBlur: () => {
569
- if (itemTouched[compositeKey2]) return;
570
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
559
+ if (touched.get(compositeKey2)) return;
560
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
571
561
  },
572
562
  onSelectionChange: (v) => {
573
563
  const fixedValue = typeof v === "string" || v === null ? v : Array.from(v)[0] || null;
@@ -576,6 +566,7 @@ function useForm(initialState, {
576
566
  arr3[index2] = fixedValue;
577
567
  return { ...prev, [arrayKey2]: arr3 };
578
568
  });
569
+ validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
579
570
  },
580
571
  selectedKeys: value2 === null ? [] : [value2]
581
572
  };
@@ -596,8 +587,8 @@ function useForm(initialState, {
596
587
  ...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
597
588
  id: compositeKey2,
598
589
  onBlur: () => {
599
- if (itemTouched[compositeKey2]) return;
600
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
590
+ if (touched.get(compositeKey2)) return;
591
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
601
592
  },
602
593
  onSelectionChange: (v) => {
603
594
  if (parentIndex === void 0) return;
@@ -610,6 +601,8 @@ function useForm(initialState, {
610
601
  parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
611
602
  return { ...prev, [parentKey]: parentArr };
612
603
  });
604
+ const fieldPath = `${field2}.@${index2}`;
605
+ validateItemInput(parentKey, parentId, fieldPath, fixedValue);
613
606
  },
614
607
  selectedKeys: value2 === null ? [] : [value2]
615
608
  };
@@ -659,15 +652,17 @@ function useForm(initialState, {
659
652
  ...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
660
653
  id: compositeKey2,
661
654
  onBlur: () => {
662
- if (itemTouched[compositeKey2]) return;
663
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
655
+ if (touched.get(compositeKey2)) return;
656
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
664
657
  },
665
658
  onSelectionChange: (v) => {
659
+ const fixedValue = typeof v === "string" || v === null ? v : String(v);
666
660
  setState((prev) => {
667
661
  const arr3 = [...prev[arrayKey2]];
668
- arr3[index2] = typeof v === "string" || v === null ? v : String(v);
662
+ arr3[index2] = fixedValue;
669
663
  return { ...prev, [arrayKey2]: arr3 };
670
664
  });
665
+ validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
671
666
  },
672
667
  selectedKey: value2
673
668
  };
@@ -688,19 +683,22 @@ function useForm(initialState, {
688
683
  ...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
689
684
  id: compositeKey2,
690
685
  onBlur: () => {
691
- if (itemTouched[compositeKey2]) return;
692
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
686
+ if (touched.get(compositeKey2)) return;
687
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
693
688
  },
694
689
  onSelectionChange: (v) => {
695
690
  if (parentIndex === void 0) return;
691
+ const fixedValue = typeof v === "string" || v === null ? v : String(v);
696
692
  setState((prev) => {
697
693
  const parentArr = [...prev[parentKey]];
698
694
  const item = { ...parentArr[parentIndex] };
699
695
  const nestedArr2 = [...getNestedValue(item, field2) || []];
700
- nestedArr2[index2] = typeof v === "string" || v === null ? v : String(v);
696
+ nestedArr2[index2] = fixedValue;
701
697
  parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
702
698
  return { ...prev, [parentKey]: parentArr };
703
699
  });
700
+ const fieldPath = `${field2}.@${index2}`;
701
+ validateItemInput(parentKey, parentId, fieldPath, fixedValue);
704
702
  },
705
703
  selectedKey: value2
706
704
  };
@@ -751,8 +749,8 @@ function useForm(initialState, {
751
749
  });
752
750
  if (itemId !== void 0) {
753
751
  const prefix = `${String(arrayKey)}.${itemId}.`;
754
- setItemTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
755
- setItemErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
752
+ setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
753
+ setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
756
754
  }
757
755
  },
758
756
  removeById: (arrayKey, itemId) => {
@@ -762,8 +760,8 @@ function useForm(initialState, {
762
760
  arr.splice(index, 1);
763
761
  setState((prev) => ({ ...prev, [arrayKey]: arr }));
764
762
  const prefix = `${String(arrayKey)}.${itemId}.`;
765
- setItemTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
766
- setItemErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
763
+ setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
764
+ setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
767
765
  }
768
766
  },
769
767
  moveItem: (arrayKey, from, to) => {
@@ -803,35 +801,12 @@ function useForm(initialState, {
803
801
  },
804
802
  isDirty: JSON.stringify(state) !== JSON.stringify(initialState),
805
803
  hasInvalidValues: () => {
806
- setTouched((prev) => allToValue(prev, true));
807
- setItemTouched(
808
- (prev) => Object.keys(prev).reduce(
809
- (acc, key) => ({ ...acc, [key]: true }),
810
- {}
811
- )
812
- );
813
- setNestedTouched(
814
- (prev) => Object.keys(prev).reduce(
815
- (acc, key) => ({ ...acc, [key]: true }),
816
- {}
817
- )
818
- );
819
- const topLevelInvalid = JSON.stringify(errors2).includes(":true");
820
- const itemLevelInvalid = Object.values(itemErrors).some(
821
- (e) => e?.isInvalid
822
- );
823
- const nestedLevelInvalid = Object.values(nestedErrors).some(
824
- (e) => e?.isInvalid
825
- );
826
- return topLevelInvalid || itemLevelInvalid || nestedLevelInvalid;
804
+ const isInvalid = Array.from(errors2.values()).some((e) => e?.isInvalid);
805
+ return isInvalid;
827
806
  },
828
807
  resetForm: (preservedKeys) => {
829
- setTouched(initial.touched);
830
- setErrors(initial.errors);
831
- setItemTouched({});
832
- setItemErrors({});
833
- setNestedTouched({});
834
- setNestedErrors({});
808
+ setTouched(/* @__PURE__ */ new Map());
809
+ setErrors(/* @__PURE__ */ new Map());
835
810
  setState(
836
811
  (prev) => preservedKeys === void 0 ? initialState : preservedKeys.reduce(
837
812
  (acc, key) => ({
@@ -843,16 +818,13 @@ function useForm(initialState, {
843
818
  );
844
819
  },
845
820
  resetTouched: (preservedKeys) => {
846
- setItemTouched({});
847
- setNestedTouched({});
848
821
  setTouched(
849
- (prev) => preservedKeys === void 0 ? initialState : preservedKeys.reduce(
850
- (acc, key) => ({
851
- ...acc,
852
- [key]: prev[key]
853
- }),
854
- initial.touched
855
- )
822
+ (prev) => preservedKeys === void 0 ? /* @__PURE__ */ new Map() : preservedKeys.reduce((acc, key) => {
823
+ if (prev.has(String(key))) {
824
+ acc.set(String(key), prev.get(String(key)));
825
+ }
826
+ return acc;
827
+ }, /* @__PURE__ */ new Map())
856
828
  );
857
829
  }
858
830
  };
package/dist/index.mjs CHANGED
@@ -63,10 +63,10 @@ function getNestedValue(obj, path) {
63
63
  return path.split(".").reduce((acc, key) => acc?.[key], obj);
64
64
  }
65
65
  function removeCompositeKeysByPrefix(map2, prefix) {
66
- const result = {};
67
- for (const [key, value] of Object.entries(map2)) {
68
- if (!key.startsWith(prefix)) {
69
- result[key] = value;
66
+ const result = new Map(map2);
67
+ for (const key of map2.keys()) {
68
+ if (key.startsWith(prefix)) {
69
+ result.delete(key);
70
70
  }
71
71
  }
72
72
  return result;
@@ -82,13 +82,6 @@ function setNestedValue(state, dotPath, value) {
82
82
  current[keys[keys.length - 1]] = value;
83
83
  return copy;
84
84
  }
85
- var allToValue = (obj, value) => Object.keys(obj).reduce(
86
- (acc, key) => {
87
- acc[key] = value;
88
- return acc;
89
- },
90
- {}
91
- );
92
85
  var regex = {
93
86
  email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
94
87
  password: /^(?!.*\s)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~`!@#$%^&*()--+={}[\]|:;"'<>,.?/_₹]).{8,24}$/
@@ -207,21 +200,8 @@ function useValidate() {
207
200
  }
208
201
 
209
202
  // src/hooks/useForm.tsx
210
- function useForm(initialState, {
211
- rules,
212
- messages,
213
- arrayRules,
214
- arrayMessages,
215
- arrayIdentifiers
216
- } = {}) {
217
- const initial = {
218
- touched: allToValue(initialState, false),
219
- errors: allToValue(initialState, {
220
- isInvalid: false,
221
- errorMessage: ""
222
- })
223
- };
224
- const [state, setState] = useState(initialState), [touched, setTouched] = useState(initial.touched), [errors2, setErrors] = useState(initial.errors), [itemTouched, setItemTouched] = useState({}), [itemErrors, setItemErrors] = useState({}), [nestedTouched, setNestedTouched] = useState({}), [nestedErrors, setNestedErrors] = useState({}), { performValidations } = useValidate();
203
+ function useForm(initialState, { rules, messages, arrayIdentifiers } = {}) {
204
+ const [state, setState] = useState(initialState), [touched, setTouched] = useState(/* @__PURE__ */ new Map()), [errors2, setErrors] = useState(/* @__PURE__ */ new Map()), { performValidations } = useValidate();
225
205
  const indexMap = useMemo(() => {
226
206
  const map2 = /* @__PURE__ */ new Map();
227
207
  for (const key in state) {
@@ -247,39 +227,43 @@ function useForm(initialState, {
247
227
  },
248
228
  [indexMap]
249
229
  );
250
- const validateInput = (id, value) => setErrors(
251
- (prev) => handleNestedChange({
252
- state: prev,
253
- id,
254
- value: performValidations(value, rules?.[id], messages?.[id])
255
- })
256
- );
230
+ const getRule = (path) => {
231
+ if (rules?.[path]) return rules[path];
232
+ const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
233
+ return rules?.[genericPath];
234
+ };
235
+ const getMessage = (path) => {
236
+ if (messages?.[path]) return messages[path];
237
+ const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
238
+ return messages?.[genericPath];
239
+ };
240
+ const validateInput = (compositeKey, value, ruleKey) => {
241
+ const ruleDef = getRule(ruleKey);
242
+ const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
243
+ const message = getMessage(ruleKey);
244
+ const error = performValidations(value, rule, message);
245
+ setErrors((prev) => new Map(prev).set(compositeKey, error));
246
+ };
257
247
  const getUXProps = useCallback(
258
- (id) => {
259
- const inputError = errors2[id] || nestedErrors[id];
260
- const isTouched = touched[id] || nestedTouched[id];
248
+ (compositeKey) => {
249
+ const inputError = errors2.get(compositeKey);
250
+ const isTouched = touched.get(compositeKey);
261
251
  return {
262
252
  isInvalid: Boolean(isTouched && inputError?.isInvalid),
263
253
  errorMessage: isTouched ? inputError?.errorMessage || "" : ""
264
254
  };
265
255
  },
266
- [errors2, touched, nestedErrors, nestedTouched]
256
+ [errors2, touched]
267
257
  );
268
258
  const onBlur = (id) => {
269
- validateInput(id, state[id]);
270
- if (touched[id]) return;
271
- setTouched(
272
- (prev) => handleNestedChange({
273
- state: prev,
274
- id,
275
- value: true
276
- })
277
- );
259
+ validateInput(String(id), state[id], String(id));
260
+ if (touched.get(String(id))) return;
261
+ setTouched((prev) => new Map(prev).set(String(id), true));
278
262
  }, onValueChange = ((...args) => {
279
263
  if (args.length === 2) {
280
264
  const [id, value] = args;
281
265
  setState((prev) => handleNestedChange({ state: prev, id, value }));
282
- validateInput(id, value);
266
+ validateInput(String(id), value, String(id));
283
267
  return;
284
268
  }
285
269
  if (args.length === 3) {
@@ -325,7 +309,7 @@ function useForm(initialState, {
325
309
  value: fixedValue
326
310
  })
327
311
  );
328
- validateInput(id, fixedValue);
312
+ validateInput(String(id), fixedValue, String(id));
329
313
  };
330
314
  const getItemCompositeKey = (arrayKey, itemId, field) => `${arrayKey}.${itemId}.${field}`;
331
315
  const getPrimitiveCompositeKey = (arrayKey, index) => `${arrayKey}.@${index}`;
@@ -333,27 +317,33 @@ function useForm(initialState, {
333
317
  const validateItemInput = (arrayKey, itemId, field, value) => {
334
318
  const index = getIndex(String(arrayKey), itemId);
335
319
  if (index === void 0) return;
336
- const arrayRuleDef = arrayRules?.[arrayKey]?.[field];
337
320
  const item = state[arrayKey][index];
338
- const fieldRules = typeof arrayRuleDef === "function" ? arrayRuleDef(item, index) : arrayRuleDef;
339
- const fieldMessages = arrayMessages?.[arrayKey]?.[field];
340
321
  const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
341
- setItemErrors((prev) => ({
342
- ...prev,
343
- [compositeKey]: performValidations(value, fieldRules, fieldMessages)
344
- }));
322
+ let genericField = field.replace(/\.@\d+/, "");
323
+ if (genericField === "")
324
+ genericField = String(arrayKey);
325
+ else genericField = `${String(arrayKey)}.${genericField}`;
326
+ let effectivePath = `${String(arrayKey)}.${field}`;
327
+ if (field === "") effectivePath = String(arrayKey);
328
+ effectivePath = effectivePath.replace(/\.@\d+/g, "").replace(/\.@\d+$/, "");
329
+ const ruleDef = getRule(effectivePath);
330
+ const rule = typeof ruleDef === "function" ? ruleDef(value, state, item, index) : ruleDef;
331
+ const message = getMessage(effectivePath);
332
+ setErrors(
333
+ (prev) => new Map(prev).set(compositeKey, performValidations(value, rule, message))
334
+ );
345
335
  };
346
336
  const getItemUXProps = useCallback(
347
337
  (arrayKey, itemId, field) => {
348
338
  const compositeKey = getItemCompositeKey(arrayKey, itemId, field);
349
- const inputError = itemErrors[compositeKey];
350
- const isTouched = itemTouched[compositeKey];
339
+ const inputError = errors2.get(compositeKey);
340
+ const isTouched = touched.get(compositeKey);
351
341
  return {
352
342
  isInvalid: Boolean(isTouched && inputError?.isInvalid),
353
343
  errorMessage: isTouched ? inputError?.errorMessage || "" : ""
354
344
  };
355
345
  },
356
- [itemErrors, itemTouched]
346
+ [errors2, touched]
357
347
  );
358
348
  const onItemBlur = (arrayKey, itemId, field) => {
359
349
  const index = getIndex(String(arrayKey), itemId);
@@ -362,8 +352,8 @@ function useForm(initialState, {
362
352
  const value = getNestedValue(arr[index], field);
363
353
  validateItemInput(arrayKey, itemId, field, value);
364
354
  const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
365
- if (itemTouched[compositeKey]) return;
366
- setItemTouched((prev) => ({ ...prev, [compositeKey]: true }));
355
+ if (touched.get(compositeKey)) return;
356
+ setTouched((prev) => new Map(prev).set(compositeKey, true));
367
357
  };
368
358
  const onItemValueChange = (arrayKey, itemId, field, value) => {
369
359
  const index = getIndex(String(arrayKey), itemId);
@@ -392,17 +382,18 @@ function useForm(initialState, {
392
382
  validateItemInput(arrayKey, itemId, field, fixedValue);
393
383
  };
394
384
  const validateNestedInput = (dotPath, value) => {
395
- const topKey = dotPath.split(".")[0];
396
- setNestedErrors((prev) => ({
397
- ...prev,
398
- [dotPath]: performValidations(value, rules?.[topKey], messages?.[topKey])
399
- }));
385
+ const ruleDef = getRule(dotPath);
386
+ const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
387
+ const message = getMessage(dotPath);
388
+ setErrors(
389
+ (prev) => new Map(prev).set(dotPath, performValidations(value, rule, message))
390
+ );
400
391
  };
401
392
  const onNestedBlur = (dotPath) => {
402
393
  const value = getNestedValue(state, dotPath);
403
394
  validateNestedInput(dotPath, value);
404
- if (nestedTouched[dotPath]) return;
405
- setNestedTouched((prev) => ({ ...prev, [dotPath]: true }));
395
+ if (touched.get(dotPath)) return;
396
+ setTouched((prev) => new Map(prev).set(dotPath, true));
406
397
  };
407
398
  const onNestedValueChange = (dotPath, value) => {
408
399
  setState((prev) => setNestedValue(prev, dotPath, value));
@@ -447,12 +438,8 @@ function useForm(initialState, {
447
438
  ...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
448
439
  id: compositeKey2,
449
440
  onBlur: () => {
450
- const compositeKey3 = getPrimitiveCompositeKey(
451
- String(arrayKey2),
452
- index2
453
- );
454
- if (itemTouched[compositeKey3]) return;
455
- setItemTouched((prev) => ({ ...prev, [compositeKey3]: true }));
441
+ if (touched.get(compositeKey2)) return;
442
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
456
443
  },
457
444
  onValueChange: (v) => {
458
445
  setState((prev) => {
@@ -460,6 +447,7 @@ function useForm(initialState, {
460
447
  arr3[index2] = v;
461
448
  return { ...prev, [arrayKey2]: arr3 };
462
449
  });
450
+ validateItemInput(arrayKey2, `@${index2}`, "", v);
463
451
  },
464
452
  value: value2
465
453
  };
@@ -480,8 +468,8 @@ function useForm(initialState, {
480
468
  ...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
481
469
  id: compositeKey2,
482
470
  onBlur: () => {
483
- if (itemTouched[compositeKey2]) return;
484
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
471
+ if (touched.get(compositeKey2)) return;
472
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
485
473
  },
486
474
  onValueChange: (v) => {
487
475
  if (parentIndex === void 0) return;
@@ -493,6 +481,8 @@ function useForm(initialState, {
493
481
  parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
494
482
  return { ...prev, [parentKey]: parentArr };
495
483
  });
484
+ const fieldPath = `${field2}.@${index2}`;
485
+ validateItemInput(parentKey, parentId, fieldPath, v);
496
486
  },
497
487
  value: value2
498
488
  };
@@ -547,8 +537,8 @@ function useForm(initialState, {
547
537
  ...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
548
538
  id: compositeKey2,
549
539
  onBlur: () => {
550
- if (itemTouched[compositeKey2]) return;
551
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
540
+ if (touched.get(compositeKey2)) return;
541
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
552
542
  },
553
543
  onSelectionChange: (v) => {
554
544
  const fixedValue = typeof v === "string" || v === null ? v : Array.from(v)[0] || null;
@@ -557,6 +547,7 @@ function useForm(initialState, {
557
547
  arr3[index2] = fixedValue;
558
548
  return { ...prev, [arrayKey2]: arr3 };
559
549
  });
550
+ validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
560
551
  },
561
552
  selectedKeys: value2 === null ? [] : [value2]
562
553
  };
@@ -577,8 +568,8 @@ function useForm(initialState, {
577
568
  ...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
578
569
  id: compositeKey2,
579
570
  onBlur: () => {
580
- if (itemTouched[compositeKey2]) return;
581
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
571
+ if (touched.get(compositeKey2)) return;
572
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
582
573
  },
583
574
  onSelectionChange: (v) => {
584
575
  if (parentIndex === void 0) return;
@@ -591,6 +582,8 @@ function useForm(initialState, {
591
582
  parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
592
583
  return { ...prev, [parentKey]: parentArr };
593
584
  });
585
+ const fieldPath = `${field2}.@${index2}`;
586
+ validateItemInput(parentKey, parentId, fieldPath, fixedValue);
594
587
  },
595
588
  selectedKeys: value2 === null ? [] : [value2]
596
589
  };
@@ -640,15 +633,17 @@ function useForm(initialState, {
640
633
  ...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
641
634
  id: compositeKey2,
642
635
  onBlur: () => {
643
- if (itemTouched[compositeKey2]) return;
644
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
636
+ if (touched.get(compositeKey2)) return;
637
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
645
638
  },
646
639
  onSelectionChange: (v) => {
640
+ const fixedValue = typeof v === "string" || v === null ? v : String(v);
647
641
  setState((prev) => {
648
642
  const arr3 = [...prev[arrayKey2]];
649
- arr3[index2] = typeof v === "string" || v === null ? v : String(v);
643
+ arr3[index2] = fixedValue;
650
644
  return { ...prev, [arrayKey2]: arr3 };
651
645
  });
646
+ validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
652
647
  },
653
648
  selectedKey: value2
654
649
  };
@@ -669,19 +664,22 @@ function useForm(initialState, {
669
664
  ...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
670
665
  id: compositeKey2,
671
666
  onBlur: () => {
672
- if (itemTouched[compositeKey2]) return;
673
- setItemTouched((prev) => ({ ...prev, [compositeKey2]: true }));
667
+ if (touched.get(compositeKey2)) return;
668
+ setTouched((prev) => new Map(prev).set(compositeKey2, true));
674
669
  },
675
670
  onSelectionChange: (v) => {
676
671
  if (parentIndex === void 0) return;
672
+ const fixedValue = typeof v === "string" || v === null ? v : String(v);
677
673
  setState((prev) => {
678
674
  const parentArr = [...prev[parentKey]];
679
675
  const item = { ...parentArr[parentIndex] };
680
676
  const nestedArr2 = [...getNestedValue(item, field2) || []];
681
- nestedArr2[index2] = typeof v === "string" || v === null ? v : String(v);
677
+ nestedArr2[index2] = fixedValue;
682
678
  parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
683
679
  return { ...prev, [parentKey]: parentArr };
684
680
  });
681
+ const fieldPath = `${field2}.@${index2}`;
682
+ validateItemInput(parentKey, parentId, fieldPath, fixedValue);
685
683
  },
686
684
  selectedKey: value2
687
685
  };
@@ -732,8 +730,8 @@ function useForm(initialState, {
732
730
  });
733
731
  if (itemId !== void 0) {
734
732
  const prefix = `${String(arrayKey)}.${itemId}.`;
735
- setItemTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
736
- setItemErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
733
+ setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
734
+ setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
737
735
  }
738
736
  },
739
737
  removeById: (arrayKey, itemId) => {
@@ -743,8 +741,8 @@ function useForm(initialState, {
743
741
  arr.splice(index, 1);
744
742
  setState((prev) => ({ ...prev, [arrayKey]: arr }));
745
743
  const prefix = `${String(arrayKey)}.${itemId}.`;
746
- setItemTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
747
- setItemErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
744
+ setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
745
+ setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
748
746
  }
749
747
  },
750
748
  moveItem: (arrayKey, from, to) => {
@@ -784,35 +782,12 @@ function useForm(initialState, {
784
782
  },
785
783
  isDirty: JSON.stringify(state) !== JSON.stringify(initialState),
786
784
  hasInvalidValues: () => {
787
- setTouched((prev) => allToValue(prev, true));
788
- setItemTouched(
789
- (prev) => Object.keys(prev).reduce(
790
- (acc, key) => ({ ...acc, [key]: true }),
791
- {}
792
- )
793
- );
794
- setNestedTouched(
795
- (prev) => Object.keys(prev).reduce(
796
- (acc, key) => ({ ...acc, [key]: true }),
797
- {}
798
- )
799
- );
800
- const topLevelInvalid = JSON.stringify(errors2).includes(":true");
801
- const itemLevelInvalid = Object.values(itemErrors).some(
802
- (e) => e?.isInvalid
803
- );
804
- const nestedLevelInvalid = Object.values(nestedErrors).some(
805
- (e) => e?.isInvalid
806
- );
807
- return topLevelInvalid || itemLevelInvalid || nestedLevelInvalid;
785
+ const isInvalid = Array.from(errors2.values()).some((e) => e?.isInvalid);
786
+ return isInvalid;
808
787
  },
809
788
  resetForm: (preservedKeys) => {
810
- setTouched(initial.touched);
811
- setErrors(initial.errors);
812
- setItemTouched({});
813
- setItemErrors({});
814
- setNestedTouched({});
815
- setNestedErrors({});
789
+ setTouched(/* @__PURE__ */ new Map());
790
+ setErrors(/* @__PURE__ */ new Map());
816
791
  setState(
817
792
  (prev) => preservedKeys === void 0 ? initialState : preservedKeys.reduce(
818
793
  (acc, key) => ({
@@ -824,16 +799,13 @@ function useForm(initialState, {
824
799
  );
825
800
  },
826
801
  resetTouched: (preservedKeys) => {
827
- setItemTouched({});
828
- setNestedTouched({});
829
802
  setTouched(
830
- (prev) => preservedKeys === void 0 ? initialState : preservedKeys.reduce(
831
- (acc, key) => ({
832
- ...acc,
833
- [key]: prev[key]
834
- }),
835
- initial.touched
836
- )
803
+ (prev) => preservedKeys === void 0 ? /* @__PURE__ */ new Map() : preservedKeys.reduce((acc, key) => {
804
+ if (prev.has(String(key))) {
805
+ acc.set(String(key), prev.get(String(key)));
806
+ }
807
+ return acc;
808
+ }, /* @__PURE__ */ new Map())
837
809
  );
838
810
  }
839
811
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juantroconisf/lib",
3
- "version": "5.3.0",
3
+ "version": "6.1.0",
4
4
  "description": "A form validation library for HeroUI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",