react-f0rm 1.0.0 → 1.1.1
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 +34 -0
- package/dist/devtools/index.cjs.js +1 -1
- package/dist/devtools/index.cjs.js.map +1 -1
- package/dist/devtools/index.mjs +1 -1
- package/dist/devtools/index.mjs.map +1 -1
- package/dist/form-2_tBkEXU.mjs +2 -0
- package/dist/form-2_tBkEXU.mjs.map +1 -0
- package/dist/{form-D-A2NoKo.d.ts → form-BiDaJLjD.d.ts} +79 -5
- package/dist/form-BwLNQ6WB.cjs.js +2 -0
- package/dist/form-BwLNQ6WB.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +25 -3
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +138 -31
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +2 -2
- package/dist/index.umd.min.js.map +1 -1
- package/dist/resolvers/standard-schema.cjs.js +1 -1
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.d.ts +1 -1
- package/dist/resolvers/yup.mjs +1 -1
- package/dist/resolvers/zod.cjs.js +1 -1
- package/dist/resolvers/zod.d.ts +1 -1
- package/dist/resolvers/zod.mjs +1 -1
- package/dist/{validate-Bj2oVj82.d.ts → validate-2XUilILy.d.ts} +1 -1
- package/package.json +1 -1
- package/dist/form-D8RKC-r3.cjs.js +0 -2
- package/dist/form-D8RKC-r3.cjs.js.map +0 -1
- package/dist/form-fzTmS8jF.mjs +0 -2
- package/dist/form-fzTmS8jF.mjs.map +0 -1
package/dist/index.umd.js
CHANGED
|
@@ -49,12 +49,17 @@
|
|
|
49
49
|
};
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const PATH_CACHE_LIMIT = 1e4;
|
|
52
53
|
const pathCache = /* @__PURE__ */ new Map();
|
|
53
54
|
function normalizePath(path) {
|
|
54
55
|
if (Array.isArray(path)) return path;
|
|
55
56
|
const cached = pathCache.get(path);
|
|
56
57
|
if (cached) return cached;
|
|
57
58
|
const value = parsePath(path);
|
|
59
|
+
if (pathCache.size >= PATH_CACHE_LIMIT) {
|
|
60
|
+
const oldest = pathCache.keys().next();
|
|
61
|
+
if (!oldest.done) pathCache.delete(oldest.value);
|
|
62
|
+
}
|
|
58
63
|
pathCache.set(path, value);
|
|
59
64
|
return value;
|
|
60
65
|
}
|
|
@@ -249,7 +254,23 @@
|
|
|
249
254
|
isSubmitSuccessful: void 0
|
|
250
255
|
};
|
|
251
256
|
}
|
|
257
|
+
const valuesCaches = /* @__PURE__ */ new WeakMap();
|
|
258
|
+
function bumpValuesVersion(form) {
|
|
259
|
+
const cache = valuesCaches.get(form);
|
|
260
|
+
if (cache) cache.version++;
|
|
261
|
+
}
|
|
252
262
|
function getValues(form) {
|
|
263
|
+
let cache = valuesCaches.get(form);
|
|
264
|
+
if (!cache) {
|
|
265
|
+
cache = { version: 0, result: computeValues(form) };
|
|
266
|
+
valuesCaches.set(form, cache);
|
|
267
|
+
} else if (cache.version > 0) {
|
|
268
|
+
cache.result = computeValues(form);
|
|
269
|
+
cache.version = 0;
|
|
270
|
+
}
|
|
271
|
+
return cache.result;
|
|
272
|
+
}
|
|
273
|
+
function computeValues(form) {
|
|
253
274
|
const { initialValues, parsedValues, values, deleted } = form;
|
|
254
275
|
const owned = /* @__PURE__ */ new Set();
|
|
255
276
|
let merged = parsedValues ?? initialValues;
|
|
@@ -287,10 +308,23 @@
|
|
|
287
308
|
pruneDirtyBaselines(form, path);
|
|
288
309
|
if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);
|
|
289
310
|
bumpDirtyVersion(form);
|
|
311
|
+
bumpValuesVersion(form);
|
|
290
312
|
if (options?.shouldTouch) setTouchedByPath(form, path);
|
|
291
313
|
if (options?.shouldValidate) form.validators.get(path.key)?.();
|
|
292
314
|
emit(emitter, "change", path);
|
|
293
315
|
}
|
|
316
|
+
function seedValueByPath(form, path, value) {
|
|
317
|
+
const { values, deleted } = form;
|
|
318
|
+
values.set(path.key, value);
|
|
319
|
+
pruneDescendantKeys(values, path);
|
|
320
|
+
reviveBranch(deleted, path);
|
|
321
|
+
pruneDirtyBaselines(form, path);
|
|
322
|
+
bumpDirtyVersion(form);
|
|
323
|
+
bumpValuesVersion(form);
|
|
324
|
+
}
|
|
325
|
+
function emitChangeByPath({ emitter }, path) {
|
|
326
|
+
emit(emitter, "change", path);
|
|
327
|
+
}
|
|
294
328
|
function changeValue(form, name, value, options) {
|
|
295
329
|
changeValueByPath(form, create$1(name), value, options);
|
|
296
330
|
}
|
|
@@ -492,7 +526,8 @@
|
|
|
492
526
|
function removeField(form, name) {
|
|
493
527
|
removeFieldByPath(form, create$1(name));
|
|
494
528
|
}
|
|
495
|
-
function removeFieldByPath(form,
|
|
529
|
+
function removeFieldByPath(form, path) {
|
|
530
|
+
const { key, value: segments } = path;
|
|
496
531
|
const { emitter, values, touched, errors, validating, deleted } = form;
|
|
497
532
|
values.delete(key);
|
|
498
533
|
touched.delete(key);
|
|
@@ -501,10 +536,11 @@
|
|
|
501
536
|
clearDirtyBaselines(form, key);
|
|
502
537
|
if (!hasLiveBranch(values, segments)) deleted.add(key);
|
|
503
538
|
bumpDirtyVersion(form);
|
|
504
|
-
|
|
505
|
-
emit(emitter, "
|
|
506
|
-
emit(emitter, "
|
|
507
|
-
emit(emitter, "
|
|
539
|
+
bumpValuesVersion(form);
|
|
540
|
+
emit(emitter, "change", path);
|
|
541
|
+
emit(emitter, "touched", path);
|
|
542
|
+
emit(emitter, "errors", path);
|
|
543
|
+
emit(emitter, "validating", path);
|
|
508
544
|
}
|
|
509
545
|
function hasLiveBranch(values, segments) {
|
|
510
546
|
for (let i = 1; i < segments.length; i++) {
|
|
@@ -541,13 +577,19 @@
|
|
|
541
577
|
form.deleted.clear();
|
|
542
578
|
clearDirtyBaselines(form);
|
|
543
579
|
bumpDirtyVersion(form);
|
|
580
|
+
bumpValuesVersion(form);
|
|
544
581
|
emit(form.emitter, "change");
|
|
545
582
|
}
|
|
546
583
|
function reset(form, initialValues, options) {
|
|
547
|
-
const dirtyValues =
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
584
|
+
const dirtyValues = [];
|
|
585
|
+
if (options?.keepDirtyValues) {
|
|
586
|
+
for (const [key, value] of form.values) {
|
|
587
|
+
const segments = JSON.parse(key);
|
|
588
|
+
if (getDirtyBaseline(form, key, segments) !== value) {
|
|
589
|
+
dirtyValues.push({ segments, value });
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
}
|
|
551
593
|
form.initialValues = initialValues;
|
|
552
594
|
form.parsedValues = void 0;
|
|
553
595
|
if (!options?.keepErrors) clearErrors(form);
|
|
@@ -561,8 +603,9 @@
|
|
|
561
603
|
if (!options?.keepSubmitCount) form.submitCount = 0;
|
|
562
604
|
if (!options?.keepIsSubmitted) form.isSubmitSuccessful = void 0;
|
|
563
605
|
bumpDirtyVersion(form);
|
|
564
|
-
|
|
565
|
-
|
|
606
|
+
bumpValuesVersion(form);
|
|
607
|
+
for (const { segments, value } of dirtyValues) {
|
|
608
|
+
setValueByPath(form, create$1(segments), value);
|
|
566
609
|
}
|
|
567
610
|
emit(emitter, "change");
|
|
568
611
|
emit(emitter, "touched");
|
|
@@ -594,15 +637,16 @@
|
|
|
594
637
|
emit(emitter, "errors", path);
|
|
595
638
|
}
|
|
596
639
|
bumpDirtyVersion(form);
|
|
640
|
+
bumpValuesVersion(form);
|
|
597
641
|
}
|
|
598
642
|
function hasErrors({ errors }) {
|
|
599
643
|
return errors.size > 0;
|
|
600
644
|
}
|
|
601
645
|
async function trigger(form, name) {
|
|
602
|
-
const settle = () => waitUntil(
|
|
646
|
+
const settle = (keys2) => waitUntil(
|
|
603
647
|
form.emitter,
|
|
604
648
|
"validating",
|
|
605
|
-
() => fieldsSettled(form),
|
|
649
|
+
() => keys2 === void 0 ? fieldsSettled(form) : keys2.every((key) => !form.validating.has(key)),
|
|
606
650
|
() => false
|
|
607
651
|
);
|
|
608
652
|
if (name === void 0) {
|
|
@@ -613,7 +657,7 @@
|
|
|
613
657
|
}
|
|
614
658
|
const keys = typeof name === "string" || isSegmentsPath(name) ? [create$1(name).key] : name.map((one) => create$1(one).key);
|
|
615
659
|
keys.forEach((key) => form.validators.get(key)?.());
|
|
616
|
-
await settle();
|
|
660
|
+
await settle(keys);
|
|
617
661
|
return keys.every((key) => !form.errors.has(key));
|
|
618
662
|
}
|
|
619
663
|
function isSegmentsPath(name) {
|
|
@@ -653,6 +697,7 @@
|
|
|
653
697
|
function setParsedValues(form, values) {
|
|
654
698
|
if (values === void 0 || values === form.parsedValues) return;
|
|
655
699
|
form.parsedValues = values;
|
|
700
|
+
bumpValuesVersion(form);
|
|
656
701
|
emit(form.emitter, "change");
|
|
657
702
|
}
|
|
658
703
|
function applyValidateResult(form, result) {
|
|
@@ -794,6 +839,46 @@
|
|
|
794
839
|
});
|
|
795
840
|
}
|
|
796
841
|
}
|
|
842
|
+
const fieldValidateDeps = /* @__PURE__ */ new WeakMap();
|
|
843
|
+
function registerFieldValidateDeps(form, key, depKeys) {
|
|
844
|
+
let deps = fieldValidateDeps.get(form);
|
|
845
|
+
if (!deps) {
|
|
846
|
+
deps = /* @__PURE__ */ new Map();
|
|
847
|
+
fieldValidateDeps.set(form, deps);
|
|
848
|
+
}
|
|
849
|
+
for (const depKey of depKeys) {
|
|
850
|
+
let dependents = deps.get(depKey);
|
|
851
|
+
if (!dependents) {
|
|
852
|
+
dependents = /* @__PURE__ */ new Set();
|
|
853
|
+
deps.set(depKey, dependents);
|
|
854
|
+
}
|
|
855
|
+
dependents.add(key);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
function unregisterFieldValidateDeps(form, key, depKeys) {
|
|
859
|
+
const deps = fieldValidateDeps.get(form);
|
|
860
|
+
if (!deps) return;
|
|
861
|
+
for (const depKey of depKeys) {
|
|
862
|
+
const dependents = deps.get(depKey);
|
|
863
|
+
if (!dependents?.delete(key)) continue;
|
|
864
|
+
if (!dependents.size) deps.delete(depKey);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function revalidateDependentsOnChange(form, path, mode) {
|
|
868
|
+
const dependents = fieldValidateDeps.get(form)?.get(path.key);
|
|
869
|
+
if (!dependents?.size) return;
|
|
870
|
+
for (const dependent of dependents) {
|
|
871
|
+
if (dependent === path.key) continue;
|
|
872
|
+
if (mode === "onChange" || mode === "all" || mode === "onTouched" && hasTouchedByPath(form, path) || form.reValidateMode === "onChange" && form.errors.has(dependent)) {
|
|
873
|
+
form.validators.get(dependent)?.();
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
function validationError(form) {
|
|
878
|
+
const error = new Error(getFirstError(form));
|
|
879
|
+
error.errors = getErrors(form);
|
|
880
|
+
return error;
|
|
881
|
+
}
|
|
797
882
|
async function ensureValidate(form) {
|
|
798
883
|
form.validators.forEach((validator) => validator());
|
|
799
884
|
await waitUntil(
|
|
@@ -802,11 +887,11 @@
|
|
|
802
887
|
() => fieldsSettled(form),
|
|
803
888
|
() => hasErrors(form)
|
|
804
889
|
).catch(() => {
|
|
805
|
-
throw
|
|
890
|
+
throw validationError(form);
|
|
806
891
|
});
|
|
807
892
|
if (form.validate) {
|
|
808
893
|
await runFormValidate(form);
|
|
809
|
-
if (hasErrors(form)) throw
|
|
894
|
+
if (hasErrors(form)) throw validationError(form);
|
|
810
895
|
}
|
|
811
896
|
}
|
|
812
897
|
async function validate(form) {
|
|
@@ -1216,6 +1301,7 @@
|
|
|
1216
1301
|
if (seededRef.current === null)
|
|
1217
1302
|
seededRef.current = { done: false, source: void 0 };
|
|
1218
1303
|
React.useEffect(() => {
|
|
1304
|
+
if (initialValues === void 0) return;
|
|
1219
1305
|
const seeded = seededRef.current;
|
|
1220
1306
|
if (seeded.done && (seeded.source === initialValues || isEqual(seeded.source, initialValues))) {
|
|
1221
1307
|
return;
|
|
@@ -1512,6 +1598,7 @@
|
|
|
1512
1598
|
validate,
|
|
1513
1599
|
rules,
|
|
1514
1600
|
validateDebounce,
|
|
1601
|
+
validateDeps,
|
|
1515
1602
|
delayError,
|
|
1516
1603
|
disabled,
|
|
1517
1604
|
mode: modeOption
|
|
@@ -1520,6 +1607,17 @@
|
|
|
1520
1607
|
const form = f1 || contextForm;
|
|
1521
1608
|
if (!form) throw new Error("no form provided");
|
|
1522
1609
|
const path = usePath(name);
|
|
1610
|
+
const seededRef = React.useRef(false);
|
|
1611
|
+
const seeded = initialValue !== void 0 && getValueByPath(form, path) === void 0;
|
|
1612
|
+
if (seeded) {
|
|
1613
|
+
seedValueByPath(form, path, initialValue);
|
|
1614
|
+
seededRef.current = true;
|
|
1615
|
+
}
|
|
1616
|
+
React.useEffect(() => {
|
|
1617
|
+
if (!seededRef.current) return;
|
|
1618
|
+
seededRef.current = false;
|
|
1619
|
+
emitChangeByPath(form, path);
|
|
1620
|
+
});
|
|
1523
1621
|
const validator = useValidate(
|
|
1524
1622
|
combineRulesAndValidate(rules, validate),
|
|
1525
1623
|
path,
|
|
@@ -1535,17 +1633,12 @@
|
|
|
1535
1633
|
const value = useValueByPath(form, path);
|
|
1536
1634
|
const formDisabled = useWatch(form.emitter, "disabled", () => form.disabled);
|
|
1537
1635
|
const mode = modeOption ?? form.mode;
|
|
1538
|
-
React.useEffect(() => {
|
|
1539
|
-
if (initialValue === void 0) return;
|
|
1540
|
-
if (getValueByPath(form, path) === void 0) {
|
|
1541
|
-
setValueByPath(form, path, initialValue);
|
|
1542
|
-
}
|
|
1543
|
-
}, [form, path, initialValue]);
|
|
1544
1636
|
const onChange = useStageFn((v) => {
|
|
1545
1637
|
setValueByPath(form, path, v);
|
|
1546
1638
|
if (mode === "onChange" || mode === "all" || mode === "onTouched" && hasTouchedByPath(form, path) || liveErrors.length > 0 && form.reValidateMode === "onChange")
|
|
1547
1639
|
validator();
|
|
1548
1640
|
revalidateFormOnChange(form, path, mode);
|
|
1641
|
+
revalidateDependentsOnChange(form, path, mode);
|
|
1549
1642
|
});
|
|
1550
1643
|
React.useEffect(() => {
|
|
1551
1644
|
form.changeHandlers.set(path.key, onChange);
|
|
@@ -1554,6 +1647,13 @@
|
|
|
1554
1647
|
form.changeHandlers.delete(path.key);
|
|
1555
1648
|
};
|
|
1556
1649
|
}, [form, path.key, onChange]);
|
|
1650
|
+
const depsKey = validateDeps?.length ? validateDeps.join("\n") : void 0;
|
|
1651
|
+
React.useEffect(() => {
|
|
1652
|
+
if (!depsKey) return;
|
|
1653
|
+
const depKeys = validateDeps.map((dep) => create$1(dep).key);
|
|
1654
|
+
registerFieldValidateDeps(form, path.key, depKeys);
|
|
1655
|
+
return () => unregisterFieldValidateDeps(form, path.key, depKeys);
|
|
1656
|
+
}, [form, path.key, depsKey]);
|
|
1557
1657
|
const onBlur = useStageFn(() => {
|
|
1558
1658
|
setTouchedByPath(form, path);
|
|
1559
1659
|
if (mode === "onBlur" || mode === "onTouched" || mode === "all" || liveErrors.length > 0 && form.reValidateMode === "onBlur")
|
|
@@ -1583,9 +1683,11 @@
|
|
|
1583
1683
|
return useFieldCore(options, FormContext);
|
|
1584
1684
|
}
|
|
1585
1685
|
|
|
1586
|
-
|
|
1587
|
-
function generateId() {
|
|
1588
|
-
|
|
1686
|
+
const idCounters = /* @__PURE__ */ new WeakMap();
|
|
1687
|
+
function generateId(form) {
|
|
1688
|
+
const next = (idCounters.get(form) ?? 0) + 1;
|
|
1689
|
+
idCounters.set(form, next);
|
|
1690
|
+
return `_${next}`;
|
|
1589
1691
|
}
|
|
1590
1692
|
const arrayIdsRegistry = /* @__PURE__ */ new WeakMap();
|
|
1591
1693
|
function getArrayIds(form, key) {
|
|
@@ -1621,13 +1723,13 @@
|
|
|
1621
1723
|
const computeFields = React.useCallback(() => {
|
|
1622
1724
|
const arr = getArray();
|
|
1623
1725
|
while (idsRef.current.length < arr.length) {
|
|
1624
|
-
idsRef.current.push(generateId());
|
|
1726
|
+
idsRef.current.push(generateId(form));
|
|
1625
1727
|
}
|
|
1626
1728
|
while (idsRef.current.length > arr.length) {
|
|
1627
1729
|
idsRef.current.pop();
|
|
1628
1730
|
}
|
|
1629
1731
|
return idsRef.current.map((id, index) => ({ id, index }));
|
|
1630
|
-
}, [getArray]);
|
|
1732
|
+
}, [getArray, form]);
|
|
1631
1733
|
const [fields, syncFields] = React.useReducer(
|
|
1632
1734
|
computeFields,
|
|
1633
1735
|
void 0,
|
|
@@ -1647,17 +1749,17 @@
|
|
|
1647
1749
|
}, [form, path.key]);
|
|
1648
1750
|
const append = useStageFn((value) => {
|
|
1649
1751
|
const arr = getArray();
|
|
1650
|
-
idsRef.current.push(generateId());
|
|
1752
|
+
idsRef.current.push(generateId(form));
|
|
1651
1753
|
setArray([...arr, value]);
|
|
1652
1754
|
});
|
|
1653
1755
|
const prepend = useStageFn((value) => {
|
|
1654
1756
|
const arr = getArray();
|
|
1655
|
-
idsRef.current.unshift(generateId());
|
|
1757
|
+
idsRef.current.unshift(generateId(form));
|
|
1656
1758
|
setArray([value, ...arr]);
|
|
1657
1759
|
});
|
|
1658
1760
|
const insert = useStageFn((index, value) => {
|
|
1659
1761
|
const arr = getArray();
|
|
1660
|
-
idsRef.current.splice(index, 0, generateId());
|
|
1762
|
+
idsRef.current.splice(index, 0, generateId(form));
|
|
1661
1763
|
const newArr = [...arr.slice(0, index), value, ...arr.slice(index)];
|
|
1662
1764
|
setArray(newArr);
|
|
1663
1765
|
});
|
|
@@ -1687,7 +1789,7 @@
|
|
|
1687
1789
|
setArray(newArr);
|
|
1688
1790
|
});
|
|
1689
1791
|
const replace = useStageFn((values) => {
|
|
1690
|
-
idsRef.current = values.map(() => generateId());
|
|
1792
|
+
idsRef.current = values.map(() => generateId(form));
|
|
1691
1793
|
setArray([...values]);
|
|
1692
1794
|
});
|
|
1693
1795
|
const update = useStageFn((index, value) => {
|
|
@@ -2074,6 +2176,7 @@
|
|
|
2074
2176
|
exports.clearErrors = clearErrors;
|
|
2075
2177
|
exports.createForm = create;
|
|
2076
2178
|
exports.createFormContext = createFormContext;
|
|
2179
|
+
exports.emitChangeByPath = emitChangeByPath;
|
|
2077
2180
|
exports.ensureValidate = ensureValidate;
|
|
2078
2181
|
exports.fieldErrorId = fieldErrorId;
|
|
2079
2182
|
exports.getDirtyFields = getDirtyFields;
|
|
@@ -2095,11 +2198,14 @@
|
|
|
2095
2198
|
exports.incrementSubmitCount = incrementSubmitCount;
|
|
2096
2199
|
exports.isDirty = isDirty;
|
|
2097
2200
|
exports.isTouched = isTouched;
|
|
2201
|
+
exports.registerFieldValidateDeps = registerFieldValidateDeps;
|
|
2098
2202
|
exports.removeField = removeField;
|
|
2099
2203
|
exports.removeFieldByPath = removeFieldByPath;
|
|
2100
2204
|
exports.reset = reset;
|
|
2101
2205
|
exports.resetField = resetField;
|
|
2206
|
+
exports.revalidateDependentsOnChange = revalidateDependentsOnChange;
|
|
2102
2207
|
exports.revalidateFormOnChange = revalidateFormOnChange;
|
|
2208
|
+
exports.seedValueByPath = seedValueByPath;
|
|
2103
2209
|
exports.setDisabled = setDisabled;
|
|
2104
2210
|
exports.setError = setError;
|
|
2105
2211
|
exports.setErrorByPath = setErrorByPath;
|
|
@@ -2115,6 +2221,7 @@
|
|
|
2115
2221
|
exports.setValueByPath = setValueByPath;
|
|
2116
2222
|
exports.subscribe = subscribe;
|
|
2117
2223
|
exports.trigger = trigger;
|
|
2224
|
+
exports.unregisterFieldValidateDeps = unregisterFieldValidateDeps;
|
|
2118
2225
|
exports.unsetValidatingByPath = unsetValidatingByPath;
|
|
2119
2226
|
exports.useCanSubmit = useCanSubmit;
|
|
2120
2227
|
exports.useCheckboxGroupContext = useCheckboxGroupContext;
|