@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.
- package/README.md +180 -437
- package/dist/index.js +150 -151
- package/dist/index.mjs +150 -151
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -18,11 +18,13 @@ function handleNestedChange({
|
|
|
18
18
|
value,
|
|
19
19
|
hasNestedValues = false
|
|
20
20
|
}) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
const isNested = hasNestedValues || String(id).includes(".");
|
|
22
|
+
if (!isNested) return { ...state, [id]: value };
|
|
23
|
+
const keys = String(id).split(".");
|
|
24
|
+
const newState = { ...state };
|
|
25
|
+
let current = newState;
|
|
26
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
27
|
+
const key = keys[i];
|
|
26
28
|
if (Array.isArray(current[key])) {
|
|
27
29
|
current[key] = [...current[key]];
|
|
28
30
|
} else {
|
|
@@ -30,8 +32,8 @@ function handleNestedChange({
|
|
|
30
32
|
}
|
|
31
33
|
current = current[key];
|
|
32
34
|
}
|
|
33
|
-
current[
|
|
34
|
-
return
|
|
35
|
+
current[keys[keys.length - 1]] = value;
|
|
36
|
+
return newState;
|
|
35
37
|
}
|
|
36
38
|
function handleArrayItemChange({
|
|
37
39
|
state,
|
|
@@ -72,21 +74,6 @@ function removeCompositeKeysByPrefix(map, prefix) {
|
|
|
72
74
|
}
|
|
73
75
|
return result;
|
|
74
76
|
}
|
|
75
|
-
function setNestedValue(state, dotPath, value) {
|
|
76
|
-
const keys = dotPath.split(".");
|
|
77
|
-
const copy = { ...state };
|
|
78
|
-
let current = copy;
|
|
79
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
80
|
-
if (Array.isArray(current[keys[i]])) {
|
|
81
|
-
current[keys[i]] = [...current[keys[i]]];
|
|
82
|
-
} else {
|
|
83
|
-
current[keys[i]] = { ...current[keys[i]] };
|
|
84
|
-
}
|
|
85
|
-
current = current[keys[i]];
|
|
86
|
-
}
|
|
87
|
-
current[keys[keys.length - 1]] = value;
|
|
88
|
-
return copy;
|
|
89
|
-
}
|
|
90
77
|
|
|
91
78
|
// src/hooks/useForm.tsx
|
|
92
79
|
import { Form } from "@heroui/react";
|
|
@@ -381,7 +368,7 @@ function useForm(schema, {
|
|
|
381
368
|
}, [schema]);
|
|
382
369
|
const [state, setState] = useState(initialState), [metadata, setMetadata] = useState(/* @__PURE__ */ new Map());
|
|
383
370
|
useComponentLanguage();
|
|
384
|
-
const stateRef = useRef(state), metadataRef = useRef(metadata);
|
|
371
|
+
const stateRef = useRef(state), metadataRef = useRef(metadata), propsCache = useRef(/* @__PURE__ */ new Map());
|
|
385
372
|
stateRef.current = state;
|
|
386
373
|
metadataRef.current = metadata;
|
|
387
374
|
const indexMap = useMemo(() => {
|
|
@@ -442,14 +429,7 @@ function useForm(schema, {
|
|
|
442
429
|
const runValidation = useCallback(
|
|
443
430
|
(ruleDef, value, compositeKey, realPath, fullState) => {
|
|
444
431
|
if (isSchema(ruleDef)) {
|
|
445
|
-
|
|
446
|
-
if (validationSchema && realPath && fullState !== void 0) {
|
|
447
|
-
validationSchema.validateSyncAt(realPath, fullState);
|
|
448
|
-
} else {
|
|
449
|
-
ruleDef.validateSync(value);
|
|
450
|
-
}
|
|
451
|
-
return false;
|
|
452
|
-
} catch (err) {
|
|
432
|
+
const updateMetadata = (err) => {
|
|
453
433
|
const error = {
|
|
454
434
|
isInvalid: true,
|
|
455
435
|
errorMessage: err.message || "Invalid"
|
|
@@ -464,7 +444,32 @@ function useForm(schema, {
|
|
|
464
444
|
newMap.set(compositeKey, { ...currentMeta, ...error });
|
|
465
445
|
return newMap;
|
|
466
446
|
});
|
|
467
|
-
|
|
447
|
+
};
|
|
448
|
+
try {
|
|
449
|
+
if (validationSchema && realPath && fullState !== void 0) {
|
|
450
|
+
validationSchema.validateSyncAt(realPath, fullState);
|
|
451
|
+
} else {
|
|
452
|
+
ruleDef.validateSync(value);
|
|
453
|
+
}
|
|
454
|
+
return false;
|
|
455
|
+
} catch (err) {
|
|
456
|
+
if (err.name === "ValidationError") {
|
|
457
|
+
updateMetadata(err);
|
|
458
|
+
return true;
|
|
459
|
+
}
|
|
460
|
+
return (async () => {
|
|
461
|
+
try {
|
|
462
|
+
if (validationSchema && realPath && fullState !== void 0) {
|
|
463
|
+
await validationSchema.validateAt(realPath, fullState);
|
|
464
|
+
} else {
|
|
465
|
+
await ruleDef.validate(value);
|
|
466
|
+
}
|
|
467
|
+
return false;
|
|
468
|
+
} catch (asyncErr) {
|
|
469
|
+
updateMetadata(asyncErr);
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
})();
|
|
468
473
|
}
|
|
469
474
|
}
|
|
470
475
|
return false;
|
|
@@ -475,35 +480,46 @@ function useForm(schema, {
|
|
|
475
480
|
(compositeKey, fieldPath, realPath, value, fullState) => {
|
|
476
481
|
let schemaRule = getRule(fieldPath, validationSchema);
|
|
477
482
|
if (schemaRule) {
|
|
478
|
-
|
|
479
|
-
|
|
483
|
+
const result = runValidation(
|
|
484
|
+
schemaRule,
|
|
485
|
+
value,
|
|
486
|
+
compositeKey,
|
|
487
|
+
realPath,
|
|
488
|
+
fullState
|
|
489
|
+
);
|
|
490
|
+
if (result === true) return true;
|
|
491
|
+
if (result instanceof Promise) {
|
|
492
|
+
return result.then((res) => {
|
|
493
|
+
if (!res) clearError();
|
|
494
|
+
return res;
|
|
495
|
+
});
|
|
496
|
+
}
|
|
480
497
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
498
|
+
function clearError() {
|
|
499
|
+
setMetadata((prev) => {
|
|
500
|
+
const newMap = new Map(prev);
|
|
501
|
+
const currentMeta = newMap.get(compositeKey) || {
|
|
502
|
+
isTouched: false,
|
|
503
|
+
isInvalid: false,
|
|
504
|
+
errorMessage: ""
|
|
505
|
+
};
|
|
506
|
+
newMap.set(compositeKey, {
|
|
507
|
+
...currentMeta,
|
|
508
|
+
isInvalid: false,
|
|
509
|
+
errorMessage: ""
|
|
510
|
+
});
|
|
511
|
+
return newMap;
|
|
492
512
|
});
|
|
493
|
-
|
|
494
|
-
|
|
513
|
+
}
|
|
514
|
+
clearError();
|
|
495
515
|
return false;
|
|
496
516
|
},
|
|
497
517
|
[getRule, runValidation, validationSchema]
|
|
498
518
|
);
|
|
499
519
|
const validateAll = useCallback(() => {
|
|
500
520
|
if (!validationSchema) return false;
|
|
501
|
-
let hasError = false;
|
|
502
521
|
const newMetadata = new Map(metadataRef.current);
|
|
503
|
-
|
|
504
|
-
validationSchema.validateSync(state, { abortEarly: false });
|
|
505
|
-
} catch (err) {
|
|
506
|
-
hasError = true;
|
|
522
|
+
const handleErrors = (err) => {
|
|
507
523
|
if (err.inner) {
|
|
508
524
|
err.inner.forEach((validationError) => {
|
|
509
525
|
const yupPath = validationError.path;
|
|
@@ -544,9 +560,26 @@ function useForm(schema, {
|
|
|
544
560
|
});
|
|
545
561
|
});
|
|
546
562
|
}
|
|
563
|
+
setMetadata(newMetadata);
|
|
564
|
+
return true;
|
|
565
|
+
};
|
|
566
|
+
try {
|
|
567
|
+
validationSchema.validateSync(state, { abortEarly: false });
|
|
568
|
+
} catch (err) {
|
|
569
|
+
if (err.name === "ValidationError") {
|
|
570
|
+
return handleErrors(err);
|
|
571
|
+
}
|
|
572
|
+
return (async () => {
|
|
573
|
+
try {
|
|
574
|
+
await validationSchema.validate(state, { abortEarly: false });
|
|
575
|
+
return false;
|
|
576
|
+
} catch (asyncErr) {
|
|
577
|
+
return handleErrors(asyncErr);
|
|
578
|
+
}
|
|
579
|
+
})();
|
|
547
580
|
}
|
|
548
581
|
setMetadata(newMetadata);
|
|
549
|
-
return
|
|
582
|
+
return false;
|
|
550
583
|
}, [validationSchema, state, arrayIdentifiers]);
|
|
551
584
|
const handleFieldChange = useCallback(
|
|
552
585
|
(resolution, newValue) => {
|
|
@@ -631,7 +664,12 @@ function useForm(schema, {
|
|
|
631
664
|
nextState = { ...nextState, [parentKey]: parentArr };
|
|
632
665
|
}
|
|
633
666
|
} else if (type === "deep" /* Deep */) {
|
|
634
|
-
nextState =
|
|
667
|
+
nextState = handleNestedChange({
|
|
668
|
+
state: nextState,
|
|
669
|
+
id: resolution.realPath,
|
|
670
|
+
value: finalValue,
|
|
671
|
+
hasNestedValues: true
|
|
672
|
+
});
|
|
635
673
|
}
|
|
636
674
|
setState(nextState);
|
|
637
675
|
validateField(
|
|
@@ -687,8 +725,8 @@ function useForm(schema, {
|
|
|
687
725
|
[validateField, getRule, validationSchema]
|
|
688
726
|
);
|
|
689
727
|
const on = useMemo(
|
|
690
|
-
() =>
|
|
691
|
-
|
|
728
|
+
() => {
|
|
729
|
+
const getCachedProps = (method, args, factory) => {
|
|
692
730
|
const data = resolveFieldData(
|
|
693
731
|
args,
|
|
694
732
|
stateRef.current,
|
|
@@ -698,117 +736,78 @@ function useForm(schema, {
|
|
|
698
736
|
validationSchema
|
|
699
737
|
);
|
|
700
738
|
if (!data) return {};
|
|
701
|
-
|
|
739
|
+
const meta = metadataRef.current.get(data.compositeKey);
|
|
740
|
+
const deps = JSON.stringify([
|
|
741
|
+
data.value,
|
|
742
|
+
meta?.isInvalid,
|
|
743
|
+
meta?.errorMessage,
|
|
744
|
+
meta?.isTouched
|
|
745
|
+
]);
|
|
746
|
+
const cacheKey = `${method}:${JSON.stringify(args)}`;
|
|
747
|
+
const cached = propsCache.current.get(cacheKey);
|
|
748
|
+
if (cached && cached.deps === deps) {
|
|
749
|
+
return cached.props;
|
|
750
|
+
}
|
|
751
|
+
const props = factory(data);
|
|
752
|
+
propsCache.current.set(cacheKey, { props, deps });
|
|
753
|
+
return props;
|
|
754
|
+
};
|
|
755
|
+
return {
|
|
756
|
+
input: (...args) => getCachedProps("input", args, (data) => ({
|
|
702
757
|
...createHandlers(data),
|
|
703
758
|
value: data.value === null || data.value === void 0 ? "" : typeof data.value === "boolean" ? data.value : String(data.value),
|
|
704
759
|
onValueChange: (v) => handleFieldChange(data, v)
|
|
705
|
-
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
return {
|
|
719
|
-
...createHandlers(data),
|
|
720
|
-
selectedKeys: data.value === null || data.value === void 0 ? [] : isArray ? data.value.map(String) : [String(data.value)],
|
|
721
|
-
onSelectionChange: (v) => {
|
|
722
|
-
const fixed = typeof v === "string" || v === null ? v : isArray ? Array.from(v) : Array.from(v)[0] ?? null;
|
|
723
|
-
handleFieldChange(data, fixed);
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
},
|
|
727
|
-
autocomplete: (...args) => {
|
|
728
|
-
const data = resolveFieldData(
|
|
729
|
-
args,
|
|
730
|
-
stateRef.current,
|
|
731
|
-
getIndex,
|
|
732
|
-
getNestedValue,
|
|
733
|
-
getRule,
|
|
734
|
-
validationSchema
|
|
735
|
-
);
|
|
736
|
-
if (!data) return {};
|
|
737
|
-
return {
|
|
760
|
+
})),
|
|
761
|
+
select: (...args) => getCachedProps("select", args, (data) => {
|
|
762
|
+
const isArray = Array.isArray(data.value);
|
|
763
|
+
return {
|
|
764
|
+
...createHandlers(data),
|
|
765
|
+
selectedKeys: data.value === null || data.value === void 0 ? [] : isArray ? data.value.map(String) : [String(data.value)],
|
|
766
|
+
onSelectionChange: (v) => {
|
|
767
|
+
const fixed = typeof v === "string" || v === null ? v : isArray ? Array.from(v) : Array.from(v)[0] ?? null;
|
|
768
|
+
handleFieldChange(data, fixed);
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
}),
|
|
772
|
+
autocomplete: (...args) => getCachedProps("autocomplete", args, (data) => ({
|
|
738
773
|
...createHandlers(data),
|
|
739
774
|
selectedKey: data.value === null || data.value === void 0 ? null : String(data.value),
|
|
740
775
|
onSelectionChange: (v) => {
|
|
741
776
|
const fixed = typeof v === "string" || v === null || v === void 0 ? v : String(v);
|
|
742
777
|
handleFieldChange(data, fixed);
|
|
743
778
|
}
|
|
744
|
-
}
|
|
745
|
-
|
|
746
|
-
numberInput: (...args) => {
|
|
747
|
-
const data = resolveFieldData(
|
|
748
|
-
args,
|
|
749
|
-
stateRef.current,
|
|
750
|
-
getIndex,
|
|
751
|
-
getNestedValue,
|
|
752
|
-
getRule,
|
|
753
|
-
validationSchema
|
|
754
|
-
);
|
|
755
|
-
if (!data) return {};
|
|
756
|
-
return {
|
|
779
|
+
})),
|
|
780
|
+
numberInput: (...args) => getCachedProps("numberInput", args, (data) => ({
|
|
757
781
|
...createHandlers(data),
|
|
758
782
|
value: data.value === null || data.value === void 0 ? "" : String(data.value),
|
|
759
783
|
onValueChange: (v) => handleFieldChange(data, v)
|
|
760
|
-
}
|
|
761
|
-
|
|
762
|
-
checkbox: (...args) => {
|
|
763
|
-
const data = resolveFieldData(
|
|
764
|
-
args,
|
|
765
|
-
stateRef.current,
|
|
766
|
-
getIndex,
|
|
767
|
-
getNestedValue,
|
|
768
|
-
getRule,
|
|
769
|
-
validationSchema
|
|
770
|
-
);
|
|
771
|
-
if (!data) return {};
|
|
772
|
-
return {
|
|
784
|
+
})),
|
|
785
|
+
checkbox: (...args) => getCachedProps("checkbox", args, (data) => ({
|
|
773
786
|
...createHandlers(data),
|
|
774
787
|
isSelected: Boolean(data.value),
|
|
775
788
|
onValueChange: (v) => handleFieldChange(data, v)
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
switch: (...args) => {
|
|
779
|
-
const data = resolveFieldData(
|
|
780
|
-
args,
|
|
781
|
-
stateRef.current,
|
|
782
|
-
getIndex,
|
|
783
|
-
getNestedValue,
|
|
784
|
-
getRule,
|
|
785
|
-
validationSchema
|
|
786
|
-
);
|
|
787
|
-
if (!data) return {};
|
|
788
|
-
return {
|
|
789
|
+
})),
|
|
790
|
+
switch: (...args) => getCachedProps("switch", args, (data) => ({
|
|
789
791
|
...createHandlers(data),
|
|
790
792
|
isSelected: Boolean(data.value),
|
|
791
793
|
onValueChange: (v) => handleFieldChange(data, v)
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
radio: (...args) => {
|
|
795
|
-
const data = resolveFieldData(
|
|
796
|
-
args,
|
|
797
|
-
stateRef.current,
|
|
798
|
-
getIndex,
|
|
799
|
-
getNestedValue,
|
|
800
|
-
getRule,
|
|
801
|
-
validationSchema
|
|
802
|
-
);
|
|
803
|
-
if (!data) return {};
|
|
804
|
-
return {
|
|
794
|
+
})),
|
|
795
|
+
radio: (...args) => getCachedProps("radio", args, (data) => ({
|
|
805
796
|
...createHandlers(data),
|
|
806
797
|
value: data.value === null || data.value === void 0 ? "" : String(data.value),
|
|
807
798
|
onValueChange: (v) => handleFieldChange(data, v)
|
|
808
|
-
}
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
[
|
|
799
|
+
}))
|
|
800
|
+
};
|
|
801
|
+
},
|
|
802
|
+
[
|
|
803
|
+
createHandlers,
|
|
804
|
+
getIndex,
|
|
805
|
+
handleFieldChange,
|
|
806
|
+
getRule,
|
|
807
|
+
validationSchema,
|
|
808
|
+
state,
|
|
809
|
+
metadata
|
|
810
|
+
]
|
|
812
811
|
);
|
|
813
812
|
const helpers = useMemo(
|
|
814
813
|
() => ({
|
|
@@ -925,7 +924,7 @@ function useForm(schema, {
|
|
|
925
924
|
return getNestedValue(stateRef.current, arrayKey)[index];
|
|
926
925
|
}
|
|
927
926
|
}),
|
|
928
|
-
[getIndex, arrayIdentifiers]
|
|
927
|
+
[getIndex, arrayIdentifiers, state, metadata]
|
|
929
928
|
);
|
|
930
929
|
const onBlur = useCallback(
|
|
931
930
|
(id) => {
|
|
@@ -1009,9 +1008,9 @@ function useForm(schema, {
|
|
|
1009
1008
|
[getIndex, handleFieldChange, getRule, validationSchema]
|
|
1010
1009
|
);
|
|
1011
1010
|
const onFormSubmit = useCallback(
|
|
1012
|
-
(fn) => (e) => {
|
|
1011
|
+
(fn) => async (e) => {
|
|
1013
1012
|
e.preventDefault();
|
|
1014
|
-
if (validateAll()) return;
|
|
1013
|
+
if (await validateAll()) return;
|
|
1015
1014
|
fn(stateRef.current, e);
|
|
1016
1015
|
},
|
|
1017
1016
|
[validateAll]
|
|
@@ -1044,9 +1043,9 @@ function useForm(schema, {
|
|
|
1044
1043
|
const ControlledForm = useMemo(() => {
|
|
1045
1044
|
return (props) => {
|
|
1046
1045
|
const { onSubmit, ...rest } = props;
|
|
1047
|
-
const handleSubmit = (e) => {
|
|
1046
|
+
const handleSubmit = async (e) => {
|
|
1048
1047
|
e.preventDefault();
|
|
1049
|
-
if (validateAllRef.current()) {
|
|
1048
|
+
if (await validateAllRef.current()) {
|
|
1050
1049
|
return;
|
|
1051
1050
|
}
|
|
1052
1051
|
onFormSubmitPropRef.current?.(stateRef.current, e);
|