@octanejs/hook-form 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +62 -0
  3. package/package.json +46 -0
  4. package/src/FormProvider.tsrx +76 -0
  5. package/src/FormProvider.tsrx.d.ts +10 -0
  6. package/src/constants.ts +31 -0
  7. package/src/controller.tsrx +8 -0
  8. package/src/controller.tsrx.d.ts +52 -0
  9. package/src/form.tsrx +119 -0
  10. package/src/form.tsrx.d.ts +6 -0
  11. package/src/formStateSubscribe.tsrx +10 -0
  12. package/src/formStateSubscribe.tsrx.d.ts +16 -0
  13. package/src/index.ts +19 -0
  14. package/src/logic/appendErrors.ts +19 -0
  15. package/src/logic/createFormControl.ts +1841 -0
  16. package/src/logic/generateId.ts +14 -0
  17. package/src/logic/generateWatchOutput.ts +27 -0
  18. package/src/logic/getCheckboxValue.ts +36 -0
  19. package/src/logic/getDirtyFields.ts +120 -0
  20. package/src/logic/getEventValue.ts +12 -0
  21. package/src/logic/getFieldValue.ts +33 -0
  22. package/src/logic/getFieldValueAs.ts +22 -0
  23. package/src/logic/getFocusFieldName.ts +13 -0
  24. package/src/logic/getNodeParentName.ts +4 -0
  25. package/src/logic/getProxyFormState.ts +33 -0
  26. package/src/logic/getRadioValue.ts +24 -0
  27. package/src/logic/getResolverOptions.ts +33 -0
  28. package/src/logic/getRuleValue.ts +16 -0
  29. package/src/logic/getValidateError.ts +22 -0
  30. package/src/logic/getValidationModes.ts +11 -0
  31. package/src/logic/getValueAndMessage.ts +12 -0
  32. package/src/logic/hasPromiseValidation.ts +27 -0
  33. package/src/logic/hasValidation.ts +12 -0
  34. package/src/logic/index.ts +3 -0
  35. package/src/logic/isNameInFieldArray.ts +7 -0
  36. package/src/logic/isWatched.ts +11 -0
  37. package/src/logic/iterateFieldsByAction.ts +37 -0
  38. package/src/logic/schemaErrorLookup.ts +54 -0
  39. package/src/logic/shouldRenderFormState.ts +25 -0
  40. package/src/logic/shouldSubscribeByName.ts +18 -0
  41. package/src/logic/skipValidation.ts +21 -0
  42. package/src/logic/unsetEmptyArray.ts +6 -0
  43. package/src/logic/updateFieldArrayRootError.ts +17 -0
  44. package/src/logic/validateField.ts +273 -0
  45. package/src/types/controller.ts +98 -0
  46. package/src/types/errors.ts +56 -0
  47. package/src/types/events.ts +26 -0
  48. package/src/types/fieldArray.ts +288 -0
  49. package/src/types/fields.ts +46 -0
  50. package/src/types/form.ts +961 -0
  51. package/src/types/index.ts +12 -0
  52. package/src/types/path/common.ts +391 -0
  53. package/src/types/path/eager.ts +224 -0
  54. package/src/types/path/index.ts +16 -0
  55. package/src/types/resolvers.ts +38 -0
  56. package/src/types/utils.ts +125 -0
  57. package/src/types/validator.ts +94 -0
  58. package/src/types/watch.ts +66 -0
  59. package/src/useController.ts +268 -0
  60. package/src/useFieldArray.ts +490 -0
  61. package/src/useForm.ts +182 -0
  62. package/src/useFormContext.ts +47 -0
  63. package/src/useFormControlContext.ts +25 -0
  64. package/src/useFormState.ts +86 -0
  65. package/src/useIsomorphicLayoutEffect.ts +6 -0
  66. package/src/useWatch.ts +356 -0
  67. package/src/utils/append.ts +4 -0
  68. package/src/utils/cloneObject.ts +32 -0
  69. package/src/utils/compact.ts +2 -0
  70. package/src/utils/convertToArrayPayload.ts +2 -0
  71. package/src/utils/createSubject.ts +48 -0
  72. package/src/utils/deepEqual.ts +81 -0
  73. package/src/utils/deepMerge.ts +27 -0
  74. package/src/utils/extractFormValues.ts +28 -0
  75. package/src/utils/fillEmptyArray.ts +3 -0
  76. package/src/utils/flatten.ts +23 -0
  77. package/src/utils/get.ts +29 -0
  78. package/src/utils/index.ts +3 -0
  79. package/src/utils/insert.ts +8 -0
  80. package/src/utils/isBoolean.ts +2 -0
  81. package/src/utils/isCheckBoxInput.ts +4 -0
  82. package/src/utils/isDateObject.ts +2 -0
  83. package/src/utils/isEmptyObject.ts +7 -0
  84. package/src/utils/isFileInput.ts +4 -0
  85. package/src/utils/isFunction.ts +2 -0
  86. package/src/utils/isHTMLElement.ts +13 -0
  87. package/src/utils/isKey.ts +4 -0
  88. package/src/utils/isMultipleSelect.ts +5 -0
  89. package/src/utils/isNullOrUndefined.ts +2 -0
  90. package/src/utils/isObject.ts +8 -0
  91. package/src/utils/isPlainObject.ts +8 -0
  92. package/src/utils/isPrimitive.ts +8 -0
  93. package/src/utils/isRadioInput.ts +4 -0
  94. package/src/utils/isRadioOrCheckbox.ts +8 -0
  95. package/src/utils/isRegex.ts +2 -0
  96. package/src/utils/isString.ts +2 -0
  97. package/src/utils/isUndefined.ts +2 -0
  98. package/src/utils/isWeb.ts +4 -0
  99. package/src/utils/live.ts +6 -0
  100. package/src/utils/move.ts +15 -0
  101. package/src/utils/noop.ts +2 -0
  102. package/src/utils/objectHasFunction.ts +11 -0
  103. package/src/utils/prepend.ts +7 -0
  104. package/src/utils/remove.ts +24 -0
  105. package/src/utils/set.ts +36 -0
  106. package/src/utils/sleep.ts +2 -0
  107. package/src/utils/stringToPath.ts +4 -0
  108. package/src/utils/swap.ts +4 -0
  109. package/src/utils/unset.ts +65 -0
  110. package/src/utils/update.ts +5 -0
  111. package/src/watch.tsrx +7 -0
  112. package/src/watch.tsrx.d.ts +42 -0
@@ -0,0 +1,125 @@
1
+ // Vendored from react-hook-form@7.81.0 src/types/utils.ts (octane port).
2
+ import type { NestedValue } from './form';
3
+
4
+ /*
5
+ Projects that React Hook Form installed don't include the DOM library need these interfaces to compile.
6
+ React Native applications is no DOM available. The JavaScript runtime is ES6/ES2015 only.
7
+ These definitions allow such projects to compile with only --lib ES6.
8
+
9
+ Warning: all of these interfaces are empty.
10
+ If you want type definitions for various properties, you need to add `--lib DOM` (via command line or tsconfig.json).
11
+ */
12
+
13
+ export type Noop = () => void;
14
+
15
+ interface File extends Blob {
16
+ readonly lastModified: number;
17
+ readonly name: string;
18
+ }
19
+
20
+ interface FileList {
21
+ readonly length: number;
22
+ item(index: number): File | null;
23
+ [index: number]: File;
24
+ }
25
+
26
+ export type Primitive = null | undefined | string | number | boolean | symbol | bigint;
27
+
28
+ export type BrowserNativeObject = Date | FileList | File;
29
+
30
+ export type EmptyObject = { [K in string | number]: never };
31
+
32
+ export type NonUndefined<T> = T extends undefined ? never : T;
33
+
34
+ export type LiteralUnion<T extends U, U extends Primitive> = T | (U & { _?: never });
35
+
36
+ export type ExtractObjects<T> = T extends infer U ? (U extends object ? U : never) : never;
37
+
38
+ type IsPrimitiveLike<T> = T extends Primitive ? true : T extends Primitive & object ? true : false;
39
+
40
+ export type DeepPartial<T> =
41
+ IsPrimitiveLike<T> extends true
42
+ ? T
43
+ : T extends BrowserNativeObject | NestedValue
44
+ ? T
45
+ : {
46
+ [K in keyof T]?: ExtractObjects<T[K]> extends never ? T[K] : DeepPartial<T[K]>;
47
+ };
48
+
49
+ export type DeepPartialSkipArrayKey<T> =
50
+ IsPrimitiveLike<T> extends true
51
+ ? T
52
+ : T extends BrowserNativeObject | NestedValue
53
+ ? T
54
+ : T extends ReadonlyArray<any>
55
+ ? { [K in keyof T]: DeepPartialSkipArrayKey<T[K]> }
56
+ : { [K in keyof T]?: DeepPartialSkipArrayKey<T[K]> };
57
+
58
+ /**
59
+ * Checks whether the type is any
60
+ * See {@link https://stackoverflow.com/a/49928360/3406963}
61
+ * @typeParam T - type which may be any
62
+ * ```
63
+ * IsAny<any> = true
64
+ * IsAny<string> = false
65
+ * ```
66
+ */
67
+ export type IsAny<T> = 0 extends 1 & T ? true : false;
68
+
69
+ /**
70
+ * Checks whether the type is never
71
+ * @typeParam T - type which may be never
72
+ * ```
73
+ * IsNever<never> = true
74
+ * IsNever<string> = false
75
+ * ```
76
+ */
77
+ export type IsNever<T> = [T] extends [never] ? true : false;
78
+
79
+ /**
80
+ * Checks whether T1 can be exactly (mutually) assigned to T2
81
+ * @typeParam T1 - type to check
82
+ * @typeParam T2 - type to check against
83
+ * ```
84
+ * IsEqual<string, string> = true
85
+ * IsEqual<'foo', 'foo'> = true
86
+ * IsEqual<string, number> = false
87
+ * IsEqual<string, number> = false
88
+ * IsEqual<string, 'foo'> = false
89
+ * IsEqual<'foo', string> = false
90
+ * IsEqual<'foo' | 'bar', 'foo'> = boolean // 'foo' is assignable, but 'bar' is not (true | false) -> boolean
91
+ * ```
92
+ */
93
+ export type IsEqual<T1, T2> = T1 extends T2
94
+ ? (<G>() => G extends T1 ? 1 : 2) extends <G>() => G extends T2 ? 1 : 2
95
+ ? true
96
+ : false
97
+ : false;
98
+
99
+ export type DeepMap<T, TValue> =
100
+ IsAny<T> extends true
101
+ ? any
102
+ : T extends BrowserNativeObject | NestedValue
103
+ ? TValue
104
+ : T extends ReadonlyArray<infer U>
105
+ ? Array<DeepMap<NonUndefined<U>, TValue> | undefined>
106
+ : T extends object
107
+ ? { [K in keyof T]: DeepMap<NonUndefined<T[K]>, TValue> }
108
+ : TValue;
109
+
110
+ export type IsFlatObject<T extends object> =
111
+ Extract<Exclude<T[keyof T], NestedValue | Date | FileList>, any[] | object> extends never
112
+ ? true
113
+ : false;
114
+
115
+ export type Merge<A, B> = {
116
+ [K in keyof A | keyof B]?: K extends keyof A & keyof B
117
+ ? [A[K], B[K]] extends [object, object]
118
+ ? Merge<A[K], B[K]>
119
+ : B[K]
120
+ : K extends keyof A
121
+ ? A[K]
122
+ : K extends keyof B
123
+ ? B[K]
124
+ : never;
125
+ };
@@ -0,0 +1,94 @@
1
+ // Vendored from react-hook-form@7.81.0 src/types/validator.ts (octane port).
2
+ import type { EVENTS, INPUT_VALIDATION_RULES } from '../constants';
3
+
4
+ import type { Message } from './errors';
5
+ import type { FieldValues } from './fields';
6
+ import type { FormState } from './form';
7
+ import type { FieldPath, FieldPathValue } from './path';
8
+
9
+ export type ValidationValue = boolean | number | string | RegExp;
10
+
11
+ export type ValidationRule<TValidationValue extends ValidationValue = ValidationValue> =
12
+ | TValidationValue
13
+ | ValidationValueMessage<TValidationValue>;
14
+
15
+ export type ValidationValueMessage<TValidationValue extends ValidationValue = ValidationValue> = {
16
+ value: TValidationValue;
17
+ message: Message;
18
+ };
19
+
20
+ export type ValidateResult = Message | Message[] | boolean | undefined;
21
+
22
+ export type FormValidateResult<T> =
23
+ | Partial<
24
+ Record<
25
+ keyof T,
26
+ {
27
+ message: Message | Message[] | boolean | undefined;
28
+ type: string;
29
+ }
30
+ >
31
+ >
32
+ | string
33
+ | boolean;
34
+
35
+ export type Validate<TFieldValue, TFormValues> = (
36
+ value: TFieldValue,
37
+ formValues: TFormValues,
38
+ ) => ValidateResult | Promise<ValidateResult>;
39
+
40
+ export type ValidateFormEventType = (typeof EVENTS)[keyof typeof EVENTS];
41
+
42
+ export type ValidateForm<
43
+ TFormValues extends FieldValues,
44
+ TFieldName extends FieldPath<TFormValues> = FieldPath<TFormValues>,
45
+ > = (props: {
46
+ formValues: TFormValues;
47
+ formState: FormState<TFormValues>;
48
+ eventType?: ValidateFormEventType;
49
+ name?: TFieldName | TFieldName[];
50
+ }) => FormValidateResult<TFormValues> | Promise<FormValidateResult<TFormValues>>;
51
+
52
+ export type RegisterOptions<
53
+ TFieldValues extends FieldValues = FieldValues,
54
+ TFieldName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
55
+ > = Partial<{
56
+ required: Message | ValidationRule<boolean>;
57
+ min: ValidationRule<number | string>;
58
+ max: ValidationRule<number | string>;
59
+ maxLength: ValidationRule<number>;
60
+ minLength: ValidationRule<number>;
61
+ validate:
62
+ | Validate<FieldPathValue<TFieldValues, TFieldName>, TFieldValues>
63
+ | Record<string, Validate<FieldPathValue<TFieldValues, TFieldName>, TFieldValues>>;
64
+ value: FieldPathValue<TFieldValues, TFieldName>;
65
+ setValueAs: (value: any) => any;
66
+ shouldUnregister?: boolean;
67
+ onChange?: (event: any) => void;
68
+ onBlur?: (event: any) => void;
69
+ disabled: boolean;
70
+ deps: FieldPath<TFieldValues> | FieldPath<TFieldValues>[];
71
+ }> &
72
+ (
73
+ | {
74
+ pattern?: ValidationRule<RegExp>;
75
+ valueAsNumber?: false;
76
+ valueAsDate?: false;
77
+ }
78
+ | {
79
+ pattern?: undefined;
80
+ valueAsNumber?: false;
81
+ valueAsDate?: true;
82
+ }
83
+ | {
84
+ pattern?: undefined;
85
+ valueAsNumber?: true;
86
+ valueAsDate?: false;
87
+ }
88
+ );
89
+
90
+ export type InputValidationRules = typeof INPUT_VALIDATION_RULES;
91
+
92
+ export type MaxType = InputValidationRules['max'] | InputValidationRules['maxLength'];
93
+
94
+ export type MinType = InputValidationRules['min'] | InputValidationRules['minLength'];
@@ -0,0 +1,66 @@
1
+ // Vendored from react-hook-form@7.81.0 src/types/watch.ts.
2
+ // octane: upstream's ReactNode becomes `unknown` — any octane renderable.
3
+ type ReactNode = unknown;
4
+
5
+ import type { FieldValues } from './fields';
6
+ import type { Control } from './form';
7
+ import type { FieldPath, FieldPathValue, FieldPathValues } from './path';
8
+ import type { DeepPartialSkipArrayKey } from './utils';
9
+
10
+ export type UseWatchProps<TFieldValues extends FieldValues = FieldValues> = {
11
+ defaultValue?: unknown;
12
+ disabled?: boolean;
13
+ name?: FieldPath<TFieldValues> | FieldPath<TFieldValues>[] | readonly FieldPath<TFieldValues>[];
14
+ control?: Control<TFieldValues>;
15
+ exact?: boolean;
16
+ compute?: (formValues: TFieldValues) => TFieldValues;
17
+ };
18
+
19
+ export type WatchDefaultValue<TFieldName, TFieldValues extends FieldValues = FieldValues> =
20
+ TFieldName extends FieldPath<TFieldValues>
21
+ ? FieldPathValue<TFieldValues, TFieldName>
22
+ : DeepPartialSkipArrayKey<TFieldValues>;
23
+
24
+ export type WatchName<TFieldValues extends FieldValues> =
25
+ | FieldPath<TFieldValues>
26
+ | FieldPath<TFieldValues>[]
27
+ | readonly FieldPath<TFieldValues>[]
28
+ | undefined;
29
+
30
+ export type WatchValue<
31
+ TFieldName,
32
+ TFieldValues extends FieldValues = FieldValues,
33
+ > = TFieldName extends FieldPath<TFieldValues>[] | readonly FieldPath<TFieldValues>[]
34
+ ? FieldPathValues<TFieldValues, TFieldName>
35
+ : TFieldName extends FieldPath<TFieldValues>
36
+ ? FieldPathValue<TFieldValues, TFieldName>
37
+ : TFieldValues;
38
+
39
+ export type WatchRenderValue<
40
+ TFieldName,
41
+ TFieldValues extends FieldValues,
42
+ TComputeValue,
43
+ > = TComputeValue extends undefined ? WatchValue<TFieldName, TFieldValues> : TComputeValue;
44
+
45
+ export type WatchProps<
46
+ TFieldName extends WatchName<TFieldValues>,
47
+ TFieldValues extends FieldValues = FieldValues,
48
+ TContext = any,
49
+ TTransformedValues = TFieldValues,
50
+ TComputeValue = undefined,
51
+ > = {
52
+ control?: Control<TFieldValues, TContext, TTransformedValues>;
53
+ /**
54
+ * @deprecated This prop will be renamed to `name` in the next major release.
55
+ * Use `name` instead.
56
+ */
57
+ names?: TFieldName;
58
+ name?: TFieldName;
59
+ disabled?: boolean;
60
+ exact?: boolean;
61
+ defaultValue?: WatchDefaultValue<TFieldName, TFieldValues>;
62
+ compute?: (value: WatchValue<TFieldName, TFieldValues>) => TComputeValue;
63
+ render: (
64
+ value: WatchRenderValue<TFieldName, TFieldValues, TComputeValue>,
65
+ ) => ReactNode | ReactNode[];
66
+ };
@@ -0,0 +1,268 @@
1
+ // Vendored from react-hook-form@7.81.0 src/useController.ts (octane port).
2
+ import { useRef, useEffect, useMemo, useCallback } from 'octane';
3
+
4
+ import getEventValue from './logic/getEventValue';
5
+ import isNameInFieldArray from './logic/isNameInFieldArray';
6
+ import cloneObject from './utils/cloneObject';
7
+ import get from './utils/get';
8
+ import isBoolean from './utils/isBoolean';
9
+ import isFunction from './utils/isFunction';
10
+ import isUndefined from './utils/isUndefined';
11
+ import set from './utils/set';
12
+ import { EVENTS } from './constants';
13
+ import type {
14
+ ControllerFieldState,
15
+ Field,
16
+ FieldPath,
17
+ FieldPathValue,
18
+ FieldValues,
19
+ InternalFieldName,
20
+ UseControllerProps,
21
+ UseControllerReturn,
22
+ } from './types';
23
+ import { useFormControlContext } from './useFormControlContext';
24
+ import { useFormState } from './useFormState';
25
+ import { useWatch } from './useWatch';
26
+
27
+ /**
28
+ * Custom hook to work with controlled component, this function provide you with both form and field level state. Re-render is isolated at the hook level.
29
+ *
30
+ * @remarks
31
+ * [API](https://react-hook-form.com/docs/usecontroller) • [Demo](https://codesandbox.io/s/usecontroller-0o8px)
32
+ *
33
+ * @param props - the path name to the form field value, and validation rules.
34
+ *
35
+ * @returns field properties, field and form state. {@link UseControllerReturn}
36
+ *
37
+ * @example
38
+ * ```tsx
39
+ * function Input(props) {
40
+ * const { field, fieldState, formState } = useController(props);
41
+ * return (
42
+ * <div>
43
+ * <input {...field} placeholder={props.name} />
44
+ * <p>{fieldState.isTouched && "Touched"}</p>
45
+ * <p>{formState.isSubmitted ? "submitted" : ""}</p>
46
+ * </div>
47
+ * );
48
+ * }
49
+ * ```
50
+ */
51
+ export function useController<
52
+ TFieldValues extends FieldValues = FieldValues,
53
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
54
+ TTransformedValues = TFieldValues,
55
+ >(
56
+ props: UseControllerProps<TFieldValues, TName, TTransformedValues>,
57
+ ): UseControllerReturn<TFieldValues, TName> {
58
+ const formControl = useFormControlContext<TFieldValues, any, TTransformedValues>();
59
+ const {
60
+ name,
61
+ disabled,
62
+ control = formControl,
63
+ shouldUnregister,
64
+ defaultValue,
65
+ exact = true,
66
+ } = props;
67
+ const isArrayField = isNameInFieldArray(control._names.array, name);
68
+
69
+ const defaultValueMemo = useMemo(
70
+ () => get(control._formValues, name, get(control._defaultValues, name, defaultValue)),
71
+ [control, name, defaultValue],
72
+ );
73
+
74
+ const value = useWatch({
75
+ control,
76
+ name,
77
+ defaultValue: defaultValueMemo,
78
+ exact,
79
+ }) as FieldPathValue<TFieldValues, TName>;
80
+
81
+ const formState = useFormState({
82
+ control,
83
+ name,
84
+ exact,
85
+ });
86
+
87
+ const _props = useRef(props);
88
+ const _proxyRef = useRef<any>(null);
89
+
90
+ const _registerProps = useRef(
91
+ control.register(name, {
92
+ ...props.rules,
93
+ value,
94
+ ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
95
+ }),
96
+ );
97
+
98
+ _props.current = props;
99
+
100
+ const fieldState = useMemo(
101
+ () =>
102
+ Object.defineProperties(
103
+ {},
104
+ {
105
+ invalid: {
106
+ enumerable: true,
107
+ get: () => !!get(formState.errors, name),
108
+ },
109
+ isDirty: {
110
+ enumerable: true,
111
+ get: () => !!get(formState.dirtyFields, name),
112
+ },
113
+ isTouched: {
114
+ enumerable: true,
115
+ get: () => !!get(formState.touchedFields, name),
116
+ },
117
+ isValidating: {
118
+ enumerable: true,
119
+ get: () => !!get(formState.validatingFields, name),
120
+ },
121
+ error: {
122
+ enumerable: true,
123
+ get: () => get(formState.errors, name),
124
+ },
125
+ },
126
+ ) as ControllerFieldState,
127
+ [formState, name],
128
+ );
129
+
130
+ // octane: upstream names this `onChange` — exposed as `onInput` because
131
+ // octane events are native (input = per-keystroke). Still accepts an event
132
+ // OR a raw value (getEventValue unwraps), and programmatic calls keep the
133
+ // upstream 'change' event type.
134
+ const onInput = useCallback(
135
+ (event: any) => {
136
+ const value = getEventValue(event);
137
+
138
+ if (!get(control._fields, name)) {
139
+ _registerProps.current = control.register(name, {
140
+ ..._props.current.rules,
141
+ value,
142
+ });
143
+ }
144
+
145
+ return _registerProps.current.onInput({
146
+ target: {
147
+ value: getEventValue(event),
148
+ name: name as InternalFieldName,
149
+ },
150
+ type: EVENTS.CHANGE,
151
+ });
152
+ },
153
+ [name, control],
154
+ );
155
+
156
+ const onBlur = useCallback(
157
+ () =>
158
+ _registerProps.current.onBlur({
159
+ target: {
160
+ value: get(control._formValues, name),
161
+ name: name as InternalFieldName,
162
+ },
163
+ type: EVENTS.BLUR,
164
+ }),
165
+ [name, control._formValues],
166
+ );
167
+
168
+ const ref = useCallback(
169
+ (elm: any) => {
170
+ if (elm) {
171
+ _proxyRef.current = {
172
+ focus: () => isFunction(elm.focus) && elm.focus(),
173
+ select: () => isFunction(elm.select) && elm.select(),
174
+ setCustomValidity: (message: string) =>
175
+ isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
176
+ reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
177
+ };
178
+ }
179
+
180
+ const field = get(control._fields, name);
181
+
182
+ if (field && field._f && elm) {
183
+ field._f.ref = _proxyRef.current;
184
+ }
185
+ },
186
+ [control._fields, name],
187
+ );
188
+
189
+ const field = useMemo(
190
+ () => ({
191
+ name,
192
+ value,
193
+ ...(isBoolean(disabled) || formState.disabled
194
+ ? { disabled: formState.disabled || disabled }
195
+ : {}),
196
+ onInput,
197
+ onBlur,
198
+ ref,
199
+ }),
200
+ [name, disabled, formState.disabled, onInput, onBlur, ref, value],
201
+ );
202
+
203
+ useEffect(() => {
204
+ const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
205
+
206
+ control.register(name, {
207
+ ..._props.current.rules,
208
+ ...(isBoolean(_props.current.disabled) ? { disabled: _props.current.disabled } : {}),
209
+ });
210
+
211
+ const updateMounted = (name: InternalFieldName, value: boolean) => {
212
+ const field: Field = get(control._fields, name);
213
+
214
+ if (field && field._f) {
215
+ field._f.mount = value;
216
+ }
217
+ };
218
+
219
+ updateMounted(name, true);
220
+
221
+ if (_shouldUnregisterField) {
222
+ const value = cloneObject(
223
+ get(
224
+ shouldUnregister
225
+ ? control._defaultValues
226
+ : control._options.values || control._defaultValues,
227
+ name,
228
+ get(control._options.defaultValues, name, _props.current.defaultValue),
229
+ ),
230
+ );
231
+ set(control._defaultValues, name, value);
232
+ if (isUndefined(get(control._formValues, name))) {
233
+ set(control._formValues, name, value);
234
+ }
235
+ }
236
+
237
+ !isArrayField && control.register(name);
238
+
239
+ if (_proxyRef.current) {
240
+ const field: Field = get(control._fields, name);
241
+ if (field && field._f) {
242
+ field._f.ref = _proxyRef.current;
243
+ }
244
+ }
245
+
246
+ return () => {
247
+ (isArrayField ? _shouldUnregisterField && !control._state.action : _shouldUnregisterField)
248
+ ? control.unregister(name)
249
+ : updateMounted(name, false);
250
+ };
251
+ }, [name, control, isArrayField, shouldUnregister]);
252
+
253
+ useEffect(() => {
254
+ control._setDisabledField({
255
+ disabled,
256
+ name,
257
+ });
258
+ }, [disabled, name, control]);
259
+
260
+ return useMemo(
261
+ () => ({
262
+ field,
263
+ formState,
264
+ fieldState,
265
+ }),
266
+ [field, formState, fieldState],
267
+ );
268
+ }