react-hook-form 7.43.1 → 7.44.0-next.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.
- package/dist/__tests__/form.test.d.ts +2 -0
- package/dist/__tests__/form.test.d.ts.map +1 -0
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/form.d.ts +46 -0
- package/dist/form.d.ts.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.mjs +135 -45
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/createFormControl.d.ts +1 -0
- package/dist/logic/createFormControl.d.ts.map +1 -1
- package/dist/types/errors.d.ts +2 -2
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/form.d.ts +5 -2
- package/dist/types/form.d.ts.map +1 -1
- package/dist/useForm.d.ts +1 -1
- package/package.json +8 -3
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC"}
|
package/dist/index.esm.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
import React from 'react';
|
1
|
+
import * as React from 'react';
|
2
|
+
import React__default from 'react';
|
2
3
|
|
3
4
|
var isCheckBoxInput = (element) => element.type === 'checkbox';
|
4
5
|
|
@@ -58,9 +59,10 @@ const INPUT_VALIDATION_RULES = {
|
|
58
59
|
pattern: 'pattern',
|
59
60
|
required: 'required',
|
60
61
|
validate: 'validate',
|
61
|
-
};
|
62
|
+
};
|
63
|
+
const SERVER_ERROR_TYPE = 'root.server';
|
62
64
|
|
63
|
-
const HookFormContext =
|
65
|
+
const HookFormContext = React__default.createContext(null);
|
64
66
|
/**
|
65
67
|
* This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
|
66
68
|
*
|
@@ -91,7 +93,7 @@ const HookFormContext = React.createContext(null);
|
|
91
93
|
* }
|
92
94
|
* ```
|
93
95
|
*/
|
94
|
-
const useFormContext = () =>
|
96
|
+
const useFormContext = () => React__default.useContext(HookFormContext);
|
95
97
|
/**
|
96
98
|
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://reactjs.org/docs/context.html) API. To be used with {@link useFormContext}.
|
97
99
|
*
|
@@ -124,7 +126,7 @@ const useFormContext = () => React.useContext(HookFormContext);
|
|
124
126
|
*/
|
125
127
|
const FormProvider = (props) => {
|
126
128
|
const { children, ...data } = props;
|
127
|
-
return (
|
129
|
+
return (React__default.createElement(HookFormContext.Provider, { value: data }, children));
|
128
130
|
};
|
129
131
|
|
130
132
|
var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
|
@@ -169,9 +171,9 @@ var shouldSubscribeByName = (name, signalName, exact) => exact && signalName
|
|
169
171
|
signalName.startsWith(currentName)));
|
170
172
|
|
171
173
|
function useSubscribe(props) {
|
172
|
-
const _props =
|
174
|
+
const _props = React__default.useRef(props);
|
173
175
|
_props.current = props;
|
174
|
-
|
176
|
+
React__default.useEffect(() => {
|
175
177
|
const subscription = !props.disabled &&
|
176
178
|
_props.current.subject.subscribe({
|
177
179
|
next: _props.current.next,
|
@@ -215,9 +217,9 @@ function useSubscribe(props) {
|
|
215
217
|
function useFormState(props) {
|
216
218
|
const methods = useFormContext();
|
217
219
|
const { control = methods.control, disabled, name, exact } = props || {};
|
218
|
-
const [formState, updateFormState] =
|
219
|
-
const _mounted =
|
220
|
-
const _localProxyFormState =
|
220
|
+
const [formState, updateFormState] = React__default.useState(control._formState);
|
221
|
+
const _mounted = React__default.useRef(true);
|
222
|
+
const _localProxyFormState = React__default.useRef({
|
221
223
|
isDirty: false,
|
222
224
|
isLoading: false,
|
223
225
|
dirtyFields: false,
|
@@ -226,7 +228,7 @@ function useFormState(props) {
|
|
226
228
|
isValid: false,
|
227
229
|
errors: false,
|
228
230
|
});
|
229
|
-
const _name =
|
231
|
+
const _name = React__default.useRef(name);
|
230
232
|
_name.current = name;
|
231
233
|
useSubscribe({
|
232
234
|
disabled,
|
@@ -239,7 +241,7 @@ function useFormState(props) {
|
|
239
241
|
}),
|
240
242
|
subject: control._subjects.state,
|
241
243
|
});
|
242
|
-
|
244
|
+
React__default.useEffect(() => {
|
243
245
|
_mounted.current = true;
|
244
246
|
const isDirty = control._proxyFormState.isDirty && control._getDirty();
|
245
247
|
if (isDirty !== control._formState.isDirty) {
|
@@ -324,7 +326,7 @@ function cloneObject(data) {
|
|
324
326
|
function useWatch(props) {
|
325
327
|
const methods = useFormContext();
|
326
328
|
const { control = methods.control, name, defaultValue, disabled, exact, } = props || {};
|
327
|
-
const _name =
|
329
|
+
const _name = React__default.useRef(name);
|
328
330
|
_name.current = name;
|
329
331
|
useSubscribe({
|
330
332
|
disabled,
|
@@ -335,8 +337,8 @@ function useWatch(props) {
|
|
335
337
|
}
|
336
338
|
},
|
337
339
|
});
|
338
|
-
const [value, updateValue] =
|
339
|
-
|
340
|
+
const [value, updateValue] = React__default.useState(control._getWatch(name, defaultValue));
|
341
|
+
React__default.useEffect(() => control._removeUnmounted());
|
340
342
|
return value;
|
341
343
|
}
|
342
344
|
|
@@ -378,11 +380,11 @@ function useController(props) {
|
|
378
380
|
control,
|
379
381
|
name,
|
380
382
|
});
|
381
|
-
const _registerProps =
|
383
|
+
const _registerProps = React__default.useRef(control.register(name, {
|
382
384
|
...props.rules,
|
383
385
|
value,
|
384
386
|
}));
|
385
|
-
|
387
|
+
React__default.useEffect(() => {
|
386
388
|
const updateMounted = (name, value) => {
|
387
389
|
const field = get(control._fields, name);
|
388
390
|
if (field) {
|
@@ -403,14 +405,14 @@ function useController(props) {
|
|
403
405
|
field: {
|
404
406
|
name,
|
405
407
|
value,
|
406
|
-
onChange:
|
408
|
+
onChange: React__default.useCallback((event) => _registerProps.current.onChange({
|
407
409
|
target: {
|
408
410
|
value: getEventValue(event),
|
409
411
|
name: name,
|
410
412
|
},
|
411
413
|
type: EVENTS.CHANGE,
|
412
414
|
}), [name]),
|
413
|
-
onBlur:
|
415
|
+
onBlur: React__default.useCallback(() => _registerProps.current.onBlur({
|
414
416
|
target: {
|
415
417
|
value: get(control._formValues, name),
|
416
418
|
name: name,
|
@@ -495,6 +497,89 @@ function useController(props) {
|
|
495
497
|
*/
|
496
498
|
const Controller = (props) => props.render(useController(props));
|
497
499
|
|
500
|
+
const POST_REQUEST = 'post';
|
501
|
+
/**
|
502
|
+
* Form component to manage submission.
|
503
|
+
*
|
504
|
+
* @param props - to setup submission detail. {@link FormProps}
|
505
|
+
*
|
506
|
+
* @returns form component or headless render prop.
|
507
|
+
*
|
508
|
+
* @example
|
509
|
+
* ```tsx
|
510
|
+
* function App() {
|
511
|
+
* const { control, formState: { errors } } = useForm();
|
512
|
+
*
|
513
|
+
* return (
|
514
|
+
* <Form action="/api" control={control}>
|
515
|
+
* <input {...register("name")} />
|
516
|
+
* <p>{errors?.root?.server && 'Server error'}</p>
|
517
|
+
* <button>Submit</button>
|
518
|
+
* </form>
|
519
|
+
* );
|
520
|
+
* }
|
521
|
+
* ```
|
522
|
+
*/
|
523
|
+
function Form(props) {
|
524
|
+
const methods = useFormContext();
|
525
|
+
const [mounted, setMounted] = React.useState(false);
|
526
|
+
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
527
|
+
const isPostRequest = method === POST_REQUEST;
|
528
|
+
const submit = control.handleSubmit(async (data) => {
|
529
|
+
onSubmit && onSubmit(data);
|
530
|
+
if (action) {
|
531
|
+
const formData = new FormData();
|
532
|
+
let shouldStringifySubmissionData = false;
|
533
|
+
if (headers) {
|
534
|
+
shouldStringifySubmissionData =
|
535
|
+
headers['Content-Type'].includes('json');
|
536
|
+
}
|
537
|
+
else {
|
538
|
+
control._names.mount.forEach((name) => formData.append(name, get(data, name)));
|
539
|
+
}
|
540
|
+
try {
|
541
|
+
const response = await fetch(action, {
|
542
|
+
method,
|
543
|
+
headers: {
|
544
|
+
...headers,
|
545
|
+
...(encType ? { 'Content-Type': encType } : {}),
|
546
|
+
},
|
547
|
+
...(isPostRequest
|
548
|
+
? {
|
549
|
+
body: shouldStringifySubmissionData
|
550
|
+
? JSON.stringify(data)
|
551
|
+
: formData,
|
552
|
+
}
|
553
|
+
: {}),
|
554
|
+
});
|
555
|
+
if (validateStatus
|
556
|
+
? !validateStatus(response.status)
|
557
|
+
: response.status < 200 || response.status >= 300) {
|
558
|
+
control.setError(SERVER_ERROR_TYPE, {
|
559
|
+
type: String(response.status),
|
560
|
+
});
|
561
|
+
onError && onError({ response });
|
562
|
+
}
|
563
|
+
else {
|
564
|
+
onSuccess && onSuccess({ response });
|
565
|
+
}
|
566
|
+
}
|
567
|
+
catch (error) {
|
568
|
+
control.setError(SERVER_ERROR_TYPE, {
|
569
|
+
type: 'error',
|
570
|
+
});
|
571
|
+
onError && onError({ error });
|
572
|
+
}
|
573
|
+
}
|
574
|
+
});
|
575
|
+
React.useEffect(() => {
|
576
|
+
setMounted(true);
|
577
|
+
}, []);
|
578
|
+
return render ? (React.createElement(React.Fragment, null, render({
|
579
|
+
submit,
|
580
|
+
}))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
|
581
|
+
}
|
582
|
+
|
498
583
|
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
499
584
|
? {
|
500
585
|
...errors[name],
|
@@ -603,7 +688,7 @@ var isHTMLElement = (value) => {
|
|
603
688
|
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
604
689
|
};
|
605
690
|
|
606
|
-
var isMessage = (value) => isString(value) ||
|
691
|
+
var isMessage = (value) => isString(value) || React__default.isValidElement(value);
|
607
692
|
|
608
693
|
var isRadioInput = (element) => element.type === 'radio';
|
609
694
|
|
@@ -972,11 +1057,11 @@ var updateAt = (fieldValues, index, value) => {
|
|
972
1057
|
function useFieldArray(props) {
|
973
1058
|
const methods = useFormContext();
|
974
1059
|
const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
|
975
|
-
const [fields, setFields] =
|
976
|
-
const ids =
|
977
|
-
const _fieldIds =
|
978
|
-
const _name =
|
979
|
-
const _actioned =
|
1060
|
+
const [fields, setFields] = React__default.useState(control._getFieldArray(name));
|
1061
|
+
const ids = React__default.useRef(control._getFieldArray(name).map(generateId));
|
1062
|
+
const _fieldIds = React__default.useRef(fields);
|
1063
|
+
const _name = React__default.useRef(name);
|
1064
|
+
const _actioned = React__default.useRef(false);
|
980
1065
|
_name.current = name;
|
981
1066
|
_fieldIds.current = fields;
|
982
1067
|
control._names.array.add(name);
|
@@ -994,7 +1079,7 @@ function useFieldArray(props) {
|
|
994
1079
|
},
|
995
1080
|
subject: control._subjects.array,
|
996
1081
|
});
|
997
|
-
const updateValues =
|
1082
|
+
const updateValues = React__default.useCallback((updatedFieldArrayValues) => {
|
998
1083
|
_actioned.current = true;
|
999
1084
|
control._updateFieldArray(name, updatedFieldArrayValues);
|
1000
1085
|
}, [control, name]);
|
@@ -1081,7 +1166,7 @@ function useFieldArray(props) {
|
|
1081
1166
|
setFields([...updatedFieldArrayValues]);
|
1082
1167
|
control._updateFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
1083
1168
|
};
|
1084
|
-
|
1169
|
+
React__default.useEffect(() => {
|
1085
1170
|
control._stateFlags.action = false;
|
1086
1171
|
isWatched(name, control._names) && control._subjects.state.next({});
|
1087
1172
|
if (_actioned.current &&
|
@@ -1120,7 +1205,7 @@ function useFieldArray(props) {
|
|
1120
1205
|
control._names.focus = '';
|
1121
1206
|
control._updateValid();
|
1122
1207
|
}, [fields, name, control]);
|
1123
|
-
|
1208
|
+
React__default.useEffect(() => {
|
1124
1209
|
!get(control._formValues, name) && control._updateFieldArray(name);
|
1125
1210
|
return () => {
|
1126
1211
|
(control._options.shouldUnregister || shouldUnregister) &&
|
@@ -1128,15 +1213,15 @@ function useFieldArray(props) {
|
|
1128
1213
|
};
|
1129
1214
|
}, [name, control, keyName, shouldUnregister]);
|
1130
1215
|
return {
|
1131
|
-
swap:
|
1132
|
-
move:
|
1133
|
-
prepend:
|
1134
|
-
append:
|
1135
|
-
remove:
|
1136
|
-
insert:
|
1137
|
-
update:
|
1138
|
-
replace:
|
1139
|
-
fields:
|
1216
|
+
swap: React__default.useCallback(swap, [updateValues, name, control]),
|
1217
|
+
move: React__default.useCallback(move, [updateValues, name, control]),
|
1218
|
+
prepend: React__default.useCallback(prepend$1, [updateValues, name, control]),
|
1219
|
+
append: React__default.useCallback(append$1, [updateValues, name, control]),
|
1220
|
+
remove: React__default.useCallback(remove, [updateValues, name, control]),
|
1221
|
+
insert: React__default.useCallback(insert$1, [updateValues, name, control]),
|
1222
|
+
update: React__default.useCallback(update, [updateValues, name, control]),
|
1223
|
+
replace: React__default.useCallback(replace, [updateValues, name, control]),
|
1224
|
+
fields: React__default.useMemo(() => fields.map((field, index) => ({
|
1140
1225
|
...field,
|
1141
1226
|
[keyName]: ids.current[index] || generateId(),
|
1142
1227
|
})), [fields, keyName]),
|
@@ -1865,6 +1950,9 @@ function createFormControl(props = {}, flushRootRender) {
|
|
1865
1950
|
name,
|
1866
1951
|
errors: _formState.errors,
|
1867
1952
|
isValid: false,
|
1953
|
+
...(error.type === SERVER_ERROR_TYPE
|
1954
|
+
? { isSubmitSuccessful: false }
|
1955
|
+
: {}),
|
1868
1956
|
});
|
1869
1957
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
1870
1958
|
};
|
@@ -1918,7 +2006,7 @@ function createFormControl(props = {}, flushRootRender) {
|
|
1918
2006
|
: updateValidAndValue(name, true, options.value);
|
1919
2007
|
return {
|
1920
2008
|
...(disabledIsDefined ? { disabled: options.disabled } : {}),
|
1921
|
-
...(_options.shouldUseNativeValidation
|
2009
|
+
...(_options.shouldUseNativeValidation || _options.progressive
|
1922
2010
|
? {
|
1923
2011
|
required: !!options.required,
|
1924
2012
|
min: getRuleValue(options.min),
|
@@ -2161,6 +2249,8 @@ function createFormControl(props = {}, flushRootRender) {
|
|
2161
2249
|
register,
|
2162
2250
|
unregister,
|
2163
2251
|
getFieldState,
|
2252
|
+
handleSubmit,
|
2253
|
+
setError,
|
2164
2254
|
_executeSchema,
|
2165
2255
|
_focusError,
|
2166
2256
|
_getWatch,
|
@@ -2249,15 +2339,15 @@ function createFormControl(props = {}, flushRootRender) {
|
|
2249
2339
|
* <input defaultValue="test" {...register("example")} />
|
2250
2340
|
* <input {...register("exampleRequired", { required: true })} />
|
2251
2341
|
* {errors.exampleRequired && <span>This field is required</span>}
|
2252
|
-
* <
|
2342
|
+
* <button>Submit</button>
|
2253
2343
|
* </form>
|
2254
2344
|
* );
|
2255
2345
|
* }
|
2256
2346
|
* ```
|
2257
2347
|
*/
|
2258
2348
|
function useForm(props = {}) {
|
2259
|
-
const _formControl =
|
2260
|
-
const [formState, updateFormState] =
|
2349
|
+
const _formControl = React__default.useRef();
|
2350
|
+
const [formState, updateFormState] = React__default.useState({
|
2261
2351
|
isDirty: false,
|
2262
2352
|
isValidating: false,
|
2263
2353
|
isLoading: true,
|
@@ -2289,7 +2379,7 @@ function useForm(props = {}) {
|
|
2289
2379
|
}
|
2290
2380
|
},
|
2291
2381
|
});
|
2292
|
-
|
2382
|
+
React__default.useEffect(() => {
|
2293
2383
|
if (!control._stateFlags.mount) {
|
2294
2384
|
control._updateValid();
|
2295
2385
|
control._stateFlags.mount = true;
|
@@ -2300,17 +2390,17 @@ function useForm(props = {}) {
|
|
2300
2390
|
}
|
2301
2391
|
control._removeUnmounted();
|
2302
2392
|
});
|
2303
|
-
|
2393
|
+
React__default.useEffect(() => {
|
2304
2394
|
if (props.values && !deepEqual(props.values, control._defaultValues)) {
|
2305
2395
|
control._reset(props.values, control._options.resetOptions);
|
2306
2396
|
}
|
2307
2397
|
}, [props.values, control]);
|
2308
|
-
|
2398
|
+
React__default.useEffect(() => {
|
2309
2399
|
formState.submitCount && control._focusError();
|
2310
2400
|
}, [control, formState.submitCount]);
|
2311
2401
|
_formControl.current.formState = getProxyFormState(formState, control);
|
2312
2402
|
return _formControl.current;
|
2313
2403
|
}
|
2314
2404
|
|
2315
|
-
export { Controller, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
2405
|
+
export { Controller, Form, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
2316
2406
|
//# sourceMappingURL=index.esm.mjs.map
|