@gorgo/medusa-integration 0.2.0 → 0.3.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -316,55 +316,45 @@ const IntegrationFieldValue = ({
316
316
  return /* @__PURE__ */ jsx(Text, { size: "small", leading: "compact", children: String(value) });
317
317
  };
318
318
  var isCheckBoxInput = (element) => element.type === "checkbox";
319
+ var isFileInput = (element) => element.type === "file";
319
320
  var isDateObject = (value) => value instanceof Date;
320
321
  var isNullOrUndefined = (value) => value == null;
321
322
  const isObjectType = (value) => typeof value === "object";
322
323
  var isObject = (value) => !isNullOrUndefined(value) && !Array.isArray(value) && isObjectType(value) && !isDateObject(value);
323
- var getEventValue = (event) => isObject(event) && event.target ? isCheckBoxInput(event.target) ? event.target.checked : event.target.value : event;
324
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
325
- var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
324
+ var getEventValue = (event) => isObject(event) && event.target ? isCheckBoxInput(event.target) ? event.target.checked : isFileInput(event.target) ? event.target.files : event.target.value : event;
325
+ var isNameInFieldArray = (names, name) => name.split(".").some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join(".")));
326
326
  var isPlainObject = (tempObject) => {
327
327
  const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
328
328
  return isObject(prototypeCopy) && prototypeCopy.hasOwnProperty("isPrototypeOf");
329
329
  };
330
330
  var isWeb = typeof window !== "undefined" && typeof window.HTMLElement !== "undefined" && typeof document !== "undefined";
331
331
  function cloneObject(data) {
332
- let copy;
333
- const isArray = Array.isArray(data);
334
332
  if (data instanceof Date) {
335
- copy = new Date(data);
336
- } else if (data instanceof Set) {
337
- copy = new Set(data);
338
- } else if (!(isWeb && (data instanceof Blob || data instanceof FileList)) && (isArray || isObject(data))) {
339
- copy = isArray ? [] : {};
340
- if (!isArray && !isPlainObject(data)) {
341
- copy = data;
342
- } else {
343
- for (const key in data) {
344
- if (data.hasOwnProperty(key)) {
345
- copy[key] = cloneObject(data[key]);
346
- }
347
- }
348
- }
349
- } else {
333
+ return new Date(data);
334
+ }
335
+ const isFileListInstance = typeof FileList !== "undefined" && data instanceof FileList;
336
+ if (isWeb && (data instanceof Blob || isFileListInstance)) {
350
337
  return data;
351
338
  }
339
+ const isArray = Array.isArray(data);
340
+ if (!isArray && !(isObject(data) && isPlainObject(data))) {
341
+ return data;
342
+ }
343
+ const copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
344
+ for (const key in data) {
345
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
346
+ copy[key] = cloneObject(data[key]);
347
+ }
348
+ }
352
349
  return copy;
353
350
  }
354
- var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
355
- var isUndefined = (val) => val === void 0;
356
- var get = (object, path, defaultValue) => {
357
- if (!path || !isObject(object)) {
358
- return defaultValue;
359
- }
360
- const result = compact(path.split(/[,[\].]+?/)).reduce((result2, key) => isNullOrUndefined(result2) ? result2 : result2[key], object);
361
- return isUndefined(result) || result === object ? isUndefined(object[path]) ? defaultValue : object[path] : result;
362
- };
363
- var isBoolean = (value) => typeof value === "boolean";
364
351
  const EVENTS = {
365
352
  BLUR: "blur",
366
353
  FOCUS_OUT: "focusout",
367
- CHANGE: "change"
354
+ CHANGE: "change",
355
+ SUBMIT: "submit",
356
+ TRIGGER: "trigger",
357
+ VALID: "valid"
368
358
  };
369
359
  const VALIDATION_MODE = {
370
360
  onBlur: "onBlur",
@@ -382,12 +372,52 @@ const INPUT_VALIDATION_RULES = {
382
372
  required: "required",
383
373
  validate: "validate"
384
374
  };
385
- const HookFormContext = React.createContext(null);
386
- const useFormContext = () => React.useContext(HookFormContext);
375
+ const ROOT_ERROR_TYPE = "root";
376
+ const PROTOTYPE_KEYWORDS = ["__proto__", "constructor", "prototype"];
377
+ const IS_KEY_RE = /^\w*$/;
378
+ var isKey = (value) => IS_KEY_RE.test(value);
379
+ var isUndefined = (val) => val === void 0;
380
+ const FIELD_PATH_RE = /[.[\]'"]/;
381
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
382
+ var get = (object, path, defaultValue) => {
383
+ if (!path || !isObject(object)) {
384
+ return defaultValue;
385
+ }
386
+ const paths = isKey(path) ? [path] : stringToPath(path);
387
+ if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
388
+ return defaultValue;
389
+ }
390
+ const result = paths.reduce((result2, key) => {
391
+ return isNullOrUndefined(result2) ? void 0 : result2[key];
392
+ }, object);
393
+ return isUndefined(result) || result === object ? isUndefined(object[path]) ? defaultValue : object[path] : result;
394
+ };
395
+ var isBoolean = (value) => typeof value === "boolean";
396
+ var isFunction = (value) => typeof value === "function";
397
+ var set = (object, path, value) => {
398
+ let index = -1;
399
+ const tempPath = isKey(path) ? [path] : stringToPath(path);
400
+ const length = tempPath.length;
401
+ const lastIndex = length - 1;
402
+ while (++index < length) {
403
+ const key = tempPath[index];
404
+ let newValue = value;
405
+ if (index !== lastIndex) {
406
+ const objValue = object[key];
407
+ newValue = isObject(objValue) || Array.isArray(objValue) ? objValue : !isNaN(+tempPath[index + 1]) ? [] : {};
408
+ }
409
+ if (PROTOTYPE_KEYWORDS.includes(key)) {
410
+ return;
411
+ }
412
+ object[key] = newValue;
413
+ object = object[key];
414
+ }
415
+ };
416
+ const HookFormControlContext = React.createContext(null);
417
+ HookFormControlContext.displayName = "HookFormControlContext";
418
+ const useFormControlContext = () => React.useContext(HookFormControlContext);
387
419
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
388
- const result = {
389
- defaultValues: control._defaultValues
390
- };
420
+ const result = {};
391
421
  for (const key in formState) {
392
422
  Object.defineProperty(result, key, {
393
423
  get: () => {
@@ -402,58 +432,40 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
402
432
  }
403
433
  return result;
404
434
  };
405
- var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
406
- var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
407
- updateFormState(formStateData);
408
- const { name, ...formState } = formStateData;
409
- return isEmptyObject(formState) || Object.keys(formState).length >= Object.keys(_proxyFormState).length || Object.keys(formState).find((key) => _proxyFormState[key] === (!isRoot || VALIDATION_MODE.all));
410
- };
411
- var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
412
- var shouldSubscribeByName = (name, signalName, exact) => !name || !signalName || name === signalName || convertToArrayPayload(name).some((currentName) => currentName && (exact ? currentName === signalName : currentName.startsWith(signalName) || signalName.startsWith(currentName)));
413
- function useSubscribe(props) {
414
- const _props = React.useRef(props);
415
- _props.current = props;
416
- React.useEffect(() => {
417
- const subscription = !props.disabled && _props.current.subject && _props.current.subject.subscribe({
418
- next: _props.current.next
419
- });
420
- return () => {
421
- subscription && subscription.unsubscribe();
422
- };
423
- }, [props.disabled]);
424
- }
435
+ const useIsomorphicLayoutEffect = isWeb ? React.useLayoutEffect : React.useEffect;
425
436
  function useFormState(props) {
426
- const methods = useFormContext();
427
- const { control = methods.control, disabled, name, exact } = props || {};
428
- const [formState, updateFormState] = React.useState(control._formState);
429
- const _mounted = React.useRef(true);
437
+ const formControl = useFormControlContext();
438
+ const { control = formControl, disabled, name, exact } = props || {};
439
+ const [formState, updateFormState] = React.useState(() => ({
440
+ ...control._formState,
441
+ defaultValues: control._defaultValues
442
+ }));
430
443
  const _localProxyFormState = React.useRef({
431
444
  isDirty: false,
432
445
  isLoading: false,
433
446
  dirtyFields: false,
434
447
  touchedFields: false,
448
+ validatingFields: false,
435
449
  isValidating: false,
436
450
  isValid: false,
437
451
  errors: false
438
452
  });
439
- const _name = React.useRef(name);
440
- _name.current = name;
441
- useSubscribe({
442
- disabled,
443
- next: (value) => _mounted.current && shouldSubscribeByName(_name.current, value.name, exact) && shouldRenderFormState(value, _localProxyFormState.current, control._updateFormState) && updateFormState({
444
- ...control._formState,
445
- ...value
446
- }),
447
- subject: control._subjects.state
448
- });
453
+ useIsomorphicLayoutEffect(() => control._subscribe({
454
+ name,
455
+ formState: _localProxyFormState.current,
456
+ exact,
457
+ callback: (formState2) => {
458
+ !disabled && updateFormState({
459
+ ...control._formState,
460
+ ...formState2,
461
+ defaultValues: control._defaultValues
462
+ });
463
+ }
464
+ }), [name, disabled, exact]);
449
465
  React.useEffect(() => {
450
- _mounted.current = true;
451
- _localProxyFormState.current.isValid && control._updateValid(true);
452
- return () => {
453
- _mounted.current = false;
454
- };
466
+ _localProxyFormState.current.isValid && control._setValid(true);
455
467
  }, [control]);
456
- return getProxyFormState(formState, control, _localProxyFormState.current, false);
468
+ return React.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]);
457
469
  }
458
470
  var isString = (value) => typeof value === "string";
459
471
  var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => {
@@ -467,152 +479,250 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
467
479
  isGlobal && (_names.watchAll = true);
468
480
  return formValues;
469
481
  };
470
- function useWatch(props) {
471
- const methods = useFormContext();
472
- const { control = methods.control, name, defaultValue, disabled, exact } = props || {};
473
- const _name = React.useRef(name);
474
- _name.current = name;
475
- useSubscribe({
476
- disabled,
477
- subject: control._subjects.values,
478
- next: (formState) => {
479
- if (shouldSubscribeByName(_name.current, formState.name, exact)) {
480
- updateValue(cloneObject(generateWatchOutput(_name.current, control._names, formState.values || control._formValues, false, defaultValue)));
482
+ var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
483
+ const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
484
+ function deepEqual(object1, object2, visited = /* @__PURE__ */ new WeakMap()) {
485
+ if (object1 === object2) {
486
+ return true;
487
+ }
488
+ if (isPrimitive(object1) || isPrimitive(object2)) {
489
+ return Object.is(object1, object2);
490
+ }
491
+ if (isDateObject(object1) && isDateObject(object2)) {
492
+ return Object.is(object1.getTime(), object2.getTime());
493
+ }
494
+ const keys1 = Object.keys(object1);
495
+ const keys2 = Object.keys(object2);
496
+ if (keys1.length !== keys2.length) {
497
+ return false;
498
+ }
499
+ if (isEmptyObjectWithCustomPrototype(object1, keys1) || isEmptyObjectWithCustomPrototype(object2, keys2)) {
500
+ return Object.is(object1, object2);
501
+ }
502
+ if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
503
+ return false;
504
+ }
505
+ const visitedPairs = visited.get(object1);
506
+ if (visitedPairs && visitedPairs.has(object2)) {
507
+ return true;
508
+ }
509
+ if (visitedPairs) {
510
+ visitedPairs.add(object2);
511
+ } else {
512
+ const ws = /* @__PURE__ */ new WeakSet();
513
+ ws.add(object2);
514
+ visited.set(object1, ws);
515
+ }
516
+ for (const key of keys1) {
517
+ const val1 = object1[key];
518
+ if (!(key in object2)) {
519
+ return false;
520
+ }
521
+ if (key !== "ref") {
522
+ const val2 = object2[key];
523
+ if (isDateObject(val1) && isDateObject(val2) || (isObject(val1) || Array.isArray(val1)) && (isObject(val2) || Array.isArray(val2)) ? !deepEqual(val1, val2, visited) : !Object.is(val1, val2)) {
524
+ return false;
481
525
  }
482
526
  }
527
+ }
528
+ return true;
529
+ }
530
+ function useWatch(props) {
531
+ const formControl = useFormControlContext();
532
+ const { control = formControl, name, defaultValue, disabled, exact, compute } = props || {};
533
+ const _defaultValue = React.useRef(defaultValue);
534
+ const _compute = React.useRef(compute);
535
+ const _computeFormValues = React.useRef(void 0);
536
+ const _prevControl = React.useRef(control);
537
+ const _prevName = React.useRef(name);
538
+ _compute.current = compute;
539
+ const [value, updateValue] = React.useState(() => {
540
+ const defaultValue2 = control._getWatch(name, _defaultValue.current);
541
+ return _compute.current ? _compute.current(defaultValue2) : defaultValue2;
483
542
  });
484
- const [value, updateValue] = React.useState(control._getWatch(name, defaultValue));
543
+ const getCurrentOutput = React.useCallback((values) => {
544
+ const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
545
+ return _compute.current ? _compute.current(formValues) : formValues;
546
+ }, [control._formValues, control._names, name]);
547
+ const refreshValue = React.useCallback((values) => {
548
+ if (!disabled) {
549
+ const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
550
+ if (_compute.current) {
551
+ const computedFormValues = _compute.current(formValues);
552
+ if (!deepEqual(computedFormValues, _computeFormValues.current)) {
553
+ updateValue(computedFormValues);
554
+ _computeFormValues.current = computedFormValues;
555
+ }
556
+ } else {
557
+ updateValue(formValues);
558
+ }
559
+ }
560
+ }, [control._formValues, control._names, disabled, name]);
561
+ useIsomorphicLayoutEffect(() => {
562
+ if (_prevControl.current !== control || !deepEqual(_prevName.current, name)) {
563
+ _prevControl.current = control;
564
+ _prevName.current = name;
565
+ refreshValue();
566
+ }
567
+ return control._subscribe({
568
+ name,
569
+ formState: {
570
+ values: true
571
+ },
572
+ exact,
573
+ callback: (formState) => {
574
+ refreshValue(formState.values);
575
+ }
576
+ });
577
+ }, [control, exact, name, refreshValue]);
485
578
  React.useEffect(() => control._removeUnmounted());
486
- return value;
579
+ const controlChanged = _prevControl.current !== control;
580
+ const prevName = _prevName.current;
581
+ const computedOutput = React.useMemo(() => {
582
+ if (disabled) {
583
+ return null;
584
+ }
585
+ const nameChanged = !controlChanged && !deepEqual(prevName, name);
586
+ const shouldReturnImmediate = controlChanged || nameChanged;
587
+ return shouldReturnImmediate ? getCurrentOutput() : null;
588
+ }, [disabled, controlChanged, name, prevName, getCurrentOutput]);
589
+ return computedOutput !== null ? computedOutput : value;
487
590
  }
488
- var isKey = (value) => /^\w*$/.test(value);
489
- var stringToPath = (input) => compact(input.replace(/["|']|\]/g, "").split(/\.|\[/));
490
- var set = (object, path, value) => {
491
- let index = -1;
492
- const tempPath = isKey(path) ? [path] : stringToPath(path);
493
- const length = tempPath.length;
494
- const lastIndex = length - 1;
495
- while (++index < length) {
496
- const key = tempPath[index];
497
- let newValue = value;
498
- if (index !== lastIndex) {
499
- const objValue = object[key];
500
- newValue = isObject(objValue) || Array.isArray(objValue) ? objValue : !isNaN(+tempPath[index + 1]) ? [] : {};
501
- }
502
- object[key] = newValue;
503
- object = object[key];
504
- }
505
- return object;
506
- };
507
591
  function useController(props) {
508
- const methods = useFormContext();
509
- const { name, disabled, control = methods.control, shouldUnregister } = props;
592
+ const formControl = useFormControlContext();
593
+ const { name, disabled, control = formControl, shouldUnregister, defaultValue, exact = true } = props;
510
594
  const isArrayField = isNameInFieldArray(control._names.array, name);
595
+ const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
511
596
  const value = useWatch({
512
597
  control,
513
598
  name,
514
- defaultValue: get(control._formValues, name, get(control._defaultValues, name, props.defaultValue)),
515
- exact: true
599
+ defaultValue: defaultValueMemo,
600
+ exact
516
601
  });
517
602
  const formState = useFormState({
518
603
  control,
519
- name
604
+ name,
605
+ exact
520
606
  });
607
+ const _props = React.useRef(props);
608
+ const _proxyRef = React.useRef(null);
521
609
  const _registerProps = React.useRef(control.register(name, {
522
610
  ...props.rules,
523
611
  value,
524
612
  ...isBoolean(props.disabled) ? { disabled: props.disabled } : {}
525
613
  }));
614
+ _props.current = props;
615
+ const fieldState = React.useMemo(() => Object.defineProperties({}, {
616
+ invalid: {
617
+ enumerable: true,
618
+ get: () => !!get(formState.errors, name)
619
+ },
620
+ isDirty: {
621
+ enumerable: true,
622
+ get: () => !!get(formState.dirtyFields, name)
623
+ },
624
+ isTouched: {
625
+ enumerable: true,
626
+ get: () => !!get(formState.touchedFields, name)
627
+ },
628
+ isValidating: {
629
+ enumerable: true,
630
+ get: () => !!get(formState.validatingFields, name)
631
+ },
632
+ error: {
633
+ enumerable: true,
634
+ get: () => get(formState.errors, name)
635
+ }
636
+ }), [formState, name]);
637
+ const onChange = React.useCallback((event) => {
638
+ const value2 = getEventValue(event);
639
+ if (!get(control._fields, name)) {
640
+ _registerProps.current = control.register(name, {
641
+ ..._props.current.rules,
642
+ value: value2
643
+ });
644
+ }
645
+ return _registerProps.current.onChange({
646
+ target: {
647
+ value: getEventValue(event),
648
+ name
649
+ },
650
+ type: EVENTS.CHANGE
651
+ });
652
+ }, [name, control]);
653
+ const onBlur = React.useCallback(() => _registerProps.current.onBlur({
654
+ target: {
655
+ value: get(control._formValues, name),
656
+ name
657
+ },
658
+ type: EVENTS.BLUR
659
+ }), [name, control._formValues]);
660
+ const ref = React.useCallback((elm) => {
661
+ if (elm) {
662
+ _proxyRef.current = {
663
+ focus: () => isFunction(elm.focus) && elm.focus(),
664
+ select: () => isFunction(elm.select) && elm.select(),
665
+ setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
666
+ reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity()
667
+ };
668
+ }
669
+ const field2 = get(control._fields, name);
670
+ if (field2 && field2._f && elm) {
671
+ field2._f.ref = _proxyRef.current;
672
+ }
673
+ }, [control._fields, name]);
674
+ const field = React.useMemo(() => ({
675
+ name,
676
+ value,
677
+ ...isBoolean(disabled) || formState.disabled ? { disabled: formState.disabled || disabled } : {},
678
+ onChange,
679
+ onBlur,
680
+ ref
681
+ }), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
526
682
  React.useEffect(() => {
527
683
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
684
+ _registerProps.current = control.register(name, {
685
+ ..._props.current.rules,
686
+ ...isBoolean(_props.current.disabled) ? { disabled: _props.current.disabled } : {}
687
+ });
528
688
  const updateMounted = (name2, value2) => {
529
- const field = get(control._fields, name2);
530
- if (field) {
531
- field._f.mount = value2;
689
+ const field2 = get(control._fields, name2);
690
+ if (field2 && field2._f) {
691
+ field2._f.mount = value2;
532
692
  }
533
693
  };
534
694
  updateMounted(name, true);
535
695
  if (_shouldUnregisterField) {
536
- const value2 = cloneObject(get(control._options.defaultValues, name));
696
+ const value2 = cloneObject(get(shouldUnregister ? control._defaultValues : control._options.values || control._defaultValues, name, get(control._options.defaultValues, name, _props.current.defaultValue)));
537
697
  set(control._defaultValues, name, value2);
538
698
  if (isUndefined(get(control._formValues, name))) {
539
699
  set(control._formValues, name, value2);
540
700
  }
541
701
  }
702
+ !isArrayField && control.register(name);
703
+ if (_proxyRef.current) {
704
+ const field2 = get(control._fields, name);
705
+ if (field2 && field2._f) {
706
+ field2._f.ref = _proxyRef.current;
707
+ }
708
+ }
542
709
  return () => {
543
710
  (isArrayField ? _shouldUnregisterField && !control._state.action : _shouldUnregisterField) ? control.unregister(name) : updateMounted(name, false);
544
711
  };
545
712
  }, [name, control, isArrayField, shouldUnregister]);
546
713
  React.useEffect(() => {
547
- if (get(control._fields, name)) {
548
- control._updateDisabledField({
549
- disabled,
550
- fields: control._fields,
551
- name,
552
- value: get(control._fields, name)._f.value
553
- });
554
- }
714
+ control._setDisabledField({
715
+ disabled,
716
+ name
717
+ });
555
718
  }, [disabled, name, control]);
556
- return {
557
- field: {
558
- name,
559
- value,
560
- ...isBoolean(disabled) || isBoolean(formState.disabled) ? { disabled: formState.disabled || disabled } : {},
561
- onChange: React.useCallback((event) => _registerProps.current.onChange({
562
- target: {
563
- value: getEventValue(event),
564
- name
565
- },
566
- type: EVENTS.CHANGE
567
- }), [name]),
568
- onBlur: React.useCallback(() => _registerProps.current.onBlur({
569
- target: {
570
- value: get(control._formValues, name),
571
- name
572
- },
573
- type: EVENTS.BLUR
574
- }), [name, control]),
575
- ref: (elm) => {
576
- const field = get(control._fields, name);
577
- if (field && elm) {
578
- field._f.ref = {
579
- focus: () => elm.focus(),
580
- select: () => elm.select(),
581
- setCustomValidity: (message) => elm.setCustomValidity(message),
582
- reportValidity: () => elm.reportValidity()
583
- };
584
- }
585
- }
586
- },
719
+ return React.useMemo(() => ({
720
+ field,
587
721
  formState,
588
- fieldState: Object.defineProperties({}, {
589
- invalid: {
590
- enumerable: true,
591
- get: () => !!get(formState.errors, name)
592
- },
593
- isDirty: {
594
- enumerable: true,
595
- get: () => !!get(formState.dirtyFields, name)
596
- },
597
- isTouched: {
598
- enumerable: true,
599
- get: () => !!get(formState.touchedFields, name)
600
- },
601
- error: {
602
- enumerable: true,
603
- get: () => get(formState.errors, name)
604
- }
605
- })
606
- };
722
+ fieldState
723
+ }), [field, formState, fieldState]);
607
724
  }
608
725
  const Controller = (props) => props.render(useController(props));
609
- var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria ? {
610
- ...errors[name],
611
- types: {
612
- ...errors[name] && errors[name].types ? errors[name].types : {},
613
- [type]: message || true
614
- }
615
- } : {};
616
726
  var getValidationModes = (mode) => ({
617
727
  isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
618
728
  isOnBlur: mode === VALIDATION_MODE.onBlur,
@@ -620,7 +730,17 @@ var getValidationModes = (mode) => ({
620
730
  isOnAll: mode === VALIDATION_MODE.all,
621
731
  isOnTouch: mode === VALIDATION_MODE.onTouched
622
732
  });
623
- var isWatched = (name, _names, isBlurEvent) => !isBlurEvent && (_names.watchAll || _names.watch.has(name) || [..._names.watch].some((watchName) => name.startsWith(watchName) && /^\.\w+/.test(name.slice(watchName.length))));
733
+ var isWatched = (name, _names, isBlurEvent) => {
734
+ if (isBlurEvent)
735
+ return false;
736
+ if (_names.watchAll || _names.watch.has(name))
737
+ return true;
738
+ for (const watchName of _names.watch) {
739
+ if (name.startsWith(watchName) && name.charAt(watchName.length) === ".")
740
+ return true;
741
+ }
742
+ return false;
743
+ };
624
744
  const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
625
745
  for (const key of fieldsNames || Object.keys(fields)) {
626
746
  const field = get(fields, key);
@@ -628,26 +748,31 @@ const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
628
748
  const { _f, ...currentField } = field;
629
749
  if (_f) {
630
750
  if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
631
- break;
751
+ return true;
632
752
  } else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
633
- break;
753
+ return true;
634
754
  } else {
635
- iterateFieldsByAction(currentField, action);
755
+ if (iterateFieldsByAction(currentField, action)) {
756
+ break;
757
+ }
636
758
  }
637
759
  } else if (isObject(currentField)) {
638
- iterateFieldsByAction(currentField, action);
760
+ if (iterateFieldsByAction(currentField, action)) {
761
+ break;
762
+ }
639
763
  }
640
764
  }
641
765
  }
766
+ return;
642
767
  };
643
768
  var updateFieldArrayRootError = (errors, error, name) => {
644
- const fieldArrayErrors = compact(get(errors, name));
645
- set(fieldArrayErrors, "root", error[name]);
769
+ const existingErrors = get(errors, name);
770
+ const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
771
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
646
772
  set(errors, name, fieldArrayErrors);
647
773
  return errors;
648
774
  };
649
- var isFileInput = (element) => element.type === "file";
650
- var isFunction = (value) => typeof value === "function";
775
+ var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
651
776
  var isHTMLElement = (value) => {
652
777
  if (!isWeb) {
653
778
  return false;
@@ -655,9 +780,15 @@ var isHTMLElement = (value) => {
655
780
  const owner = value ? value.ownerDocument : 0;
656
781
  return value instanceof (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement);
657
782
  };
658
- var isMessage = (value) => isString(value);
659
783
  var isRadioInput = (element) => element.type === "radio";
660
784
  var isRegex = (value) => value instanceof RegExp;
785
+ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria ? {
786
+ ...errors[name],
787
+ types: {
788
+ ...errors[name] && errors[name].types ? errors[name].types : {},
789
+ [type]: message || true
790
+ }
791
+ } : {};
661
792
  const defaultResult = {
662
793
  value: false,
663
794
  isValid: false
@@ -685,10 +816,10 @@ var getRadioValue = (options) => Array.isArray(options) ? options.reduce((previo
685
816
  value: option.value
686
817
  } : previous, defaultReturn) : defaultReturn;
687
818
  function getValidateError(result, ref, type = "validate") {
688
- if (isMessage(result) || Array.isArray(result) && result.every(isMessage) || isBoolean(result) && !result) {
819
+ if (isString(result) || Array.isArray(result) && result.every(isString) || isBoolean(result) && !result) {
689
820
  return {
690
821
  type,
691
- message: isMessage(result) ? result : "",
822
+ message: isString(result) ? result : "",
692
823
  ref
693
824
  };
694
825
  }
@@ -697,16 +828,21 @@ var getValueAndMessage = (validationData) => isObject(validationData) && !isRege
697
828
  value: validationData,
698
829
  message: ""
699
830
  };
700
- var validateField = async (field, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
701
- const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, disabled } = field._f;
831
+ var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
832
+ const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount } = field._f;
702
833
  const inputValue = get(formValues, name);
703
- if (!mount || disabled) {
834
+ if (!mount || disabledFieldNames.has(name)) {
704
835
  return {};
705
836
  }
706
837
  const inputRef = refs ? refs[0] : ref;
707
838
  const setCustomValidity = (message) => {
708
839
  if (shouldUseNativeValidation && inputRef.reportValidity) {
709
- inputRef.setCustomValidity(isBoolean(message) ? "" : message || "");
840
+ const validityMessage = isBoolean(message) ? "" : message || "";
841
+ if (refs) {
842
+ refs.forEach((ref2) => ref2.setCustomValidity(validityMessage));
843
+ } else {
844
+ inputRef.setCustomValidity(validityMessage);
845
+ }
710
846
  inputRef.reportValidity();
711
847
  }
712
848
  };
@@ -726,7 +862,7 @@ var validateField = async (field, formValues, validateAllFieldCriteria, shouldUs
726
862
  };
727
863
  };
728
864
  if (isFieldArray ? !Array.isArray(inputValue) || !inputValue.length : required && (!isRadioOrCheckbox2 && (isEmpty || isNullOrUndefined(inputValue)) || isBoolean(inputValue) && !inputValue || isCheckBox && !getCheckboxValue(refs).isValid || isRadio && !getRadioValue(refs).isValid)) {
729
- const { value, message } = isMessage(required) ? { value: !!required, message: required } : getValueAndMessage(required);
865
+ const { value, message } = isString(required) ? { value: !!required, message: required } : getValueAndMessage(required);
730
866
  if (value) {
731
867
  error[name] = {
732
868
  type: INPUT_VALIDATION_RULES.required,
@@ -847,11 +983,18 @@ var validateField = async (field, formValues, validateAllFieldCriteria, shouldUs
847
983
  setCustomValidity(true);
848
984
  return error;
849
985
  };
986
+ var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
987
+ var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
850
988
  function baseGet(object, updatePath) {
851
989
  const length = updatePath.slice(0, -1).length;
852
990
  let index = 0;
853
991
  while (index < length) {
854
- object = isUndefined(object) ? index++ : object[updatePath[index++]];
992
+ if (isNullOrUndefined(object)) {
993
+ object = void 0;
994
+ break;
995
+ }
996
+ object = object[updatePath[index]];
997
+ index++;
855
998
  }
856
999
  return object;
857
1000
  }
@@ -864,7 +1007,14 @@ function isEmptyArray(obj) {
864
1007
  return true;
865
1008
  }
866
1009
  function unset(object, path) {
1010
+ if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
1011
+ delete object[path];
1012
+ return object;
1013
+ }
867
1014
  const paths = Array.isArray(path) ? path : isKey(path) ? [path] : stringToPath(path);
1015
+ if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
1016
+ return object;
1017
+ }
868
1018
  const childObject = paths.length === 1 ? object : baseGet(object, paths);
869
1019
  const index = paths.length - 1;
870
1020
  const key = paths[index];
@@ -876,6 +1026,22 @@ function unset(object, path) {
876
1026
  }
877
1027
  return object;
878
1028
  }
1029
+ const flatten = (obj) => {
1030
+ const output = {};
1031
+ for (const key of Object.keys(obj)) {
1032
+ if (isObjectType(obj[key]) && obj[key] !== null && !isDateObject(obj[key])) {
1033
+ const nested = flatten(obj[key]);
1034
+ for (const nestedKey of Object.keys(nested)) {
1035
+ output[`${key}.${nestedKey}`] = nested[nestedKey];
1036
+ }
1037
+ } else {
1038
+ output[key] = obj[key];
1039
+ }
1040
+ }
1041
+ return output;
1042
+ };
1043
+ const HookFormContext = React.createContext(null);
1044
+ HookFormContext.displayName = "HookFormContext";
879
1045
  var createSubject = () => {
880
1046
  let _observers = [];
881
1047
  const next = (value) => {
@@ -903,32 +1069,23 @@ var createSubject = () => {
903
1069
  unsubscribe
904
1070
  };
905
1071
  };
906
- var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
907
- function deepEqual(object1, object2) {
908
- if (isPrimitive(object1) || isPrimitive(object2)) {
909
- return object1 === object2;
910
- }
911
- if (isDateObject(object1) && isDateObject(object2)) {
912
- return object1.getTime() === object2.getTime();
913
- }
914
- const keys1 = Object.keys(object1);
915
- const keys2 = Object.keys(object2);
916
- if (keys1.length !== keys2.length) {
917
- return false;
918
- }
919
- for (const key of keys1) {
920
- const val1 = object1[key];
921
- if (!keys2.includes(key)) {
922
- return false;
923
- }
924
- if (key !== "ref") {
925
- const val2 = object2[key];
926
- if (isDateObject(val1) && isDateObject(val2) || isObject(val1) && isObject(val2) || Array.isArray(val1) && Array.isArray(val2) ? !deepEqual(val1, val2) : val1 !== val2) {
927
- return false;
1072
+ function extractFormValues(fieldsState, formValues) {
1073
+ const values = {};
1074
+ for (const key in fieldsState) {
1075
+ if (fieldsState.hasOwnProperty(key)) {
1076
+ const fieldState = fieldsState[key];
1077
+ const fieldValue = formValues[key];
1078
+ if (fieldState && isObject(fieldState) && fieldValue) {
1079
+ const nestedFieldsState = extractFormValues(fieldState, fieldValue);
1080
+ if (isObject(nestedFieldsState)) {
1081
+ values[key] = nestedFieldsState;
1082
+ }
1083
+ } else if (fieldsState[key]) {
1084
+ values[key] = fieldValue;
928
1085
  }
929
1086
  }
930
1087
  }
931
- return true;
1088
+ return values;
932
1089
  }
933
1090
  var isMultipleSelect = (element) => element.type === `select-multiple`;
934
1091
  var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
@@ -941,44 +1098,65 @@ var objectHasFunction = (data) => {
941
1098
  }
942
1099
  return false;
943
1100
  };
944
- function markFieldsDirty(data, fields = {}) {
945
- const isParentNodeArray = Array.isArray(data);
946
- if (isObject(data) || isParentNodeArray) {
947
- for (const key in data) {
948
- if (Array.isArray(data[key]) || isObject(data[key]) && !objectHasFunction(data[key])) {
949
- fields[key] = Array.isArray(data[key]) ? [] : {};
950
- markFieldsDirty(data[key], fields[key]);
951
- } else if (!isNullOrUndefined(data[key])) {
952
- fields[key] = true;
1101
+ function isTraversable(value) {
1102
+ return Array.isArray(value) || isObject(value) && !objectHasFunction(value);
1103
+ }
1104
+ function isRegisteredLeaf(fieldRef) {
1105
+ return !!(fieldRef && "_f" in fieldRef);
1106
+ }
1107
+ function isEmptyDirtyContainer(value) {
1108
+ return Array.isArray(value) ? !value.some((item) => !isUndefined(item)) : !Object.keys(value).length;
1109
+ }
1110
+ function clearDirtyField(container, key) {
1111
+ if (Array.isArray(container)) {
1112
+ container[key] = void 0;
1113
+ } else {
1114
+ delete container[key];
1115
+ }
1116
+ }
1117
+ function markFieldsDirty(data, fields = {}, fieldRefs) {
1118
+ for (const key in data) {
1119
+ const value = data[key];
1120
+ const fieldRef = fieldRefs && fieldRefs[key];
1121
+ if (isTraversable(value) && (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
1122
+ fields[key] = Array.isArray(value) ? [] : {};
1123
+ markFieldsDirty(value, fields[key], fieldRef);
1124
+ if (isEmptyDirtyContainer(fields[key])) {
1125
+ clearDirtyField(fields, key);
953
1126
  }
1127
+ } else if (!isUndefined(value)) {
1128
+ fields[key] = true;
954
1129
  }
955
1130
  }
956
1131
  return fields;
957
1132
  }
958
- function getDirtyFieldsFromDefaultValues(data, formValues, dirtyFieldsFromValues) {
959
- const isParentNodeArray = Array.isArray(data);
960
- if (isObject(data) || isParentNodeArray) {
961
- for (const key in data) {
962
- if (Array.isArray(data[key]) || isObject(data[key]) && !objectHasFunction(data[key])) {
963
- if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
964
- dirtyFieldsFromValues[key] = Array.isArray(data[key]) ? markFieldsDirty(data[key], []) : { ...markFieldsDirty(data[key]) };
965
- } else {
966
- getDirtyFieldsFromDefaultValues(data[key], isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
967
- }
1133
+ function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
1134
+ if (!dirtyFieldsFromValues) {
1135
+ dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
1136
+ }
1137
+ for (const key in data) {
1138
+ const value = data[key];
1139
+ const fieldRef = fieldRefs && fieldRefs[key];
1140
+ if (isTraversable(value) && (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
1141
+ if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
1142
+ dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
968
1143
  } else {
969
- dirtyFieldsFromValues[key] = !deepEqual(data[key], formValues[key]);
1144
+ getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
970
1145
  }
1146
+ if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) {
1147
+ clearDirtyField(dirtyFieldsFromValues, key);
1148
+ }
1149
+ } else if (deepEqual(value, formValues[key])) {
1150
+ clearDirtyField(dirtyFieldsFromValues, key);
1151
+ } else {
1152
+ dirtyFieldsFromValues[key] = true;
971
1153
  }
972
1154
  }
973
1155
  return dirtyFieldsFromValues;
974
1156
  }
975
- var getDirtyFields = (defaultValues, formValues) => getDirtyFieldsFromDefaultValues(defaultValues, formValues, markFieldsDirty(formValues));
976
1157
  var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value) ? value : valueAsNumber ? value === "" ? NaN : value ? +value : value : valueAsDate && isString(value) ? new Date(value) : setValueAs ? setValueAs(value) : value;
977
1158
  function getFieldValue(_f) {
978
1159
  const ref = _f.ref;
979
- if (_f.refs ? _f.refs.every((ref2) => ref2.disabled) : ref.disabled) {
980
- return;
981
- }
982
1160
  if (isFileInput(ref)) {
983
1161
  return ref.files;
984
1162
  }
@@ -1007,6 +1185,22 @@ var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeVal
1007
1185
  };
1008
1186
  };
1009
1187
  var getRuleValue = (rule) => isUndefined(rule) ? rule : isRegex(rule) ? rule.source : isObject(rule) ? isRegex(rule.value) ? rule.value.source : rule.value : rule;
1188
+ const ASYNC_FUNCTION = "AsyncFunction";
1189
+ var hasPromiseValidation = (fieldReference) => {
1190
+ if (!fieldReference || !fieldReference.validate)
1191
+ return false;
1192
+ if (isFunction(fieldReference.validate)) {
1193
+ return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
1194
+ }
1195
+ if (isObject(fieldReference.validate)) {
1196
+ for (const key in fieldReference.validate) {
1197
+ if (fieldReference.validate[key].constructor.name === ASYNC_FUNCTION) {
1198
+ return true;
1199
+ }
1200
+ }
1201
+ }
1202
+ return false;
1203
+ };
1010
1204
  var hasValidation = (options) => options.mount && (options.required || options.min || options.max || options.maxLength || options.minLength || options.pattern || options.validate);
1011
1205
  function schemaErrorLookup(errors, _fields, name) {
1012
1206
  const error = get(errors, name);
@@ -1030,12 +1224,25 @@ function schemaErrorLookup(errors, _fields, name) {
1030
1224
  error: foundError
1031
1225
  };
1032
1226
  }
1227
+ if (foundError && foundError.root && foundError.root.type) {
1228
+ return {
1229
+ name: `${fieldName}.root`,
1230
+ error: foundError.root
1231
+ };
1232
+ }
1033
1233
  names.pop();
1034
1234
  }
1035
1235
  return {
1036
1236
  name
1037
1237
  };
1038
1238
  }
1239
+ var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
1240
+ updateFormState(formStateData);
1241
+ const { name, ...formState } = formStateData;
1242
+ const keys = Object.keys(formState);
1243
+ return !keys.length || isRoot && keys.length >= Object.keys(_proxyFormState).length || keys.find((key) => _proxyFormState[key] === (!isRoot || VALIDATION_MODE.all));
1244
+ };
1245
+ var shouldSubscribeByName = (name, signalName, exact) => !name || !signalName || name === signalName || convertToArrayPayload(name).some((currentName) => currentName && (exact ? currentName === signalName || currentName.startsWith(signalName + ".") : currentName.startsWith(signalName) || signalName.startsWith(currentName)));
1039
1246
  var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
1040
1247
  if (mode.isOnAll) {
1041
1248
  return false;
@@ -1054,24 +1261,38 @@ const defaultOptions = {
1054
1261
  reValidateMode: VALIDATION_MODE.onChange,
1055
1262
  shouldFocusError: true
1056
1263
  };
1057
- function createFormControl(props = {}, flushRootRender) {
1264
+ const FORM_ERROR_TYPE = "form";
1265
+ const updateDirtyFields = (dirtyFields, nextDirtyFields) => {
1266
+ for (const key in dirtyFields) {
1267
+ if (!(key in nextDirtyFields)) {
1268
+ delete dirtyFields[key];
1269
+ }
1270
+ }
1271
+ Object.assign(dirtyFields, nextDirtyFields);
1272
+ };
1273
+ const DEFAULT_FORM_STATE = {
1274
+ submitCount: 0,
1275
+ isDirty: false,
1276
+ isReady: false,
1277
+ isValidating: false,
1278
+ isSubmitted: false,
1279
+ isSubmitting: false,
1280
+ isSubmitSuccessful: false,
1281
+ isValid: false,
1282
+ touchedFields: {},
1283
+ dirtyFields: {},
1284
+ validatingFields: {}
1285
+ };
1286
+ function createFormControl(props = {}) {
1058
1287
  let _options = {
1059
1288
  ...defaultOptions,
1060
1289
  ...props
1061
1290
  };
1062
1291
  let _formState = {
1063
- submitCount: 0,
1064
- isDirty: false,
1292
+ ...cloneObject(DEFAULT_FORM_STATE),
1065
1293
  isLoading: isFunction(_options.defaultValues),
1066
- isValidating: false,
1067
- isSubmitted: false,
1068
- isSubmitting: false,
1069
- isSubmitSuccessful: false,
1070
- isValid: false,
1071
- touchedFields: {},
1072
- dirtyFields: {},
1073
1294
  errors: _options.errors || {},
1074
- disabled: false
1295
+ disabled: _options.disabled || false
1075
1296
  };
1076
1297
  let _fields = {};
1077
1298
  let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values) ? cloneObject(_options.defaultValues || _options.values) || {} : {};
@@ -1079,52 +1300,89 @@ function createFormControl(props = {}, flushRootRender) {
1079
1300
  let _state = {
1080
1301
  action: false,
1081
1302
  mount: false,
1082
- watch: false
1303
+ watch: false,
1304
+ keepIsValid: false
1083
1305
  };
1084
1306
  let _names = {
1085
1307
  mount: /* @__PURE__ */ new Set(),
1308
+ disabled: /* @__PURE__ */ new Set(),
1086
1309
  unMount: /* @__PURE__ */ new Set(),
1087
1310
  array: /* @__PURE__ */ new Set(),
1088
- watch: /* @__PURE__ */ new Set()
1311
+ watch: /* @__PURE__ */ new Set(),
1312
+ registerName: /* @__PURE__ */ new Set()
1089
1313
  };
1090
- let delayErrorCallback;
1091
- let timer = 0;
1092
- const _proxyFormState = {
1314
+ const delayErrorCallbacks = {};
1315
+ const timers = {};
1316
+ let _valuesSubscriberCount = 0;
1317
+ let _validationModeBeforeSubmit = getValidationModes(_options.mode);
1318
+ let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1319
+ const defaultProxyFormState = {
1093
1320
  isDirty: false,
1094
1321
  dirtyFields: false,
1322
+ validatingFields: false,
1095
1323
  touchedFields: false,
1096
1324
  isValidating: false,
1097
1325
  isValid: false,
1098
1326
  errors: false
1099
1327
  };
1328
+ const _proxyFormState = {
1329
+ ...defaultProxyFormState
1330
+ };
1331
+ let _proxySubscribeFormState = {
1332
+ ..._proxyFormState
1333
+ };
1100
1334
  const _subjects = {
1101
- values: createSubject(),
1102
1335
  array: createSubject(),
1103
1336
  state: createSubject()
1104
1337
  };
1105
- const shouldCaptureDirtyFields = props.resetOptions && props.resetOptions.keepDirtyValues;
1106
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1107
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1338
+ let _setValidCallId = 0;
1108
1339
  const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
1109
- const debounce = (callback) => (wait) => {
1110
- clearTimeout(timer);
1111
- timer = setTimeout(callback, wait);
1112
- };
1113
- const _updateValid = async (shouldUpdateValid) => {
1114
- if (_proxyFormState.isValid || shouldUpdateValid) {
1115
- const isValid = _options.resolver ? isEmptyObject((await _executeSchema()).errors) : await executeBuiltInValidation(_fields, true);
1116
- if (isValid !== _formState.isValid) {
1340
+ const debounce = (name, callback) => (wait) => {
1341
+ clearTimeout(timers[name]);
1342
+ timers[name] = setTimeout(callback, wait);
1343
+ };
1344
+ const _setValid = async (shouldUpdateValid) => {
1345
+ if (_state.keepIsValid) {
1346
+ return;
1347
+ }
1348
+ if (!_options.disabled && (_proxyFormState.isValid || _proxySubscribeFormState.isValid || shouldUpdateValid)) {
1349
+ const callId = ++_setValidCallId;
1350
+ let isValid;
1351
+ if (_options.resolver) {
1352
+ isValid = isEmptyObject((await _runSchema()).errors);
1353
+ callId === _setValidCallId && _updateIsValidating();
1354
+ } else {
1355
+ isValid = await executeBuiltInValidation({
1356
+ fields: _fields,
1357
+ onlyCheckValid: true,
1358
+ eventType: EVENTS.VALID
1359
+ });
1360
+ }
1361
+ if (callId === _setValidCallId && isValid !== _formState.isValid) {
1117
1362
  _subjects.state.next({
1118
1363
  isValid
1119
1364
  });
1120
1365
  }
1121
1366
  }
1122
1367
  };
1123
- const _updateIsValidating = (value) => _proxyFormState.isValidating && _subjects.state.next({
1124
- isValidating: value
1125
- });
1126
- const _updateFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1127
- if (args && method) {
1368
+ const _updateIsValidating = (names, isValidating) => {
1369
+ if (!_options.disabled && (_proxyFormState.isValidating || _proxyFormState.validatingFields || _proxySubscribeFormState.isValidating || _proxySubscribeFormState.validatingFields)) {
1370
+ (names || Array.from(_names.mount)).forEach((name) => {
1371
+ if (name) {
1372
+ isValidating ? set(_formState.validatingFields, name, isValidating) : unset(_formState.validatingFields, name);
1373
+ }
1374
+ });
1375
+ _subjects.state.next({
1376
+ validatingFields: _formState.validatingFields,
1377
+ isValidating: !isEmptyObject(_formState.validatingFields)
1378
+ });
1379
+ }
1380
+ };
1381
+ const _updateDirtyFields = () => {
1382
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, void 0, _fields);
1383
+ };
1384
+ const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1385
+ if (args && method && !_options.disabled) {
1128
1386
  _state.action = true;
1129
1387
  if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
1130
1388
  const fieldValues = method(get(_fields, name), args.argA, args.argB);
@@ -1135,12 +1393,12 @@ function createFormControl(props = {}, flushRootRender) {
1135
1393
  shouldSetValues && set(_formState.errors, name, errors);
1136
1394
  unsetEmptyArray(_formState.errors, name);
1137
1395
  }
1138
- if (_proxyFormState.touchedFields && shouldUpdateFieldsAndState && Array.isArray(get(_formState.touchedFields, name))) {
1396
+ if ((_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) && shouldUpdateFieldsAndState && Array.isArray(get(_formState.touchedFields, name))) {
1139
1397
  const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
1140
1398
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1141
1399
  }
1142
- if (_proxyFormState.dirtyFields) {
1143
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1400
+ if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
1401
+ _updateDirtyFields();
1144
1402
  }
1145
1403
  _subjects.state.next({
1146
1404
  name,
@@ -1155,6 +1413,7 @@ function createFormControl(props = {}, flushRootRender) {
1155
1413
  };
1156
1414
  const updateErrors = (name, error) => {
1157
1415
  set(_formState.errors, name, error);
1416
+ _formState.errors = { ..._formState.errors };
1158
1417
  _subjects.state.next({
1159
1418
  errors: _formState.errors
1160
1419
  });
@@ -1166,12 +1425,42 @@ function createFormControl(props = {}, flushRootRender) {
1166
1425
  isValid: false
1167
1426
  });
1168
1427
  };
1428
+ const hasExplicitNullIntermediate = (name) => {
1429
+ const segments = isKey(name) ? [name] : stringToPath(name);
1430
+ let formValues = _formValues;
1431
+ let defaultValues = _defaultValues;
1432
+ for (let i = 0; i < segments.length - 1; i++) {
1433
+ const key = segments[i];
1434
+ formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
1435
+ defaultValues = isNullOrUndefined(defaultValues) ? defaultValues : defaultValues[key];
1436
+ if (formValues === null && defaultValues !== null) {
1437
+ return true;
1438
+ }
1439
+ }
1440
+ return false;
1441
+ };
1169
1442
  const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
1170
1443
  const field = get(_fields, name);
1171
1444
  if (field) {
1445
+ if (hasExplicitNullIntermediate(name)) {
1446
+ return;
1447
+ }
1448
+ const wasUnsetInFormValues = isUndefined(get(_formValues, name));
1172
1449
  const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
1173
1450
  isUndefined(defaultValue) || ref && ref.defaultChecked || shouldSkipSetValueAs ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f)) : setFieldValue(name, defaultValue);
1174
- _state.mount && _updateValid();
1451
+ if (_state.mount && !_state.action) {
1452
+ _setValid();
1453
+ if (wasUnsetInFormValues && _formState.isDirty && (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
1454
+ const isDirty = _getDirty();
1455
+ if (!isDirty) {
1456
+ _formState.isDirty = false;
1457
+ _subjects.state.next({ ..._formState });
1458
+ }
1459
+ }
1460
+ if (props.shouldUnregister && wasUnsetInFormValues && !isUndefined(get(_formValues, name)) && isWatched(name, _names)) {
1461
+ _state.watch = true;
1462
+ }
1463
+ }
1175
1464
  }
1176
1465
  };
1177
1466
  const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
@@ -1180,40 +1469,46 @@ function createFormControl(props = {}, flushRootRender) {
1180
1469
  const output = {
1181
1470
  name
1182
1471
  };
1183
- const disabledField = get(_fields, name) && get(_fields, name)._f.disabled;
1184
- if (!isBlurEvent || shouldDirty) {
1185
- if (_proxyFormState.isDirty) {
1186
- isPreviousDirty = _formState.isDirty;
1187
- _formState.isDirty = output.isDirty = _getDirty();
1188
- shouldUpdateField = isPreviousDirty !== output.isDirty;
1189
- }
1190
- const isCurrentFieldPristine = disabledField || deepEqual(get(_defaultValues, name), fieldValue);
1191
- isPreviousDirty = !disabledField && get(_formState.dirtyFields, name);
1192
- isCurrentFieldPristine || disabledField ? unset(_formState.dirtyFields, name) : set(_formState.dirtyFields, name, true);
1193
- output.dirtyFields = _formState.dirtyFields;
1194
- shouldUpdateField = shouldUpdateField || _proxyFormState.dirtyFields && isPreviousDirty !== !isCurrentFieldPristine;
1195
- }
1196
- if (isBlurEvent) {
1197
- const isPreviousFieldTouched = get(_formState.touchedFields, name);
1198
- if (!isPreviousFieldTouched) {
1199
- set(_formState.touchedFields, name, isBlurEvent);
1200
- output.touchedFields = _formState.touchedFields;
1201
- shouldUpdateField = shouldUpdateField || _proxyFormState.touchedFields && isPreviousFieldTouched !== isBlurEvent;
1202
- }
1203
- }
1204
- shouldUpdateField && shouldRender && _subjects.state.next(output);
1472
+ if (!_options.disabled || shouldDirty === true) {
1473
+ if (!isBlurEvent || shouldDirty) {
1474
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1475
+ if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
1476
+ isPreviousDirty = _formState.isDirty;
1477
+ _formState.isDirty = output.isDirty = !isCurrentFieldPristine || _getDirty();
1478
+ shouldUpdateField = isPreviousDirty !== output.isDirty;
1479
+ }
1480
+ isPreviousDirty = !!get(_formState.dirtyFields, name);
1481
+ if (isCurrentFieldPristine !== _formState.isDirty) {
1482
+ updateDirtyFields(_formState.dirtyFields, getDirtyFields(_defaultValues, _formValues, void 0, _fields));
1483
+ } else {
1484
+ isCurrentFieldPristine ? unset(_formState.dirtyFields, name) : set(_formState.dirtyFields, name, true);
1485
+ }
1486
+ output.dirtyFields = _formState.dirtyFields;
1487
+ shouldUpdateField = shouldUpdateField || (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) && isPreviousDirty !== !isCurrentFieldPristine;
1488
+ }
1489
+ if (isBlurEvent) {
1490
+ const isPreviousFieldTouched = get(_formState.touchedFields, name);
1491
+ if (!isPreviousFieldTouched) {
1492
+ set(_formState.touchedFields, name, isBlurEvent);
1493
+ output.touchedFields = _formState.touchedFields;
1494
+ shouldUpdateField = shouldUpdateField || (_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) && isPreviousFieldTouched !== isBlurEvent;
1495
+ }
1496
+ }
1497
+ shouldUpdateField && shouldRender && _subjects.state.next(output);
1498
+ }
1205
1499
  return shouldUpdateField ? output : {};
1206
1500
  };
1207
1501
  const shouldRenderByError = (name, isValid, error, fieldState) => {
1208
1502
  const previousFieldError = get(_formState.errors, name);
1209
- const shouldUpdateValid = _proxyFormState.isValid && isBoolean(isValid) && _formState.isValid !== isValid;
1210
- if (props.delayError && error) {
1211
- delayErrorCallback = debounce(() => updateErrors(name, error));
1212
- delayErrorCallback(props.delayError);
1503
+ const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) && isBoolean(isValid) && _formState.isValid !== isValid;
1504
+ if (_options.delayError && error) {
1505
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
1506
+ delayErrorCallbacks[name](_options.delayError);
1213
1507
  } else {
1214
- clearTimeout(timer);
1215
- delayErrorCallback = null;
1508
+ clearTimeout(timers[name]);
1509
+ delete delayErrorCallbacks[name];
1216
1510
  error ? set(_formState.errors, name, error) : unset(_formState.errors, name);
1511
+ _formState.errors = { ..._formState.errors };
1217
1512
  }
1218
1513
  if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) || !isEmptyObject(fieldState) || shouldUpdateValid) {
1219
1514
  const updatedFormState = {
@@ -1228,40 +1523,105 @@ function createFormControl(props = {}, flushRootRender) {
1228
1523
  };
1229
1524
  _subjects.state.next(updatedFormState);
1230
1525
  }
1231
- _updateIsValidating(false);
1232
1526
  };
1233
- const _executeSchema = async (name) => _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1527
+ const _runSchema = async (name) => {
1528
+ _updateIsValidating(name, true);
1529
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1530
+ };
1234
1531
  const executeSchemaAndUpdateState = async (names) => {
1235
- const { errors } = await _executeSchema(names);
1532
+ const { errors } = await _runSchema(names);
1533
+ _updateIsValidating(names);
1236
1534
  if (names) {
1237
1535
  for (const name of names) {
1238
1536
  const error = get(errors, name);
1239
- error ? set(_formState.errors, name, error) : unset(_formState.errors, name);
1537
+ error ? _names.array.has(name) && isObject(error) && !Object.keys(error).some((key) => !Number.isNaN(Number(key))) ? updateFieldArrayRootError(_formState.errors, { [name]: error }, name) : set(_formState.errors, name, error) : unset(_formState.errors, name);
1240
1538
  }
1539
+ _formState.errors = { ..._formState.errors };
1241
1540
  } else {
1242
1541
  _formState.errors = errors;
1243
1542
  }
1244
1543
  return errors;
1245
1544
  };
1246
- const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
1247
- valid: true
1248
- }) => {
1249
- for (const name in fields) {
1250
- const field = fields[name];
1545
+ const validateForm = async ({ name, eventType }) => {
1546
+ if (props.validate) {
1547
+ const result = await props.validate({
1548
+ formValues: _formValues,
1549
+ formState: _formState,
1550
+ name,
1551
+ eventType
1552
+ });
1553
+ if (isObject(result)) {
1554
+ for (const key in result) {
1555
+ const error = result[key];
1556
+ if (error) {
1557
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
1558
+ message: isString(error.message) ? error.message : "",
1559
+ type: error.type || INPUT_VALIDATION_RULES.validate
1560
+ });
1561
+ }
1562
+ }
1563
+ } else if (isString(result) || !result) {
1564
+ setError(FORM_ERROR_TYPE, {
1565
+ message: result || "",
1566
+ type: INPUT_VALIDATION_RULES.validate
1567
+ });
1568
+ } else {
1569
+ clearErrors(FORM_ERROR_TYPE);
1570
+ }
1571
+ return result;
1572
+ }
1573
+ return true;
1574
+ };
1575
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1576
+ valid: true,
1577
+ runRootValidation: false
1578
+ } }) => {
1579
+ if (props.validate) {
1580
+ context.runRootValidation = true;
1581
+ const result = await validateForm({
1582
+ name,
1583
+ eventType
1584
+ });
1585
+ if (!result) {
1586
+ context.valid = false;
1587
+ if (onlyCheckValid) {
1588
+ return context.valid;
1589
+ }
1590
+ }
1591
+ }
1592
+ for (const name2 in fields) {
1593
+ const field = fields[name2];
1251
1594
  if (field) {
1252
1595
  const { _f, ...fieldValue } = field;
1253
1596
  if (_f) {
1254
1597
  const isFieldArrayRoot = _names.array.has(_f.name);
1255
- const fieldError = await validateField(field, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1598
+ const isPromiseFunction = field._f && hasPromiseValidation(field._f);
1599
+ const shouldTrackIsValidatingState = _proxyFormState.validatingFields || _proxyFormState.isValidating || _proxySubscribeFormState.validatingFields || _proxySubscribeFormState.isValidating;
1600
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1601
+ _updateIsValidating([_f.name], true);
1602
+ }
1603
+ const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1604
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1605
+ _updateIsValidating([_f.name]);
1606
+ }
1256
1607
  if (fieldError[_f.name]) {
1257
1608
  context.valid = false;
1258
- if (shouldOnlyCheckValid) {
1609
+ if (onlyCheckValid) {
1259
1610
  break;
1260
1611
  }
1261
1612
  }
1262
- !shouldOnlyCheckValid && (get(fieldError, _f.name) ? isFieldArrayRoot ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name) : set(_formState.errors, _f.name, fieldError[_f.name]) : unset(_formState.errors, _f.name));
1613
+ !onlyCheckValid && (get(fieldError, _f.name) ? isFieldArrayRoot ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name) : set(_formState.errors, _f.name, fieldError[_f.name]) : unset(_formState.errors, _f.name));
1614
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1615
+ break;
1616
+ }
1263
1617
  }
1264
- fieldValue && await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context);
1618
+ !isEmptyObject(fieldValue) && await executeBuiltInValidation({
1619
+ context,
1620
+ onlyCheckValid,
1621
+ fields: fieldValue,
1622
+ name: name2,
1623
+ eventType
1624
+ });
1265
1625
  }
1266
1626
  }
1267
1627
  return context.valid;
@@ -1273,12 +1633,12 @@ function createFormControl(props = {}, flushRootRender) {
1273
1633
  }
1274
1634
  _names.unMount = /* @__PURE__ */ new Set();
1275
1635
  };
1276
- const _getDirty = (name, data) => (name && data && set(_formValues, name, data), !deepEqual(getValues(), _defaultValues));
1636
+ const _getDirty = (name, data) => (name && data && set(_formValues, name, data), !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1277
1637
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1278
1638
  ..._state.mount ? _formValues : isUndefined(defaultValue) ? _defaultValues : isString(names) ? { [names]: defaultValue } : defaultValue
1279
1639
  }, isGlobal, defaultValue);
1280
- const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []));
1281
- const setFieldValue = (name, value, options = {}) => {
1640
+ const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1641
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
1282
1642
  const field = get(_fields, name);
1283
1643
  let fieldValue = value;
1284
1644
  if (field) {
@@ -1290,7 +1650,15 @@ function createFormControl(props = {}, flushRootRender) {
1290
1650
  [...fieldReference.ref.options].forEach((optionRef) => optionRef.selected = fieldValue.includes(optionRef.value));
1291
1651
  } else if (fieldReference.refs) {
1292
1652
  if (isCheckBoxInput(fieldReference.ref)) {
1293
- fieldReference.refs.length > 1 ? fieldReference.refs.forEach((checkboxRef) => (!checkboxRef.defaultChecked || !checkboxRef.disabled) && (checkboxRef.checked = Array.isArray(fieldValue) ? !!fieldValue.find((data) => data === checkboxRef.value) : fieldValue === checkboxRef.value)) : fieldReference.refs[0] && (fieldReference.refs[0].checked = !!fieldValue);
1653
+ fieldReference.refs.forEach((checkboxRef) => {
1654
+ if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
1655
+ if (Array.isArray(fieldValue)) {
1656
+ checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
1657
+ } else {
1658
+ checkboxRef.checked = fieldValue === checkboxRef.value || !!fieldValue;
1659
+ }
1660
+ }
1661
+ });
1294
1662
  } else {
1295
1663
  fieldReference.refs.forEach((radioRef) => radioRef.checked = radioRef.value === fieldValue);
1296
1664
  }
@@ -1298,112 +1666,184 @@ function createFormControl(props = {}, flushRootRender) {
1298
1666
  fieldReference.ref.value = "";
1299
1667
  } else {
1300
1668
  fieldReference.ref.value = fieldValue;
1301
- if (!fieldReference.ref.type) {
1302
- _subjects.values.next({
1669
+ if (!fieldReference.ref.type && !skipRender) {
1670
+ _subjects.state.next({
1303
1671
  name,
1304
- values: { ..._formValues }
1672
+ values: skipClone ? _formValues : cloneObject(_formValues)
1305
1673
  });
1306
1674
  }
1307
1675
  }
1308
1676
  }
1309
1677
  }
1310
- (options.shouldDirty || options.shouldTouch) && updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1311
- options.shouldValidate && trigger(name);
1678
+ (options.shouldDirty || options.shouldTouch) && updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
1679
+ options.shouldValidate && trigger(name, {
1680
+ delayError: options.delayError
1681
+ });
1312
1682
  };
1313
- const setValues = (name, value, options) => {
1683
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1314
1684
  for (const fieldKey in value) {
1685
+ if (!value.hasOwnProperty(fieldKey)) {
1686
+ return;
1687
+ }
1315
1688
  const fieldValue = value[fieldKey];
1316
- const fieldName = `${name}.${fieldKey}`;
1689
+ const fieldName = name + "." + fieldKey;
1317
1690
  const field = get(_fields, fieldName);
1318
- (_names.array.has(name) || !isPrimitive(fieldValue) || field && !field._f) && !isDateObject(fieldValue) ? setValues(fieldName, fieldValue, options) : setFieldValue(fieldName, fieldValue, options);
1691
+ (_names.array.has(name) || isObject(fieldValue) || field && !field._f) && !isDateObject(fieldValue) ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender) : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1319
1692
  }
1320
1693
  };
1321
- const setValue = (name, value, options = {}) => {
1694
+ const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
1322
1695
  const field = get(_fields, name);
1323
1696
  const isFieldArray = _names.array.has(name);
1324
- const cloneValue = cloneObject(value);
1325
- set(_formValues, name, cloneValue);
1697
+ const cloneValue = skipClone ? value : cloneObject(value);
1698
+ const previousValue = get(_formValues, name);
1699
+ const isValueUnchanged = deepEqual(previousValue, cloneValue);
1700
+ if (!isValueUnchanged) {
1701
+ set(_formValues, name, cloneValue);
1702
+ }
1326
1703
  if (isFieldArray) {
1327
1704
  _subjects.array.next({
1328
1705
  name,
1329
- values: { ..._formValues }
1706
+ values: skipClone ? _formValues : cloneObject(_formValues)
1330
1707
  });
1331
- if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) && options.shouldDirty) {
1332
- _subjects.state.next({
1333
- name,
1334
- dirtyFields: getDirtyFields(_defaultValues, _formValues),
1335
- isDirty: _getDirty(name, cloneValue)
1336
- });
1708
+ if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields || _proxySubscribeFormState.isDirty || _proxySubscribeFormState.dirtyFields) && options.shouldDirty) {
1709
+ _updateDirtyFields();
1710
+ if (!skipStateEmit) {
1711
+ _subjects.state.next({
1712
+ name,
1713
+ dirtyFields: _formState.dirtyFields,
1714
+ isDirty: _getDirty(name, cloneValue)
1715
+ });
1716
+ }
1337
1717
  }
1338
1718
  } else {
1339
- field && !field._f && !isNullOrUndefined(cloneValue) ? setValues(name, cloneValue, options) : setFieldValue(name, cloneValue, options);
1719
+ const isEmpty = Array.isArray(cloneValue) && !cloneValue.length || isEmptyObject(cloneValue);
1720
+ if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
1721
+ setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
1722
+ } else {
1723
+ setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
1724
+ }
1725
+ }
1726
+ if (!isValueUnchanged && !skipStateEmit) {
1727
+ const watched = isWatched(name, _names);
1728
+ const values = skipClone ? _formValues : cloneObject(_formValues);
1729
+ _subjects.state.next({
1730
+ ...watched && _formState,
1731
+ name: _state.mount || watched ? name : void 0,
1732
+ values
1733
+ });
1734
+ }
1735
+ };
1736
+ const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
1737
+ const setValues = (formValues, options = {}) => {
1738
+ const updatedFormValues = isFunction(formValues) ? formValues(_formValues) : formValues;
1739
+ if (!deepEqual(_formValues, updatedFormValues)) {
1740
+ _formValues = {
1741
+ ..._formValues,
1742
+ ...updatedFormValues
1743
+ };
1744
+ const flattenedUpdates = flatten(updatedFormValues);
1745
+ for (const fieldName of _names.mount) {
1746
+ if (fieldName in flattenedUpdates) {
1747
+ _setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
1748
+ }
1749
+ }
1750
+ _subjects.state.next({
1751
+ ..._formState,
1752
+ name: void 0,
1753
+ type: void 0,
1754
+ ..._valuesSubscriberCount ? { values: _formValues } : {}
1755
+ });
1756
+ if (options.shouldValidate) {
1757
+ _setValid();
1758
+ }
1340
1759
  }
1341
- isWatched(name, _names) && _subjects.state.next({ ..._formState });
1342
- _subjects.values.next({
1343
- name,
1344
- values: { ..._formValues }
1345
- });
1346
- !_state.mount && flushRootRender();
1347
1760
  };
1348
1761
  const onChange = async (event) => {
1762
+ _state.mount = true;
1349
1763
  const target = event.target;
1350
1764
  let name = target.name;
1351
1765
  let isFieldValueUpdated = true;
1352
1766
  const field = get(_fields, name);
1353
- const getCurrentFieldValue = () => target.type ? getFieldValue(field._f) : getEventValue(event);
1354
1767
  const _updateIsFieldValueUpdated = (fieldValue) => {
1355
- isFieldValueUpdated = Number.isNaN(fieldValue) || fieldValue === get(_formValues, name, fieldValue);
1768
+ isFieldValueUpdated = Number.isNaN(fieldValue) || isDateObject(fieldValue) && isNaN(fieldValue.getTime()) || deepEqual(fieldValue, get(_formValues, name, fieldValue));
1356
1769
  };
1357
1770
  if (field) {
1358
1771
  let error;
1359
1772
  let isValid;
1360
- const fieldValue = getCurrentFieldValue();
1773
+ const fieldValue = target.type ? getFieldValue(field._f) : getEventValue(event);
1361
1774
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1362
- const shouldSkipValidation = !hasValidation(field._f) && !_options.resolver && !get(_formState.errors, name) && !field._f.deps || skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1775
+ const hasNoValidationEffect = !hasValidation(field._f) && !props.validate && !_options.resolver && !get(_formState.errors, name) && !field._f.deps;
1776
+ const shouldSkipValidation = hasNoValidationEffect || skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
1363
1777
  const watched = isWatched(name, _names, isBlurEvent);
1364
1778
  set(_formValues, name, fieldValue);
1365
1779
  if (isBlurEvent) {
1366
- field._f.onBlur && field._f.onBlur(event);
1367
- delayErrorCallback && delayErrorCallback(0);
1780
+ if (!target || !target.readOnly) {
1781
+ field._f.onBlur && field._f.onBlur(event);
1782
+ const pendingDelayError = delayErrorCallbacks[name];
1783
+ pendingDelayError && pendingDelayError(0);
1784
+ }
1368
1785
  } else if (field._f.onChange) {
1369
1786
  field._f.onChange(event);
1370
1787
  }
1371
- const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
1788
+ const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
1372
1789
  const shouldRender = !isEmptyObject(fieldState) || watched;
1373
- !isBlurEvent && _subjects.values.next({
1790
+ !isBlurEvent && _subjects.state.next({
1374
1791
  name,
1375
1792
  type: event.type,
1376
- values: { ..._formValues }
1793
+ ..._valuesSubscriberCount ? { values: cloneObject(_formValues) } : {}
1377
1794
  });
1378
1795
  if (shouldSkipValidation) {
1379
- _proxyFormState.isValid && _updateValid();
1796
+ if ((!hasNoValidationEffect || !_formState.isValid) && (_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
1797
+ if (_options.mode === "onBlur") {
1798
+ if (isBlurEvent) {
1799
+ _setValid();
1800
+ }
1801
+ } else if (!isBlurEvent) {
1802
+ _setValid();
1803
+ }
1804
+ }
1380
1805
  return shouldRender && _subjects.state.next({ name, ...watched ? {} : fieldState });
1381
1806
  }
1807
+ if (!_options.resolver && props.validate) {
1808
+ await validateForm({
1809
+ name,
1810
+ eventType: event.type
1811
+ });
1812
+ }
1382
1813
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
1383
- _updateIsValidating(true);
1384
1814
  if (_options.resolver) {
1385
- const { errors } = await _executeSchema([name]);
1815
+ const { errors } = await _runSchema([name]);
1816
+ _updateIsValidating([name]);
1386
1817
  _updateIsFieldValueUpdated(fieldValue);
1387
- if (isFieldValueUpdated) {
1388
- const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
1389
- const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
1390
- error = errorLookupResult.error;
1391
- name = errorLookupResult.name;
1392
- isValid = isEmptyObject(errors);
1818
+ if (!isFieldValueUpdated) {
1819
+ !isEmptyObject(fieldState) && _subjects.state.next(fieldState);
1820
+ return;
1393
1821
  }
1822
+ const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
1823
+ const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
1824
+ error = errorLookupResult.error;
1825
+ name = errorLookupResult.name;
1826
+ isValid = isEmptyObject(errors);
1394
1827
  } else {
1395
- error = (await validateField(field, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1828
+ _updateIsValidating([name], true);
1829
+ error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1830
+ _updateIsValidating([name]);
1396
1831
  _updateIsFieldValueUpdated(fieldValue);
1397
1832
  if (isFieldValueUpdated) {
1398
1833
  if (error) {
1399
1834
  isValid = false;
1400
- } else if (_proxyFormState.isValid) {
1401
- isValid = await executeBuiltInValidation(_fields, true);
1835
+ } else if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
1836
+ isValid = await executeBuiltInValidation({
1837
+ fields: _fields,
1838
+ onlyCheckValid: true,
1839
+ name,
1840
+ eventType: event.type
1841
+ });
1402
1842
  }
1403
1843
  }
1404
1844
  }
1405
1845
  if (isFieldValueUpdated) {
1406
- field._f.deps && trigger(field._f.deps);
1846
+ field._f.deps && (!Array.isArray(field._f.deps) || field._f.deps.length > 0) && trigger(field._f.deps);
1407
1847
  shouldRenderByError(name, isValid, error, fieldState);
1408
1848
  }
1409
1849
  }
@@ -1419,7 +1859,6 @@ function createFormControl(props = {}, flushRootRender) {
1419
1859
  let isValid;
1420
1860
  let validationResult;
1421
1861
  const fieldNames = convertToArrayPayload(name);
1422
- _updateIsValidating(true);
1423
1862
  if (_options.resolver) {
1424
1863
  const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
1425
1864
  isValid = isEmptyObject(errors);
@@ -1427,43 +1866,77 @@ function createFormControl(props = {}, flushRootRender) {
1427
1866
  } else if (name) {
1428
1867
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1429
1868
  const field = get(_fields, fieldName);
1430
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
1869
+ return await executeBuiltInValidation({
1870
+ fields: field && field._f ? { [fieldName]: field } : field,
1871
+ eventType: EVENTS.TRIGGER
1872
+ });
1431
1873
  }))).every(Boolean);
1432
- !(!validationResult && !_formState.isValid) && _updateValid();
1874
+ !(!validationResult && !_formState.isValid) && _setValid();
1433
1875
  } else {
1434
- validationResult = isValid = await executeBuiltInValidation(_fields);
1876
+ validationResult = isValid = await executeBuiltInValidation({
1877
+ fields: _fields,
1878
+ name,
1879
+ eventType: EVENTS.TRIGGER
1880
+ });
1881
+ }
1882
+ if (options.delayError && _options.delayError && isString(name)) {
1883
+ const error = get(_formState.errors, name);
1884
+ if (error) {
1885
+ unset(_formState.errors, name);
1886
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
1887
+ delayErrorCallbacks[name](_options.delayError);
1888
+ } else {
1889
+ clearTimeout(timers[name]);
1890
+ delete delayErrorCallbacks[name];
1891
+ }
1435
1892
  }
1436
1893
  _subjects.state.next({
1437
- ...!isString(name) || _proxyFormState.isValid && isValid !== _formState.isValid ? {} : { name },
1894
+ ...!isString(name) || (_proxyFormState.isValid || _proxySubscribeFormState.isValid) && isValid !== _formState.isValid ? {} : { name },
1438
1895
  ..._options.resolver || !name ? { isValid } : {},
1439
- errors: _formState.errors,
1440
- isValidating: false
1896
+ errors: _formState.errors
1441
1897
  });
1442
1898
  options.shouldFocus && !validationResult && iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
1443
1899
  return validationResult;
1444
1900
  };
1445
- const getValues = (fieldNames) => {
1446
- const values = {
1447
- ..._defaultValues,
1448
- ..._state.mount ? _formValues : {}
1901
+ const getValues = (fieldNames, config2) => {
1902
+ let values = {
1903
+ ..._state.mount ? _formValues : _defaultValues
1449
1904
  };
1905
+ if (config2) {
1906
+ values = extractFormValues(config2.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
1907
+ }
1450
1908
  return isUndefined(fieldNames) ? values : isString(fieldNames) ? get(values, fieldNames) : fieldNames.map((name) => get(values, name));
1451
1909
  };
1452
1910
  const getFieldState = (name, formState) => ({
1453
1911
  invalid: !!get((formState || _formState).errors, name),
1454
1912
  isDirty: !!get((formState || _formState).dirtyFields, name),
1455
- isTouched: !!get((formState || _formState).touchedFields, name),
1456
- error: get((formState || _formState).errors, name)
1913
+ error: get((formState || _formState).errors, name),
1914
+ isValidating: !!get(_formState.validatingFields, name),
1915
+ isTouched: !!get((formState || _formState).touchedFields, name)
1457
1916
  });
1458
1917
  const clearErrors = (name) => {
1459
- name && convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
1460
- _subjects.state.next({
1461
- errors: name ? _formState.errors : {}
1462
- });
1918
+ const names = name ? convertToArrayPayload(name) : void 0;
1919
+ names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
1920
+ if (names) {
1921
+ names.forEach((inputName) => {
1922
+ _subjects.state.next({
1923
+ name: inputName,
1924
+ errors: _formState.errors
1925
+ });
1926
+ });
1927
+ } else {
1928
+ _formState.errors = {};
1929
+ _subjects.state.next({
1930
+ errors: _formState.errors
1931
+ });
1932
+ }
1463
1933
  };
1464
1934
  const setError = (name, error, options) => {
1465
1935
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
1936
+ const currentError = get(_formState.errors, name) || {};
1937
+ const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
1466
1938
  set(_formState.errors, name, {
1939
+ ...restOfErrorTree,
1467
1940
  ...error,
1468
1941
  ref
1469
1942
  });
@@ -1474,9 +1947,72 @@ function createFormControl(props = {}, flushRootRender) {
1474
1947
  });
1475
1948
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1476
1949
  };
1477
- const watch = (name, defaultValue) => isFunction(name) ? _subjects.values.subscribe({
1478
- next: (payload) => name(_getWatch(void 0, defaultValue), payload)
1479
- }) : _getWatch(name, defaultValue, true);
1950
+ const watch = (name, defaultValue) => {
1951
+ if (isFunction(name)) {
1952
+ _valuesSubscriberCount++;
1953
+ const { unsubscribe } = _subjects.state.subscribe({
1954
+ next: (payload) => "values" in payload && name(payload.values || _getWatch(void 0, defaultValue), payload)
1955
+ });
1956
+ let called = false;
1957
+ return {
1958
+ unsubscribe: () => {
1959
+ if (called) {
1960
+ return;
1961
+ }
1962
+ called = true;
1963
+ _valuesSubscriberCount--;
1964
+ unsubscribe();
1965
+ }
1966
+ };
1967
+ }
1968
+ return _getWatch(name, defaultValue, true);
1969
+ };
1970
+ const _subscribe = (props2) => {
1971
+ var _a;
1972
+ const needsValues = !!((_a = props2.formState) === null || _a === void 0 ? void 0 : _a.values);
1973
+ if (needsValues) {
1974
+ _valuesSubscriberCount++;
1975
+ }
1976
+ const { unsubscribe } = _subjects.state.subscribe({
1977
+ next: (formState) => {
1978
+ if (shouldSubscribeByName(props2.name, formState.name, props2.exact) && shouldRenderFormState(formState, props2.formState || _proxyFormState, _setFormState, props2.reRenderRoot)) {
1979
+ const snapshot = { ..._formValues };
1980
+ props2.callback({
1981
+ values: snapshot,
1982
+ ..._formState,
1983
+ ...formState,
1984
+ defaultValues: _defaultValues
1985
+ });
1986
+ }
1987
+ }
1988
+ });
1989
+ if (!needsValues) {
1990
+ return unsubscribe;
1991
+ }
1992
+ let called = false;
1993
+ return () => {
1994
+ if (called) {
1995
+ return;
1996
+ }
1997
+ called = true;
1998
+ _valuesSubscriberCount--;
1999
+ unsubscribe();
2000
+ };
2001
+ };
2002
+ const subscribe = (props2) => {
2003
+ _state.mount = true;
2004
+ _proxySubscribeFormState = {
2005
+ ..._proxySubscribeFormState,
2006
+ ...props2.formState
2007
+ };
2008
+ return _subscribe({
2009
+ ...props2,
2010
+ formState: {
2011
+ ...defaultProxyFormState,
2012
+ ...props2.formState
2013
+ }
2014
+ });
2015
+ };
1480
2016
  const unregister = (name, options = {}) => {
1481
2017
  for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
1482
2018
  _names.mount.delete(fieldName);
@@ -1488,27 +2024,31 @@ function createFormControl(props = {}, flushRootRender) {
1488
2024
  !options.keepError && unset(_formState.errors, fieldName);
1489
2025
  !options.keepDirty && unset(_formState.dirtyFields, fieldName);
1490
2026
  !options.keepTouched && unset(_formState.touchedFields, fieldName);
2027
+ !options.keepIsValidating && unset(_formState.validatingFields, fieldName);
1491
2028
  !_options.shouldUnregister && !options.keepDefaultValue && unset(_defaultValues, fieldName);
1492
2029
  }
1493
- _subjects.values.next({
1494
- values: { ..._formValues }
2030
+ _subjects.state.next({
2031
+ values: cloneObject(_formValues)
1495
2032
  });
1496
2033
  _subjects.state.next({
1497
2034
  ..._formState,
1498
2035
  ...!options.keepDirty ? {} : { isDirty: _getDirty() }
1499
2036
  });
1500
- !options.keepIsValid && _updateValid();
2037
+ !options.keepIsValid && _setValid();
1501
2038
  };
1502
- const _updateDisabledField = ({ disabled, name, field, fields, value }) => {
1503
- if (isBoolean(disabled)) {
1504
- const inputValue = disabled ? void 0 : isUndefined(value) ? getFieldValue(field ? field._f : get(fields, name)._f) : value;
1505
- set(_formValues, name, inputValue);
1506
- updateTouchAndDirty(name, inputValue, false, false, true);
2039
+ const _setDisabledField = ({ disabled, name }) => {
2040
+ if (isBoolean(disabled) && _state.mount || !!disabled || _names.disabled.has(name)) {
2041
+ const wasDisabled = _names.disabled.has(name);
2042
+ const isDisabled = !!disabled;
2043
+ const disabledStateChanged = wasDisabled !== isDisabled;
2044
+ disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
2045
+ disabledStateChanged && _state.mount && !_state.action && _setValid();
1507
2046
  }
1508
2047
  };
1509
2048
  const register = (name, options = {}) => {
1510
2049
  let field = get(_fields, name);
1511
- const disabledIsDefined = isBoolean(options.disabled);
2050
+ const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
2051
+ const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
1512
2052
  set(_fields, name, {
1513
2053
  ...field || {},
1514
2054
  _f: {
@@ -1519,17 +2059,16 @@ function createFormControl(props = {}, flushRootRender) {
1519
2059
  }
1520
2060
  });
1521
2061
  _names.mount.add(name);
1522
- if (field) {
1523
- _updateDisabledField({
1524
- field,
1525
- disabled: options.disabled,
2062
+ if (field && !shouldRevalidateRemount) {
2063
+ _setDisabledField({
2064
+ disabled: isBoolean(options.disabled) ? options.disabled : _options.disabled,
1526
2065
  name
1527
2066
  });
1528
2067
  } else {
1529
2068
  updateValidAndValue(name, true, options.value);
1530
2069
  }
1531
2070
  return {
1532
- ...disabledIsDefined ? { disabled: options.disabled } : {},
2071
+ ...disabledIsDefined ? { disabled: options.disabled || _options.disabled } : {},
1533
2072
  ..._options.progressive ? {
1534
2073
  required: !!options.required,
1535
2074
  min: getRuleValue(options.min),
@@ -1543,7 +2082,9 @@ function createFormControl(props = {}, flushRootRender) {
1543
2082
  onBlur: onChange,
1544
2083
  ref: (ref) => {
1545
2084
  if (ref) {
2085
+ _names.registerName.add(name);
1546
2086
  register(name, options);
2087
+ _names.registerName.delete(name);
1547
2088
  field = get(_fields, name);
1548
2089
  const fieldRef = isUndefined(ref.value) ? ref.querySelectorAll ? ref.querySelectorAll("input,select,textarea")[0] || ref : ref : ref;
1549
2090
  const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
@@ -1551,18 +2092,22 @@ function createFormControl(props = {}, flushRootRender) {
1551
2092
  if (radioOrCheckbox ? refs.find((option) => option === fieldRef) : fieldRef === field._f.ref) {
1552
2093
  return;
1553
2094
  }
2095
+ const newField = {
2096
+ ...field._f
2097
+ };
2098
+ if (radioOrCheckbox) {
2099
+ newField.refs = [
2100
+ ...refs.filter(live),
2101
+ fieldRef,
2102
+ ...Array.isArray(get(_defaultValues, name)) ? [{}] : []
2103
+ ];
2104
+ newField.ref = { type: fieldRef.type, name };
2105
+ } else {
2106
+ newField.ref = fieldRef;
2107
+ delete newField.refs;
2108
+ }
1554
2109
  set(_fields, name, {
1555
- _f: {
1556
- ...field._f,
1557
- ...radioOrCheckbox ? {
1558
- refs: [
1559
- ...refs.filter(live),
1560
- fieldRef,
1561
- ...Array.isArray(get(_defaultValues, name)) ? [{}] : []
1562
- ],
1563
- ref: { type: fieldRef.type, name }
1564
- } : { ref: fieldRef }
1565
- }
2110
+ _f: newField
1566
2111
  });
1567
2112
  updateValidAndValue(name, false, void 0, fieldRef);
1568
2113
  } else {
@@ -1575,21 +2120,25 @@ function createFormControl(props = {}, flushRootRender) {
1575
2120
  }
1576
2121
  };
1577
2122
  };
1578
- const _focusError = () => _options.shouldFocusError && iterateFieldsByAction(_fields, _focusInput, _names.mount);
2123
+ const _focusError = () => _options.shouldFocusError && !_options.shouldUseNativeValidation && iterateFieldsByAction(_fields, _focusInput, _names.mount);
1579
2124
  const _disableForm = (disabled) => {
1580
2125
  if (isBoolean(disabled)) {
1581
2126
  _subjects.state.next({ disabled });
1582
2127
  iterateFieldsByAction(_fields, (ref, name) => {
1583
- let requiredDisabledState = disabled;
1584
2128
  const currentField = get(_fields, name);
1585
- if (currentField && isBoolean(currentField._f.disabled)) {
1586
- requiredDisabledState || (requiredDisabledState = currentField._f.disabled);
2129
+ if (currentField) {
2130
+ ref.disabled = currentField._f.disabled || disabled;
2131
+ if (Array.isArray(currentField._f.refs)) {
2132
+ currentField._f.refs.forEach((inputRef) => {
2133
+ inputRef.disabled = currentField._f.disabled || disabled;
2134
+ });
2135
+ }
1587
2136
  }
1588
- ref.disabled = requiredDisabledState;
1589
2137
  }, 0, false);
1590
2138
  }
1591
2139
  };
1592
2140
  const handleSubmit = (onValid, onInvalid) => async (e) => {
2141
+ let onValidError = void 0;
1593
2142
  if (e) {
1594
2143
  e.preventDefault && e.preventDefault();
1595
2144
  e.persist && e.persist();
@@ -1599,18 +2148,31 @@ function createFormControl(props = {}, flushRootRender) {
1599
2148
  isSubmitting: true
1600
2149
  });
1601
2150
  if (_options.resolver) {
1602
- const { errors, values } = await _executeSchema();
2151
+ const { errors, values } = await _runSchema();
2152
+ _updateIsValidating();
1603
2153
  _formState.errors = errors;
1604
- fieldValues = values;
2154
+ fieldValues = cloneObject(values);
1605
2155
  } else {
1606
- await executeBuiltInValidation(_fields);
2156
+ await executeBuiltInValidation({
2157
+ fields: _fields,
2158
+ eventType: EVENTS.SUBMIT
2159
+ });
1607
2160
  }
1608
- unset(_formState.errors, "root");
2161
+ if (_names.disabled.size) {
2162
+ for (const name of _names.disabled) {
2163
+ unset(fieldValues, name);
2164
+ }
2165
+ }
2166
+ unset(_formState.errors, ROOT_ERROR_TYPE);
1609
2167
  if (isEmptyObject(_formState.errors)) {
1610
2168
  _subjects.state.next({
1611
2169
  errors: {}
1612
2170
  });
1613
- await onValid(fieldValues, e);
2171
+ try {
2172
+ await onValid(fieldValues, e);
2173
+ } catch (error) {
2174
+ onValidError = error;
2175
+ }
1614
2176
  } else {
1615
2177
  if (onInvalid) {
1616
2178
  await onInvalid({ ..._formState.errors }, e);
@@ -1621,29 +2183,32 @@ function createFormControl(props = {}, flushRootRender) {
1621
2183
  _subjects.state.next({
1622
2184
  isSubmitted: true,
1623
2185
  isSubmitting: false,
1624
- isSubmitSuccessful: isEmptyObject(_formState.errors),
2186
+ isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
1625
2187
  submitCount: _formState.submitCount + 1,
1626
2188
  errors: _formState.errors
1627
2189
  });
2190
+ if (onValidError) {
2191
+ throw onValidError;
2192
+ }
1628
2193
  };
1629
2194
  const resetField = (name, options = {}) => {
1630
2195
  if (get(_fields, name)) {
1631
2196
  if (isUndefined(options.defaultValue)) {
1632
- setValue(name, get(_defaultValues, name));
2197
+ setValue(name, cloneObject(get(_defaultValues, name)));
1633
2198
  } else {
1634
2199
  setValue(name, options.defaultValue);
1635
- set(_defaultValues, name, options.defaultValue);
2200
+ set(_defaultValues, name, cloneObject(options.defaultValue));
1636
2201
  }
1637
2202
  if (!options.keepTouched) {
1638
2203
  unset(_formState.touchedFields, name);
1639
2204
  }
1640
2205
  if (!options.keepDirty) {
1641
2206
  unset(_formState.dirtyFields, name);
1642
- _formState.isDirty = options.defaultValue ? _getDirty(name, get(_defaultValues, name)) : _getDirty();
2207
+ _formState.isDirty = options.defaultValue ? _getDirty(name, cloneObject(get(_defaultValues, name))) : _getDirty();
1643
2208
  }
1644
2209
  if (!options.keepError) {
1645
2210
  unset(_formState.errors, name);
1646
- _proxyFormState.isValid && _updateValid();
2211
+ _proxyFormState.isValid && _setValid();
1647
2212
  }
1648
2213
  _subjects.state.next({ ..._formState });
1649
2214
  }
@@ -1651,14 +2216,27 @@ function createFormControl(props = {}, flushRootRender) {
1651
2216
  const _reset = (formValues, keepStateOptions = {}) => {
1652
2217
  const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
1653
2218
  const cloneUpdatedValues = cloneObject(updatedValues);
1654
- const values = formValues && !isEmptyObject(formValues) ? cloneUpdatedValues : _defaultValues;
2219
+ const isEmptyResetValues = isEmptyObject(formValues);
2220
+ const values = cloneUpdatedValues;
2221
+ const fieldRefs = _fields;
1655
2222
  if (!keepStateOptions.keepDefaultValues) {
1656
2223
  _defaultValues = updatedValues;
1657
2224
  }
1658
2225
  if (!keepStateOptions.keepValues) {
1659
- if (keepStateOptions.keepDirtyValues || shouldCaptureDirtyFields) {
1660
- for (const fieldName of _names.mount) {
1661
- get(_formState.dirtyFields, fieldName) ? set(values, fieldName, get(_formValues, fieldName)) : setValue(fieldName, get(values, fieldName));
2226
+ if (keepStateOptions.keepDirtyValues) {
2227
+ const fieldsToCheck = /* @__PURE__ */ new Set([
2228
+ ..._names.mount,
2229
+ ...Object.keys(getDirtyFields(_defaultValues, _formValues, void 0, fieldRefs))
2230
+ ]);
2231
+ for (const fieldName of Array.from(fieldsToCheck)) {
2232
+ const isDirty = get(_formState.dirtyFields, fieldName);
2233
+ const existingValue = get(_formValues, fieldName);
2234
+ const newValue = get(values, fieldName);
2235
+ if (isDirty && !isUndefined(existingValue)) {
2236
+ set(values, fieldName, existingValue);
2237
+ } else if (!isDirty && !isUndefined(newValue)) {
2238
+ setValue(fieldName, newValue);
2239
+ }
1662
2240
  }
1663
2241
  } else {
1664
2242
  if (isWeb && isUndefined(formValues)) {
@@ -1676,54 +2254,81 @@ function createFormControl(props = {}, flushRootRender) {
1676
2254
  }
1677
2255
  }
1678
2256
  }
1679
- _fields = {};
2257
+ if (keepStateOptions.keepFieldsRef) {
2258
+ for (const fieldName of _names.mount) {
2259
+ setValue(fieldName, get(values, fieldName));
2260
+ }
2261
+ } else {
2262
+ _fields = {};
2263
+ }
2264
+ }
2265
+ if (_options.shouldUnregister) {
2266
+ _formValues = keepStateOptions.keepDefaultValues ? cloneObject(_defaultValues) : {};
2267
+ if (keepStateOptions.keepFieldsRef) {
2268
+ for (const fieldName of _names.mount) {
2269
+ set(_formValues, fieldName, get(values, fieldName));
2270
+ }
2271
+ }
2272
+ } else {
2273
+ _formValues = cloneObject(values);
1680
2274
  }
1681
- _formValues = props.shouldUnregister ? keepStateOptions.keepDefaultValues ? cloneObject(_defaultValues) : {} : cloneObject(values);
1682
2275
  _subjects.array.next({
1683
2276
  values: { ...values }
1684
2277
  });
1685
- _subjects.values.next({
2278
+ _subjects.state.next({
2279
+ name: void 0,
2280
+ type: void 0,
1686
2281
  values: { ...values }
1687
2282
  });
1688
2283
  }
1689
2284
  _names = {
1690
- mount: /* @__PURE__ */ new Set(),
2285
+ mount: keepStateOptions.keepDirtyValues ? _names.mount : /* @__PURE__ */ new Set(),
1691
2286
  unMount: /* @__PURE__ */ new Set(),
1692
2287
  array: /* @__PURE__ */ new Set(),
2288
+ registerName: /* @__PURE__ */ new Set(),
2289
+ disabled: /* @__PURE__ */ new Set(),
1693
2290
  watch: /* @__PURE__ */ new Set(),
1694
2291
  watchAll: false,
1695
2292
  focus: ""
1696
2293
  };
1697
- !_state.mount && flushRootRender();
1698
- _state.mount = !_proxyFormState.isValid || !!keepStateOptions.keepIsValid;
1699
- _state.watch = !!props.shouldUnregister;
2294
+ _state.mount = !_proxyFormState.isValid || !!keepStateOptions.keepIsValid || !!keepStateOptions.keepDirtyValues || !_options.shouldUnregister && !isEmptyObject(values);
2295
+ _state.watch = !!_options.shouldUnregister;
2296
+ _state.keepIsValid = !!keepStateOptions.keepIsValid;
2297
+ _state.action = false;
2298
+ if (!keepStateOptions.keepErrors) {
2299
+ _formState.errors = {};
2300
+ }
1700
2301
  _subjects.state.next({
1701
2302
  submitCount: keepStateOptions.keepSubmitCount ? _formState.submitCount : 0,
1702
- isDirty: keepStateOptions.keepDirty ? _formState.isDirty : !!(keepStateOptions.keepDefaultValues && !deepEqual(formValues, _defaultValues)),
2303
+ isDirty: isEmptyResetValues ? false : keepStateOptions.keepDirty ? _formState.isDirty : keepStateOptions.keepValues ? _getDirty() : !!(keepStateOptions.keepDefaultValues && !deepEqual(formValues, _defaultValues)),
1703
2304
  isSubmitted: keepStateOptions.keepIsSubmitted ? _formState.isSubmitted : false,
1704
- dirtyFields: keepStateOptions.keepDirtyValues ? _formState.dirtyFields : keepStateOptions.keepDefaultValues && formValues ? getDirtyFields(_defaultValues, formValues) : {},
2305
+ dirtyFields: isEmptyResetValues ? {} : keepStateOptions.keepDirtyValues ? keepStateOptions.keepDefaultValues && _formValues ? getDirtyFields(_defaultValues, _formValues, void 0, fieldRefs) : _formState.dirtyFields : keepStateOptions.keepDefaultValues && formValues ? getDirtyFields(_defaultValues, formValues, void 0, fieldRefs) : keepStateOptions.keepDirty ? _formState.dirtyFields : {},
1705
2306
  touchedFields: keepStateOptions.keepTouched ? _formState.touchedFields : {},
1706
2307
  errors: keepStateOptions.keepErrors ? _formState.errors : {},
1707
2308
  isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful ? _formState.isSubmitSuccessful : false,
1708
- isSubmitting: false
2309
+ isSubmitting: false,
2310
+ defaultValues: _defaultValues
1709
2311
  });
1710
2312
  };
1711
- const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues) ? formValues(_formValues) : formValues, keepStateOptions);
2313
+ const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues) ? formValues(_formValues) : formValues, { ..._options.resetOptions, ...keepStateOptions });
1712
2314
  const setFocus = (name, options = {}) => {
1713
2315
  const field = get(_fields, name);
1714
2316
  const fieldReference = field && field._f;
1715
2317
  if (fieldReference) {
1716
2318
  const fieldRef = fieldReference.refs ? fieldReference.refs[0] : fieldReference.ref;
1717
2319
  if (fieldRef.focus) {
1718
- fieldRef.focus();
1719
- options.shouldSelect && fieldRef.select();
2320
+ setTimeout(() => {
2321
+ fieldRef.focus();
2322
+ options.shouldSelect && isFunction(fieldRef.select) && fieldRef.select();
2323
+ });
1720
2324
  }
1721
2325
  }
1722
2326
  };
1723
- const _updateFormState = (updatedFormState) => {
2327
+ const _setFormState = (updatedFormState) => {
2328
+ const { name, type, values, ...formState } = updatedFormState;
1724
2329
  _formState = {
1725
2330
  ..._formState,
1726
- ...updatedFormState
2331
+ ...formState
1727
2332
  };
1728
2333
  };
1729
2334
  const _resetDefaultValues = () => isFunction(_options.defaultValues) && _options.defaultValues().then((values) => {
@@ -1732,28 +2337,45 @@ function createFormControl(props = {}, flushRootRender) {
1732
2337
  isLoading: false
1733
2338
  });
1734
2339
  });
1735
- return {
2340
+ const resetDefaultValues = (values, options = {}) => {
2341
+ _defaultValues = cloneObject(values);
2342
+ if (!options.keepDirty) {
2343
+ const newDirtyFields = getDirtyFields(_defaultValues, _formValues, void 0, _fields);
2344
+ _formState.dirtyFields = newDirtyFields;
2345
+ _formState.isDirty = !isEmptyObject(newDirtyFields);
2346
+ }
2347
+ if (!options.keepIsValid) {
2348
+ _setValid();
2349
+ }
2350
+ _subjects.state.next({
2351
+ ..._formState,
2352
+ defaultValues: _defaultValues
2353
+ });
2354
+ };
2355
+ const methods = {
1736
2356
  control: {
1737
2357
  register,
1738
2358
  unregister,
1739
2359
  getFieldState,
1740
2360
  handleSubmit,
1741
2361
  setError,
1742
- _executeSchema,
2362
+ _subscribe,
2363
+ _runSchema,
2364
+ _updateIsValidating,
2365
+ _focusError,
1743
2366
  _getWatch,
1744
2367
  _getDirty,
1745
- _updateValid,
1746
- _removeUnmounted,
1747
- _updateFieldArray,
1748
- _updateDisabledField,
2368
+ _setValid,
2369
+ _setFieldArray,
2370
+ _setDisabledField,
2371
+ _setErrors,
1749
2372
  _getFieldArray,
1750
2373
  _reset,
1751
2374
  _resetDefaultValues,
1752
- _updateFormState,
2375
+ _removeUnmounted,
1753
2376
  _disableForm,
1754
2377
  _subjects,
1755
2378
  _proxyFormState,
1756
- _setErrors,
1757
2379
  get _fields() {
1758
2380
  return _fields;
1759
2381
  },
@@ -1778,9 +2400,6 @@ function createFormControl(props = {}, flushRootRender) {
1778
2400
  get _formState() {
1779
2401
  return _formState;
1780
2402
  },
1781
- set _formState(value) {
1782
- _formState = value;
1783
- },
1784
2403
  get _options() {
1785
2404
  return _options;
1786
2405
  },
@@ -1789,58 +2408,99 @@ function createFormControl(props = {}, flushRootRender) {
1789
2408
  ..._options,
1790
2409
  ...value
1791
2410
  };
2411
+ _validationModeBeforeSubmit = getValidationModes(_options.mode);
2412
+ _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1792
2413
  }
1793
2414
  },
2415
+ subscribe,
1794
2416
  trigger,
1795
2417
  register,
1796
2418
  handleSubmit,
1797
2419
  watch,
1798
2420
  setValue,
2421
+ setValues,
1799
2422
  getValues,
1800
2423
  reset,
1801
2424
  resetField,
2425
+ resetDefaultValues,
1802
2426
  clearErrors,
1803
2427
  unregister,
1804
2428
  setError,
1805
2429
  setFocus,
1806
2430
  getFieldState
1807
2431
  };
2432
+ return {
2433
+ ...methods,
2434
+ formControl: methods
2435
+ };
1808
2436
  }
1809
2437
  function useForm(props = {}) {
1810
- const _formControl = React.useRef();
1811
- const _values = React.useRef();
1812
- const [formState, updateFormState] = React.useState({
1813
- isDirty: false,
1814
- isValidating: false,
2438
+ const _formControl = React.useRef(void 0);
2439
+ const _values = React.useRef(void 0);
2440
+ const _formControlProp = React.useRef(props.formControl);
2441
+ const [formState, updateFormState] = React.useState(() => ({
2442
+ ...cloneObject(DEFAULT_FORM_STATE),
1815
2443
  isLoading: isFunction(props.defaultValues),
1816
- isSubmitted: false,
1817
- isSubmitting: false,
1818
- isSubmitSuccessful: false,
1819
- isValid: false,
1820
- submitCount: 0,
1821
- dirtyFields: {},
1822
- touchedFields: {},
1823
2444
  errors: props.errors || {},
1824
- disabled: false,
2445
+ disabled: props.disabled || false,
1825
2446
  defaultValues: isFunction(props.defaultValues) ? void 0 : props.defaultValues
1826
- });
1827
- if (!_formControl.current) {
1828
- _formControl.current = {
1829
- ...createFormControl(props, () => updateFormState((formState2) => ({ ...formState2 }))),
1830
- formState
1831
- };
2447
+ }));
2448
+ if (!_formControl.current || props.formControl && _formControlProp.current !== props.formControl) {
2449
+ _formControlProp.current = props.formControl;
2450
+ if (props.formControl) {
2451
+ _formControl.current = {
2452
+ ...props.formControl,
2453
+ formState
2454
+ };
2455
+ if (props.defaultValues && !isFunction(props.defaultValues)) {
2456
+ props.formControl.reset(props.defaultValues, props.resetOptions);
2457
+ }
2458
+ } else {
2459
+ const { formControl, ...rest } = createFormControl(props);
2460
+ _formControl.current = {
2461
+ ...rest,
2462
+ formState
2463
+ };
2464
+ }
1832
2465
  }
1833
2466
  const control = _formControl.current.control;
1834
2467
  control._options = props;
1835
- useSubscribe({
1836
- subject: control._subjects.state,
1837
- next: (value) => {
1838
- if (shouldRenderFormState(value, control._proxyFormState, control._updateFormState, true)) {
1839
- updateFormState({ ...control._formState });
1840
- }
1841
- }
1842
- });
2468
+ useIsomorphicLayoutEffect(() => {
2469
+ const sub = control._subscribe({
2470
+ formState: control._proxyFormState,
2471
+ callback: () => updateFormState({
2472
+ ...control._formState,
2473
+ defaultValues: control._defaultValues
2474
+ }),
2475
+ reRenderRoot: true
2476
+ });
2477
+ updateFormState((data) => ({
2478
+ ...data,
2479
+ isReady: true
2480
+ }));
2481
+ control._formState.isReady = true;
2482
+ return sub;
2483
+ }, [control]);
1843
2484
  React.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]);
2485
+ React.useEffect(() => {
2486
+ if (props.mode) {
2487
+ control._options.mode = props.mode;
2488
+ }
2489
+ if (props.reValidateMode) {
2490
+ control._options.reValidateMode = props.reValidateMode;
2491
+ }
2492
+ }, [control, props.mode, props.reValidateMode]);
2493
+ React.useEffect(() => {
2494
+ if (props.errors) {
2495
+ control._setErrors(props.errors);
2496
+ control._focusError();
2497
+ }
2498
+ }, [control, props.errors]);
2499
+ React.useEffect(() => {
2500
+ props.shouldUnregister && control._subjects.state.next({
2501
+ values: control._getWatch()
2502
+ });
2503
+ }, [control, props.shouldUnregister]);
1844
2504
  React.useEffect(() => {
1845
2505
  if (control._proxyFormState.isDirty) {
1846
2506
  const isDirty = control._getDirty();
@@ -1852,22 +2512,24 @@ function useForm(props = {}) {
1852
2512
  }
1853
2513
  }, [control, formState.isDirty]);
1854
2514
  React.useEffect(() => {
2515
+ var _a;
1855
2516
  if (props.values && !deepEqual(props.values, _values.current)) {
1856
- control._reset(props.values, control._options.resetOptions);
2517
+ control._reset(props.values, {
2518
+ keepFieldsRef: true,
2519
+ ...control._options.resetOptions
2520
+ });
2521
+ if (!((_a = control._options.resetOptions) === null || _a === void 0 ? void 0 : _a.keepIsValid)) {
2522
+ control._setValid();
2523
+ }
1857
2524
  _values.current = props.values;
1858
2525
  updateFormState((state) => ({ ...state }));
1859
2526
  } else {
1860
2527
  control._resetDefaultValues();
1861
2528
  }
1862
- }, [props.values, control]);
1863
- React.useEffect(() => {
1864
- if (props.errors) {
1865
- control._setErrors(props.errors);
1866
- }
1867
- }, [props.errors, control]);
2529
+ }, [control, props.values]);
1868
2530
  React.useEffect(() => {
1869
2531
  if (!control._state.mount) {
1870
- control._updateValid();
2532
+ control._setValid();
1871
2533
  control._state.mount = true;
1872
2534
  }
1873
2535
  if (control._state.watch) {
@@ -1876,7 +2538,7 @@ function useForm(props = {}) {
1876
2538
  }
1877
2539
  control._removeUnmounted();
1878
2540
  });
1879
- _formControl.current.formState = getProxyFormState(formState, control);
2541
+ _formControl.current.formState = React.useMemo(() => getProxyFormState(formState, control), [control, formState]);
1880
2542
  return _formControl.current;
1881
2543
  }
1882
2544
  const jsonToText = (v) => v == null || v === "" ? "" : JSON.stringify(v, null, 2);