@vuehookform/core 0.3.3 → 0.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.
@@ -1,7 +1,20 @@
1
1
  import { computed, inject, nextTick, provide, reactive, ref, shallowRef, toValue, watch } from "vue";
2
+ var pathCache = /* @__PURE__ */ new Map();
3
+ var PATH_CACHE_MAX_SIZE = 256;
4
+ function getPathSegments(path) {
5
+ let segments = pathCache.get(path);
6
+ if (segments) return segments;
7
+ segments = path.split(".");
8
+ if (pathCache.size >= PATH_CACHE_MAX_SIZE) {
9
+ const firstKey = pathCache.keys().next().value;
10
+ if (firstKey !== void 0) pathCache.delete(firstKey);
11
+ }
12
+ pathCache.set(path, segments);
13
+ return segments;
14
+ }
2
15
  function get(obj, path) {
3
16
  if (!path || obj === null || obj === void 0) return obj;
4
- const keys = path.split(".");
17
+ const keys = getPathSegments(path);
5
18
  let result = obj;
6
19
  for (const key of keys) {
7
20
  if (result === null || result === void 0) return;
@@ -11,7 +24,7 @@ function get(obj, path) {
11
24
  }
12
25
  function set(obj, path, value) {
13
26
  if (!path) return;
14
- const keys = path.split(".");
27
+ const keys = getPathSegments(path).slice();
15
28
  const UNSAFE_KEYS = [
16
29
  "__proto__",
17
30
  "constructor",
@@ -36,7 +49,7 @@ function set(obj, path, value) {
36
49
  }
37
50
  function unset(obj, path) {
38
51
  if (!path) return;
39
- const keys = path.split(".");
52
+ const keys = getPathSegments(path).slice();
40
53
  const lastKey = keys.pop();
41
54
  let current = obj;
42
55
  for (const key of keys) {
@@ -52,6 +65,15 @@ function generateId() {
52
65
  const random = Math.random().toString(36).substring(2, 11);
53
66
  return `field_${Date.now()}_${idCounter++}_${random}`;
54
67
  }
68
+ function deepClone(obj) {
69
+ if (obj === null || obj === void 0) return obj;
70
+ if (typeof obj !== "object") return obj;
71
+ if (obj instanceof Date) return new Date(obj.getTime());
72
+ if (Array.isArray(obj)) return obj.map((item) => deepClone(item));
73
+ const cloned = {};
74
+ for (const key in obj) if (Object.prototype.hasOwnProperty.call(obj, key)) cloned[key] = deepClone(obj[key]);
75
+ return cloned;
76
+ }
55
77
  const __DEV__ = globalThis.process?.env?.NODE_ENV !== "production";
56
78
  var warnedMessages = /* @__PURE__ */ new Set();
57
79
  function warnOnce(message, key) {
@@ -80,7 +102,7 @@ function traverseSchemaPath(schema, path) {
80
102
  const segment = segments[i];
81
103
  if (!segment) continue;
82
104
  currentSchema = unwrapSchema(currentSchema);
83
- if (isZodObject(currentSchema)) {
105
+ if (isZodObject$1(currentSchema)) {
84
106
  const shape = currentSchema.shape;
85
107
  if (segment in shape) {
86
108
  const nextSchema = shape[segment];
@@ -95,7 +117,7 @@ function traverseSchemaPath(schema, path) {
95
117
  segmentIndex: i
96
118
  };
97
119
  }
98
- if (isZodArray(currentSchema) && /^\d+$/.test(segment)) {
120
+ if (isZodArray$1(currentSchema) && /^\d+$/.test(segment)) {
99
121
  currentSchema = currentSchema.element;
100
122
  continue;
101
123
  }
@@ -125,7 +147,7 @@ function isArrayFieldInSchema(schema, path) {
125
147
  try {
126
148
  const result = traverseSchemaPath(schema, path);
127
149
  if ("error" in result) return null;
128
- return isZodArray(unwrapSchema(result.schema));
150
+ return isZodArray$1(unwrapSchema(result.schema));
129
151
  } catch {
130
152
  return null;
131
153
  }
@@ -178,22 +200,22 @@ function warnArrayIndexOutOfBounds(operation, path, index, length) {
178
200
  if (!__DEV__) return;
179
201
  warn(`${operation}() on "${path}": Index ${index} is out of bounds (array length: ${length}). Operation was silently ignored.`);
180
202
  }
181
- function getDefProp(schema, prop) {
203
+ function getDefProp$1(schema, prop) {
182
204
  return schema.def[prop];
183
205
  }
184
206
  function getTypeName(schema) {
185
- return getDefProp(schema, "typeName");
207
+ return getDefProp$1(schema, "typeName");
186
208
  }
187
- function isZodObject(schema) {
209
+ function isZodObject$1(schema) {
188
210
  return getTypeName(schema) === "ZodObject";
189
211
  }
190
- function isZodArray(schema) {
212
+ function isZodArray$1(schema) {
191
213
  return getTypeName(schema) === "ZodArray";
192
214
  }
193
215
  function unwrapSchema(schema) {
194
216
  const typeName = getTypeName(schema);
195
- const innerType = getDefProp(schema, "innerType");
196
- const schemaType = getDefProp(schema, "schema");
217
+ const innerType = getDefProp$1(schema, "innerType");
218
+ const schemaType = getDefProp$1(schema, "schema");
197
219
  if ((typeName === "ZodOptional" || typeName === "ZodNullable" || typeName === "ZodDefault") && innerType) return unwrapSchema(innerType);
198
220
  if (typeName === "ZodEffects" && schemaType) return unwrapSchema(schemaType);
199
221
  return schema;
@@ -226,7 +248,7 @@ function createFormContext(options) {
226
248
  const submitCount = ref(0);
227
249
  const defaultValuesError = ref(null);
228
250
  const isSubmitSuccessful = ref(false);
229
- const validatingFields = shallowRef({});
251
+ const validatingFields = shallowRef(/* @__PURE__ */ new Set());
230
252
  const externalErrors = shallowRef({});
231
253
  const errorDelayTimers = /* @__PURE__ */ new Map();
232
254
  const pendingErrors = /* @__PURE__ */ new Map();
@@ -237,6 +259,10 @@ function createFormContext(options) {
237
259
  const debounceTimers = /* @__PURE__ */ new Map();
238
260
  const validationRequestIds = /* @__PURE__ */ new Map();
239
261
  const resetGeneration = ref(0);
262
+ const dirtyFieldCount = ref(0);
263
+ const touchedFieldCount = ref(0);
264
+ const validationCache = /* @__PURE__ */ new Map();
265
+ const schemaValidationTimers = /* @__PURE__ */ new Map();
240
266
  const isDisabled = ref(false);
241
267
  if (options.disabled !== void 0) {
242
268
  isDisabled.value = toValue(options.disabled) ?? false;
@@ -294,24 +320,136 @@ function createFormContext(options) {
294
320
  validationRequestIds,
295
321
  resetGeneration,
296
322
  isDisabled,
323
+ dirtyFieldCount,
324
+ touchedFieldCount,
325
+ validationCache,
326
+ schemaValidationTimers,
297
327
  options
298
328
  };
299
329
  }
330
+ var uniqueIdCounter = 0;
331
+ function hashValue(value) {
332
+ if (value === null) return "null";
333
+ if (value === void 0) return "undefined";
334
+ const type = typeof value;
335
+ if (type === "string") return `s:${value}`;
336
+ if (type === "number") return `n:${value}`;
337
+ if (type === "boolean") return `b:${value}`;
338
+ if (type === "object") try {
339
+ return `o:${JSON.stringify(value)}`;
340
+ } catch {
341
+ return `o:_${++uniqueIdCounter}`;
342
+ }
343
+ return `x:_${++uniqueIdCounter}`;
344
+ }
345
+ function getDefType(schema) {
346
+ return schema._def?.type;
347
+ }
348
+ function getDefProp(schema, prop) {
349
+ return schema._def?.[prop];
350
+ }
351
+ function isZodObject(schema) {
352
+ return getDefType(schema) === "object";
353
+ }
354
+ function isZodArray(schema) {
355
+ return getDefType(schema) === "array";
356
+ }
357
+ function hasChecks(schema) {
358
+ const checks = getDefProp(schema, "checks");
359
+ return Array.isArray(checks) && checks.length > 0;
360
+ }
361
+ function unwrapNonEffects(schema) {
362
+ const type = getDefType(schema);
363
+ const innerType = getDefProp(schema, "innerType");
364
+ if ((type === "optional" || type === "nullable" || type === "default") && innerType) return unwrapNonEffects(innerType);
365
+ return schema;
366
+ }
367
+ var analysisCache = /* @__PURE__ */ new WeakMap();
368
+ function hasRootEffects(schema) {
369
+ return hasChecks(schema);
370
+ }
371
+ function extractSubSchema(schema, path) {
372
+ const segments = path.split(".");
373
+ let currentSchema = schema;
374
+ let hasEffects = false;
375
+ for (const segment of segments) {
376
+ if (!segment) continue;
377
+ if (hasChecks(currentSchema)) hasEffects = true;
378
+ const unwrapped = unwrapNonEffects(currentSchema);
379
+ if (hasChecks(unwrapped)) hasEffects = true;
380
+ if (isZodObject(unwrapped)) {
381
+ const shape = getDefProp(unwrapped, "shape");
382
+ if (!shape || !(segment in shape)) return null;
383
+ currentSchema = shape[segment];
384
+ } else if (isZodArray(unwrapped) && /^\d+$/.test(segment)) {
385
+ const element = getDefProp(unwrapped, "element");
386
+ if (!element) return null;
387
+ currentSchema = element;
388
+ } else return null;
389
+ }
390
+ const finalUnwrapped = unwrapNonEffects(currentSchema);
391
+ const finalChecks = getDefProp(finalUnwrapped, "checks");
392
+ if (finalChecks) {
393
+ for (const check of finalChecks) if (check && typeof check === "object" && "type" in check && check.type === "custom") {
394
+ hasEffects = true;
395
+ break;
396
+ }
397
+ }
398
+ return {
399
+ schema: finalUnwrapped,
400
+ hasEffects
401
+ };
402
+ }
403
+ function analyzeSchemaPath(schema, path) {
404
+ let cache = analysisCache.get(schema);
405
+ if (!cache) {
406
+ cache = /* @__PURE__ */ new Map();
407
+ analysisCache.set(schema, cache);
408
+ }
409
+ const cached = cache.get(path);
410
+ if (cached) return cached;
411
+ if (hasRootEffects(schema)) {
412
+ const result$1 = {
413
+ canPartialValidate: false,
414
+ reason: "root-checks"
415
+ };
416
+ cache.set(path, result$1);
417
+ return result$1;
418
+ }
419
+ const extracted = extractSubSchema(schema, path);
420
+ if (!extracted) {
421
+ const result$1 = {
422
+ canPartialValidate: false,
423
+ reason: "invalid-path"
424
+ };
425
+ cache.set(path, result$1);
426
+ return result$1;
427
+ }
428
+ if (extracted.hasEffects) {
429
+ const result$1 = {
430
+ canPartialValidate: false,
431
+ reason: "path-checks"
432
+ };
433
+ cache.set(path, result$1);
434
+ return result$1;
435
+ }
436
+ const result = {
437
+ canPartialValidate: true,
438
+ subSchema: extracted.schema
439
+ };
440
+ cache.set(path, result);
441
+ return result;
442
+ }
300
443
  function clearFieldErrors$1(errors, fieldPath) {
301
444
  const newErrors = { ...errors };
302
445
  for (const key of Object.keys(newErrors)) if (key === fieldPath || key.startsWith(`${fieldPath}.`)) delete newErrors[key];
303
446
  return newErrors;
304
447
  }
305
448
  function setValidating(ctx, fieldPath, isValidating) {
306
- if (isValidating) ctx.validatingFields.value = {
307
- ...ctx.validatingFields.value,
308
- [fieldPath]: true
309
- };
310
- else {
311
- const newValidating = { ...ctx.validatingFields.value };
312
- delete newValidating[fieldPath];
313
- ctx.validatingFields.value = newValidating;
314
- }
449
+ const newSet = new Set(ctx.validatingFields.value);
450
+ if (isValidating) newSet.add(fieldPath);
451
+ else newSet.delete(fieldPath);
452
+ ctx.validatingFields.value = newSet;
315
453
  }
316
454
  function groupErrorsByPath(issues) {
317
455
  const grouped = /* @__PURE__ */ new Map();
@@ -353,6 +491,18 @@ function createValidation(ctx) {
353
491
  if (!ctx.options.shouldUseNativeValidation) return;
354
492
  for (const [path] of ctx.fieldRefs) applyNativeValidation(path, null);
355
493
  }
494
+ function scheduleErrorsBatch(errors) {
495
+ if ((ctx.options.delayError || 0) <= 0) {
496
+ const newErrors = { ...ctx.errors.value };
497
+ for (const [fieldPath, error] of errors) {
498
+ set(newErrors, fieldPath, error);
499
+ applyNativeValidation(fieldPath, typeof error === "string" ? error : error.message);
500
+ }
501
+ ctx.errors.value = newErrors;
502
+ return;
503
+ }
504
+ for (const [fieldPath, error] of errors) scheduleError(fieldPath, error);
505
+ }
356
506
  function scheduleError(fieldPath, error) {
357
507
  const delayMs = ctx.options.delayError || 0;
358
508
  const errorMessage = typeof error === "string" ? error : error.message;
@@ -394,42 +544,108 @@ function createValidation(ctx) {
394
544
  ctx.errorDelayTimers.clear();
395
545
  ctx.pendingErrors.clear();
396
546
  }
547
+ async function validateFieldPartial(fieldPath, subSchema, valueHash, criteriaMode, generationAtStart) {
548
+ const fieldValue = get(ctx.formData, fieldPath);
549
+ setValidating(ctx, fieldPath, true);
550
+ try {
551
+ const result = await subSchema.safeParseAsync(fieldValue);
552
+ if (ctx.resetGeneration.value !== generationAtStart) return true;
553
+ if (result.success) {
554
+ ctx.errors.value = cancelError(fieldPath);
555
+ if (valueHash) ctx.validationCache.set(fieldPath, {
556
+ hash: valueHash,
557
+ isValid: true
558
+ });
559
+ return true;
560
+ }
561
+ const fieldErrors = result.error.issues.map((issue) => ({
562
+ ...issue,
563
+ path: fieldPath.split(".").concat(issue.path.map(String))
564
+ }));
565
+ ctx.errors.value = cancelError(fieldPath);
566
+ const grouped = groupErrorsByPath(fieldErrors);
567
+ const errorBatch = [];
568
+ for (const [path, errors] of grouped) errorBatch.push([path, createFieldError(errors, criteriaMode)]);
569
+ scheduleErrorsBatch(errorBatch);
570
+ if (valueHash) ctx.validationCache.set(fieldPath, {
571
+ hash: valueHash,
572
+ isValid: false
573
+ });
574
+ return false;
575
+ } finally {
576
+ setValidating(ctx, fieldPath, false);
577
+ }
578
+ }
579
+ async function validateFieldFull(fieldPath, valueHash, criteriaMode, generationAtStart) {
580
+ setValidating(ctx, fieldPath, true);
581
+ try {
582
+ const result = await ctx.options.schema.safeParseAsync(ctx.formData);
583
+ if (ctx.resetGeneration.value !== generationAtStart) return true;
584
+ if (result.success) {
585
+ ctx.errors.value = cancelError(fieldPath);
586
+ if (valueHash) ctx.validationCache.set(fieldPath, {
587
+ hash: valueHash,
588
+ isValid: true
589
+ });
590
+ return true;
591
+ }
592
+ const fieldErrors = result.error.issues.filter((issue) => {
593
+ const path = issue.path.join(".");
594
+ return path === fieldPath || path.startsWith(`${fieldPath}.`);
595
+ });
596
+ if (fieldErrors.length === 0) {
597
+ ctx.errors.value = cancelError(fieldPath);
598
+ if (valueHash) ctx.validationCache.set(fieldPath, {
599
+ hash: valueHash,
600
+ isValid: true
601
+ });
602
+ return true;
603
+ }
604
+ ctx.errors.value = cancelError(fieldPath);
605
+ const grouped = groupErrorsByPath(fieldErrors);
606
+ const errorBatch = [];
607
+ for (const [path, errors] of grouped) errorBatch.push([path, createFieldError(errors, criteriaMode)]);
608
+ scheduleErrorsBatch(errorBatch);
609
+ if (valueHash) ctx.validationCache.set(fieldPath, {
610
+ hash: valueHash,
611
+ isValid: false
612
+ });
613
+ return false;
614
+ } finally {
615
+ setValidating(ctx, fieldPath, false);
616
+ }
617
+ }
397
618
  async function validate(fieldPath) {
398
619
  const generationAtStart = ctx.resetGeneration.value;
399
620
  const criteriaMode = ctx.options.criteriaMode || "firstError";
400
- const validatingKey = fieldPath || "_form";
621
+ let valueHash;
622
+ if (fieldPath) {
623
+ valueHash = hashValue(get(ctx.formData, fieldPath));
624
+ const cached = ctx.validationCache.get(fieldPath);
625
+ if (cached && cached.hash === valueHash) return cached.isValid;
626
+ const analysis = analyzeSchemaPath(ctx.options.schema, fieldPath);
627
+ if (analysis.canPartialValidate && analysis.subSchema) return validateFieldPartial(fieldPath, analysis.subSchema, valueHash, criteriaMode, generationAtStart);
628
+ return validateFieldFull(fieldPath, valueHash, criteriaMode, generationAtStart);
629
+ }
630
+ const validatingKey = "_form";
401
631
  setValidating(ctx, validatingKey, true);
402
632
  try {
403
633
  const result = await ctx.options.schema.safeParseAsync(ctx.formData);
404
634
  if (ctx.resetGeneration.value !== generationAtStart) return true;
405
635
  if (result.success) {
406
- if (fieldPath) ctx.errors.value = cancelError(fieldPath);
407
- else {
408
- clearAllPendingErrors();
409
- ctx.errors.value = {};
410
- clearAllNativeValidation();
411
- }
636
+ clearAllPendingErrors();
637
+ ctx.errors.value = {};
638
+ clearAllNativeValidation();
639
+ ctx.validationCache.clear();
412
640
  return true;
413
641
  }
414
- const zodErrors = result.error.issues;
415
- if (fieldPath) {
416
- const fieldErrors = zodErrors.filter((issue) => {
417
- const path = issue.path.join(".");
418
- return path === fieldPath || path.startsWith(`${fieldPath}.`);
419
- });
420
- if (fieldErrors.length === 0) {
421
- ctx.errors.value = cancelError(fieldPath);
422
- return true;
423
- }
424
- ctx.errors.value = cancelError(fieldPath);
425
- const grouped$1 = groupErrorsByPath(fieldErrors);
426
- for (const [path, errors] of grouped$1) scheduleError(path, createFieldError(errors, criteriaMode));
427
- return false;
428
- }
429
642
  clearAllPendingErrors();
430
643
  ctx.errors.value = {};
431
- const grouped = groupErrorsByPath(zodErrors);
432
- for (const [path, errors] of grouped) scheduleError(path, createFieldError(errors, criteriaMode));
644
+ const grouped = groupErrorsByPath(result.error.issues);
645
+ const errorBatch = [];
646
+ for (const [path, errors] of grouped) errorBatch.push([path, createFieldError(errors, criteriaMode)]);
647
+ scheduleErrorsBatch(errorBatch);
648
+ ctx.validationCache.clear();
433
649
  return false;
434
650
  } finally {
435
651
  setValidating(ctx, validatingKey, false);
@@ -440,6 +656,48 @@ function createValidation(ctx) {
440
656
  clearAllPendingErrors
441
657
  };
442
658
  }
659
+ function markFieldDirty(dirtyFields, dirtyFieldCount, fieldName) {
660
+ if (dirtyFields.value[fieldName]) return;
661
+ dirtyFields.value = {
662
+ ...dirtyFields.value,
663
+ [fieldName]: true
664
+ };
665
+ dirtyFieldCount.value++;
666
+ }
667
+ function markFieldTouched(touchedFields, touchedFieldCount, fieldName) {
668
+ if (touchedFields.value[fieldName]) return;
669
+ touchedFields.value = {
670
+ ...touchedFields.value,
671
+ [fieldName]: true
672
+ };
673
+ touchedFieldCount.value++;
674
+ }
675
+ function clearFieldDirty(dirtyFields, dirtyFieldCount, fieldName) {
676
+ if (!(fieldName in dirtyFields.value)) return;
677
+ const newDirty = { ...dirtyFields.value };
678
+ delete newDirty[fieldName];
679
+ dirtyFields.value = newDirty;
680
+ dirtyFieldCount.value--;
681
+ }
682
+ function clearFieldTouched(touchedFields, touchedFieldCount, fieldName) {
683
+ if (!(fieldName in touchedFields.value)) return;
684
+ const newTouched = { ...touchedFields.value };
685
+ delete newTouched[fieldName];
686
+ touchedFields.value = newTouched;
687
+ touchedFieldCount.value--;
688
+ }
689
+ function clearFieldErrors(errors, fieldName) {
690
+ const currentErrors = errors.value;
691
+ const keys = Object.keys(currentErrors);
692
+ if (keys.length === 0) return;
693
+ const prefix = `${fieldName}.`;
694
+ const keysToDelete = [];
695
+ for (const key of keys) if (key === fieldName || key.startsWith(prefix)) keysToDelete.push(key);
696
+ if (keysToDelete.length === 0) return;
697
+ const newErrors = { ...currentErrors };
698
+ for (const key of keysToDelete) delete newErrors[key];
699
+ errors.value = newErrors;
700
+ }
443
701
  var validationRequestCounter = 0;
444
702
  function createFieldRegistration(ctx, validate) {
445
703
  function register(name, registerOptions) {
@@ -481,16 +739,30 @@ function createFieldRegistration(ctx, validate) {
481
739
  const target = e.target;
482
740
  const value = target.type === "checkbox" ? target.checked : target.value;
483
741
  set(ctx.formData, name, value);
484
- ctx.dirtyFields.value = {
485
- ...ctx.dirtyFields.value,
486
- [name]: true
487
- };
742
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
743
+ const fieldOpts = ctx.fieldOptions.get(name);
488
744
  if (ctx.options.mode === "onChange" || ctx.options.mode === "onTouched" && ctx.touchedFields.value[name] || ctx.touchedFields.value[name] && ctx.options.reValidateMode === "onChange") {
489
- await validate(name);
490
- const fieldOpts$1 = ctx.fieldOptions.get(name);
491
- if (fieldOpts$1?.deps && fieldOpts$1.deps.length > 0) for (const depField of fieldOpts$1.deps) validate(depField);
745
+ const validationDebounceMs = ctx.options.validationDebounce || 0;
746
+ if (validationDebounceMs > 0) {
747
+ const existingTimer = ctx.schemaValidationTimers.get(name);
748
+ if (existingTimer) clearTimeout(existingTimer);
749
+ const timer = setTimeout(async () => {
750
+ ctx.schemaValidationTimers.delete(name);
751
+ await validate(name);
752
+ if (fieldOpts?.deps && fieldOpts.deps.length > 0) {
753
+ const uniqueDeps = [...new Set(fieldOpts.deps)];
754
+ await Promise.all(uniqueDeps.map((depField) => validate(depField)));
755
+ }
756
+ }, validationDebounceMs);
757
+ ctx.schemaValidationTimers.set(name, timer);
758
+ } else {
759
+ await validate(name);
760
+ if (fieldOpts?.deps && fieldOpts.deps.length > 0) {
761
+ const uniqueDeps = [...new Set(fieldOpts.deps)];
762
+ await Promise.all(uniqueDeps.map((depField) => validate(depField)));
763
+ }
764
+ }
492
765
  }
493
- const fieldOpts = ctx.fieldOptions.get(name);
494
766
  if (fieldOpts?.validate && !fieldOpts.disabled) {
495
767
  const requestId = ++validationRequestCounter;
496
768
  ctx.validationRequestIds.set(name, requestId);
@@ -499,23 +771,24 @@ function createFieldRegistration(ctx, validate) {
499
771
  if (debounceMs > 0) {
500
772
  const existingTimer = ctx.debounceTimers.get(name);
501
773
  if (existingTimer) clearTimeout(existingTimer);
502
- const timer = setTimeout(() => {
774
+ const timer = setTimeout(async () => {
503
775
  ctx.debounceTimers.delete(name);
504
- runCustomValidation(name, value, requestId, resetGenAtStart);
776
+ await runCustomValidation(name, value, requestId, resetGenAtStart);
777
+ ctx.validationRequestIds.delete(name);
505
778
  }, debounceMs);
506
779
  ctx.debounceTimers.set(name, timer);
507
780
  } else await runCustomValidation(name, value, requestId, resetGenAtStart);
508
781
  }
509
782
  };
510
783
  const onBlur = async (_e) => {
511
- ctx.touchedFields.value = {
512
- ...ctx.touchedFields.value,
513
- [name]: true
514
- };
784
+ markFieldTouched(ctx.touchedFields, ctx.touchedFieldCount, name);
515
785
  if (ctx.options.mode === "onBlur" || ctx.options.mode === "onTouched" || ctx.submitCount.value > 0 && ctx.options.reValidateMode === "onBlur") {
516
786
  await validate(name);
517
787
  const fieldOpts = ctx.fieldOptions.get(name);
518
- if (fieldOpts?.deps && fieldOpts.deps.length > 0) for (const depField of fieldOpts.deps) validate(depField);
788
+ if (fieldOpts?.deps && fieldOpts.deps.length > 0) {
789
+ const uniqueDeps = [...new Set(fieldOpts.deps)];
790
+ await Promise.all(uniqueDeps.map((depField) => validate(depField)));
791
+ }
519
792
  }
520
793
  };
521
794
  const refCallback = (el) => {
@@ -537,18 +810,17 @@ function createFieldRegistration(ctx, validate) {
537
810
  clearTimeout(timer);
538
811
  ctx.debounceTimers.delete(name);
539
812
  }
813
+ const schemaTimer = ctx.schemaValidationTimers.get(name);
814
+ if (schemaTimer) {
815
+ clearTimeout(schemaTimer);
816
+ ctx.schemaValidationTimers.delete(name);
817
+ }
540
818
  ctx.validationRequestIds.delete(name);
541
819
  if (opts?.shouldUnregister ?? ctx.options.shouldUnregister ?? false) {
542
820
  unset(ctx.formData, name);
543
- const newErrors = { ...ctx.errors.value };
544
- delete newErrors[name];
545
- ctx.errors.value = newErrors;
546
- const newTouched = { ...ctx.touchedFields.value };
547
- delete newTouched[name];
548
- ctx.touchedFields.value = newTouched;
549
- const newDirty = { ...ctx.dirtyFields.value };
550
- delete newDirty[name];
551
- ctx.dirtyFields.value = newDirty;
821
+ clearFieldErrors(ctx.errors, name);
822
+ clearFieldTouched(ctx.touchedFields, ctx.touchedFieldCount, name);
823
+ clearFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
552
824
  ctx.fieldRefs.delete(name);
553
825
  ctx.fieldOptions.delete(name);
554
826
  ctx.fieldHandlers.delete(name);
@@ -572,10 +844,7 @@ function createFieldRegistration(ctx, validate) {
572
844
  get: () => get(ctx.formData, name),
573
845
  set: (val) => {
574
846
  set(ctx.formData, name, val);
575
- ctx.dirtyFields.value = {
576
- ...ctx.dirtyFields.value,
577
- [name]: true
578
- };
847
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
579
848
  }
580
849
  }) }
581
850
  };
@@ -583,21 +852,9 @@ function createFieldRegistration(ctx, validate) {
583
852
  function unregister(name, options) {
584
853
  const opts = options || {};
585
854
  if (!opts.keepValue) unset(ctx.formData, name);
586
- if (!opts.keepError) {
587
- const newErrors = { ...ctx.errors.value };
588
- delete newErrors[name];
589
- ctx.errors.value = newErrors;
590
- }
591
- if (!opts.keepTouched) {
592
- const newTouched = { ...ctx.touchedFields.value };
593
- delete newTouched[name];
594
- ctx.touchedFields.value = newTouched;
595
- }
596
- if (!opts.keepDirty) {
597
- const newDirty = { ...ctx.dirtyFields.value };
598
- delete newDirty[name];
599
- ctx.dirtyFields.value = newDirty;
600
- }
855
+ if (!opts.keepError) clearFieldErrors(ctx.errors, name);
856
+ if (!opts.keepTouched) clearFieldTouched(ctx.touchedFields, ctx.touchedFieldCount, name);
857
+ if (!opts.keepDirty) clearFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
601
858
  ctx.fieldRefs.delete(name);
602
859
  ctx.fieldOptions.delete(name);
603
860
  ctx.fieldHandlers.delete(name);
@@ -606,6 +863,11 @@ function createFieldRegistration(ctx, validate) {
606
863
  clearTimeout(timer);
607
864
  ctx.debounceTimers.delete(name);
608
865
  }
866
+ const schemaTimer = ctx.schemaValidationTimers.get(name);
867
+ if (schemaTimer) {
868
+ clearTimeout(schemaTimer);
869
+ ctx.schemaValidationTimers.delete(name);
870
+ }
609
871
  ctx.validationRequestIds.delete(name);
610
872
  }
611
873
  return {
@@ -642,6 +904,35 @@ function createFieldArrayManager(ctx, validate, setFocus) {
642
904
  indexCache.set(item.key, idx);
643
905
  });
644
906
  };
907
+ const appendToCache = (startIndex) => {
908
+ const items = fa.items.value;
909
+ for (let i = startIndex; i < items.length; i++) {
910
+ const item = items[i];
911
+ if (item) indexCache.set(item.key, i);
912
+ }
913
+ };
914
+ const updateCacheAfterInsert = (insertIndex, _insertCount) => {
915
+ const items = fa.items.value;
916
+ for (let i = insertIndex; i < items.length; i++) {
917
+ const item = items[i];
918
+ if (item) indexCache.set(item.key, i);
919
+ }
920
+ };
921
+ const swapInCache = (indexA, indexB) => {
922
+ const items = fa.items.value;
923
+ const itemA = items[indexA];
924
+ const itemB = items[indexB];
925
+ if (itemA) indexCache.set(itemA.key, indexA);
926
+ if (itemB) indexCache.set(itemB.key, indexB);
927
+ };
928
+ const updateCacheAfterRemove = (removedKey, startIndex) => {
929
+ indexCache.delete(removedKey);
930
+ const items = fa.items.value;
931
+ for (let i = startIndex; i < items.length; i++) {
932
+ const item = items[i];
933
+ if (item) indexCache.set(item.key, i);
934
+ }
935
+ };
645
936
  const createItem = (key) => ({
646
937
  key,
647
938
  get index() {
@@ -684,11 +975,8 @@ function createFieldArrayManager(ctx, validate, setFocus) {
684
975
  set(ctx.formData, name, newValues);
685
976
  const newItems = values.map(() => createItem(generateId()));
686
977
  fa.items.value = [...fa.items.value, ...newItems];
687
- rebuildIndexCache();
688
- ctx.dirtyFields.value = {
689
- ...ctx.dirtyFields.value,
690
- [name]: true
691
- };
978
+ appendToCache(insertIndex);
979
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
692
980
  if (ctx.options.mode === "onChange") validate(name);
693
981
  handleFocus(insertIndex, values.length, focusOptions);
694
982
  return true;
@@ -709,11 +997,8 @@ function createFieldArrayManager(ctx, validate, setFocus) {
709
997
  set(ctx.formData, name, newValues);
710
998
  const newItems = values.map(() => createItem(generateId()));
711
999
  fa.items.value = [...newItems, ...fa.items.value];
712
- rebuildIndexCache();
713
- ctx.dirtyFields.value = {
714
- ...ctx.dirtyFields.value,
715
- [name]: true
716
- };
1000
+ updateCacheAfterInsert(0, values.length);
1001
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
717
1002
  if (ctx.options.mode === "onChange") validate(name);
718
1003
  handleFocus(0, values.length, focusOptions);
719
1004
  return true;
@@ -727,10 +1012,7 @@ function createFieldArrayManager(ctx, validate, setFocus) {
727
1012
  const newValues = [...currentValues];
728
1013
  newValues[index] = value;
729
1014
  set(ctx.formData, name, newValues);
730
- ctx.dirtyFields.value = {
731
- ...ctx.dirtyFields.value,
732
- [name]: true
733
- };
1015
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
734
1016
  if (ctx.options.mode === "onChange") validate(name);
735
1017
  return true;
736
1018
  };
@@ -752,11 +1034,8 @@ function createFieldArrayManager(ctx, validate, setFocus) {
752
1034
  set(ctx.formData, name, newValues);
753
1035
  const keyToRemove = fa.items.value[index]?.key;
754
1036
  fa.items.value = fa.items.value.filter((item) => item.key !== keyToRemove);
755
- rebuildIndexCache();
756
- ctx.dirtyFields.value = {
757
- ...ctx.dirtyFields.value,
758
- [name]: true
759
- };
1037
+ if (keyToRemove) updateCacheAfterRemove(keyToRemove, index);
1038
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
760
1039
  if (ctx.options.mode === "onChange") validate(name);
761
1040
  return true;
762
1041
  };
@@ -785,11 +1064,8 @@ function createFieldArrayManager(ctx, validate, setFocus) {
785
1064
  ...newItems,
786
1065
  ...fa.items.value.slice(clampedIndex)
787
1066
  ];
788
- rebuildIndexCache();
789
- ctx.dirtyFields.value = {
790
- ...ctx.dirtyFields.value,
791
- [name]: true
792
- };
1067
+ updateCacheAfterInsert(clampedIndex, values.length);
1068
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
793
1069
  if (ctx.options.mode === "onChange") validate(name);
794
1070
  handleFocus(clampedIndex, values.length, focusOptions);
795
1071
  return true;
@@ -810,12 +1086,9 @@ function createFieldArrayManager(ctx, validate, setFocus) {
810
1086
  newItems[indexA] = itemB;
811
1087
  newItems[indexB] = itemA;
812
1088
  fa.items.value = newItems;
813
- rebuildIndexCache();
1089
+ swapInCache(indexA, indexB);
814
1090
  }
815
- ctx.dirtyFields.value = {
816
- ...ctx.dirtyFields.value,
817
- [name]: true
818
- };
1091
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
819
1092
  if (ctx.options.mode === "onChange") validate(name);
820
1093
  return true;
821
1094
  };
@@ -838,12 +1111,15 @@ function createFieldArrayManager(ctx, validate, setFocus) {
838
1111
  const clampedTo = Math.min(to, newItems.length);
839
1112
  newItems.splice(clampedTo, 0, removedItem);
840
1113
  fa.items.value = newItems;
841
- rebuildIndexCache();
1114
+ const minIdx = Math.min(from, clampedTo);
1115
+ const maxIdx = Math.max(from, clampedTo);
1116
+ const items = fa.items.value;
1117
+ for (let i = minIdx; i <= maxIdx; i++) {
1118
+ const item = items[i];
1119
+ if (item) indexCache.set(item.key, i);
1120
+ }
842
1121
  }
843
- ctx.dirtyFields.value = {
844
- ...ctx.dirtyFields.value,
845
- [name]: true
846
- };
1122
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
847
1123
  if (ctx.options.mode === "onChange") validate(name);
848
1124
  return true;
849
1125
  };
@@ -852,10 +1128,7 @@ function createFieldArrayManager(ctx, validate, setFocus) {
852
1128
  set(ctx.formData, name, newValues);
853
1129
  fa.items.value = newValues.map(() => createItem(generateId()));
854
1130
  rebuildIndexCache();
855
- ctx.dirtyFields.value = {
856
- ...ctx.dirtyFields.value,
857
- [name]: true
858
- };
1131
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
859
1132
  if (ctx.options.mode === "onChange") validate(name);
860
1133
  return true;
861
1134
  };
@@ -870,11 +1143,8 @@ function createFieldArrayManager(ctx, validate, setFocus) {
870
1143
  }
871
1144
  set(ctx.formData, name, []);
872
1145
  fa.items.value = [];
873
- rebuildIndexCache();
874
- ctx.dirtyFields.value = {
875
- ...ctx.dirtyFields.value,
876
- [name]: true
877
- };
1146
+ indexCache.clear();
1147
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
878
1148
  if (ctx.options.mode === "onChange") validate(name);
879
1149
  return true;
880
1150
  };
@@ -893,14 +1163,15 @@ function createFieldArrayManager(ctx, validate, setFocus) {
893
1163
  }
894
1164
  const sortedIndices = [...new Set(validIndices)].sort((a, b) => b - a);
895
1165
  const indicesToRemove = new Set(sortedIndices);
1166
+ const keysToRemove = fa.items.value.filter((_, i) => indicesToRemove.has(i)).map((item) => item.key);
896
1167
  const newValues = currentValues.filter((_, i) => !indicesToRemove.has(i));
897
1168
  set(ctx.formData, name, newValues);
898
1169
  fa.items.value = fa.items.value.filter((_, i) => !indicesToRemove.has(i));
899
- rebuildIndexCache();
900
- ctx.dirtyFields.value = {
901
- ...ctx.dirtyFields.value,
902
- [name]: true
903
- };
1170
+ for (const key of keysToRemove) indexCache.delete(key);
1171
+ fa.items.value.forEach((item, idx) => {
1172
+ indexCache.set(item.key, idx);
1173
+ });
1174
+ markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
904
1175
  if (ctx.options.mode === "onChange") validate(name);
905
1176
  return true;
906
1177
  };
@@ -932,33 +1203,6 @@ function updateDomElement(el, value) {
932
1203
  if (el.type === "checkbox") el.checked = value;
933
1204
  else el.value = value;
934
1205
  }
935
- function markFieldDirty(dirtyFields, fieldName) {
936
- dirtyFields.value = {
937
- ...dirtyFields.value,
938
- [fieldName]: true
939
- };
940
- }
941
- function markFieldTouched(touchedFields, fieldName) {
942
- touchedFields.value = {
943
- ...touchedFields.value,
944
- [fieldName]: true
945
- };
946
- }
947
- function clearFieldDirty(dirtyFields, fieldName) {
948
- const newDirty = { ...dirtyFields.value };
949
- delete newDirty[fieldName];
950
- dirtyFields.value = newDirty;
951
- }
952
- function clearFieldTouched(touchedFields, fieldName) {
953
- const newTouched = { ...touchedFields.value };
954
- delete newTouched[fieldName];
955
- touchedFields.value = newTouched;
956
- }
957
- function clearFieldErrors(errors, fieldName) {
958
- const newErrors = { ...errors.value };
959
- for (const key of Object.keys(newErrors)) if (key === fieldName || key.startsWith(`${fieldName}.`)) delete newErrors[key];
960
- errors.value = newErrors;
961
- }
962
1206
  function useForm(options) {
963
1207
  const ctx = createFormContext(options);
964
1208
  const { validate, clearAllPendingErrors } = createValidation(ctx);
@@ -982,32 +1226,84 @@ function useForm(options) {
982
1226
  }
983
1227
  const setFocusWrapper = (name) => setFocus(name);
984
1228
  const { fields } = createFieldArrayManager(ctx, validate, setFocusWrapper);
1229
+ let lastSyncTime = 0;
1230
+ const SYNC_DEBOUNCE_MS = 16;
1231
+ function syncWithDebounce() {
1232
+ const now = typeof performance !== "undefined" ? performance.now() : Date.now();
1233
+ if (now - lastSyncTime < SYNC_DEBOUNCE_MS) return;
1234
+ syncUncontrolledInputs(ctx.fieldRefs, ctx.fieldOptions, ctx.formData);
1235
+ lastSyncTime = now;
1236
+ }
1237
+ let lastErrors = ctx.errors.value;
1238
+ let lastExternalErrors = ctx.externalErrors.value;
1239
+ let cachedMergedErrors = null;
985
1240
  function getMergedErrors() {
986
- return {
1241
+ if (cachedMergedErrors !== null && lastErrors === ctx.errors.value && lastExternalErrors === ctx.externalErrors.value) return cachedMergedErrors;
1242
+ lastErrors = ctx.errors.value;
1243
+ lastExternalErrors = ctx.externalErrors.value;
1244
+ cachedMergedErrors = {
987
1245
  ...ctx.errors.value,
988
1246
  ...ctx.externalErrors.value
989
1247
  };
1248
+ return cachedMergedErrors;
990
1249
  }
991
- const formState = computed(() => {
992
- const mergedErrors = getMergedErrors();
993
- return {
994
- errors: mergedErrors,
995
- isDirty: Object.keys(ctx.dirtyFields.value).some((k) => ctx.dirtyFields.value[k]),
996
- dirtyFields: ctx.dirtyFields.value,
997
- isValid: (ctx.submitCount.value > 0 || Object.keys(ctx.touchedFields.value).length > 0) && Object.keys(mergedErrors).length === 0,
998
- isSubmitting: ctx.isSubmitting.value,
999
- isLoading: ctx.isLoading.value,
1000
- isReady: !ctx.isLoading.value,
1001
- isValidating: Object.keys(ctx.validatingFields.value).some((k) => ctx.validatingFields.value[k]),
1002
- validatingFields: ctx.validatingFields.value,
1003
- touchedFields: ctx.touchedFields.value,
1004
- submitCount: ctx.submitCount.value,
1005
- defaultValuesError: ctx.defaultValuesError.value,
1006
- isSubmitted: ctx.submitCount.value > 0,
1007
- isSubmitSuccessful: ctx.isSubmitSuccessful.value,
1008
- disabled: ctx.isDisabled.value
1009
- };
1250
+ const isDirtyComputed = computed(() => ctx.dirtyFieldCount.value > 0);
1251
+ const errorsComputed = computed(() => getMergedErrors());
1252
+ const isValidComputed = computed(() => {
1253
+ if (!(ctx.submitCount.value > 0 || ctx.touchedFieldCount.value > 0)) return false;
1254
+ return Object.keys(errorsComputed.value).length === 0;
1010
1255
  });
1256
+ const isReadyComputed = computed(() => !ctx.isLoading.value);
1257
+ const isValidatingComputed = computed(() => ctx.validatingFields.value.size > 0);
1258
+ const isSubmittedComputed = computed(() => ctx.submitCount.value > 0);
1259
+ const formStateInternal = reactive({
1260
+ get errors() {
1261
+ return errorsComputed.value;
1262
+ },
1263
+ get isDirty() {
1264
+ return isDirtyComputed.value;
1265
+ },
1266
+ get dirtyFields() {
1267
+ return ctx.dirtyFields.value;
1268
+ },
1269
+ get isValid() {
1270
+ return isValidComputed.value;
1271
+ },
1272
+ get isSubmitting() {
1273
+ return ctx.isSubmitting.value;
1274
+ },
1275
+ get isLoading() {
1276
+ return ctx.isLoading.value;
1277
+ },
1278
+ get isReady() {
1279
+ return isReadyComputed.value;
1280
+ },
1281
+ get isValidating() {
1282
+ return isValidatingComputed.value;
1283
+ },
1284
+ get validatingFields() {
1285
+ return ctx.validatingFields.value;
1286
+ },
1287
+ get touchedFields() {
1288
+ return ctx.touchedFields.value;
1289
+ },
1290
+ get submitCount() {
1291
+ return ctx.submitCount.value;
1292
+ },
1293
+ get defaultValuesError() {
1294
+ return ctx.defaultValuesError.value;
1295
+ },
1296
+ get isSubmitted() {
1297
+ return isSubmittedComputed.value;
1298
+ },
1299
+ get isSubmitSuccessful() {
1300
+ return ctx.isSubmitSuccessful.value;
1301
+ },
1302
+ get disabled() {
1303
+ return ctx.isDisabled.value;
1304
+ }
1305
+ });
1306
+ const formState = computed(() => formStateInternal);
1011
1307
  function handleSubmit(onValid, onInvalid) {
1012
1308
  return async (e) => {
1013
1309
  e.preventDefault();
@@ -1017,7 +1313,7 @@ function useForm(options) {
1017
1313
  ctx.submitCount.value++;
1018
1314
  ctx.isSubmitSuccessful.value = false;
1019
1315
  try {
1020
- syncUncontrolledInputs(ctx.fieldRefs, ctx.fieldOptions, ctx.formData);
1316
+ syncWithDebounce();
1021
1317
  if (await validate()) {
1022
1318
  await onValid(ctx.formData);
1023
1319
  ctx.isSubmitSuccessful.value = true;
@@ -1043,8 +1339,8 @@ function useForm(options) {
1043
1339
  }
1044
1340
  }
1045
1341
  set(ctx.formData, name, value);
1046
- if (setValueOptions?.shouldDirty !== false) markFieldDirty(ctx.dirtyFields, name);
1047
- if (setValueOptions?.shouldTouch) markFieldTouched(ctx.touchedFields, name);
1342
+ if (setValueOptions?.shouldDirty !== false) markFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
1343
+ if (setValueOptions?.shouldTouch) markFieldTouched(ctx.touchedFields, ctx.touchedFieldCount, name);
1048
1344
  if (!ctx.fieldOptions.get(name)?.controlled) {
1049
1345
  const fieldRef = ctx.fieldRefs.get(name);
1050
1346
  if (fieldRef?.value) updateDomElement(fieldRef.value, value);
@@ -1055,15 +1351,23 @@ function useForm(options) {
1055
1351
  const opts = resetOptions || {};
1056
1352
  ctx.resetGeneration.value++;
1057
1353
  clearAllPendingErrors();
1058
- ctx.validatingFields.value = {};
1354
+ ctx.validatingFields.value = /* @__PURE__ */ new Set();
1355
+ ctx.validationCache.clear();
1356
+ for (const timer of ctx.schemaValidationTimers.values()) clearTimeout(timer);
1357
+ ctx.schemaValidationTimers.clear();
1059
1358
  if (!opts.keepDefaultValues && values) Object.assign(ctx.defaultValues, values);
1060
1359
  Object.keys(ctx.formData).forEach((key) => delete ctx.formData[key]);
1061
- const sourceValues = values || ctx.defaultValues;
1062
- const newValues = JSON.parse(JSON.stringify(sourceValues));
1360
+ const newValues = deepClone(values || ctx.defaultValues);
1063
1361
  Object.assign(ctx.formData, newValues);
1064
1362
  if (!opts.keepErrors) ctx.errors.value = {};
1065
- if (!opts.keepTouched) ctx.touchedFields.value = {};
1066
- if (!opts.keepDirty) ctx.dirtyFields.value = {};
1363
+ if (!opts.keepTouched) {
1364
+ ctx.touchedFields.value = {};
1365
+ ctx.touchedFieldCount.value = 0;
1366
+ }
1367
+ if (!opts.keepDirty) {
1368
+ ctx.dirtyFields.value = {};
1369
+ ctx.dirtyFieldCount.value = 0;
1370
+ }
1067
1371
  if (!opts.keepSubmitCount) ctx.submitCount.value = 0;
1068
1372
  if (!opts.keepIsSubmitting) ctx.isSubmitting.value = false;
1069
1373
  if (!opts.keepIsSubmitSuccessful) ctx.isSubmitSuccessful.value = false;
@@ -1097,11 +1401,11 @@ function useForm(options) {
1097
1401
  let defaultValue = opts.defaultValue;
1098
1402
  if (defaultValue === void 0) defaultValue = get(ctx.defaultValues, name);
1099
1403
  else set(ctx.defaultValues, name, defaultValue);
1100
- const clonedValue = defaultValue !== void 0 ? JSON.parse(JSON.stringify(defaultValue)) : void 0;
1404
+ const clonedValue = defaultValue !== void 0 ? deepClone(defaultValue) : void 0;
1101
1405
  set(ctx.formData, name, clonedValue);
1102
1406
  if (!opts.keepError) clearFieldErrors(ctx.errors, name);
1103
- if (!opts.keepDirty) clearFieldDirty(ctx.dirtyFields, name);
1104
- if (!opts.keepTouched) clearFieldTouched(ctx.touchedFields, name);
1407
+ if (!opts.keepDirty) clearFieldDirty(ctx.dirtyFields, ctx.dirtyFieldCount, name);
1408
+ if (!opts.keepTouched) clearFieldTouched(ctx.touchedFields, ctx.touchedFieldCount, name);
1105
1409
  if (!ctx.fieldOptions.get(name)?.controlled) {
1106
1410
  const fieldRef = ctx.fieldRefs.get(name);
1107
1411
  if (fieldRef?.value) updateDomElement(fieldRef.value, clonedValue ?? (fieldRef.value.type === "checkbox" ? false : ""));
@@ -1191,7 +1495,7 @@ function useForm(options) {
1191
1495
  }
1192
1496
  }
1193
1497
  }
1194
- syncUncontrolledInputs(ctx.fieldRefs, ctx.fieldOptions, ctx.formData);
1498
+ syncWithDebounce();
1195
1499
  if (nameOrNames === void 0) return { ...ctx.formData };
1196
1500
  if (Array.isArray(nameOrNames)) {
1197
1501
  const result = {};