@juantroconisf/lib 11.6.0 → 11.7.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.
Files changed (4) hide show
  1. package/README.md +180 -437
  2. package/dist/index.js +150 -151
  3. package/dist/index.mjs +150 -151
  4. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -44,11 +44,13 @@ function handleNestedChange({
44
44
  value,
45
45
  hasNestedValues = false
46
46
  }) {
47
- if (!hasNestedValues) return { ...state, [id]: value };
48
- const propertyDepth = String(id).split("."), newValues = { ...state };
49
- let current = newValues;
50
- for (let i = 0; i < propertyDepth.length - 1; i++) {
51
- const key = propertyDepth[i];
47
+ const isNested = hasNestedValues || String(id).includes(".");
48
+ if (!isNested) return { ...state, [id]: value };
49
+ const keys = String(id).split(".");
50
+ const newState = { ...state };
51
+ let current = newState;
52
+ for (let i = 0; i < keys.length - 1; i++) {
53
+ const key = keys[i];
52
54
  if (Array.isArray(current[key])) {
53
55
  current[key] = [...current[key]];
54
56
  } else {
@@ -56,8 +58,8 @@ function handleNestedChange({
56
58
  }
57
59
  current = current[key];
58
60
  }
59
- current[propertyDepth[propertyDepth.length - 1]] = value;
60
- return { ...newValues };
61
+ current[keys[keys.length - 1]] = value;
62
+ return newState;
61
63
  }
62
64
  function handleArrayItemChange({
63
65
  state,
@@ -98,21 +100,6 @@ function removeCompositeKeysByPrefix(map, prefix) {
98
100
  }
99
101
  return result;
100
102
  }
101
- function setNestedValue(state, dotPath, value) {
102
- const keys = dotPath.split(".");
103
- const copy = { ...state };
104
- let current = copy;
105
- for (let i = 0; i < keys.length - 1; i++) {
106
- if (Array.isArray(current[keys[i]])) {
107
- current[keys[i]] = [...current[keys[i]]];
108
- } else {
109
- current[keys[i]] = { ...current[keys[i]] };
110
- }
111
- current = current[keys[i]];
112
- }
113
- current[keys[keys.length - 1]] = value;
114
- return copy;
115
- }
116
103
 
117
104
  // src/hooks/useForm.tsx
118
105
  var import_react3 = require("@heroui/react");
@@ -407,7 +394,7 @@ function useForm(schema, {
407
394
  }, [schema]);
408
395
  const [state, setState] = (0, import_react2.useState)(initialState), [metadata, setMetadata] = (0, import_react2.useState)(/* @__PURE__ */ new Map());
409
396
  useComponentLanguage();
410
- const stateRef = (0, import_react2.useRef)(state), metadataRef = (0, import_react2.useRef)(metadata);
397
+ const stateRef = (0, import_react2.useRef)(state), metadataRef = (0, import_react2.useRef)(metadata), propsCache = (0, import_react2.useRef)(/* @__PURE__ */ new Map());
411
398
  stateRef.current = state;
412
399
  metadataRef.current = metadata;
413
400
  const indexMap = (0, import_react2.useMemo)(() => {
@@ -468,14 +455,7 @@ function useForm(schema, {
468
455
  const runValidation = (0, import_react2.useCallback)(
469
456
  (ruleDef, value, compositeKey, realPath, fullState) => {
470
457
  if ((0, import_yup2.isSchema)(ruleDef)) {
471
- try {
472
- if (validationSchema && realPath && fullState !== void 0) {
473
- validationSchema.validateSyncAt(realPath, fullState);
474
- } else {
475
- ruleDef.validateSync(value);
476
- }
477
- return false;
478
- } catch (err) {
458
+ const updateMetadata = (err) => {
479
459
  const error = {
480
460
  isInvalid: true,
481
461
  errorMessage: err.message || "Invalid"
@@ -490,7 +470,32 @@ function useForm(schema, {
490
470
  newMap.set(compositeKey, { ...currentMeta, ...error });
491
471
  return newMap;
492
472
  });
493
- return true;
473
+ };
474
+ try {
475
+ if (validationSchema && realPath && fullState !== void 0) {
476
+ validationSchema.validateSyncAt(realPath, fullState);
477
+ } else {
478
+ ruleDef.validateSync(value);
479
+ }
480
+ return false;
481
+ } catch (err) {
482
+ if (err.name === "ValidationError") {
483
+ updateMetadata(err);
484
+ return true;
485
+ }
486
+ return (async () => {
487
+ try {
488
+ if (validationSchema && realPath && fullState !== void 0) {
489
+ await validationSchema.validateAt(realPath, fullState);
490
+ } else {
491
+ await ruleDef.validate(value);
492
+ }
493
+ return false;
494
+ } catch (asyncErr) {
495
+ updateMetadata(asyncErr);
496
+ return true;
497
+ }
498
+ })();
494
499
  }
495
500
  }
496
501
  return false;
@@ -501,35 +506,46 @@ function useForm(schema, {
501
506
  (compositeKey, fieldPath, realPath, value, fullState) => {
502
507
  let schemaRule = getRule(fieldPath, validationSchema);
503
508
  if (schemaRule) {
504
- if (runValidation(schemaRule, value, compositeKey, realPath, fullState))
505
- return true;
509
+ const result = runValidation(
510
+ schemaRule,
511
+ value,
512
+ compositeKey,
513
+ realPath,
514
+ fullState
515
+ );
516
+ if (result === true) return true;
517
+ if (result instanceof Promise) {
518
+ return result.then((res) => {
519
+ if (!res) clearError();
520
+ return res;
521
+ });
522
+ }
506
523
  }
507
- setMetadata((prev) => {
508
- const newMap = new Map(prev);
509
- const currentMeta = newMap.get(compositeKey) || {
510
- isTouched: false,
511
- isInvalid: false,
512
- errorMessage: ""
513
- };
514
- newMap.set(compositeKey, {
515
- ...currentMeta,
516
- isInvalid: false,
517
- errorMessage: ""
524
+ function clearError() {
525
+ setMetadata((prev) => {
526
+ const newMap = new Map(prev);
527
+ const currentMeta = newMap.get(compositeKey) || {
528
+ isTouched: false,
529
+ isInvalid: false,
530
+ errorMessage: ""
531
+ };
532
+ newMap.set(compositeKey, {
533
+ ...currentMeta,
534
+ isInvalid: false,
535
+ errorMessage: ""
536
+ });
537
+ return newMap;
518
538
  });
519
- return newMap;
520
- });
539
+ }
540
+ clearError();
521
541
  return false;
522
542
  },
523
543
  [getRule, runValidation, validationSchema]
524
544
  );
525
545
  const validateAll = (0, import_react2.useCallback)(() => {
526
546
  if (!validationSchema) return false;
527
- let hasError = false;
528
547
  const newMetadata = new Map(metadataRef.current);
529
- try {
530
- validationSchema.validateSync(state, { abortEarly: false });
531
- } catch (err) {
532
- hasError = true;
548
+ const handleErrors = (err) => {
533
549
  if (err.inner) {
534
550
  err.inner.forEach((validationError) => {
535
551
  const yupPath = validationError.path;
@@ -570,9 +586,26 @@ function useForm(schema, {
570
586
  });
571
587
  });
572
588
  }
589
+ setMetadata(newMetadata);
590
+ return true;
591
+ };
592
+ try {
593
+ validationSchema.validateSync(state, { abortEarly: false });
594
+ } catch (err) {
595
+ if (err.name === "ValidationError") {
596
+ return handleErrors(err);
597
+ }
598
+ return (async () => {
599
+ try {
600
+ await validationSchema.validate(state, { abortEarly: false });
601
+ return false;
602
+ } catch (asyncErr) {
603
+ return handleErrors(asyncErr);
604
+ }
605
+ })();
573
606
  }
574
607
  setMetadata(newMetadata);
575
- return hasError;
608
+ return false;
576
609
  }, [validationSchema, state, arrayIdentifiers]);
577
610
  const handleFieldChange = (0, import_react2.useCallback)(
578
611
  (resolution, newValue) => {
@@ -657,7 +690,12 @@ function useForm(schema, {
657
690
  nextState = { ...nextState, [parentKey]: parentArr };
658
691
  }
659
692
  } else if (type === "deep" /* Deep */) {
660
- nextState = setNestedValue(nextState, resolution.realPath, finalValue);
693
+ nextState = handleNestedChange({
694
+ state: nextState,
695
+ id: resolution.realPath,
696
+ value: finalValue,
697
+ hasNestedValues: true
698
+ });
661
699
  }
662
700
  setState(nextState);
663
701
  validateField(
@@ -713,8 +751,8 @@ function useForm(schema, {
713
751
  [validateField, getRule, validationSchema]
714
752
  );
715
753
  const on = (0, import_react2.useMemo)(
716
- () => ({
717
- input: (...args) => {
754
+ () => {
755
+ const getCachedProps = (method, args, factory) => {
718
756
  const data = resolveFieldData(
719
757
  args,
720
758
  stateRef.current,
@@ -724,117 +762,78 @@ function useForm(schema, {
724
762
  validationSchema
725
763
  );
726
764
  if (!data) return {};
727
- return {
765
+ const meta = metadataRef.current.get(data.compositeKey);
766
+ const deps = JSON.stringify([
767
+ data.value,
768
+ meta?.isInvalid,
769
+ meta?.errorMessage,
770
+ meta?.isTouched
771
+ ]);
772
+ const cacheKey = `${method}:${JSON.stringify(args)}`;
773
+ const cached = propsCache.current.get(cacheKey);
774
+ if (cached && cached.deps === deps) {
775
+ return cached.props;
776
+ }
777
+ const props = factory(data);
778
+ propsCache.current.set(cacheKey, { props, deps });
779
+ return props;
780
+ };
781
+ return {
782
+ input: (...args) => getCachedProps("input", args, (data) => ({
728
783
  ...createHandlers(data),
729
784
  value: data.value === null || data.value === void 0 ? "" : typeof data.value === "boolean" ? data.value : String(data.value),
730
785
  onValueChange: (v) => handleFieldChange(data, v)
731
- };
732
- },
733
- select: (...args) => {
734
- const data = resolveFieldData(
735
- args,
736
- stateRef.current,
737
- getIndex,
738
- getNestedValue,
739
- getRule,
740
- validationSchema
741
- );
742
- if (!data) return {};
743
- const isArray = Array.isArray(data.value);
744
- return {
745
- ...createHandlers(data),
746
- selectedKeys: data.value === null || data.value === void 0 ? [] : isArray ? data.value.map(String) : [String(data.value)],
747
- onSelectionChange: (v) => {
748
- const fixed = typeof v === "string" || v === null ? v : isArray ? Array.from(v) : Array.from(v)[0] ?? null;
749
- handleFieldChange(data, fixed);
750
- }
751
- };
752
- },
753
- autocomplete: (...args) => {
754
- const data = resolveFieldData(
755
- args,
756
- stateRef.current,
757
- getIndex,
758
- getNestedValue,
759
- getRule,
760
- validationSchema
761
- );
762
- if (!data) return {};
763
- return {
786
+ })),
787
+ select: (...args) => getCachedProps("select", args, (data) => {
788
+ const isArray = Array.isArray(data.value);
789
+ return {
790
+ ...createHandlers(data),
791
+ selectedKeys: data.value === null || data.value === void 0 ? [] : isArray ? data.value.map(String) : [String(data.value)],
792
+ onSelectionChange: (v) => {
793
+ const fixed = typeof v === "string" || v === null ? v : isArray ? Array.from(v) : Array.from(v)[0] ?? null;
794
+ handleFieldChange(data, fixed);
795
+ }
796
+ };
797
+ }),
798
+ autocomplete: (...args) => getCachedProps("autocomplete", args, (data) => ({
764
799
  ...createHandlers(data),
765
800
  selectedKey: data.value === null || data.value === void 0 ? null : String(data.value),
766
801
  onSelectionChange: (v) => {
767
802
  const fixed = typeof v === "string" || v === null || v === void 0 ? v : String(v);
768
803
  handleFieldChange(data, fixed);
769
804
  }
770
- };
771
- },
772
- numberInput: (...args) => {
773
- const data = resolveFieldData(
774
- args,
775
- stateRef.current,
776
- getIndex,
777
- getNestedValue,
778
- getRule,
779
- validationSchema
780
- );
781
- if (!data) return {};
782
- return {
805
+ })),
806
+ numberInput: (...args) => getCachedProps("numberInput", args, (data) => ({
783
807
  ...createHandlers(data),
784
808
  value: data.value === null || data.value === void 0 ? "" : String(data.value),
785
809
  onValueChange: (v) => handleFieldChange(data, v)
786
- };
787
- },
788
- checkbox: (...args) => {
789
- const data = resolveFieldData(
790
- args,
791
- stateRef.current,
792
- getIndex,
793
- getNestedValue,
794
- getRule,
795
- validationSchema
796
- );
797
- if (!data) return {};
798
- return {
810
+ })),
811
+ checkbox: (...args) => getCachedProps("checkbox", args, (data) => ({
799
812
  ...createHandlers(data),
800
813
  isSelected: Boolean(data.value),
801
814
  onValueChange: (v) => handleFieldChange(data, v)
802
- };
803
- },
804
- switch: (...args) => {
805
- const data = resolveFieldData(
806
- args,
807
- stateRef.current,
808
- getIndex,
809
- getNestedValue,
810
- getRule,
811
- validationSchema
812
- );
813
- if (!data) return {};
814
- return {
815
+ })),
816
+ switch: (...args) => getCachedProps("switch", args, (data) => ({
815
817
  ...createHandlers(data),
816
818
  isSelected: Boolean(data.value),
817
819
  onValueChange: (v) => handleFieldChange(data, v)
818
- };
819
- },
820
- radio: (...args) => {
821
- const data = resolveFieldData(
822
- args,
823
- stateRef.current,
824
- getIndex,
825
- getNestedValue,
826
- getRule,
827
- validationSchema
828
- );
829
- if (!data) return {};
830
- return {
820
+ })),
821
+ radio: (...args) => getCachedProps("radio", args, (data) => ({
831
822
  ...createHandlers(data),
832
823
  value: data.value === null || data.value === void 0 ? "" : String(data.value),
833
824
  onValueChange: (v) => handleFieldChange(data, v)
834
- };
835
- }
836
- }),
837
- [createHandlers, getIndex, handleFieldChange, getRule, validationSchema]
825
+ }))
826
+ };
827
+ },
828
+ [
829
+ createHandlers,
830
+ getIndex,
831
+ handleFieldChange,
832
+ getRule,
833
+ validationSchema,
834
+ state,
835
+ metadata
836
+ ]
838
837
  );
839
838
  const helpers = (0, import_react2.useMemo)(
840
839
  () => ({
@@ -951,7 +950,7 @@ function useForm(schema, {
951
950
  return getNestedValue(stateRef.current, arrayKey)[index];
952
951
  }
953
952
  }),
954
- [getIndex, arrayIdentifiers]
953
+ [getIndex, arrayIdentifiers, state, metadata]
955
954
  );
956
955
  const onBlur = (0, import_react2.useCallback)(
957
956
  (id) => {
@@ -1035,9 +1034,9 @@ function useForm(schema, {
1035
1034
  [getIndex, handleFieldChange, getRule, validationSchema]
1036
1035
  );
1037
1036
  const onFormSubmit = (0, import_react2.useCallback)(
1038
- (fn) => (e) => {
1037
+ (fn) => async (e) => {
1039
1038
  e.preventDefault();
1040
- if (validateAll()) return;
1039
+ if (await validateAll()) return;
1041
1040
  fn(stateRef.current, e);
1042
1041
  },
1043
1042
  [validateAll]
@@ -1070,9 +1069,9 @@ function useForm(schema, {
1070
1069
  const ControlledForm = (0, import_react2.useMemo)(() => {
1071
1070
  return (props) => {
1072
1071
  const { onSubmit, ...rest } = props;
1073
- const handleSubmit = (e) => {
1072
+ const handleSubmit = async (e) => {
1074
1073
  e.preventDefault();
1075
- if (validateAllRef.current()) {
1074
+ if (await validateAllRef.current()) {
1076
1075
  return;
1077
1076
  }
1078
1077
  onFormSubmitPropRef.current?.(stateRef.current, e);