react-f0rm 1.3.0 → 1.4.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 (98) hide show
  1. package/README.md +88 -1143
  2. package/devtools.d.ts +1 -0
  3. package/devtools.js +1 -0
  4. package/dist/array-3hAjl6Bz.d.ts +160 -0
  5. package/dist/devtools/index.cjs.js +1 -1
  6. package/dist/devtools/index.cjs.js.map +1 -1
  7. package/dist/devtools/index.d.cts +34 -0
  8. package/dist/devtools/index.d.mts +34 -0
  9. package/dist/devtools/index.d.ts +3 -2
  10. package/dist/devtools/index.mjs +1 -1
  11. package/dist/devtools/index.mjs.map +1 -1
  12. package/dist/errors-8oPux7GR.cjs.js +2 -0
  13. package/dist/errors-8oPux7GR.cjs.js.map +1 -0
  14. package/dist/errors-ClH3eV1R.mjs +2 -0
  15. package/dist/errors-ClH3eV1R.mjs.map +1 -0
  16. package/dist/index.cjs.js +1 -1
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.d.cts +1833 -0
  19. package/dist/index.d.mts +1833 -0
  20. package/dist/index.d.ts +372 -117
  21. package/dist/index.mjs +1 -1
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/index.umd.js +859 -225
  24. package/dist/index.umd.js.map +1 -1
  25. package/dist/index.umd.min.js +2 -2
  26. package/dist/index.umd.min.js.map +1 -1
  27. package/dist/persist.cjs.js +1 -1
  28. package/dist/persist.cjs.js.map +1 -1
  29. package/dist/persist.d.cts +49 -0
  30. package/dist/persist.d.mts +49 -0
  31. package/dist/persist.mjs +1 -1
  32. package/dist/persist.mjs.map +1 -1
  33. package/dist/resolvers/standard-schema.cjs.js +1 -1
  34. package/dist/resolvers/standard-schema.cjs.js.map +1 -1
  35. package/dist/resolvers/standard-schema.d.cts +2 -0
  36. package/dist/resolvers/standard-schema.d.mts +2 -0
  37. package/dist/resolvers/standard-schema.d.ts +1 -67
  38. package/dist/resolvers/standard-schema.mjs +1 -1
  39. package/dist/resolvers/standard-schema.mjs.map +1 -1
  40. package/dist/resolvers/yup.cjs.js +1 -1
  41. package/dist/resolvers/yup.cjs.js.map +1 -1
  42. package/dist/resolvers/yup.d.cts +6 -0
  43. package/dist/resolvers/yup.d.mts +6 -0
  44. package/dist/resolvers/yup.d.ts +0 -1
  45. package/dist/resolvers/yup.mjs +1 -1
  46. package/dist/resolvers/yup.mjs.map +1 -1
  47. package/dist/resolvers/zod.cjs.js +1 -1
  48. package/dist/resolvers/zod.cjs.js.map +1 -1
  49. package/dist/resolvers/zod.d.cts +6 -0
  50. package/dist/resolvers/zod.d.mts +6 -0
  51. package/dist/resolvers/zod.d.ts +0 -1
  52. package/dist/resolvers/zod.mjs +1 -1
  53. package/dist/resolvers/zod.mjs.map +1 -1
  54. package/dist/server/index.cjs.js +1 -1
  55. package/dist/server/index.cjs.js.map +1 -1
  56. package/dist/server/index.d.cts +106 -0
  57. package/dist/server/index.d.mts +106 -0
  58. package/dist/server/index.d.ts +31 -2
  59. package/dist/server/index.mjs +1 -1
  60. package/dist/server/index.mjs.map +1 -1
  61. package/dist/standard-schema-CYbnugL7.d.ts +1184 -0
  62. package/dist/standardSchema-BpZvg0tZ.mjs +2 -0
  63. package/dist/standardSchema-BpZvg0tZ.mjs.map +1 -0
  64. package/dist/standardSchema-CxV_DhBO.cjs.js +2 -0
  65. package/dist/standardSchema-CxV_DhBO.cjs.js.map +1 -0
  66. package/dist/validate-BEjNsNvd.mjs +2 -0
  67. package/dist/validate-BEjNsNvd.mjs.map +1 -0
  68. package/dist/validate-BvN6hiEG.cjs.js +2 -0
  69. package/dist/validate-BvN6hiEG.cjs.js.map +1 -0
  70. package/dist/values-Bod74Kzu.mjs +2 -0
  71. package/dist/values-Bod74Kzu.mjs.map +1 -0
  72. package/dist/values-DKpOCD5J.cjs.js +2 -0
  73. package/dist/values-DKpOCD5J.cjs.js.map +1 -0
  74. package/package.json +72 -27
  75. package/persist.d.ts +1 -0
  76. package/persist.js +1 -0
  77. package/resolvers/standard-schema.d.ts +1 -0
  78. package/resolvers/standard-schema.js +1 -0
  79. package/resolvers/yup.d.ts +1 -0
  80. package/resolvers/yup.js +1 -0
  81. package/resolvers/zod.d.ts +1 -0
  82. package/resolvers/zod.js +1 -0
  83. package/server.d.ts +1 -0
  84. package/server.js +1 -0
  85. package/dist/errors-BKrUdpfI.cjs.js +0 -2
  86. package/dist/errors-BKrUdpfI.cjs.js.map +0 -1
  87. package/dist/errors-CrQBddrJ.mjs +0 -2
  88. package/dist/errors-CrQBddrJ.mjs.map +0 -1
  89. package/dist/form-CeKSBs31.d.ts +0 -486
  90. package/dist/validate-CNtuUhmk.mjs +0 -2
  91. package/dist/validate-CNtuUhmk.mjs.map +0 -1
  92. package/dist/validate-Cl4ksNFu.cjs.js +0 -2
  93. package/dist/validate-Cl4ksNFu.cjs.js.map +0 -1
  94. package/dist/validate-nksgv1pR.d.ts +0 -272
  95. package/dist/values-Cu6awQOJ.cjs.js +0 -2
  96. package/dist/values-Cu6awQOJ.cjs.js.map +0 -1
  97. package/dist/values-DRY-a32G.mjs +0 -2
  98. package/dist/values-DRY-a32G.mjs.map +0 -1
package/dist/index.umd.js CHANGED
@@ -309,6 +309,15 @@
309
309
  function isPromise(value) {
310
310
  return value && typeof value.then === "function";
311
311
  }
312
+ function extractEventValue(e, options) {
313
+ const target = e?.target;
314
+ if (!target) return e;
315
+ if (target.type === "file") return target.files;
316
+ if (target.type === "checkbox") return target.checked;
317
+ if (options?.valueAsNumber) return target.valueAsNumber;
318
+ if (options?.valueAsDate) return target.valueAsDate;
319
+ return target.value;
320
+ }
312
321
  function isEqual(a, b) {
313
322
  if (Object.is(a, b)) return true;
314
323
  if (a instanceof Date && b instanceof Date)
@@ -361,6 +370,11 @@
361
370
  const cache = valuesCaches.get(form);
362
371
  if (cache) cache.version++;
363
372
  }
373
+ const errorsCaches = /* @__PURE__ */ new WeakMap();
374
+ function bumpErrorsVersion(form) {
375
+ const cache = errorsCaches.get(form);
376
+ if (cache) cache.version++;
377
+ }
364
378
  const dirtyBaselines = /* @__PURE__ */ new WeakMap();
365
379
  function getDirtyBaseline(form, key, segments) {
366
380
  const baselines = dirtyBaselines.get(form);
@@ -430,6 +444,50 @@
430
444
  }
431
445
  return entries;
432
446
  }
447
+ function computeErrorsViews(form) {
448
+ const cached = errorsCaches.get(form);
449
+ if (cached && cached.version === 0) return;
450
+ const result = {};
451
+ const tree = {};
452
+ for (const [key, list] of form.errors) {
453
+ const segments = JSON.parse(key);
454
+ result[segments.join(".")] = list;
455
+ let node = tree;
456
+ for (let i = 0; i < segments.length - 1; i++) {
457
+ const segment = segments[i];
458
+ const slot = node[segment];
459
+ const container = slot && !(Array.isArray(slot) && slot.length > 0 && isFieldError(slot[0])) ? slot : typeof segments[i + 1] === "number" ? [] : {};
460
+ node[segment] = container;
461
+ node = container;
462
+ }
463
+ node[segments[segments.length - 1]] = list;
464
+ }
465
+ if (cached) {
466
+ cached.result = result;
467
+ cached.tree = tree;
468
+ cached.version = 0;
469
+ } else {
470
+ errorsCaches.set(form, { version: 0, result, tree });
471
+ }
472
+ }
473
+ function getErrorsRecord(form) {
474
+ computeErrorsViews(form);
475
+ return errorsCaches.get(form).result;
476
+ }
477
+ function getErrorsTree(form) {
478
+ computeErrorsViews(form);
479
+ return errorsCaches.get(form).tree;
480
+ }
481
+ function fieldPathToDottedKey(name) {
482
+ return create$1(name).value.join(".");
483
+ }
484
+ function dottedKeyToFieldPath(key) {
485
+ const segments = key.split(".");
486
+ const numeric = (segment) => /^(0|[1-9]\d*)$/.test(segment);
487
+ return segments.map(
488
+ (segment, i) => i > 0 && numeric(segment) ? `[${segment}]` : `${i > 0 ? "." : ""}${segment}`
489
+ ).join("");
490
+ }
433
491
  function getFirstError({ errors }) {
434
492
  return errors.values().next().value?.[0]?.message;
435
493
  }
@@ -441,6 +499,7 @@
441
499
  const list = normalizeErrors(error);
442
500
  if (list) errors.set(path.key, list);
443
501
  else errors.delete(path.key);
502
+ bumpErrorsVersion(form);
444
503
  emit(emitter, "errors", path);
445
504
  if (options?.shouldFocus) emit(emitter, "focusError", path.key);
446
505
  }
@@ -464,11 +523,13 @@
464
523
  const { emitter, errors } = form;
465
524
  if (name === void 0) {
466
525
  errors.clear();
526
+ bumpErrorsVersion(form);
467
527
  emit(emitter, "errors");
468
528
  return;
469
529
  }
470
530
  const paths = typeof name === "string" || isSegmentsPath(name) ? [create$1(name)] : name.map((one) => create$1(one));
471
531
  for (const { key } of paths) errors.delete(key);
532
+ bumpErrorsVersion(form);
472
533
  for (const path of paths) emit(emitter, "errors", path);
473
534
  }
474
535
  function setServerErrors(form, errors, options) {
@@ -484,10 +545,109 @@
484
545
  );
485
546
  }
486
547
  }
548
+ function clearServerErrors(form) {
549
+ let changed = false;
550
+ for (const [key, errors] of form.errors) {
551
+ const kept = errors.filter((error) => error.type !== "server");
552
+ if (kept.length === 0) {
553
+ form.errors.delete(key);
554
+ changed = true;
555
+ } else if (kept.length !== errors.length) {
556
+ form.errors.set(key, kept);
557
+ changed = true;
558
+ }
559
+ }
560
+ if (changed) {
561
+ bumpErrorsVersion(form);
562
+ emit(form.emitter, "errors");
563
+ }
564
+ }
487
565
  function hasErrors({ errors }) {
488
566
  return errors.size > 0;
489
567
  }
490
568
 
569
+ function hasStandardProps(schema) {
570
+ return !!schema && typeof schema === "object" && typeof schema["~standard"]?.validate === "function";
571
+ }
572
+ function toFieldError(issue) {
573
+ return { type: "standard", message: issue?.message || "Validation failed" };
574
+ }
575
+ function schemaToFieldValidator(schema) {
576
+ return async (value) => {
577
+ const result = await schema["~standard"].validate(value);
578
+ if (!result.issues?.length) return void 0;
579
+ return result.issues.map(toFieldError);
580
+ };
581
+ }
582
+ function schemaToFormValidator(schema) {
583
+ return async (values) => {
584
+ const result = await schema["~standard"].validate(values);
585
+ const { issues } = result;
586
+ if (!issues?.length) {
587
+ return {
588
+ [VALIDATION_OUTCOME]: true,
589
+ values: "value" in result ? result.value : void 0
590
+ };
591
+ }
592
+ const errors = {};
593
+ for (const issue of issues) {
594
+ const segments = toPathSegments(issue);
595
+ if (segments.length) {
596
+ assignAtPath(errors, segments, toFieldError(issue));
597
+ } else {
598
+ const slot = errors[FORM_ERROR] ??= [];
599
+ if (Array.isArray(slot)) slot.push(toFieldError(issue));
600
+ }
601
+ }
602
+ return { [VALIDATION_OUTCOME]: true, errors: pruneEmpty(errors) || {} };
603
+ };
604
+ }
605
+ function toPathSegments(issue) {
606
+ const path = issue.path || [];
607
+ const segments = [];
608
+ for (const segment of path) {
609
+ const key = typeof segment === "object" && segment !== null ? segment.key : segment;
610
+ segments.push(String(key));
611
+ }
612
+ return segments;
613
+ }
614
+ function assignAtPath(root, segments, error) {
615
+ let node = root;
616
+ for (let i = 0; i < segments.length - 1; i++) {
617
+ const segment = segments[i];
618
+ let next = node[segment];
619
+ if (next === void 0) {
620
+ next = node[segment] = {};
621
+ }
622
+ if (!isBranch(next)) return;
623
+ node = next;
624
+ }
625
+ const leaf = segments[segments.length - 1];
626
+ const slot = node[leaf];
627
+ if (slot === void 0) node[leaf] = [error];
628
+ else if (Array.isArray(slot)) slot.push(error);
629
+ }
630
+ function isBranch(value) {
631
+ return !!value && typeof value === "object" && !Array.isArray(value);
632
+ }
633
+ function pruneEmpty(node) {
634
+ let hasLeaf = false;
635
+ const result = {};
636
+ Object.entries(node).forEach(([key, value]) => {
637
+ if (isBranch(value)) {
638
+ const pruned = pruneEmpty(value);
639
+ if (pruned) {
640
+ result[key] = pruned;
641
+ hasLeaf = true;
642
+ }
643
+ } else {
644
+ result[key] = value;
645
+ hasLeaf = true;
646
+ }
647
+ });
648
+ return hasLeaf ? result : void 0;
649
+ }
650
+
491
651
  function isFieldDirtyByPath(form, path) {
492
652
  const live = form.values.get(path.key);
493
653
  return form.values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live;
@@ -647,7 +807,7 @@
647
807
  if (!hasLiveBranch(values, segments)) deleted.add(key);
648
808
  }
649
809
  if (!options?.keepTouched) touched.delete(key);
650
- if (!options?.keepError) errors.delete(key);
810
+ if (!options?.keepError && errors.delete(key)) bumpErrorsVersion(form);
651
811
  validating.delete(key);
652
812
  bumpDirtyVersion(form);
653
813
  bumpValuesVersion(form);
@@ -769,6 +929,7 @@
769
929
  emit(emitter, "touched", path);
770
930
  }
771
931
  if (!options?.keepErrors && errors.delete(path.key)) {
932
+ bumpErrorsVersion(form);
772
933
  emit(emitter, "errors", path);
773
934
  }
774
935
  bumpDirtyVersion(form);
@@ -978,7 +1139,7 @@
978
1139
  if (stored) footprint.set(path.key, stored);
979
1140
  }
980
1141
  function applyValidateResult(form, result) {
981
- const footprint = form.validateDeps ? getFormErrorFootprint(form) : void 0;
1142
+ const footprint = form.validateDeps || form.validateMode !== "onSubmit" ? getFormErrorFootprint(form) : void 0;
982
1143
  if (footprint) {
983
1144
  clearFormValidateErrors(form, footprint);
984
1145
  footprint.clear();
@@ -1014,6 +1175,7 @@
1014
1175
  const stored = form.errors.get(key);
1015
1176
  if (stored !== written) continue;
1016
1177
  form.errors.delete(key);
1178
+ bumpErrorsVersion(form);
1017
1179
  emit(form.emitter, "errors", create$1(JSON.parse(key)));
1018
1180
  }
1019
1181
  }
@@ -1207,6 +1369,10 @@
1207
1369
  if (mode === "onChange" || mode === "all" || mode === "onTouched" && hasTouchedByPath(form, path) || getFieldErrorsByPath(form, path).length > 0 && form.reValidateMode === "onChange")
1208
1370
  form.validators.get(path.key)?.();
1209
1371
  revalidateFormOnChange(form, path, mode);
1372
+ if (form.validateMode === "onChange" && form.validate) {
1373
+ runFormValidate(form).catch(() => {
1374
+ });
1375
+ }
1210
1376
  revalidateDependentsOnChange(form, path, mode);
1211
1377
  }
1212
1378
  function userChangeByPath(form, path, value) {
@@ -1221,6 +1387,327 @@
1221
1387
  const mode = entry.mode ?? form.mode;
1222
1388
  if (mode === "onBlur" || mode === "onTouched" || mode === "all" || getFieldErrorsByPath(form, path).length > 0 && form.reValidateMode === "onBlur")
1223
1389
  form.validators.get(path.key)?.();
1390
+ if (form.validateMode === "onBlur" && form.validate) {
1391
+ runFormValidate(form).catch(() => {
1392
+ });
1393
+ }
1394
+ }
1395
+
1396
+ function removeFieldForUnmount(form, path) {
1397
+ const { key } = path;
1398
+ const snapshot = {
1399
+ present: form.values.has(key),
1400
+ value: form.values.get(key),
1401
+ touched: form.touched.has(key),
1402
+ errors: form.errors.get(key)
1403
+ };
1404
+ removeFieldByPath(form, path);
1405
+ return snapshot;
1406
+ }
1407
+ function restoreRemovedField(form, path, snapshot) {
1408
+ const { key } = path;
1409
+ if (snapshot.present) {
1410
+ setValueByPath(form, path, snapshot.value, { shouldDirty: false });
1411
+ } else {
1412
+ form.deleted.delete(key);
1413
+ bumpValuesVersion(form);
1414
+ emit(form.emitter, "change", path);
1415
+ }
1416
+ if (snapshot.touched) setTouchedByPath(form, path);
1417
+ if (snapshot.errors) setErrorByPath(form, path, snapshot.errors);
1418
+ }
1419
+
1420
+ function hasRuleConstraints(rules) {
1421
+ return rules.required !== void 0 || rules.min !== void 0 || rules.max !== void 0 || rules.minLength !== void 0 || rules.maxLength !== void 0 || rules.pattern !== void 0 || rules.validate !== void 0;
1422
+ }
1423
+ function defaultMessage(type, bound) {
1424
+ switch (type) {
1425
+ case "required":
1426
+ return "This field is required";
1427
+ case "min":
1428
+ return `Must be at least ${bound}`;
1429
+ case "max":
1430
+ return `Must be at most ${bound}`;
1431
+ case "minLength":
1432
+ return `Must be at least ${bound} characters`;
1433
+ case "maxLength":
1434
+ return `Must be at most ${bound} characters`;
1435
+ case "pattern":
1436
+ return "Invalid format";
1437
+ default:
1438
+ return "Invalid value";
1439
+ }
1440
+ }
1441
+ function rulesToValidator(rules) {
1442
+ return (value, meta) => {
1443
+ if (rules.required) {
1444
+ if (value === "" || value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
1445
+ return [
1446
+ {
1447
+ type: "required",
1448
+ message: typeof rules.required === "string" ? rules.required : defaultMessage("required")
1449
+ }
1450
+ ];
1451
+ }
1452
+ }
1453
+ const errors = [];
1454
+ const message = (type, bound) => rules.messages?.[type] ?? defaultMessage(type, bound);
1455
+ if (rules.min !== void 0) {
1456
+ const n = Number(value);
1457
+ if (!Number.isNaN(n) && n < rules.min) {
1458
+ errors.push({ type: "min", message: message("min", rules.min) });
1459
+ }
1460
+ }
1461
+ if (rules.max !== void 0) {
1462
+ const n = Number(value);
1463
+ if (!Number.isNaN(n) && n > rules.max) {
1464
+ errors.push({ type: "max", message: message("max", rules.max) });
1465
+ }
1466
+ }
1467
+ const isSized = typeof value === "string" || Array.isArray(value);
1468
+ if (rules.minLength !== void 0 && isSized && value.length < rules.minLength) {
1469
+ errors.push({
1470
+ type: "minLength",
1471
+ message: message("minLength", rules.minLength)
1472
+ });
1473
+ }
1474
+ if (rules.maxLength !== void 0 && isSized && value.length > rules.maxLength) {
1475
+ errors.push({
1476
+ type: "maxLength",
1477
+ message: message("maxLength", rules.maxLength)
1478
+ });
1479
+ }
1480
+ if (rules.pattern && !rules.pattern.value.test(value)) {
1481
+ errors.push({
1482
+ type: "pattern",
1483
+ // pattern.message is type-required but JS consumers may omit it.
1484
+ message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
1485
+ });
1486
+ }
1487
+ if (rules.validate !== void 0) {
1488
+ const fns = typeof rules.validate === "function" ? { validate: rules.validate } : rules.validate;
1489
+ for (const [type, fn] of Object.entries(fns)) {
1490
+ const result = fn(value, meta);
1491
+ if (result === void 0) continue;
1492
+ for (const entry of Array.isArray(result) ? result : [result]) {
1493
+ errors.push(
1494
+ typeof entry === "string" ? { type, message: entry } : { ...entry, type }
1495
+ );
1496
+ }
1497
+ }
1498
+ }
1499
+ return errors.length ? errors : void 0;
1500
+ };
1501
+ }
1502
+ function rulesToConstraintAttrs(rules) {
1503
+ const attrs = {};
1504
+ if (rules.required) attrs.required = true;
1505
+ if (rules.min !== void 0) attrs.min = rules.min;
1506
+ if (rules.max !== void 0) attrs.max = rules.max;
1507
+ if (rules.minLength !== void 0) attrs.minLength = rules.minLength;
1508
+ if (rules.maxLength !== void 0) attrs.maxLength = rules.maxLength;
1509
+ if (rules.pattern) attrs.pattern = rules.pattern.value.source;
1510
+ return attrs;
1511
+ }
1512
+
1513
+ function registerField(form, name, options) {
1514
+ const path = create$1(name);
1515
+ const {
1516
+ mode,
1517
+ shouldUnregister,
1518
+ eventToValue,
1519
+ valueAsNumber,
1520
+ valueAsDate,
1521
+ rules
1522
+ } = options ?? {};
1523
+ const toValue = eventToValue ?? ((e) => {
1524
+ const target = e?.target;
1525
+ if (!target) return e;
1526
+ if (target.type === "file") return target.files;
1527
+ if (target.type === "checkbox") return target.checked;
1528
+ if (valueAsNumber) return target.valueAsNumber;
1529
+ if (valueAsDate) return target.valueAsDate;
1530
+ return target.value;
1531
+ });
1532
+ let el = null;
1533
+ let modeToken = null;
1534
+ let disposeValidator = null;
1535
+ let snapshot = null;
1536
+ let offFocus = null;
1537
+ let offBulkSync = null;
1538
+ const syncDom = () => {
1539
+ if (!el || el.type === "file") return;
1540
+ const next = getValueByPath(form, path);
1541
+ const asString = next == null ? "" : String(next);
1542
+ if (el.value !== asString) el.value = asString;
1543
+ };
1544
+ const attach = (node) => {
1545
+ if (snapshot) {
1546
+ restoreRemovedField(form, path, snapshot);
1547
+ snapshot = null;
1548
+ }
1549
+ el = node;
1550
+ if (node.type !== "file" && getValueByPath(form, path) === void 0) {
1551
+ seedValueByPath(
1552
+ form,
1553
+ path,
1554
+ node.type === "checkbox" ? node.checked : node.value
1555
+ );
1556
+ emitChangeByPath(form, path);
1557
+ }
1558
+ modeToken = registerFieldMode(form, path, mode).token;
1559
+ if (rules && hasRuleConstraints(rules)) {
1560
+ const sync = rules.required !== void 0 ? rulesToValidator({ required: rules.required }) : void 0;
1561
+ const rest = rules.required !== void 0 ? { ...rules, required: void 0 } : rules;
1562
+ disposeValidator = registerValidatorByPath(form, path, {
1563
+ validate: () => hasRuleConstraints(rest) ? rulesToValidator(rest) : void 0,
1564
+ debounce: () => 0,
1565
+ sync: () => sync
1566
+ });
1567
+ }
1568
+ offFocus = on(
1569
+ form.emitter,
1570
+ "focusError",
1571
+ (key, options2) => {
1572
+ if (key !== path.key || !el || typeof el.focus !== "function") return;
1573
+ el.focus();
1574
+ if (options2?.shouldSelect && typeof el.select === "function") {
1575
+ el.select();
1576
+ }
1577
+ }
1578
+ );
1579
+ offBulkSync = on(form.emitter, "change", (changed) => {
1580
+ if (changed) return;
1581
+ syncDom();
1582
+ });
1583
+ };
1584
+ const detach = () => {
1585
+ if (modeToken) {
1586
+ unregisterFieldMode(form, path, modeToken);
1587
+ modeToken = null;
1588
+ }
1589
+ if (disposeValidator) {
1590
+ disposeValidator();
1591
+ disposeValidator = null;
1592
+ }
1593
+ if (offFocus) {
1594
+ offFocus();
1595
+ offFocus = null;
1596
+ }
1597
+ if (offBulkSync) {
1598
+ offBulkSync();
1599
+ offBulkSync = null;
1600
+ }
1601
+ el = null;
1602
+ if ((shouldUnregister ?? form.shouldUnregister) !== false) {
1603
+ snapshot = removeFieldForUnmount(form, path);
1604
+ }
1605
+ };
1606
+ return {
1607
+ name: path.key,
1608
+ onChange: (e) => changeValueByPath(form, path, toValue(e)),
1609
+ onBlur: () => userBlur(form, path),
1610
+ ref: (node) => {
1611
+ if (node) attach(node);
1612
+ else detach();
1613
+ }
1614
+ };
1615
+ }
1616
+
1617
+ function readArray(form, path) {
1618
+ const value = getValueByPath(form, path);
1619
+ return Array.isArray(value) ? value : [];
1620
+ }
1621
+ function appendValueByPath(form, path, value) {
1622
+ const arr = readArray(form, path);
1623
+ setValueByPath(form, path, [...arr, value]);
1624
+ }
1625
+ function prependValueByPath(form, path, value) {
1626
+ const arr = readArray(form, path);
1627
+ setValueByPath(form, path, [value, ...arr]);
1628
+ }
1629
+ function insertValueByPath(form, path, index, value) {
1630
+ const arr = readArray(form, path);
1631
+ if (index < 0 || index > arr.length) return false;
1632
+ setValueByPath(form, path, [
1633
+ ...arr.slice(0, index),
1634
+ value,
1635
+ ...arr.slice(index)
1636
+ ]);
1637
+ return true;
1638
+ }
1639
+ function removeValueByPath(form, path, indices) {
1640
+ const arr = readArray(form, path);
1641
+ const drop = /* @__PURE__ */ new Set();
1642
+ for (const index of Array.isArray(indices) ? indices : [indices]) {
1643
+ if (index >= 0 && index < arr.length) drop.add(index);
1644
+ }
1645
+ if (drop.size === 0) return [];
1646
+ const dropped = [...drop].sort((a, b) => b - a);
1647
+ setValueByPath(
1648
+ form,
1649
+ path,
1650
+ arr.filter((_, i) => !drop.has(i))
1651
+ );
1652
+ return dropped;
1653
+ }
1654
+ function moveValueByPath(form, path, from, to) {
1655
+ const arr = readArray(form, path);
1656
+ if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
1657
+ return false;
1658
+ }
1659
+ if (from === to) return false;
1660
+ const next = [...arr];
1661
+ const [item] = next.splice(from, 1);
1662
+ next.splice(to, 0, item);
1663
+ setValueByPath(form, path, next);
1664
+ return true;
1665
+ }
1666
+ function swapValuesByPath(form, path, from, to) {
1667
+ const arr = readArray(form, path);
1668
+ if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
1669
+ return false;
1670
+ }
1671
+ if (from === to) return false;
1672
+ const next = [...arr];
1673
+ [next[from], next[to]] = [next[to], next[from]];
1674
+ setValueByPath(form, path, next);
1675
+ return true;
1676
+ }
1677
+ function replaceValuesByPath(form, path, values) {
1678
+ setValueByPath(form, path, [...values]);
1679
+ }
1680
+ function updateValueByPath(form, path, index, value) {
1681
+ const arr = readArray(form, path);
1682
+ if (index < 0 || index >= arr.length) return false;
1683
+ const next = [...arr];
1684
+ next[index] = value;
1685
+ setValueByPath(form, path, next);
1686
+ return true;
1687
+ }
1688
+ function appendValue(form, name, value) {
1689
+ appendValueByPath(form, create$1(name), value);
1690
+ }
1691
+ function prependValue(form, name, value) {
1692
+ prependValueByPath(form, create$1(name), value);
1693
+ }
1694
+ function insertValue(form, name, index, value) {
1695
+ return insertValueByPath(form, create$1(name), index, value);
1696
+ }
1697
+ function removeValue(form, name, indices) {
1698
+ return removeValueByPath(form, create$1(name), indices);
1699
+ }
1700
+ function moveValue(form, name, from, to) {
1701
+ return moveValueByPath(form, create$1(name), from, to);
1702
+ }
1703
+ function swapValues(form, name, from, to) {
1704
+ return swapValuesByPath(form, create$1(name), from, to);
1705
+ }
1706
+ function replaceValues(form, name, values) {
1707
+ replaceValuesByPath(form, create$1(name), values);
1708
+ }
1709
+ function updateValue(form, name, index, value) {
1710
+ return updateValueByPath(form, create$1(name), index, value);
1224
1711
  }
1225
1712
 
1226
1713
  function setIsSubmitting(form, value) {
@@ -1274,18 +1761,20 @@
1274
1761
  onValidSubmit,
1275
1762
  onInvalidSubmit,
1276
1763
  onAction,
1277
- shouldFocusError = true
1764
+ shouldFocusError = true,
1765
+ shouldUseNativeValidation = form.shouldUseNativeValidation
1278
1766
  } = options ?? {};
1279
1767
  return async (e) => {
1280
1768
  if (e && typeof e.preventDefault === "function") {
1281
1769
  e.preventDefault();
1282
1770
  }
1283
1771
  const formEl = e?.currentTarget;
1772
+ clearServerErrors(form);
1284
1773
  form.isSubmitted = true;
1285
1774
  setIsSubmitting(form, true);
1286
1775
  incrementSubmitCount(form);
1287
1776
  const values = getValues(form);
1288
- if (formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
1777
+ if (shouldUseNativeValidation && formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
1289
1778
  formEl.reportValidity();
1290
1779
  if (shouldFocusError && typeof formEl.querySelector === "function") {
1291
1780
  const invalid = formEl.querySelector(":invalid");
@@ -1311,7 +1800,14 @@
1311
1800
  const submitted = getValues(form);
1312
1801
  if (onSubmit) await onSubmit(submitted, e);
1313
1802
  if (onValidSubmit) await onValidSubmit(submitted, e);
1314
- if (onAction) await onAction(submitted, e);
1803
+ if (onAction) {
1804
+ const result = await onAction(submitted, e);
1805
+ if (result && typeof result === "object" && result.errors !== void 0 && typeof result.errors === "object") {
1806
+ setServerErrors(form, result.errors);
1807
+ setSubmitSuccessful(form, false);
1808
+ return;
1809
+ }
1810
+ }
1315
1811
  setSubmitSuccessful(form, true);
1316
1812
  } catch {
1317
1813
  setSubmitSuccessful(form, false);
@@ -1332,14 +1828,21 @@
1332
1828
  _setMaxListeners(emitter, 0);
1333
1829
  let source = options?.initialValues ?? {};
1334
1830
  if (typeof source === "function") source = source();
1831
+ const validateOption = options?.validate;
1832
+ const wrappedValidate = validateOption && hasStandardProps(validateOption) ? schemaToFormValidator(
1833
+ validateOption
1834
+ ) : validateOption;
1335
1835
  const form = {
1336
1836
  emitter,
1337
1837
  ...options,
1838
+ validate: wrappedValidate,
1338
1839
  mode: options?.mode ?? "onSubmit",
1339
1840
  reValidateMode: options?.reValidateMode ?? "onChange",
1841
+ validateMode: options?.validateMode ?? "onSubmit",
1340
1842
  disabled: options?.disabled ?? false,
1341
1843
  validateOnMount: options?.validateOnMount ?? false,
1342
1844
  asyncAlways: options?.asyncAlways ?? false,
1845
+ shouldUseNativeValidation: options?.shouldUseNativeValidation ?? true,
1343
1846
  validateDeps: options?.validateDeps ? new Set(options.validateDeps.map((dep) => create$1(dep).key)) : void 0,
1344
1847
  initialValues: {},
1345
1848
  values: /* @__PURE__ */ new Map(),
@@ -1354,7 +1857,8 @@
1354
1857
  submitCount: 0,
1355
1858
  isSubmitSuccessful: void 0,
1356
1859
  isLoading: false,
1357
- status: void 0
1860
+ status: void 0,
1861
+ register: (name, registerOptions) => registerField(form, name, registerOptions)
1358
1862
  };
1359
1863
  if (isPromise(source)) {
1360
1864
  form.isLoading = true;
@@ -1376,94 +1880,44 @@
1376
1880
  return form;
1377
1881
  }
1378
1882
 
1379
- function defaultMessage(type, bound) {
1380
- switch (type) {
1381
- case "required":
1382
- return "This field is required";
1383
- case "min":
1384
- return `Must be at least ${bound}`;
1385
- case "max":
1386
- return `Must be at most ${bound}`;
1387
- case "minLength":
1388
- return `Must be at least ${bound} characters`;
1389
- case "maxLength":
1390
- return `Must be at most ${bound} characters`;
1391
- case "pattern":
1392
- return "Invalid format";
1393
- default:
1394
- return "Invalid value";
1395
- }
1883
+ function errorIdFromKey(key) {
1884
+ const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
1885
+ return id || "field";
1396
1886
  }
1397
- function rulesToValidator(rules) {
1398
- return (value, meta) => {
1399
- if (rules.required) {
1400
- if (value === "" || value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
1401
- return [
1402
- {
1403
- type: "required",
1404
- message: typeof rules.required === "string" ? rules.required : defaultMessage("required")
1405
- }
1406
- ];
1407
- }
1408
- }
1409
- const errors = [];
1410
- const message = (type, bound) => rules.messages?.[type] ?? defaultMessage(type, bound);
1411
- if (rules.min !== void 0) {
1412
- const n = Number(value);
1413
- if (!Number.isNaN(n) && n < rules.min) {
1414
- errors.push({ type: "min", message: message("min", rules.min) });
1415
- }
1416
- }
1417
- if (rules.max !== void 0) {
1418
- const n = Number(value);
1419
- if (!Number.isNaN(n) && n > rules.max) {
1420
- errors.push({ type: "max", message: message("max", rules.max) });
1421
- }
1422
- }
1423
- const isSized = typeof value === "string" || Array.isArray(value);
1424
- if (rules.minLength !== void 0 && isSized && value.length < rules.minLength) {
1425
- errors.push({
1426
- type: "minLength",
1427
- message: message("minLength", rules.minLength)
1428
- });
1429
- }
1430
- if (rules.maxLength !== void 0 && isSized && value.length > rules.maxLength) {
1431
- errors.push({
1432
- type: "maxLength",
1433
- message: message("maxLength", rules.maxLength)
1434
- });
1435
- }
1436
- if (rules.pattern && !rules.pattern.value.test(value)) {
1437
- errors.push({
1438
- type: "pattern",
1439
- // pattern.message is type-required but JS consumers may omit it.
1440
- message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
1441
- });
1442
- }
1443
- if (rules.validate !== void 0) {
1444
- const fns = typeof rules.validate === "function" ? { validate: rules.validate } : rules.validate;
1445
- for (const [type, fn] of Object.entries(fns)) {
1446
- const result = fn(value, meta);
1447
- if (result === void 0) continue;
1448
- for (const entry of Array.isArray(result) ? result : [result]) {
1449
- errors.push(
1450
- typeof entry === "string" ? { type, message: entry } : { ...entry, type }
1451
- );
1452
- }
1453
- }
1454
- }
1455
- return errors.length ? errors : void 0;
1456
- };
1887
+ function fieldErrorId(name) {
1888
+ return errorIdFromKey(create$1(name).key);
1457
1889
  }
1458
- function rulesToConstraintAttrs(rules) {
1459
- const attrs = {};
1460
- if (rules.required) attrs.required = true;
1461
- if (rules.min !== void 0) attrs.min = rules.min;
1462
- if (rules.max !== void 0) attrs.max = rules.max;
1463
- if (rules.minLength !== void 0) attrs.minLength = rules.minLength;
1464
- if (rules.maxLength !== void 0) attrs.maxLength = rules.maxLength;
1465
- if (rules.pattern) attrs.pattern = rules.pattern.value.source;
1466
- return attrs;
1890
+
1891
+ const fieldDisabledRegistry = /* @__PURE__ */ new WeakMap();
1892
+ function registerFieldDisabled(form, path, disabled) {
1893
+ if (disabled === void 0) return null;
1894
+ let registry = fieldDisabledRegistry.get(form);
1895
+ if (!registry) {
1896
+ registry = /* @__PURE__ */ new Map();
1897
+ fieldDisabledRegistry.set(form, registry);
1898
+ }
1899
+ const token = {};
1900
+ registry.set(path.key, { disabled, token });
1901
+ emit(form.emitter, "disabled", path);
1902
+ return { token };
1903
+ }
1904
+ function unregisterFieldDisabled(form, path, token) {
1905
+ const registry = fieldDisabledRegistry.get(form);
1906
+ const entry = registry?.get(path.key);
1907
+ if (registry && entry && entry.token === token) {
1908
+ registry.delete(path.key);
1909
+ emit(form.emitter, "disabled", path);
1910
+ }
1911
+ }
1912
+ function hasDisabledAncestor(form, path) {
1913
+ const registry = fieldDisabledRegistry.get(form);
1914
+ if (!registry?.size) return false;
1915
+ const segments = path.value;
1916
+ for (let i = 1; i < segments.length; i++) {
1917
+ const prefix = JSON.stringify(segments.slice(0, i));
1918
+ if (registry.get(prefix)?.disabled) return true;
1919
+ }
1920
+ return false;
1467
1921
  }
1468
1922
 
1469
1923
  function isDescendant(key, ancestorKey) {
@@ -1495,6 +1949,41 @@
1495
1949
  });
1496
1950
  return unsubscribes.length === 1 ? unsubscribes[0] : () => unsubscribes.forEach((unsubscribe) => unsubscribe());
1497
1951
  }
1952
+ function watch(form, event, getter, isEqual) {
1953
+ const cache = { hasValue: false };
1954
+ const consumers = /* @__PURE__ */ new Set();
1955
+ const wake = () => {
1956
+ if (isEqual && cache.hasValue) {
1957
+ const next = getter();
1958
+ if (isEqual(cache.value, next)) return;
1959
+ cache.value = next;
1960
+ } else {
1961
+ cache.value = getter();
1962
+ cache.hasValue = true;
1963
+ }
1964
+ consumers.forEach((invalidate) => invalidate());
1965
+ };
1966
+ const off = on(form.emitter, event, wake);
1967
+ return {
1968
+ getSnapshot: () => {
1969
+ if (!cache.hasValue) {
1970
+ cache.value = getter();
1971
+ cache.hasValue = true;
1972
+ }
1973
+ return cache.value;
1974
+ },
1975
+ subscribe: (invalidate) => {
1976
+ consumers.add(invalidate);
1977
+ return () => {
1978
+ consumers.delete(invalidate);
1979
+ };
1980
+ },
1981
+ dispose: () => {
1982
+ off();
1983
+ consumers.clear();
1984
+ }
1985
+ };
1986
+ }
1498
1987
 
1499
1988
  function useForm(options) {
1500
1989
  const [form] = React.useState(() => {
@@ -1603,8 +2092,13 @@
1603
2092
  const { key } = path;
1604
2093
  const scope = options?.exact === false ? "branch" : "leaf";
1605
2094
  const subscribeFactory = React.useCallback(
1606
- (invalidate) => onPathEvent(emitter, "change", path, scope, invalidate),
1607
- // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `key` on purpose: useValue creates a fresh Path per render, so the object must stay out of the deps while the key string pins the subscription
2095
+ (invalidate) => onPathEvent(
2096
+ emitter,
2097
+ "change",
2098
+ create$1(JSON.parse(key)),
2099
+ scope,
2100
+ invalidate
2101
+ ),
1608
2102
  [emitter, key, scope]
1609
2103
  );
1610
2104
  return useWatchCore(subscribeFactory, () => {
@@ -1615,6 +2109,9 @@
1615
2109
  return value === void 0 ? options?.defaultValue : value;
1616
2110
  });
1617
2111
  }
2112
+ function useValues(form) {
2113
+ return useWatch(form, "change", () => getValues(form));
2114
+ }
1618
2115
  function useTouched(form, name) {
1619
2116
  return useTouchedByPath(form, create$1(name));
1620
2117
  }
@@ -1667,8 +2164,13 @@
1667
2164
  const { emitter } = form;
1668
2165
  const { key } = path;
1669
2166
  const subscribeFactory = React.useCallback(
1670
- (invalidate) => onPathEvent(emitter, "change", path, "leaf", invalidate),
1671
- // eslint-disable-next-line react-hooks/exhaustive-deps -- same key-pinning convention as useValueByPath
2167
+ (invalidate) => onPathEvent(
2168
+ emitter,
2169
+ "change",
2170
+ create$1(JSON.parse(key)),
2171
+ "leaf",
2172
+ invalidate
2173
+ ),
1672
2174
  [emitter, key]
1673
2175
  );
1674
2176
  return useWatchCore(subscribeFactory, () => isFieldDirtyByPath(form, path));
@@ -1698,6 +2200,7 @@
1698
2200
  touchedFields: getTouchedFields(form),
1699
2201
  hasErrors: hasErrors(form),
1700
2202
  isValid: !hasErrors(form),
2203
+ errors: getErrorsRecord(form),
1701
2204
  isSubmitting: form.isSubmitting,
1702
2205
  isSubmitted: form.isSubmitted,
1703
2206
  isValidating: form.validating.size > 0,
@@ -1709,7 +2212,7 @@
1709
2212
  }
1710
2213
  function isSameFormState(a, b) {
1711
2214
  const sameTouched = a.touchedFields.length === b.touchedFields.length && a.touchedFields.every((path, i) => path === b.touchedFields[i]);
1712
- return a.isDirty === b.isDirty && a.dirtyFields === b.dirtyFields && a.isTouched === b.isTouched && sameTouched && a.hasErrors === b.hasErrors && a.isValid === b.isValid && a.isSubmitting === b.isSubmitting && a.isSubmitted === b.isSubmitted && a.isValidating === b.isValidating && a.isSubmitSuccessful === b.isSubmitSuccessful && a.submitCount === b.submitCount && a.isLoading === b.isLoading && a.disabled === b.disabled;
2215
+ return a.isDirty === b.isDirty && a.dirtyFields === b.dirtyFields && a.isTouched === b.isTouched && sameTouched && a.hasErrors === b.hasErrors && a.isValid === b.isValid && a.errors === b.errors && a.isSubmitting === b.isSubmitting && a.isSubmitted === b.isSubmitted && a.isValidating === b.isValidating && a.isSubmitSuccessful === b.isSubmitSuccessful && a.submitCount === b.submitCount && a.isLoading === b.isLoading && a.disabled === b.disabled;
1713
2216
  }
1714
2217
  function useFormState(form) {
1715
2218
  const getter = React.useCallback(() => getFormState(form), [form]);
@@ -1726,9 +2229,29 @@
1726
2229
  );
1727
2230
  return useWatchCore(subscribeFactory, getter, isSameFormState);
1728
2231
  }
2232
+ function useStore(form, selector, isEqual2) {
2233
+ const subscribeFactory = React.useCallback(
2234
+ (invalidate) => {
2235
+ const offs = FORM_STATE_EVENTS.map(
2236
+ (event) => on(form.emitter, event, invalidate)
2237
+ );
2238
+ return () => {
2239
+ for (const off of offs) off();
2240
+ };
2241
+ },
2242
+ [form.emitter]
2243
+ );
2244
+ return useWatchCore(subscribeFactory, selector, isEqual2);
2245
+ }
1729
2246
  function useHasErrors(form) {
1730
2247
  return useWatch(form, "errors", hasErrors.bind(null, form));
1731
2248
  }
2249
+ function useErrors(form) {
2250
+ return useWatch(form, "errors", () => getErrorsRecord(form));
2251
+ }
2252
+ function useErrorsTree(form) {
2253
+ return useWatch(form, "errors", () => getErrorsTree(form));
2254
+ }
1732
2255
  function useIsValid(form) {
1733
2256
  return useWatch(form, "errors", () => !hasErrors(form));
1734
2257
  }
@@ -1780,8 +2303,8 @@
1780
2303
  }
1781
2304
 
1782
2305
  function usePath(name) {
1783
- const path = React.useMemo(() => create$1(normalizePath(name)), [name]);
1784
- return React.useMemo(() => path, [path.key]);
2306
+ const key = React.useMemo(() => create$1(normalizePath(name)).key, [name]);
2307
+ return React.useMemo(() => create$1(JSON.parse(key)), [key]);
1785
2308
  }
1786
2309
 
1787
2310
  function useStage(value) {
@@ -1798,38 +2321,46 @@
1798
2321
  }
1799
2322
  function useUnmountRestore(teardown, restore) {
1800
2323
  const removedRef = React.useRef(false);
2324
+ const teardownRef = useStage(teardown);
2325
+ const restoreRef = useStage(restore);
1801
2326
  React.useEffect(() => {
2327
+ const teardownOnce = teardownRef.current;
2328
+ const restoreOnce = restoreRef.current;
1802
2329
  if (removedRef.current) {
1803
2330
  removedRef.current = false;
1804
- restore();
2331
+ restoreOnce();
1805
2332
  }
1806
2333
  return () => {
1807
2334
  removedRef.current = true;
1808
- teardown();
2335
+ teardownOnce();
1809
2336
  };
1810
- }, []);
2337
+ }, [removedRef, teardownRef, restoreRef]);
1811
2338
  }
1812
2339
 
1813
2340
  function useValidate(validate, path, formProp, options) {
1814
2341
  const contextForm = React.useContext(FormContext);
1815
2342
  const form = formProp || contextForm;
1816
2343
  if (!form) throw new Error("no form provided");
1817
- const validateRef = React.useRef(validate);
1818
- validateRef.current = validate;
2344
+ const validateOption = validate;
2345
+ const validateRef = React.useRef(void 0);
2346
+ validateRef.current = validateOption && hasStandardProps(validateOption) ? schemaToFieldValidator(validateOption) : validateOption;
1819
2347
  const debounceRef = React.useRef(options?.debounce ?? 0);
1820
2348
  debounceRef.current = options?.debounce ?? 0;
1821
2349
  const syncRef = React.useRef(options?.sync);
1822
2350
  syncRef.current = options?.sync;
1823
2351
  const asyncAlwaysRef = React.useRef(options?.asyncAlways ?? false);
1824
2352
  asyncAlwaysRef.current = options?.asyncAlways ?? false;
2353
+ const validateOnMountRef = React.useRef(options?.validateOnMount);
2354
+ validateOnMountRef.current = options?.validateOnMount;
1825
2355
  React.useEffect(() => {
1826
- const dispose = registerValidatorByPath(form, path, {
2356
+ const spath = create$1(JSON.parse(path.key));
2357
+ const dispose = registerValidatorByPath(form, spath, {
1827
2358
  validate: () => validateRef.current,
1828
2359
  debounce: () => debounceRef.current,
1829
2360
  sync: () => syncRef.current,
1830
2361
  asyncAlways: () => asyncAlwaysRef.current
1831
2362
  });
1832
- const validateOnMount = options?.validateOnMount ?? form.validateOnMount;
2363
+ const validateOnMount = validateOnMountRef.current ?? form.validateOnMount;
1833
2364
  if (!validateOnMount || !validateRef.current && !syncRef.current) {
1834
2365
  return dispose;
1835
2366
  }
@@ -1854,34 +2385,7 @@
1854
2385
  return useStageFn(() => form.validators.get(path.key)?.());
1855
2386
  }
1856
2387
 
1857
- function removeFieldForUnmount(form, path) {
1858
- const { key } = path;
1859
- const snapshot = {
1860
- present: form.values.has(key),
1861
- value: form.values.get(key),
1862
- touched: form.touched.has(key),
1863
- errors: form.errors.get(key)
1864
- };
1865
- removeFieldByPath(form, path);
1866
- return snapshot;
1867
- }
1868
- function restoreRemovedField(form, path, snapshot) {
1869
- const { key } = path;
1870
- if (snapshot.present) {
1871
- setValueByPath(form, path, snapshot.value, { shouldDirty: false });
1872
- } else {
1873
- form.deleted.delete(key);
1874
- bumpValuesVersion(form);
1875
- emit(form.emitter, "change", path);
1876
- }
1877
- if (snapshot.touched) setTouchedByPath(form, path);
1878
- if (snapshot.errors) setErrorByPath(form, path, snapshot.errors);
1879
- }
1880
-
1881
2388
  const uncontrolledSyncRegistry = /* @__PURE__ */ new WeakMap();
1882
- function hasRuleConstraints(rules) {
1883
- return rules.required !== void 0 || rules.min !== void 0 || rules.max !== void 0 || rules.minLength !== void 0 || rules.maxLength !== void 0 || rules.pattern !== void 0 || rules.validate !== void 0;
1884
- }
1885
2389
  function combineRulesAndValidate(rules, validate) {
1886
2390
  if (!rules || !hasRuleConstraints(rules)) return validate;
1887
2391
  const ruleValidator = rulesToValidator(rules);
@@ -1898,22 +2402,59 @@
1898
2402
  return isPromise(result) ? result.then(merge) : merge(result);
1899
2403
  };
1900
2404
  }
1901
- function useDelayedErrors(errors, delay) {
1902
- const [shown, setShown] = React.useState(errors);
1903
- React.useEffect(() => {
1904
- if (delay === void 0) return;
1905
- if (errors.length === 0) {
1906
- setShown(errors);
1907
- return;
1908
- }
1909
- if (shown.length > 0) {
1910
- setShown(errors);
1911
- return;
1912
- }
1913
- const timer = setTimeout(() => setShown(errors), delay);
1914
- return () => clearTimeout(timer);
1915
- }, [errors, delay, shown]);
1916
- return delay === void 0 ? errors : shown;
2405
+ const NO_DELAYED_ERRORS = [];
2406
+ function useDelayedErrors(form, path, delay) {
2407
+ const pendingRef = React.useRef(false);
2408
+ const prevRef = React.useRef(false);
2409
+ const timerRef = React.useRef(null);
2410
+ const subscribeFactory = React.useCallback(
2411
+ (invalidate) => {
2412
+ const spath = create$1(JSON.parse(path.key));
2413
+ const clearTimer = () => {
2414
+ if (timerRef.current !== null) {
2415
+ clearTimeout(timerRef.current);
2416
+ timerRef.current = null;
2417
+ }
2418
+ };
2419
+ pendingRef.current = false;
2420
+ prevRef.current = false;
2421
+ clearTimer();
2422
+ const startWindow = () => {
2423
+ clearTimer();
2424
+ pendingRef.current = true;
2425
+ timerRef.current = setTimeout(() => {
2426
+ timerRef.current = null;
2427
+ pendingRef.current = false;
2428
+ invalidate();
2429
+ }, delay);
2430
+ };
2431
+ const off = onKeyEvent(form.emitter, "errors", spath.key, () => {
2432
+ const has = getFieldErrorsByPath(form, spath).length > 0;
2433
+ const was = prevRef.current;
2434
+ prevRef.current = has;
2435
+ if (delay !== void 0) {
2436
+ if (!has) {
2437
+ if (pendingRef.current) {
2438
+ clearTimer();
2439
+ pendingRef.current = false;
2440
+ }
2441
+ } else if (!was || pendingRef.current) {
2442
+ startWindow();
2443
+ }
2444
+ }
2445
+ invalidate();
2446
+ });
2447
+ return () => {
2448
+ off();
2449
+ clearTimer();
2450
+ };
2451
+ },
2452
+ [form, path.key, delay]
2453
+ );
2454
+ return useWatchCore(
2455
+ subscribeFactory,
2456
+ () => delay === void 0 || !pendingRef.current ? getFieldErrorsByPath(form, path) : NO_DELAYED_ERRORS
2457
+ );
1917
2458
  }
1918
2459
  function useFieldValue(form, path, uncontrolled) {
1919
2460
  const snapshotRef = React.useRef({
@@ -1948,7 +2489,11 @@
1948
2489
  disabled,
1949
2490
  uncontrolled,
1950
2491
  asyncAlways,
1951
- mode: modeOption
2492
+ mode: modeOption,
2493
+ eventToValue,
2494
+ valueAsNumber,
2495
+ valueAsDate,
2496
+ type
1952
2497
  }, Context) {
1953
2498
  const contextForm = React.useContext(Context);
1954
2499
  const form = f1 || contextForm;
@@ -1966,22 +2511,28 @@
1966
2511
  emitChangeByPath(form, path);
1967
2512
  });
1968
2513
  const restRules = rules ? { ...rules, required: void 0 } : void 0;
1969
- useValidate(combineRulesAndValidate(restRules, validate), path, form, {
2514
+ const validateOption = validate;
2515
+ const validateWrapped = validateOption && hasStandardProps(validateOption) ? schemaToFieldValidator(validateOption) : validateOption;
2516
+ useValidate(combineRulesAndValidate(restRules, validateWrapped), path, form, {
1970
2517
  debounce: validateDebounce,
1971
2518
  validateOnMount,
1972
2519
  asyncAlways: asyncAlways ?? form.asyncAlways,
1973
2520
  sync: rules && rules.required !== void 0 ? rulesToValidator({ required: rules.required }) : void 0
1974
2521
  });
1975
- const liveErrors = useFieldErrorsByPath(form, path);
1976
- const errors = useDelayedErrors(liveErrors, delayError);
2522
+ const errors = useDelayedErrors(form, path, delayError);
1977
2523
  const errorObject = errors[0];
1978
2524
  const error = errorObject?.message;
1979
2525
  const value = useFieldValue(form, path, !!uncontrolled);
1980
2526
  const isDirty = useWatchCore(
1981
2527
  React.useCallback(
1982
2528
  (invalidate) => uncontrolled ? () => {
1983
- } : onPathEvent(form.emitter, "change", path, "leaf", invalidate),
1984
- // eslint-disable-next-line react-hooks/exhaustive-deps -- usePath memoizes the Path per key, so key pins the subscription like every path-scoped hook
2529
+ } : onPathEvent(
2530
+ form.emitter,
2531
+ "change",
2532
+ create$1(JSON.parse(path.key)),
2533
+ "leaf",
2534
+ invalidate
2535
+ ),
1985
2536
  [form.emitter, path.key, uncontrolled]
1986
2537
  ),
1987
2538
  () => isFieldDirtyByPath(form, path)
@@ -1993,20 +2544,46 @@
1993
2544
  ),
1994
2545
  () => form.validating.has(path.key)
1995
2546
  );
1996
- const formDisabled = useWatch(form, "disabled", () => form.disabled);
2547
+ const mergedDisabled = useWatchCore(
2548
+ React.useCallback(
2549
+ (invalidate) => onPathEvent(
2550
+ form.emitter,
2551
+ "disabled",
2552
+ create$1(JSON.parse(path.key)),
2553
+ "branch",
2554
+ invalidate
2555
+ ),
2556
+ [form.emitter, path.key]
2557
+ ),
2558
+ () => form.disabled || disabled === true || disabled !== false && hasDisabledAncestor(form, path)
2559
+ );
2560
+ const disabledTokenRef = React.useRef(null);
2561
+ React.useEffect(() => {
2562
+ const spath = create$1(JSON.parse(path.key));
2563
+ const registration = registerFieldDisabled(form, spath, disabled);
2564
+ if (registration) disabledTokenRef.current = registration.token;
2565
+ return () => {
2566
+ if (disabledTokenRef.current !== null) {
2567
+ unregisterFieldDisabled(form, spath, disabledTokenRef.current);
2568
+ disabledTokenRef.current = null;
2569
+ }
2570
+ };
2571
+ }, [form, path.key, disabled]);
1997
2572
  const onChange = useStageFn((v) => userChangeByPath(form, path, v));
1998
2573
  const onBlur = useStageFn(() => userBlur(form, path));
1999
2574
  React.useEffect(() => {
2000
- const { token, displaced } = registerFieldMode(form, path, modeOption);
2001
- return () => unregisterFieldMode(form, path, token);
2575
+ const spath = create$1(JSON.parse(path.key));
2576
+ const { token, displaced } = registerFieldMode(form, spath, modeOption);
2577
+ return () => unregisterFieldMode(form, spath, token);
2002
2578
  }, [form, path.key, modeOption]);
2003
2579
  const depsKey = validateDeps?.length ? validateDeps.join("\n") : void 0;
2580
+ const validateDepsRef = useStage(validateDeps);
2004
2581
  React.useEffect(() => {
2005
2582
  if (!depsKey) return;
2006
- const depKeys = validateDeps.map((dep) => create$1(dep).key);
2583
+ const depKeys = validateDepsRef.current.map((dep) => create$1(dep).key);
2007
2584
  registerFieldValidateDeps(form, path.key, depKeys);
2008
2585
  return () => unregisterFieldValidateDeps(form, path.key, depKeys);
2009
- }, [form, path.key, depsKey]);
2586
+ }, [form, path.key, depsKey, validateDepsRef]);
2010
2587
  const elementRef = React.useRef(null);
2011
2588
  const focusRef = React.useCallback((el) => {
2012
2589
  elementRef.current = el;
@@ -2028,7 +2605,7 @@
2028
2605
  [form, path.key]
2029
2606
  );
2030
2607
  React.useEffect(() => {
2031
- if (!uncontrolled) return;
2608
+ const spath = create$1(JSON.parse(path.key));
2032
2609
  let entry = uncontrolledSyncRegistry.get(form);
2033
2610
  if (!entry) {
2034
2611
  const cells = /* @__PURE__ */ new Map();
@@ -2045,7 +2622,7 @@
2045
2622
  entry = { cells, off };
2046
2623
  uncontrolledSyncRegistry.set(form, entry);
2047
2624
  }
2048
- entry.cells.set(path.key, () => ({ el: elementRef.current, path }));
2625
+ entry.cells.set(path.key, () => ({ el: elementRef.current, path: spath }));
2049
2626
  return () => {
2050
2627
  entry.cells.delete(path.key);
2051
2628
  if (entry.cells.size === 0) {
@@ -2065,6 +2642,16 @@
2065
2642
  if (snapshot) restoreRemovedField(form, path, snapshot);
2066
2643
  });
2067
2644
  useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);
2645
+ const extract = eventToValue ?? ((e) => extractEventValue(e, { valueAsNumber, valueAsDate }));
2646
+ const inputProps = {
2647
+ name: path.key,
2648
+ ref: focusRef,
2649
+ onChange: (e) => onChange(extract(e)),
2650
+ onBlur,
2651
+ disabled: mergedDisabled,
2652
+ ...type === "checkbox" ? { checked: !!value } : type === "file" ? {} : uncontrolled ? { defaultValue: value } : { value: value ?? "" },
2653
+ ...error ? { "aria-invalid": true, "aria-describedby": errorIdFromKey(path.key) } : {}
2654
+ };
2068
2655
  return {
2069
2656
  form,
2070
2657
  value,
@@ -2076,8 +2663,9 @@
2076
2663
  onChange,
2077
2664
  onBlur,
2078
2665
  name: path.key,
2079
- disabled: formDisabled || !!disabled,
2080
- focusRef
2666
+ disabled: mergedDisabled,
2667
+ focusRef,
2668
+ inputProps
2081
2669
  };
2082
2670
  }
2083
2671
  function useField(options) {
@@ -2117,12 +2705,6 @@
2117
2705
  () => getValueByPath(form, path) || [],
2118
2706
  [form, path]
2119
2707
  );
2120
- const setArray = React.useCallback(
2121
- (arr) => {
2122
- setValueByPath(form, path, arr);
2123
- },
2124
- [form, path]
2125
- );
2126
2708
  const computeFields = React.useCallback(() => {
2127
2709
  const arr = getArray();
2128
2710
  while (idsRef.current.length < arr.length) {
@@ -2174,56 +2756,39 @@
2174
2756
  }
2175
2757
  );
2176
2758
  const append = useStageFn((value) => {
2177
- const arr = getArray();
2178
2759
  idsRef.current.push(generateId(form));
2179
- setArray([...arr, value]);
2760
+ appendValueByPath(form, path, value);
2180
2761
  });
2181
2762
  const prepend = useStageFn((value) => {
2182
- const arr = getArray();
2183
2763
  idsRef.current.unshift(generateId(form));
2184
- setArray([value, ...arr]);
2764
+ prependValueByPath(form, path, value);
2185
2765
  });
2186
2766
  const insert = useStageFn((index, value) => {
2187
- const arr = getArray();
2767
+ if (!insertValueByPath(form, path, index, value)) return;
2188
2768
  idsRef.current.splice(index, 0, generateId(form));
2189
- const newArr = [...arr.slice(0, index), value, ...arr.slice(index)];
2190
- setArray(newArr);
2191
2769
  });
2192
- const remove = useStageFn((index) => {
2193
- const arr = getArray();
2194
- idsRef.current.splice(index, 1);
2195
- const newArr = arr.filter((_, i) => i !== index);
2196
- setArray(newArr);
2770
+ const remove = useStageFn((indices) => {
2771
+ const dropped = removeValueByPath(form, path, indices);
2772
+ for (const index of dropped) idsRef.current.splice(index, 1);
2197
2773
  });
2198
2774
  const swap = useStageFn((from, to) => {
2199
- const arr = getArray();
2775
+ if (!swapValuesByPath(form, path, from, to)) return;
2200
2776
  [idsRef.current[from], idsRef.current[to]] = [
2201
2777
  idsRef.current[to],
2202
2778
  idsRef.current[from]
2203
2779
  ];
2204
- const newArr = [...arr];
2205
- [newArr[from], newArr[to]] = [newArr[to], newArr[from]];
2206
- setArray(newArr);
2207
2780
  });
2208
2781
  const move = useStageFn((from, to) => {
2209
- const arr = getArray();
2782
+ if (!moveValueByPath(form, path, from, to)) return;
2210
2783
  const [id] = idsRef.current.splice(from, 1);
2211
2784
  idsRef.current.splice(to, 0, id);
2212
- const newArr = [...arr];
2213
- const [item] = newArr.splice(from, 1);
2214
- newArr.splice(to, 0, item);
2215
- setArray(newArr);
2216
2785
  });
2217
2786
  const replace = useStageFn((values) => {
2218
2787
  idsRef.current = values.map(() => generateId(form));
2219
- setArray([...values]);
2788
+ replaceValuesByPath(form, path, values);
2220
2789
  });
2221
2790
  const update = useStageFn((index, value) => {
2222
- const arr = getArray();
2223
- if (index < 0 || index >= arr.length) return;
2224
- const newArr = [...arr];
2225
- newArr[index] = value;
2226
- setArray(newArr);
2791
+ updateValueByPath(form, path, index, value);
2227
2792
  });
2228
2793
  return { fields, append, prepend, insert, remove, swap, move, replace, update };
2229
2794
  }
@@ -2309,7 +2874,10 @@
2309
2874
  return useFieldCore(options, Context);
2310
2875
  }
2311
2876
  function useFieldArray(options) {
2312
- return useFieldArrayCore(options, Context);
2877
+ return useFieldArrayCore(
2878
+ options,
2879
+ Context
2880
+ );
2313
2881
  }
2314
2882
  function useFieldArrayItem(options) {
2315
2883
  return useFieldArrayItemCore(options, Context);
@@ -2333,23 +2901,59 @@
2333
2901
 
2334
2902
  function useTransform(form, name, options = {}) {
2335
2903
  const path = usePath(name);
2336
- const { toDisplay, fromDisplay } = options;
2904
+ const { toDisplay, fromDisplay, asyncDebounceMs } = options;
2337
2905
  const subscribeFactory = React.useCallback(
2338
- (invalidate) => onPathEvent(form.emitter, "change", path, "leaf", invalidate),
2339
- // eslint-disable-next-line react-hooks/exhaustive-deps -- usePath memoizes the Path per key, so key pins the subscription like every path-scoped hook
2906
+ (invalidate) => onPathEvent(
2907
+ form.emitter,
2908
+ "change",
2909
+ create$1(JSON.parse(path.key)),
2910
+ "leaf",
2911
+ invalidate
2912
+ ),
2340
2913
  [form.emitter, path.key]
2341
2914
  );
2342
2915
  const raw = useWatchCore(subscribeFactory, () => getValueByPath(form, path));
2343
2916
  const value = toDisplay ? toDisplay(raw) : raw;
2917
+ const timerRef = React.useRef(null);
2918
+ const seqRef = React.useRef(0);
2919
+ const fromDisplayRef = React.useRef(fromDisplay);
2920
+ fromDisplayRef.current = fromDisplay;
2921
+ const debounceRef = React.useRef(asyncDebounceMs ?? 0);
2922
+ debounceRef.current = asyncDebounceMs ?? 0;
2923
+ React.useEffect(
2924
+ () => () => {
2925
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
2926
+ },
2927
+ []
2928
+ );
2344
2929
  const onChange = React.useCallback(
2345
2930
  (display) => {
2346
- userChangeByPath(
2347
- form,
2348
- path,
2349
- fromDisplay ? fromDisplay(display) : display
2350
- );
2931
+ const run = () => {
2932
+ const seq = ++seqRef.current;
2933
+ const transform = fromDisplayRef.current;
2934
+ const commit = (next) => userChangeByPath(form, path, next);
2935
+ if (!transform) {
2936
+ commit(display);
2937
+ return;
2938
+ }
2939
+ const result = transform(display);
2940
+ if (isPromise(result)) {
2941
+ result.then((next) => {
2942
+ if (seqRef.current === seq) commit(next);
2943
+ });
2944
+ } else if (seqRef.current === seq) {
2945
+ commit(result);
2946
+ }
2947
+ };
2948
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
2949
+ timerRef.current = null;
2950
+ if (debounceRef.current > 0) {
2951
+ timerRef.current = setTimeout(run, debounceRef.current);
2952
+ } else {
2953
+ run();
2954
+ }
2351
2955
  },
2352
- [form, path, fromDisplay]
2956
+ [form, path]
2353
2957
  );
2354
2958
  return { value, onChange };
2355
2959
  }
@@ -2403,6 +3007,7 @@
2403
3007
  onInvalidSubmit,
2404
3008
  action,
2405
3009
  shouldFocusError,
3010
+ shouldUseNativeValidation,
2406
3011
  ...props
2407
3012
  }) {
2408
3013
  const f2 = useForm({
@@ -2411,7 +3016,8 @@
2411
3016
  shouldUnregister,
2412
3017
  validateOnMount,
2413
3018
  disabled,
2414
- asyncAlways
3019
+ asyncAlways,
3020
+ shouldUseNativeValidation
2415
3021
  });
2416
3022
  const form = f1 || f2;
2417
3023
  React__namespace.useEffect(() => {
@@ -2422,10 +3028,12 @@
2422
3028
  onValidSubmit,
2423
3029
  onInvalidSubmit,
2424
3030
  shouldFocusError,
2425
- onAction: action ? (values2) => action(formDataFromValues(values2)) : void 0
3031
+ shouldUseNativeValidation,
3032
+ onAction: typeof action === "function" ? (values2) => action(formDataFromValues(values2)) : void 0
2426
3033
  });
2427
3034
  const { Provider } = context ?? FormContext;
2428
- return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
3035
+ const nativeAction = typeof action === "string" ? action : void 0;
3036
+ return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, action: nativeAction, noValidate: true, onSubmit: submit }));
2429
3037
  }
2430
3038
 
2431
3039
  function FormField({ children, ...options }) {
@@ -2440,19 +3048,12 @@
2440
3048
  ref.current = value;
2441
3049
  }
2442
3050
  }
2443
- function errorIdFromKey(key) {
2444
- const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
2445
- return id || "field";
2446
- }
2447
3051
  function ariaProps(error, fieldKey, props) {
2448
3052
  return {
2449
3053
  "aria-invalid": error ? true : props["aria-invalid"],
2450
3054
  "aria-describedby": error ? [props["aria-describedby"], errorIdFromKey(fieldKey)].filter(Boolean).join(" ") : props["aria-describedby"]
2451
3055
  };
2452
3056
  }
2453
- function fieldErrorId(name) {
2454
- return errorIdFromKey(create$1(name).key);
2455
- }
2456
3057
  const Field = React__namespace.forwardRef(
2457
3058
  ({
2458
3059
  validate,
@@ -2479,6 +3080,10 @@
2479
3080
  }, ref) => {
2480
3081
  const innerRef = React__namespace.useRef(null);
2481
3082
  const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
3083
+ const contextForm = React__namespace.useContext(FormContext);
3084
+ const resolvedForm = formProp ?? contextForm;
3085
+ const validateOption = validate;
3086
+ const validateWrapped = validateOption && hasStandardProps(validateOption) ? schemaToFieldValidator(validateOption) : validateOption;
2482
3087
  const {
2483
3088
  value,
2484
3089
  onChange,
@@ -2503,15 +3108,17 @@
2503
3108
  // uncontrolled path so no `value` prop ever reaches the element.
2504
3109
  uncontrolled: uncontrolled || props.type === "file",
2505
3110
  validate: (...params) => {
2506
- const el = innerRef.current;
2507
- if (el && typeof el.checkValidity === "function") {
2508
- el.setCustomValidity("");
2509
- if (el.checkValidity() === false) {
2510
- setNativeInvalidCount((count) => count + 1);
2511
- return void 0;
3111
+ if (resolvedForm?.shouldUseNativeValidation !== false) {
3112
+ const el = innerRef.current;
3113
+ if (el && typeof el.checkValidity === "function") {
3114
+ el.setCustomValidity("");
3115
+ if (el.checkValidity() === false) {
3116
+ setNativeInvalidCount((count) => count + 1);
3117
+ return void 0;
3118
+ }
2512
3119
  }
2513
3120
  }
2514
- if (validate) return validate(...params);
3121
+ if (validateWrapped) return validateWrapped(...params);
2515
3122
  }
2516
3123
  });
2517
3124
  const mergedRef = React__namespace.useCallback(
@@ -2537,7 +3144,7 @@
2537
3144
  if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
2538
3145
  }, [nativeInvalidCount]);
2539
3146
  const isFile = props.type === "file";
2540
- const toValue = eventToValue ?? (isFile ? (e) => e.target.files : valueAsNumber ? (e) => e.target.valueAsNumber : valueAsDate ? (e) => e.target.valueAsDate : (e) => e.target.value);
3147
+ const toValue = eventToValue ?? ((e) => extractEventValue(e, { valueAsNumber, valueAsDate }));
2541
3148
  const valueProps = valueToProps ? valueToProps(value) : isFile ? {} : uncontrolled ? { defaultValue: value } : { value };
2542
3149
  const errorId = errorIdFromKey(fieldKey);
2543
3150
  const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : void 0;
@@ -2689,18 +3296,25 @@
2689
3296
  exports.FormProvider = FormProvider;
2690
3297
  exports.Select = Select;
2691
3298
  exports.VALIDATION_OUTCOME = VALIDATION_OUTCOME;
3299
+ exports.appendValue = appendValue;
3300
+ exports.appendValueByPath = appendValueByPath;
2692
3301
  exports.changeValue = changeValue;
2693
3302
  exports.changeValueByPath = changeValueByPath;
2694
3303
  exports.clearErrors = clearErrors;
3304
+ exports.clearServerErrors = clearServerErrors;
2695
3305
  exports.createForm = create;
2696
3306
  exports.createFormContext = createFormContext;
3307
+ exports.dottedKeyToFieldPath = dottedKeyToFieldPath;
2697
3308
  exports.emitChangeByPath = emitChangeByPath;
2698
3309
  exports.ensureValidate = ensureValidate;
2699
3310
  exports.fieldErrorId = fieldErrorId;
3311
+ exports.fieldPathToDottedKey = fieldPathToDottedKey;
2700
3312
  exports.getDirtyFields = getDirtyFields;
2701
3313
  exports.getError = getError;
2702
3314
  exports.getErrorByPath = getErrorByPath;
2703
3315
  exports.getErrors = getErrors;
3316
+ exports.getErrorsRecord = getErrorsRecord;
3317
+ exports.getErrorsTree = getErrorsTree;
2704
3318
  exports.getFieldErrors = getFieldErrors;
2705
3319
  exports.getFieldErrorsByPath = getFieldErrorsByPath;
2706
3320
  exports.getFieldState = getFieldState;
@@ -2714,14 +3328,25 @@
2714
3328
  exports.hasTouched = hasTouched;
2715
3329
  exports.hasTouchedByPath = hasTouchedByPath;
2716
3330
  exports.incrementSubmitCount = incrementSubmitCount;
3331
+ exports.insertValue = insertValue;
3332
+ exports.insertValueByPath = insertValueByPath;
2717
3333
  exports.isDirty = isDirty;
2718
3334
  exports.isFieldDirtyByPath = isFieldDirtyByPath;
2719
3335
  exports.isTouched = isTouched;
3336
+ exports.moveValue = moveValue;
3337
+ exports.moveValueByPath = moveValueByPath;
3338
+ exports.prependValue = prependValue;
3339
+ exports.prependValueByPath = prependValueByPath;
3340
+ exports.registerField = registerField;
2720
3341
  exports.registerFieldMode = registerFieldMode;
2721
3342
  exports.registerFieldValidateDeps = registerFieldValidateDeps;
2722
3343
  exports.registerValidatorByPath = registerValidatorByPath;
2723
3344
  exports.removeField = removeField;
2724
3345
  exports.removeFieldByPath = removeFieldByPath;
3346
+ exports.removeValue = removeValue;
3347
+ exports.removeValueByPath = removeValueByPath;
3348
+ exports.replaceValues = replaceValues;
3349
+ exports.replaceValuesByPath = replaceValuesByPath;
2725
3350
  exports.reset = reset;
2726
3351
  exports.resetField = resetField;
2727
3352
  exports.revalidateDependentsOnChange = revalidateDependentsOnChange;
@@ -2743,15 +3368,21 @@
2743
3368
  exports.setValue = setValue;
2744
3369
  exports.setValueByPath = setValueByPath;
2745
3370
  exports.subscribe = subscribe;
3371
+ exports.swapValues = swapValues;
3372
+ exports.swapValuesByPath = swapValuesByPath;
2746
3373
  exports.trigger = trigger;
2747
3374
  exports.unregisterFieldMode = unregisterFieldMode;
2748
3375
  exports.unregisterFieldValidateDeps = unregisterFieldValidateDeps;
2749
3376
  exports.unsetValidatingByPath = unsetValidatingByPath;
3377
+ exports.updateValue = updateValue;
3378
+ exports.updateValueByPath = updateValueByPath;
2750
3379
  exports.useCanSubmit = useCanSubmit;
2751
3380
  exports.useCheckboxGroupContext = useCheckboxGroupContext;
2752
3381
  exports.useDirtyFields = useDirtyFields;
2753
3382
  exports.useError = useError;
2754
3383
  exports.useErrorByPath = useErrorByPath;
3384
+ exports.useErrors = useErrors;
3385
+ exports.useErrorsTree = useErrorsTree;
2755
3386
  exports.useField = useField;
2756
3387
  exports.useFieldArray = useFieldArray;
2757
3388
  exports.useFieldArrayItem = useFieldArrayItem;
@@ -2772,6 +3403,7 @@
2772
3403
  exports.useIsValid = useIsValid;
2773
3404
  exports.useIsValidating = useIsValidating;
2774
3405
  exports.useStatus = useStatus;
3406
+ exports.useStore = useStore;
2775
3407
  exports.useSubmitCount = useSubmitCount;
2776
3408
  exports.useTouched = useTouched;
2777
3409
  exports.useTouchedByPath = useTouchedByPath;
@@ -2779,11 +3411,13 @@
2779
3411
  exports.useTransform = useTransform;
2780
3412
  exports.useValue = useValue;
2781
3413
  exports.useValueByPath = useValueByPath;
3414
+ exports.useValues = useValues;
2782
3415
  exports.useWatch = useWatch;
2783
3416
  exports.useWatchCore = useWatchCore;
2784
3417
  exports.userBlur = userBlur;
2785
3418
  exports.userChangeByPath = userChangeByPath;
2786
3419
  exports.validate = validate;
3420
+ exports.watch = watch;
2787
3421
 
2788
3422
  }));
2789
3423
  //# sourceMappingURL=index.umd.js.map