@juantroconisf/lib 11.7.0 → 11.8.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
@@ -238,6 +238,8 @@ interface HelpersFunc<O extends StateType> {
238
238
  moveById: <K extends ArrayPaths<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
239
239
  /** Gets an item from an array by its unique identifier (O(1) via indexMap). */
240
240
  getItemById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
241
+ /** Validates a single item in an array by its unique identifier. */
242
+ validateItem: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => Promise<boolean>;
241
243
  }
242
244
  /**
243
245
  * The response object from the useForm hook.
package/dist/index.d.ts CHANGED
@@ -238,6 +238,8 @@ interface HelpersFunc<O extends StateType> {
238
238
  moveById: <K extends ArrayPaths<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
239
239
  /** Gets an item from an array by its unique identifier (O(1) via indexMap). */
240
240
  getItemById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
241
+ /** Validates a single item in an array by its unique identifier. */
242
+ validateItem: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => Promise<boolean>;
241
243
  }
242
244
  /**
243
245
  * The response object from the useForm hook.
package/dist/index.js CHANGED
@@ -428,7 +428,17 @@ function useForm(schema, {
428
428
  const indexMapRef = (0, import_react2.useRef)(indexMap);
429
429
  indexMapRef.current = indexMap;
430
430
  const getIndex = (0, import_react2.useCallback)((arrayKey, itemId) => {
431
- return indexMapRef.current.get(arrayKey)?.get(itemId);
431
+ const map = indexMapRef.current.get(arrayKey);
432
+ if (!map) return void 0;
433
+ const index = map.get(itemId);
434
+ if (index !== void 0) return index;
435
+ if (typeof itemId === "string") {
436
+ const num = Number(itemId);
437
+ if (!isNaN(num)) return map.get(num);
438
+ } else if (typeof itemId === "number") {
439
+ return map.get(String(itemId));
440
+ }
441
+ return void 0;
432
442
  }, []);
433
443
  const ruleCache = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
434
444
  (0, import_react2.useMemo)(() => {
@@ -544,8 +554,14 @@ function useForm(schema, {
544
554
  );
545
555
  const validateAll = (0, import_react2.useCallback)(() => {
546
556
  if (!validationSchema) return false;
547
- const newMetadata = new Map(metadataRef.current);
557
+ const cleanMetadata = new Map(metadataRef.current);
558
+ cleanMetadata.forEach((value, key) => {
559
+ if (value.isInvalid) {
560
+ cleanMetadata.set(key, { ...value, isInvalid: false, errorMessage: "" });
561
+ }
562
+ });
548
563
  const handleErrors = (err) => {
564
+ const newMetadata = new Map(cleanMetadata);
549
565
  if (err.inner) {
550
566
  err.inner.forEach((validationError) => {
551
567
  const yupPath = validationError.path;
@@ -598,13 +614,14 @@ function useForm(schema, {
598
614
  return (async () => {
599
615
  try {
600
616
  await validationSchema.validate(state, { abortEarly: false });
617
+ setMetadata(cleanMetadata);
601
618
  return false;
602
619
  } catch (asyncErr) {
603
620
  return handleErrors(asyncErr);
604
621
  }
605
622
  })();
606
623
  }
607
- setMetadata(newMetadata);
624
+ setMetadata(cleanMetadata);
608
625
  return false;
609
626
  }, [validationSchema, state, arrayIdentifiers]);
610
627
  const handleFieldChange = (0, import_react2.useCallback)(
@@ -948,6 +965,83 @@ function useForm(schema, {
948
965
  const index = getIndex(arrayKey, itemId);
949
966
  if (index === void 0) return void 0;
950
967
  return getNestedValue(stateRef.current, arrayKey)[index];
968
+ },
969
+ validateItem: async (arrayKey, itemId) => {
970
+ if (!validationSchema) return false;
971
+ const index = getIndex(arrayKey, itemId);
972
+ if (index === void 0) return false;
973
+ const yupPath = `${String(arrayKey)}[${index}]`;
974
+ const prefix = `${String(arrayKey)}.${itemId}.`;
975
+ const cleanMetadata = new Map(metadataRef.current);
976
+ for (const key of cleanMetadata.keys()) {
977
+ if (key.startsWith(prefix) || key === `${String(arrayKey)}.${itemId}`) {
978
+ const meta = cleanMetadata.get(key);
979
+ cleanMetadata.set(key, {
980
+ ...meta,
981
+ isInvalid: false,
982
+ errorMessage: ""
983
+ });
984
+ }
985
+ }
986
+ const handleErrors = (err) => {
987
+ const newMetadata = new Map(cleanMetadata);
988
+ if (err.inner) {
989
+ err.inner.forEach((validationError) => {
990
+ const localDotPath = validationError.path.replace(
991
+ /\[(\d+)\]/g,
992
+ ".$1"
993
+ );
994
+ const parts = localDotPath.split(".");
995
+ let current = stateRef.current;
996
+ const compositeParts = [];
997
+ for (let i = 0; i < parts.length; i++) {
998
+ const part = parts[i];
999
+ if (Array.isArray(current)) {
1000
+ const idx = parseInt(part, 10);
1001
+ const item = current[idx];
1002
+ if (item && typeof item === "object") {
1003
+ const genericPath = compositeParts.join(".").replace(/\.\d+/g, "");
1004
+ const idKey = arrayIdentifiers?.[genericPath] || "id";
1005
+ const id = item[idKey];
1006
+ compositeParts.push(String(id !== void 0 ? id : idx));
1007
+ } else {
1008
+ compositeParts.push(part);
1009
+ }
1010
+ current = item;
1011
+ } else {
1012
+ compositeParts.push(part);
1013
+ current = current?.[part];
1014
+ }
1015
+ }
1016
+ const compositeKey = compositeParts.join(".");
1017
+ const currentMeta = newMetadata.get(compositeKey) || {
1018
+ isTouched: false,
1019
+ isInvalid: false,
1020
+ errorMessage: ""
1021
+ };
1022
+ newMetadata.set(compositeKey, {
1023
+ ...currentMeta,
1024
+ isTouched: true,
1025
+ isInvalid: true,
1026
+ errorMessage: validationError.message
1027
+ });
1028
+ });
1029
+ }
1030
+ setMetadata(newMetadata);
1031
+ return true;
1032
+ };
1033
+ try {
1034
+ await validationSchema.validateAt(yupPath, stateRef.current, {
1035
+ abortEarly: false
1036
+ });
1037
+ setMetadata(cleanMetadata);
1038
+ return false;
1039
+ } catch (err) {
1040
+ if (err.name === "ValidationError") {
1041
+ return handleErrors(err);
1042
+ }
1043
+ return false;
1044
+ }
951
1045
  }
952
1046
  }),
953
1047
  [getIndex, arrayIdentifiers, state, metadata]
package/dist/index.mjs CHANGED
@@ -402,7 +402,17 @@ function useForm(schema, {
402
402
  const indexMapRef = useRef(indexMap);
403
403
  indexMapRef.current = indexMap;
404
404
  const getIndex = useCallback((arrayKey, itemId) => {
405
- return indexMapRef.current.get(arrayKey)?.get(itemId);
405
+ const map = indexMapRef.current.get(arrayKey);
406
+ if (!map) return void 0;
407
+ const index = map.get(itemId);
408
+ if (index !== void 0) return index;
409
+ if (typeof itemId === "string") {
410
+ const num = Number(itemId);
411
+ if (!isNaN(num)) return map.get(num);
412
+ } else if (typeof itemId === "number") {
413
+ return map.get(String(itemId));
414
+ }
415
+ return void 0;
406
416
  }, []);
407
417
  const ruleCache = useRef(/* @__PURE__ */ new Map());
408
418
  useMemo(() => {
@@ -518,8 +528,14 @@ function useForm(schema, {
518
528
  );
519
529
  const validateAll = useCallback(() => {
520
530
  if (!validationSchema) return false;
521
- const newMetadata = new Map(metadataRef.current);
531
+ const cleanMetadata = new Map(metadataRef.current);
532
+ cleanMetadata.forEach((value, key) => {
533
+ if (value.isInvalid) {
534
+ cleanMetadata.set(key, { ...value, isInvalid: false, errorMessage: "" });
535
+ }
536
+ });
522
537
  const handleErrors = (err) => {
538
+ const newMetadata = new Map(cleanMetadata);
523
539
  if (err.inner) {
524
540
  err.inner.forEach((validationError) => {
525
541
  const yupPath = validationError.path;
@@ -572,13 +588,14 @@ function useForm(schema, {
572
588
  return (async () => {
573
589
  try {
574
590
  await validationSchema.validate(state, { abortEarly: false });
591
+ setMetadata(cleanMetadata);
575
592
  return false;
576
593
  } catch (asyncErr) {
577
594
  return handleErrors(asyncErr);
578
595
  }
579
596
  })();
580
597
  }
581
- setMetadata(newMetadata);
598
+ setMetadata(cleanMetadata);
582
599
  return false;
583
600
  }, [validationSchema, state, arrayIdentifiers]);
584
601
  const handleFieldChange = useCallback(
@@ -922,6 +939,83 @@ function useForm(schema, {
922
939
  const index = getIndex(arrayKey, itemId);
923
940
  if (index === void 0) return void 0;
924
941
  return getNestedValue(stateRef.current, arrayKey)[index];
942
+ },
943
+ validateItem: async (arrayKey, itemId) => {
944
+ if (!validationSchema) return false;
945
+ const index = getIndex(arrayKey, itemId);
946
+ if (index === void 0) return false;
947
+ const yupPath = `${String(arrayKey)}[${index}]`;
948
+ const prefix = `${String(arrayKey)}.${itemId}.`;
949
+ const cleanMetadata = new Map(metadataRef.current);
950
+ for (const key of cleanMetadata.keys()) {
951
+ if (key.startsWith(prefix) || key === `${String(arrayKey)}.${itemId}`) {
952
+ const meta = cleanMetadata.get(key);
953
+ cleanMetadata.set(key, {
954
+ ...meta,
955
+ isInvalid: false,
956
+ errorMessage: ""
957
+ });
958
+ }
959
+ }
960
+ const handleErrors = (err) => {
961
+ const newMetadata = new Map(cleanMetadata);
962
+ if (err.inner) {
963
+ err.inner.forEach((validationError) => {
964
+ const localDotPath = validationError.path.replace(
965
+ /\[(\d+)\]/g,
966
+ ".$1"
967
+ );
968
+ const parts = localDotPath.split(".");
969
+ let current = stateRef.current;
970
+ const compositeParts = [];
971
+ for (let i = 0; i < parts.length; i++) {
972
+ const part = parts[i];
973
+ if (Array.isArray(current)) {
974
+ const idx = parseInt(part, 10);
975
+ const item = current[idx];
976
+ if (item && typeof item === "object") {
977
+ const genericPath = compositeParts.join(".").replace(/\.\d+/g, "");
978
+ const idKey = arrayIdentifiers?.[genericPath] || "id";
979
+ const id = item[idKey];
980
+ compositeParts.push(String(id !== void 0 ? id : idx));
981
+ } else {
982
+ compositeParts.push(part);
983
+ }
984
+ current = item;
985
+ } else {
986
+ compositeParts.push(part);
987
+ current = current?.[part];
988
+ }
989
+ }
990
+ const compositeKey = compositeParts.join(".");
991
+ const currentMeta = newMetadata.get(compositeKey) || {
992
+ isTouched: false,
993
+ isInvalid: false,
994
+ errorMessage: ""
995
+ };
996
+ newMetadata.set(compositeKey, {
997
+ ...currentMeta,
998
+ isTouched: true,
999
+ isInvalid: true,
1000
+ errorMessage: validationError.message
1001
+ });
1002
+ });
1003
+ }
1004
+ setMetadata(newMetadata);
1005
+ return true;
1006
+ };
1007
+ try {
1008
+ await validationSchema.validateAt(yupPath, stateRef.current, {
1009
+ abortEarly: false
1010
+ });
1011
+ setMetadata(cleanMetadata);
1012
+ return false;
1013
+ } catch (err) {
1014
+ if (err.name === "ValidationError") {
1015
+ return handleErrors(err);
1016
+ }
1017
+ return false;
1018
+ }
925
1019
  }
926
1020
  }),
927
1021
  [getIndex, arrayIdentifiers, state, metadata]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juantroconisf/lib",
3
- "version": "11.7.0",
3
+ "version": "11.8.0",
4
4
  "description": "A form validation library for HeroUI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",