react-hook-form 7.0.0-rc.8 → 7.0.3

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/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import * as React from 'react';
2
2
 
3
- var isUndefined = (val) => val === undefined;
3
+ var isCheckBoxInput = (element) => element.type === 'checkbox';
4
4
 
5
5
  var isNullOrUndefined = (value) => value == null;
6
6
 
@@ -10,8 +10,20 @@ var isObject = (value) => !isNullOrUndefined(value) &&
10
10
  isObjectType(value) &&
11
11
  !(value instanceof Date);
12
12
 
13
+ var getControllerValue = (event) => isObject(event) && event.target
14
+ ? isCheckBoxInput(event.target)
15
+ ? event.target.checked
16
+ : event.target.value
17
+ : event;
18
+
19
+ var getNodeParentName = (name) => name.substring(0, name.search(/.\d/)) || name;
20
+
21
+ var isNameInFieldArray = (names, name) => [...names].some((current) => getNodeParentName(name) === current);
22
+
13
23
  var compact = (value) => value.filter(Boolean);
14
24
 
25
+ var isUndefined = (val) => val === undefined;
26
+
15
27
  var get = (obj = {}, path, defaultValue) => {
16
28
  const result = compact(path.split(/[,[\].]+?/)).reduce((result, key) => (isNullOrUndefined(result) ? result : result[key]), obj);
17
29
  return isUndefined(result) || result === obj
@@ -21,6 +33,175 @@ var get = (obj = {}, path, defaultValue) => {
21
33
  : result;
22
34
  };
23
35
 
36
+ const EVENTS = {
37
+ BLUR: 'blur',
38
+ CHANGE: 'change',
39
+ };
40
+ const VALIDATION_MODE = {
41
+ onBlur: 'onBlur',
42
+ onChange: 'onChange',
43
+ onSubmit: 'onSubmit',
44
+ onTouched: 'onTouched',
45
+ all: 'all',
46
+ };
47
+ const SELECT = 'select';
48
+ const UNDEFINED = 'undefined';
49
+ const INPUT_VALIDATION_RULES = {
50
+ max: 'max',
51
+ min: 'min',
52
+ maxLength: 'maxLength',
53
+ minLength: 'minLength',
54
+ pattern: 'pattern',
55
+ required: 'required',
56
+ validate: 'validate',
57
+ };
58
+
59
+ var omit = (source, key) => {
60
+ const copy = Object.assign({}, source);
61
+ delete copy[key];
62
+ return copy;
63
+ };
64
+
65
+ const FormContext = React.createContext(null);
66
+ FormContext.displayName = 'RHFContext';
67
+ const useFormContext = () => React.useContext(FormContext);
68
+ const FormProvider = (props) => (React.createElement(FormContext.Provider, { value: omit(props, 'children') }, props.children));
69
+
70
+ var getProxyFormState = (isProxyEnabled, formState, readFormStateRef, localReadFormStateRef, isRoot = true) => isProxyEnabled
71
+ ? new Proxy(formState, {
72
+ get: (obj, prop) => {
73
+ if (prop in obj) {
74
+ if (readFormStateRef.current[prop] !== VALIDATION_MODE.all) {
75
+ readFormStateRef.current[prop] = isRoot
76
+ ? VALIDATION_MODE.all
77
+ : true;
78
+ }
79
+ localReadFormStateRef &&
80
+ (localReadFormStateRef.current[prop] = true);
81
+ return obj[prop];
82
+ }
83
+ return undefined;
84
+ },
85
+ })
86
+ : formState;
87
+
88
+ var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
89
+
90
+ var shouldRenderFormState = (formState, readFormStateRef, isRoot) => isEmptyObject(formState) ||
91
+ Object.keys(formState).length >= Object.keys(readFormStateRef).length ||
92
+ Object.keys(formState).find((key) => readFormStateRef[key] ===
93
+ (isRoot ? VALIDATION_MODE.all : true));
94
+
95
+ var isWeb = typeof window !== UNDEFINED &&
96
+ typeof window.HTMLElement !== UNDEFINED &&
97
+ typeof document !== UNDEFINED;
98
+
99
+ const isProxyEnabled = isWeb ? 'Proxy' in window : typeof Proxy !== UNDEFINED;
100
+
101
+ function useFormState(props) {
102
+ const methods = useFormContext();
103
+ const { formStateRef, formStateSubjectRef, readFormStateRef } = (props && props.control) || methods.control;
104
+ const [formState, updateFormState] = React.useState(formStateRef.current);
105
+ const readFormState = React.useRef({
106
+ isDirty: false,
107
+ dirtyFields: false,
108
+ touchedFields: false,
109
+ isValidating: false,
110
+ isValid: false,
111
+ errors: false,
112
+ });
113
+ React.useEffect(() => {
114
+ const formStateSubscription = formStateSubjectRef.current.subscribe({
115
+ next: (formState) => {
116
+ shouldRenderFormState(formState, readFormState.current) &&
117
+ updateFormState(Object.assign(Object.assign({}, formStateRef.current), formState));
118
+ },
119
+ });
120
+ return () => formStateSubscription.unsubscribe();
121
+ }, []);
122
+ return getProxyFormState(isProxyEnabled, formState, readFormStateRef, readFormState, false);
123
+ }
124
+
125
+ function useController({ name, rules, defaultValue, control, }) {
126
+ const methods = useFormContext();
127
+ const { defaultValuesRef, register, fieldsRef, fieldArrayNamesRef, controllerSubjectRef, } = control || methods.control;
128
+ const { onChange, onBlur, ref } = register(name, rules);
129
+ const [value, setInputStateValue] = React.useState(isUndefined(get(fieldsRef.current, name)._f.value) ||
130
+ isNameInFieldArray(fieldArrayNamesRef.current, name)
131
+ ? isUndefined(defaultValue)
132
+ ? get(defaultValuesRef.current, name)
133
+ : defaultValue
134
+ : get(fieldsRef.current, name)._f.value);
135
+ const formState = useFormState({
136
+ control: control || methods.control,
137
+ });
138
+ get(fieldsRef.current, name)._f.value = value;
139
+ React.useEffect(() => {
140
+ const controllerSubscription = controllerSubjectRef.current.subscribe({
141
+ next: (data) => (!data.name || name === data.name) &&
142
+ setInputStateValue(get(data.values, name)),
143
+ });
144
+ ref({
145
+ target: value,
146
+ });
147
+ return () => controllerSubscription.unsubscribe();
148
+ }, [name]);
149
+ return {
150
+ field: {
151
+ onChange: (event) => {
152
+ const value = getControllerValue(event);
153
+ setInputStateValue(value);
154
+ onChange({
155
+ target: {
156
+ value,
157
+ name: name,
158
+ },
159
+ type: EVENTS.CHANGE,
160
+ });
161
+ },
162
+ onBlur: () => {
163
+ onBlur({
164
+ target: {
165
+ name: name,
166
+ },
167
+ type: EVENTS.BLUR,
168
+ });
169
+ },
170
+ name,
171
+ value,
172
+ ref,
173
+ },
174
+ formState,
175
+ fieldState: Object.defineProperties({}, {
176
+ invalid: {
177
+ get() {
178
+ return !!get(formState.errors, name);
179
+ },
180
+ },
181
+ isDirty: {
182
+ get() {
183
+ return !!get(formState.dirtyFields, name);
184
+ },
185
+ },
186
+ isTouched: {
187
+ get() {
188
+ return !!get(formState.touchedFields, name);
189
+ },
190
+ },
191
+ error: {
192
+ get() {
193
+ return get(formState.errors, name);
194
+ },
195
+ },
196
+ }),
197
+ };
198
+ }
199
+
200
+ const Controller = (props) => props.render(useController(props));
201
+
202
+ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
203
+ ? Object.assign(Object.assign({}, errors[name]), { types: Object.assign(Object.assign({}, (errors[name] && errors[name].types ? errors[name].types : {})), { [type]: message || true }) }) : {};
204
+
24
205
  var isKey = (value) => /^\w*$/.test(value);
25
206
 
26
207
  var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
@@ -48,12 +229,6 @@ function set(object, path, value) {
48
229
  return object;
49
230
  }
50
231
 
51
- var omit = (source, key) => {
52
- const copy = Object.assign({}, source);
53
- delete copy[key];
54
- return copy;
55
- };
56
-
57
232
  const focusFieldBy = (fields, callback, fieldsNames) => {
58
233
  for (const key of fieldsNames || Object.keys(fields)) {
59
234
  const field = get(fields, key);
@@ -76,26 +251,40 @@ const focusFieldBy = (fields, callback, fieldsNames) => {
76
251
  }
77
252
  };
78
253
 
79
- var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
80
-
81
- function deepMerge(target, source) {
82
- if (isPrimitive(target) || isPrimitive(source)) {
83
- return source;
84
- }
85
- for (const key in source) {
86
- const targetValue = target[key];
87
- const sourceValue = source[key];
88
- try {
89
- target[key] =
90
- (isObject(targetValue) && isObject(sourceValue)) ||
91
- (Array.isArray(targetValue) && Array.isArray(sourceValue))
92
- ? deepMerge(targetValue, sourceValue)
93
- : sourceValue;
254
+ const getFieldsValues = (fieldsRef, defaultValuesRef = { current: {} }, output = {}) => {
255
+ for (const name in fieldsRef.current) {
256
+ const field = fieldsRef.current[name];
257
+ if (field) {
258
+ const _f = field._f;
259
+ const current = omit(field, '_f');
260
+ set(output, name, _f
261
+ ? _f.ref.disabled || (_f.refs && _f.refs.every((ref) => ref.disabled))
262
+ ? undefined
263
+ : _f.value
264
+ : Array.isArray(field)
265
+ ? []
266
+ : {});
267
+ if (current) {
268
+ getFieldsValues({
269
+ current,
270
+ }, defaultValuesRef, output[name]);
271
+ }
94
272
  }
95
- catch (_a) { }
96
273
  }
97
- return target;
98
- }
274
+ return Object.assign(Object.assign({}, defaultValuesRef.current), output);
275
+ };
276
+
277
+ var generateId = () => {
278
+ const d = typeof performance === UNDEFINED ? Date.now() : performance.now() * 1000;
279
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
280
+ const r = (Math.random() * 16 + d) % 16 | 0;
281
+ return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
282
+ });
283
+ };
284
+
285
+ var mapIds = (values = [], keyName) => values.map((value) => (Object.assign({ [keyName]: (value && value[keyName]) || generateId() }, value)));
286
+
287
+ var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
99
288
 
100
289
  function deepEqual(object1, object2, isErrorObject) {
101
290
  if (isPrimitive(object1) ||
@@ -126,6 +315,25 @@ function deepEqual(object1, object2, isErrorObject) {
126
315
  return true;
127
316
  }
128
317
 
318
+ function deepMerge(target, source) {
319
+ if (isPrimitive(target) || isPrimitive(source)) {
320
+ return source;
321
+ }
322
+ for (const key in source) {
323
+ const targetValue = target[key];
324
+ const sourceValue = source[key];
325
+ try {
326
+ target[key] =
327
+ (isObject(targetValue) && isObject(sourceValue)) ||
328
+ (Array.isArray(targetValue) && Array.isArray(sourceValue))
329
+ ? deepMerge(targetValue, sourceValue)
330
+ : sourceValue;
331
+ }
332
+ catch (_a) { }
333
+ }
334
+ return target;
335
+ }
336
+
129
337
  function setDirtyFields(values, defaultValues, dirtyFields, parentNode, parentName) {
130
338
  let index = -1;
131
339
  while (++index < values.length) {
@@ -149,476 +357,625 @@ function setDirtyFields(values, defaultValues, dirtyFields, parentNode, parentNa
149
357
  }
150
358
  var setFieldArrayDirtyFields = (values, defaultValues, dirtyFields) => deepMerge(setDirtyFields(values, defaultValues, dirtyFields.slice(0, values.length)), setDirtyFields(defaultValues, values, dirtyFields.slice(0, values.length)));
151
359
 
152
- var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
153
-
154
- const EVENTS = {
155
- BLUR: 'blur',
156
- CHANGE: 'change',
157
- };
158
- const VALIDATION_MODE = {
159
- onBlur: 'onBlur',
160
- onChange: 'onChange',
161
- onSubmit: 'onSubmit',
162
- onTouched: 'onTouched',
163
- all: 'all',
164
- };
165
- const SELECT = 'select';
166
- const UNDEFINED = 'undefined';
167
- const INPUT_VALIDATION_RULES = {
168
- max: 'max',
169
- min: 'min',
170
- maxLength: 'maxLength',
171
- minLength: 'minLength',
172
- pattern: 'pattern',
173
- required: 'required',
174
- validate: 'validate',
175
- };
176
-
177
- var shouldRenderFormState = (formState, readFormStateRef, isRoot) => isEmptyObject(formState) ||
178
- Object.keys(formState).length >= Object.keys(readFormStateRef).length ||
179
- Object.keys(formState).find((key) => readFormStateRef[key] ===
180
- (isRoot ? VALIDATION_MODE.all : true));
181
-
182
- const getFieldsValues = (fieldsRef, defaultValuesRef = { current: {} }, output = {}) => {
183
- for (const name in fieldsRef.current) {
184
- const field = fieldsRef.current[name];
185
- if (field) {
186
- const _f = field._f;
187
- const current = omit(field, '_f');
188
- set(output, name, _f
189
- ? _f.ref.disabled || (_f.refs && _f.refs.every((ref) => ref.disabled))
190
- ? undefined
191
- : _f.value
192
- : Array.isArray(field)
193
- ? []
194
- : {});
195
- if (current) {
196
- getFieldsValues({
197
- current,
198
- }, defaultValuesRef, output[name]);
199
- }
200
- }
201
- }
202
- return Object.assign(Object.assign({}, defaultValuesRef.current), output);
203
- };
204
-
205
- const defaultReturn = {
206
- isValid: false,
207
- value: null,
208
- };
209
- var getRadioValue = (options) => Array.isArray(options)
210
- ? options.reduce((previous, option) => option && option.checked && !option.disabled
211
- ? {
212
- isValid: true,
213
- value: option.value,
214
- }
215
- : previous, defaultReturn)
216
- : defaultReturn;
217
-
218
- var getMultipleSelectValue = (options) => [...options]
219
- .filter(({ selected }) => selected)
220
- .map(({ value }) => value);
221
-
222
- var isRadioInput = (element) => element.type === 'radio';
223
-
224
- var isFileInput = (element) => element.type === 'file';
360
+ function append(data, value) {
361
+ return [...data, ...(Array.isArray(value) ? value : [value])];
362
+ }
225
363
 
226
- var isCheckBoxInput = (element) => element.type === 'checkbox';
364
+ var fillEmptyArray = (value) => Array.isArray(value) ? Array(value.length).fill(undefined) : undefined;
227
365
 
228
- var isMultipleSelect = (element) => element.type === `${SELECT}-multiple`;
366
+ function insert(data, index, value) {
367
+ return [
368
+ ...data.slice(0, index),
369
+ ...(Array.isArray(value) ? value : [value]),
370
+ ...data.slice(index),
371
+ ];
372
+ }
229
373
 
230
- const defaultResult = {
231
- value: false,
232
- isValid: false,
233
- };
234
- const validResult = { value: true, isValid: true };
235
- var getCheckboxValue = (options) => {
236
- if (Array.isArray(options)) {
237
- if (options.length > 1) {
238
- const values = options
239
- .filter((option) => option && option.checked && !option.disabled)
240
- .map((option) => option.value);
241
- return { value: values, isValid: !!values.length };
374
+ var moveArrayAt = (data, from, to) => {
375
+ if (Array.isArray(data)) {
376
+ if (isUndefined(data[to])) {
377
+ data[to] = undefined;
242
378
  }
243
- return options[0].checked && !options[0].disabled
244
- ? // @ts-expect-error expected to work in the browser
245
- options[0].attributes && !isUndefined(options[0].attributes.value)
246
- ? isUndefined(options[0].value)
247
- ? validResult
248
- : { value: options[0].value, isValid: true }
249
- : validResult
250
- : defaultResult;
379
+ data.splice(to, 0, data.splice(from, 1)[0]);
380
+ return data;
251
381
  }
252
- return defaultResult;
382
+ return [];
253
383
  };
254
384
 
255
- var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => valueAsNumber
256
- ? value === ''
257
- ? NaN
258
- : +value
259
- : valueAsDate
260
- ? new Date(value)
261
- : setValueAs
262
- ? setValueAs(value)
263
- : value;
385
+ function prepend(data, value) {
386
+ return [...(Array.isArray(value) ? value : [value]), ...data];
387
+ }
264
388
 
265
- function getFieldValue(field) {
266
- if (field && field._f) {
267
- const ref = field._f.ref;
268
- if (ref.disabled) {
269
- return;
270
- }
271
- if (isFileInput(ref)) {
272
- return ref.files;
273
- }
274
- if (isRadioInput(ref)) {
275
- return getRadioValue(field._f.refs).value;
276
- }
277
- if (isMultipleSelect(ref)) {
278
- return getMultipleSelectValue(ref.options);
279
- }
280
- if (isCheckBoxInput(ref)) {
281
- return getCheckboxValue(field._f.refs).value;
282
- }
283
- return getFieldValueAs(isUndefined(ref.value) ? field._f.ref.value : ref.value, field._f);
389
+ function removeAtIndexes(data, indexes) {
390
+ let i = 0;
391
+ const temp = [...data];
392
+ for (const index of indexes) {
393
+ temp.splice(index - i, 1);
394
+ i++;
284
395
  }
285
- }
396
+ return compact(temp).length ? temp : [];
397
+ }
398
+ var removeArrayAt = (data, index) => isUndefined(index)
399
+ ? []
400
+ : removeAtIndexes(data, (Array.isArray(index) ? index : [index]).sort((a, b) => a - b));
286
401
 
287
- var isErrorStateChanged = ({ errors, name, error, validFields, fieldsWithValidation, }) => {
288
- const isValid = isUndefined(error);
289
- const previousError = get(errors, name);
290
- return ((isValid && !!previousError) ||
291
- (!isValid && !deepEqual(previousError, error, true)) ||
292
- (isValid && get(fieldsWithValidation, name) && !get(validFields, name)));
402
+ var swapArrayAt = (data, indexA, indexB) => {
403
+ data[indexA] = [data[indexB], (data[indexB] = data[indexA])][0];
293
404
  };
294
405
 
295
- var isRegex = (value) => value instanceof RegExp;
296
-
297
- var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
298
- ? validationData
299
- : {
300
- value: validationData,
301
- message: '',
302
- };
303
-
304
- var isString = (value) => typeof value === 'string';
305
-
306
- var isFunction = (value) => typeof value === 'function';
307
-
308
406
  var isBoolean = (value) => typeof value === 'boolean';
309
407
 
310
- var isMessage = (value) => isString(value) || React.isValidElement(value);
311
-
312
- function getValidateError(result, ref, type = 'validate') {
313
- if (isMessage(result) || (isBoolean(result) && !result)) {
314
- return {
315
- type,
316
- message: isMessage(result) ? result : '',
317
- ref,
318
- };
408
+ function baseGet(object, updatePath) {
409
+ const length = updatePath.slice(0, -1).length;
410
+ let index = 0;
411
+ while (index < length) {
412
+ object = isUndefined(object) ? index++ : object[updatePath[index++]];
319
413
  }
320
- }
321
-
322
- var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
323
- ? Object.assign(Object.assign({}, errors[name]), { types: Object.assign(Object.assign({}, (errors[name] && errors[name].types ? errors[name].types : {})), { [type]: message || true }) }) : {};
324
-
325
- var validateField = async ({ _f: { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, value: inputValue, }, }, validateAllFieldCriteria) => {
326
- const error = {};
327
- const isRadio = isRadioInput(ref);
328
- const isCheckBox = isCheckBoxInput(ref);
329
- const isRadioOrCheckbox = isRadio || isCheckBox;
330
- const isEmpty = !inputValue || (Array.isArray(inputValue) && !inputValue.length);
331
- const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
332
- const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => {
333
- const message = exceedMax ? maxLengthMessage : minLengthMessage;
334
- error[name] = Object.assign({ type: exceedMax ? maxType : minType, message,
335
- ref }, appendErrorsCurry(exceedMax ? maxType : minType, message));
336
- };
337
- if (required &&
338
- ((!isRadio && !isCheckBox && (isEmpty || isNullOrUndefined(inputValue))) ||
339
- (isBoolean(inputValue) && !inputValue) ||
340
- (isCheckBox && !getCheckboxValue(refs).isValid) ||
341
- (isRadio && !getRadioValue(refs).isValid))) {
342
- const { value, message } = isMessage(required)
343
- ? { value: !!required, message: required }
344
- : getValueAndMessage(required);
345
- if (value) {
346
- error[name] = Object.assign({ type: INPUT_VALIDATION_RULES.required, message, ref: isRadioOrCheckbox ? (refs || [])[0] || {} : ref }, appendErrorsCurry(INPUT_VALIDATION_RULES.required, message));
347
- if (!validateAllFieldCriteria) {
348
- return error;
414
+ return object;
415
+ }
416
+ function unset(object, path) {
417
+ const updatePath = isKey(path) ? [path] : stringToPath(path);
418
+ const childObject = updatePath.length == 1 ? object : baseGet(object, updatePath);
419
+ const key = updatePath[updatePath.length - 1];
420
+ let previousObjRef;
421
+ if (childObject) {
422
+ delete childObject[key];
423
+ }
424
+ for (let k = 0; k < updatePath.slice(0, -1).length; k++) {
425
+ let index = -1;
426
+ let objectRef;
427
+ const currentPaths = updatePath.slice(0, -(k + 1));
428
+ const currentPathsLength = currentPaths.length - 1;
429
+ if (k > 0) {
430
+ previousObjRef = object;
431
+ }
432
+ while (++index < currentPaths.length) {
433
+ const item = currentPaths[index];
434
+ objectRef = objectRef ? objectRef[item] : object[item];
435
+ if (currentPathsLength === index &&
436
+ ((isObject(objectRef) && isEmptyObject(objectRef)) ||
437
+ (Array.isArray(objectRef) &&
438
+ !objectRef.filter((data) => (isObject(data) && !isEmptyObject(data)) || isBoolean(data)).length))) {
439
+ previousObjRef ? delete previousObjRef[item] : delete object[item];
349
440
  }
441
+ previousObjRef = objectRef;
350
442
  }
351
443
  }
352
- if ((!isNullOrUndefined(min) || !isNullOrUndefined(max)) &&
353
- inputValue !== '') {
354
- let exceedMax;
355
- let exceedMin;
356
- const maxOutput = getValueAndMessage(max);
357
- const minOutput = getValueAndMessage(min);
358
- if (!isNaN(inputValue)) {
359
- const valueNumber = ref.valueAsNumber || parseFloat(inputValue);
360
- if (!isNullOrUndefined(maxOutput.value)) {
361
- exceedMax = valueNumber > maxOutput.value;
362
- }
363
- if (!isNullOrUndefined(minOutput.value)) {
364
- exceedMin = valueNumber < minOutput.value;
365
- }
444
+ return object;
445
+ }
446
+
447
+ const useFieldArray = ({ control, name, keyName = 'id', }) => {
448
+ const methods = useFormContext();
449
+ const focusNameRef = React.useRef('');
450
+ const { isWatchAllRef, watchFieldsRef, getFormIsDirty, watchSubjectRef, fieldArraySubjectRef, fieldArrayNamesRef, fieldsRef, defaultValuesRef, formStateRef, formStateSubjectRef, readFormStateRef, validFieldsRef, fieldsWithValidationRef, fieldArrayDefaultValuesRef, } = control || methods.control;
451
+ const [fields, setFields] = React.useState(mapIds(get(fieldArrayDefaultValuesRef.current, getNodeParentName(name))
452
+ ? get(fieldArrayDefaultValuesRef.current, name, [])
453
+ : get(defaultValuesRef.current, name, []), keyName));
454
+ set(fieldArrayDefaultValuesRef.current, name, [...fields]);
455
+ fieldArrayNamesRef.current.add(name);
456
+ const omitKey = (fields) => fields.map((field) => omit((field || {}), keyName));
457
+ const getCurrentFieldsValues = () => {
458
+ const values = get(getFieldsValues(fieldsRef, defaultValuesRef), name, []);
459
+ return mapIds(get(fieldArrayDefaultValuesRef.current, name, []).map((item, index) => (Object.assign(Object.assign({}, item), values[index]))), keyName);
460
+ };
461
+ const getFocusDetail = (index, options) => options
462
+ ? !isUndefined(options.focusIndex)
463
+ ? `${name}.${options.focusIndex}`
464
+ : options.focusName
465
+ ? options.focusName
466
+ : !options.shouldFocus
467
+ ? ''
468
+ : `${name}.${index}`
469
+ : `${name}.${index}`;
470
+ const resetFields = (index) => (Array.isArray(index) ? index : [index]).forEach((currentIndex) => set(fieldsRef.current, `${name}${isUndefined(currentIndex) ? '' : `.${currentIndex}`}`, isUndefined(currentIndex) ? [] : undefined));
471
+ const setFieldsAndNotify = (fieldsValues = []) => setFields(mapIds(fieldsValues, keyName));
472
+ const cleanup = (ref) => !compact(get(ref, name, [])).length && unset(ref, name);
473
+ const updateDirtyFieldsWithDefaultValues = (updatedFieldArrayValues) => updatedFieldArrayValues &&
474
+ set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
475
+ const batchStateUpdate = (method, args, updatedFieldArrayValues = [], shouldSet = true) => {
476
+ if (get(fieldsRef.current, name)) {
477
+ const output = method(get(fieldsRef.current, name), args.argA, args.argB);
478
+ shouldSet && set(fieldsRef.current, name, output);
366
479
  }
367
- else {
368
- const valueDate = ref.valueAsDate || new Date(inputValue);
369
- if (isString(maxOutput.value)) {
370
- exceedMax = valueDate > new Date(maxOutput.value);
371
- }
372
- if (isString(minOutput.value)) {
373
- exceedMin = valueDate < new Date(minOutput.value);
374
- }
480
+ if (Array.isArray(get(formStateRef.current.errors, name))) {
481
+ const output = method(get(formStateRef.current.errors, name), args.argA, args.argB);
482
+ shouldSet && set(formStateRef.current.errors, name, output);
483
+ cleanup(formStateRef.current.errors);
375
484
  }
376
- if (exceedMax || exceedMin) {
377
- getMinMaxMessage(!!exceedMax, maxOutput.message, minOutput.message, INPUT_VALIDATION_RULES.max, INPUT_VALIDATION_RULES.min);
378
- if (!validateAllFieldCriteria) {
379
- return error;
380
- }
485
+ if (readFormStateRef.current.touchedFields &&
486
+ get(formStateRef.current.touchedFields, name)) {
487
+ const output = method(get(formStateRef.current.touchedFields, name), args.argA, args.argB);
488
+ shouldSet && set(formStateRef.current.touchedFields, name, output);
489
+ cleanup(formStateRef.current.touchedFields);
381
490
  }
382
- }
383
- if (isString(inputValue) && !isEmpty && (maxLength || minLength)) {
384
- const maxLengthOutput = getValueAndMessage(maxLength);
385
- const minLengthOutput = getValueAndMessage(minLength);
386
- const exceedMax = !isNullOrUndefined(maxLengthOutput.value) &&
387
- inputValue.length > maxLengthOutput.value;
388
- const exceedMin = !isNullOrUndefined(minLengthOutput.value) &&
389
- inputValue.length < minLengthOutput.value;
390
- if (exceedMax || exceedMin) {
391
- getMinMaxMessage(exceedMax, maxLengthOutput.message, minLengthOutput.message);
392
- if (!validateAllFieldCriteria) {
393
- return error;
394
- }
491
+ if (readFormStateRef.current.dirtyFields ||
492
+ readFormStateRef.current.isDirty) {
493
+ set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
494
+ updateDirtyFieldsWithDefaultValues(updatedFieldArrayValues);
495
+ cleanup(formStateRef.current.dirtyFields);
395
496
  }
396
- }
397
- if (isString(inputValue) && pattern && !isEmpty) {
398
- const { value: patternValue, message } = getValueAndMessage(pattern);
399
- if (isRegex(patternValue) && !patternValue.test(inputValue)) {
400
- error[name] = Object.assign({ type: INPUT_VALIDATION_RULES.pattern, message,
401
- ref }, appendErrorsCurry(INPUT_VALIDATION_RULES.pattern, message));
402
- if (!validateAllFieldCriteria) {
403
- return error;
404
- }
497
+ if (readFormStateRef.current.isValid) {
498
+ set(validFieldsRef.current, name, method(get(validFieldsRef.current, name, []), args.argA));
499
+ cleanup(validFieldsRef.current);
500
+ set(fieldsWithValidationRef.current, name, method(get(fieldsWithValidationRef.current, name, []), args.argA));
501
+ cleanup(fieldsWithValidationRef.current);
405
502
  }
406
- }
407
- if (validate) {
408
- const validateRef = isRadioOrCheckbox && refs ? refs[0] : ref;
409
- if (isFunction(validate)) {
410
- const result = await validate(inputValue);
411
- const validateError = getValidateError(result, validateRef);
412
- if (validateError) {
413
- error[name] = Object.assign(Object.assign({}, validateError), appendErrorsCurry(INPUT_VALIDATION_RULES.validate, validateError.message));
414
- if (!validateAllFieldCriteria) {
415
- return error;
416
- }
417
- }
503
+ formStateSubjectRef.current.next({
504
+ isDirty: getFormIsDirty(name, omitKey(updatedFieldArrayValues)),
505
+ errors: formStateRef.current.errors,
506
+ isValid: formStateRef.current.isValid,
507
+ });
508
+ };
509
+ const registerFieldArray = (values, index = 0, parentName = '') => values.forEach((appendValueItem, valueIndex) => Object.entries(appendValueItem).forEach(([key, value]) => {
510
+ const inputName = `${parentName || name}.${parentName ? valueIndex : index + valueIndex}.${key}`;
511
+ Array.isArray(value)
512
+ ? registerFieldArray(value, valueIndex, inputName)
513
+ : set(fieldsRef.current, inputName, {
514
+ _f: {
515
+ ref: {
516
+ name: inputName,
517
+ },
518
+ name: inputName,
519
+ value,
520
+ },
521
+ });
522
+ }));
523
+ const append$1 = (value, options) => {
524
+ const appendValue = Array.isArray(value) ? value : [value];
525
+ const updatedFieldArrayValues = append(getCurrentFieldsValues(), appendValue);
526
+ const currentIndex = updatedFieldArrayValues.length - appendValue.length;
527
+ setFieldsAndNotify(updatedFieldArrayValues);
528
+ batchStateUpdate(append, {
529
+ argA: fillEmptyArray(value),
530
+ }, updatedFieldArrayValues, false);
531
+ registerFieldArray(appendValue, currentIndex);
532
+ focusNameRef.current = getFocusDetail(currentIndex, options);
533
+ };
534
+ const prepend$1 = (value, options) => {
535
+ const prependValue = Array.isArray(value) ? value : [value];
536
+ const updatedFieldArrayValues = prepend(getCurrentFieldsValues(), prependValue);
537
+ setFieldsAndNotify(updatedFieldArrayValues);
538
+ batchStateUpdate(prepend, {
539
+ argA: fillEmptyArray(value),
540
+ }, updatedFieldArrayValues);
541
+ registerFieldArray(prependValue);
542
+ focusNameRef.current = getFocusDetail(0, options);
543
+ };
544
+ const remove = (index) => {
545
+ const updatedFieldArrayValues = removeArrayAt(getCurrentFieldsValues(), index);
546
+ resetFields(index);
547
+ setFieldsAndNotify(updatedFieldArrayValues);
548
+ batchStateUpdate(removeArrayAt, {
549
+ argA: index,
550
+ }, updatedFieldArrayValues);
551
+ };
552
+ const insert$1 = (index, value, options) => {
553
+ const insertValue = Array.isArray(value) ? value : [value];
554
+ const updatedFieldArrayValues = insert(getCurrentFieldsValues(), index, insertValue);
555
+ setFieldsAndNotify(updatedFieldArrayValues);
556
+ batchStateUpdate(insert, {
557
+ argA: index,
558
+ argB: fillEmptyArray(value),
559
+ }, updatedFieldArrayValues);
560
+ registerFieldArray(insertValue, index);
561
+ focusNameRef.current = getFocusDetail(index, options);
562
+ };
563
+ const swap = (indexA, indexB) => {
564
+ const fieldValues = getCurrentFieldsValues();
565
+ swapArrayAt(fieldValues, indexA, indexB);
566
+ batchStateUpdate(swapArrayAt, {
567
+ argA: indexA,
568
+ argB: indexB,
569
+ }, fieldValues, false);
570
+ setFieldsAndNotify(fieldValues);
571
+ };
572
+ const move = (from, to) => {
573
+ const fieldValues = getCurrentFieldsValues();
574
+ moveArrayAt(fieldValues, from, to);
575
+ setFieldsAndNotify(fieldValues);
576
+ batchStateUpdate(moveArrayAt, {
577
+ argA: from,
578
+ argB: to,
579
+ }, fieldValues, false);
580
+ };
581
+ React.useEffect(() => {
582
+ if (isWatchAllRef.current) {
583
+ formStateSubjectRef.current.next({});
418
584
  }
419
- else if (isObject(validate)) {
420
- let validationResult = {};
421
- for (const [key, validateFunction] of Object.entries(validate)) {
422
- if (!isEmptyObject(validationResult) && !validateAllFieldCriteria) {
585
+ else {
586
+ for (const watchField of watchFieldsRef.current) {
587
+ if (name.startsWith(watchField)) {
588
+ formStateSubjectRef.current.next({});
423
589
  break;
424
590
  }
425
- const validateResult = await validateFunction(inputValue);
426
- const validateError = getValidateError(validateResult, validateRef, key);
427
- if (validateError) {
428
- validationResult = Object.assign(Object.assign({}, validateError), appendErrorsCurry(key, validateError.message));
429
- if (validateAllFieldCriteria) {
430
- error[name] = validationResult;
431
- }
432
- }
433
- }
434
- if (!isEmptyObject(validationResult)) {
435
- error[name] = Object.assign({ ref: validateRef }, validationResult);
436
- if (!validateAllFieldCriteria) {
437
- return error;
438
- }
439
591
  }
440
592
  }
441
- }
442
- return error;
593
+ watchSubjectRef.current.next({
594
+ name,
595
+ value: get(getFieldsValues(fieldsRef, defaultValuesRef), name, []),
596
+ });
597
+ focusNameRef.current &&
598
+ focusFieldBy(fieldsRef.current, (key) => key.startsWith(focusNameRef.current));
599
+ focusNameRef.current = '';
600
+ fieldArraySubjectRef.current.next({
601
+ name,
602
+ fields: omitKey([...fields]),
603
+ });
604
+ }, [fields, name]);
605
+ React.useEffect(() => {
606
+ const fieldArraySubscription = fieldArraySubjectRef.current.subscribe({
607
+ next({ name: inputFieldArrayName, fields, isReset }) {
608
+ if (isReset) {
609
+ unset(fieldsRef.current, inputFieldArrayName || name);
610
+ inputFieldArrayName
611
+ ? set(fieldArrayDefaultValuesRef.current, inputFieldArrayName, fields)
612
+ : (fieldArrayDefaultValuesRef.current = fields);
613
+ setFieldsAndNotify(get(fieldArrayDefaultValuesRef.current, name));
614
+ }
615
+ },
616
+ });
617
+ !get(fieldsRef.current, name) && set(fieldsRef.current, name, []);
618
+ return () => {
619
+ fieldArrayDefaultValuesRef.current = getFieldsValues(fieldsRef);
620
+ fieldArraySubscription.unsubscribe();
621
+ };
622
+ }, []);
623
+ return {
624
+ swap: React.useCallback(swap, [name]),
625
+ move: React.useCallback(move, [name]),
626
+ prepend: React.useCallback(prepend$1, [name]),
627
+ append: React.useCallback(append$1, [name]),
628
+ remove: React.useCallback(remove, [name]),
629
+ insert: React.useCallback(insert$1, [name]),
630
+ fields: fields,
631
+ };
443
632
  };
444
633
 
445
- var skipValidation = ({ isOnBlur, isOnChange, isOnTouch, isTouched, isReValidateOnBlur, isReValidateOnChange, isBlurEvent, isSubmitted, isOnAll, }) => {
446
- if (isOnAll) {
447
- return false;
448
- }
449
- else if (!isSubmitted && isOnTouch) {
450
- return !(isTouched || isBlurEvent);
451
- }
452
- else if (isSubmitted ? isReValidateOnBlur : isOnBlur) {
453
- return !isBlurEvent;
634
+ function getFields(fieldsNames, fieldsRefs) {
635
+ const currentFields = {};
636
+ for (const name of fieldsNames) {
637
+ const field = get(fieldsRefs, name);
638
+ if (field) {
639
+ !isKey(name)
640
+ ? set(currentFields, name, field._f)
641
+ : (currentFields[name] = field._f);
642
+ }
454
643
  }
455
- else if (isSubmitted ? isReValidateOnChange : isOnChange) {
456
- return isBlurEvent;
644
+ return currentFields;
645
+ }
646
+
647
+ var isFileInput = (element) => element.type === 'file';
648
+
649
+ var isMultipleSelect = (element) => element.type === `${SELECT}-multiple`;
650
+
651
+ var isRadioInput = (element) => element.type === 'radio';
652
+
653
+ const defaultResult = {
654
+ value: false,
655
+ isValid: false,
656
+ };
657
+ const validResult = { value: true, isValid: true };
658
+ var getCheckboxValue = (options) => {
659
+ if (Array.isArray(options)) {
660
+ if (options.length > 1) {
661
+ const values = options
662
+ .filter((option) => option && option.checked && !option.disabled)
663
+ .map((option) => option.value);
664
+ return { value: values, isValid: !!values.length };
665
+ }
666
+ return options[0].checked && !options[0].disabled
667
+ ? // @ts-expect-error expected to work in the browser
668
+ options[0].attributes && !isUndefined(options[0].attributes.value)
669
+ ? isUndefined(options[0].value) || options[0].value === ''
670
+ ? validResult
671
+ : { value: options[0].value, isValid: true }
672
+ : validResult
673
+ : defaultResult;
457
674
  }
458
- return true;
675
+ return defaultResult;
459
676
  };
460
677
 
461
- var getNodeParentName = (name) => name.substring(0, name.search(/.\d/)) || name;
678
+ var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => valueAsNumber
679
+ ? value === ''
680
+ ? NaN
681
+ : +value
682
+ : valueAsDate
683
+ ? new Date(value)
684
+ : setValueAs
685
+ ? setValueAs(value)
686
+ : value;
462
687
 
463
- var getProxyFormState = (isProxyEnabled, formState, readFormStateRef, localReadFormStateRef, isRoot = true) => isProxyEnabled
464
- ? new Proxy(formState, {
465
- get: (obj, prop) => {
466
- if (prop in obj) {
467
- if (readFormStateRef.current[prop] !== VALIDATION_MODE.all) {
468
- readFormStateRef.current[prop] = isRoot
469
- ? VALIDATION_MODE.all
470
- : true;
471
- }
472
- localReadFormStateRef &&
473
- (localReadFormStateRef.current[prop] = true);
474
- return obj[prop];
475
- }
476
- return undefined;
477
- },
478
- })
479
- : formState;
688
+ var getMultipleSelectValue = (options) => [...options]
689
+ .filter(({ selected }) => selected)
690
+ .map(({ value }) => value);
480
691
 
481
- class Subscription {
482
- constructor() {
483
- this.tearDowns = [];
484
- }
485
- add(tearDown) {
486
- this.tearDowns.push(tearDown);
487
- }
488
- unsubscribe() {
489
- for (const teardown of this.tearDowns) {
490
- teardown();
692
+ const defaultReturn = {
693
+ isValid: false,
694
+ value: null,
695
+ };
696
+ var getRadioValue = (options) => Array.isArray(options)
697
+ ? options.reduce((previous, option) => option && option.checked && !option.disabled
698
+ ? {
699
+ isValid: true,
700
+ value: option.value,
491
701
  }
492
- this.tearDowns = [];
493
- }
494
- }
495
- class Subscriber {
496
- constructor(observer, subscription) {
497
- this.observer = observer;
498
- this.closed = false;
499
- subscription.add(() => (this.closed = true));
500
- }
501
- next(value) {
502
- if (!this.closed) {
503
- this.observer.next(value);
702
+ : previous, defaultReturn)
703
+ : defaultReturn;
704
+
705
+ function getFieldValue(field) {
706
+ if (field && field._f) {
707
+ const ref = field._f.ref;
708
+ if (ref.disabled) {
709
+ return;
504
710
  }
505
- }
506
- }
507
- class Subject {
508
- constructor() {
509
- this.observers = [];
510
- }
511
- next(value) {
512
- for (const observer of this.observers) {
513
- observer.next(value);
711
+ if (isFileInput(ref)) {
712
+ return ref.files;
514
713
  }
515
- }
516
- subscribe(observer) {
517
- const subscription = new Subscription();
518
- const subscriber = new Subscriber(observer, subscription);
519
- this.observers.push(subscriber);
520
- return subscription;
521
- }
522
- unsubscribe() {
523
- this.observers = [];
714
+ if (isRadioInput(ref)) {
715
+ return getRadioValue(field._f.refs).value;
716
+ }
717
+ if (isMultipleSelect(ref)) {
718
+ return getMultipleSelectValue(ref.options);
719
+ }
720
+ if (isCheckBoxInput(ref)) {
721
+ return getCheckboxValue(field._f.refs).value;
722
+ }
723
+ return getFieldValueAs(isUndefined(ref.value) ? field._f.ref.value : ref.value, field._f);
524
724
  }
525
725
  }
526
726
 
527
- var isWeb = typeof window !== UNDEFINED &&
528
- typeof window.HTMLElement !== UNDEFINED &&
529
- typeof document !== UNDEFINED;
530
-
531
- const isProxyEnabled = isWeb ? 'Proxy' in window : typeof Proxy !== UNDEFINED;
727
+ var isErrorStateChanged = ({ errors, name, error, validFields, fieldsWithValidation, }) => {
728
+ const isValid = isUndefined(error);
729
+ const previousError = get(errors, name);
730
+ return ((isValid && !!previousError) ||
731
+ (!isValid && !deepEqual(previousError, error, true)) ||
732
+ (isValid && get(fieldsWithValidation, name) && !get(validFields, name)));
733
+ };
532
734
 
533
- function baseGet(object, updatePath) {
534
- const length = updatePath.slice(0, -1).length;
535
- let index = 0;
536
- while (index < length) {
537
- object = isUndefined(object) ? index++ : object[updatePath[index++]];
735
+ var skipValidation = ({ isOnBlur, isOnChange, isOnTouch, isTouched, isReValidateOnBlur, isReValidateOnChange, isBlurEvent, isSubmitted, isOnAll, }) => {
736
+ if (isOnAll) {
737
+ return false;
538
738
  }
539
- return object;
540
- }
541
- function unset(object, path) {
542
- const updatePath = isKey(path) ? [path] : stringToPath(path);
543
- const childObject = updatePath.length == 1 ? object : baseGet(object, updatePath);
544
- const key = updatePath[updatePath.length - 1];
545
- let previousObjRef;
546
- if (childObject) {
547
- delete childObject[key];
739
+ else if (!isSubmitted && isOnTouch) {
740
+ return !(isTouched || isBlurEvent);
548
741
  }
549
- for (let k = 0; k < updatePath.slice(0, -1).length; k++) {
550
- let index = -1;
551
- let objectRef;
552
- const currentPaths = updatePath.slice(0, -(k + 1));
553
- const currentPathsLength = currentPaths.length - 1;
554
- if (k > 0) {
555
- previousObjRef = object;
556
- }
557
- while (++index < currentPaths.length) {
558
- const item = currentPaths[index];
559
- objectRef = objectRef ? objectRef[item] : object[item];
560
- if (currentPathsLength === index &&
561
- ((isObject(objectRef) && isEmptyObject(objectRef)) ||
562
- (Array.isArray(objectRef) &&
563
- !objectRef.filter((data) => (isObject(data) && !isEmptyObject(data)) || isBoolean(data)).length))) {
564
- previousObjRef ? delete previousObjRef[item] : delete object[item];
565
- }
566
- previousObjRef = objectRef;
567
- }
742
+ else if (isSubmitted ? isReValidateOnBlur : isOnBlur) {
743
+ return !isBlurEvent;
568
744
  }
569
- return object;
570
- }
745
+ else if (isSubmitted ? isReValidateOnChange : isOnChange) {
746
+ return isBlurEvent;
747
+ }
748
+ return true;
749
+ };
571
750
 
572
- var getValidationModes = (mode) => ({
573
- isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
574
- isOnBlur: mode === VALIDATION_MODE.onBlur,
575
- isOnChange: mode === VALIDATION_MODE.onChange,
576
- isOnAll: mode === VALIDATION_MODE.all,
577
- isOnTouch: mode === VALIDATION_MODE.onTouched,
578
- });
751
+ var isFunction = (value) => typeof value === 'function';
579
752
 
580
- var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
753
+ var isString = (value) => typeof value === 'string';
581
754
 
582
- var isHTMLElement = (value) => value instanceof HTMLElement;
755
+ var isMessage = (value) => isString(value) || React.isValidElement(value);
583
756
 
584
- function getFields(fieldsNames, fieldsRefs) {
585
- const currentFields = {};
586
- for (const name of fieldsNames) {
587
- const field = get(fieldsRefs, name);
588
- if (field) {
589
- !isKey(name)
590
- ? set(currentFields, name, field._f)
591
- : (currentFields[name] = field._f);
592
- }
757
+ var isRegex = (value) => value instanceof RegExp;
758
+
759
+ function getValidateError(result, ref, type = 'validate') {
760
+ if (isMessage(result) || (isBoolean(result) && !result)) {
761
+ return {
762
+ type,
763
+ message: isMessage(result) ? result : '',
764
+ ref,
765
+ };
593
766
  }
594
- return currentFields;
595
767
  }
596
768
 
597
- const isWindowUndefined = typeof window === UNDEFINED;
598
- function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_MODE.onChange, resolver, context, defaultValues = {}, shouldFocusError = true, criteriaMode, } = {}) {
599
- const fieldsRef = React.useRef({});
600
- const fieldsNamesRef = React.useRef(new Set());
601
- const formStateSubjectRef = React.useRef(new Subject());
602
- const watchSubjectRef = React.useRef(new Subject());
603
- const controllerSubjectRef = React.useRef(new Subject());
604
- const fieldArraySubjectRef = React.useRef(new Subject());
605
- const fieldArrayDefaultValuesRef = React.useRef({});
606
- const watchFieldsRef = React.useRef(new Set());
607
- const isMountedRef = React.useRef(false);
608
- const fieldsWithValidationRef = React.useRef({});
609
- const validFieldsRef = React.useRef({});
610
- const defaultValuesRef = React.useRef(defaultValues);
611
- const isWatchAllRef = React.useRef(false);
612
- const contextRef = React.useRef(context);
613
- const resolverRef = React.useRef(resolver);
614
- const fieldArrayNamesRef = React.useRef(new Set());
615
- const validationMode = getValidationModes(mode);
616
- const isValidateAllFieldCriteria = criteriaMode === VALIDATION_MODE.all;
617
- const [formState, setFormState] = React.useState({
618
- isDirty: false,
619
- isValidating: false,
620
- dirtyFields: {},
621
- isSubmitted: false,
769
+ var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
770
+ ? validationData
771
+ : {
772
+ value: validationData,
773
+ message: '',
774
+ };
775
+
776
+ var validateField = async ({ _f: { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, value: inputValue, }, }, validateAllFieldCriteria) => {
777
+ const error = {};
778
+ const isRadio = isRadioInput(ref);
779
+ const isCheckBox = isCheckBoxInput(ref);
780
+ const isRadioOrCheckbox = isRadio || isCheckBox;
781
+ const isEmpty = inputValue === '' || (Array.isArray(inputValue) && !inputValue.length);
782
+ const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
783
+ const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => {
784
+ const message = exceedMax ? maxLengthMessage : minLengthMessage;
785
+ error[name] = Object.assign({ type: exceedMax ? maxType : minType, message,
786
+ ref }, appendErrorsCurry(exceedMax ? maxType : minType, message));
787
+ };
788
+ if (required &&
789
+ ((!isRadio && !isCheckBox && (isEmpty || isNullOrUndefined(inputValue))) ||
790
+ (isBoolean(inputValue) && !inputValue) ||
791
+ (isCheckBox && !getCheckboxValue(refs).isValid) ||
792
+ (isRadio && !getRadioValue(refs).isValid))) {
793
+ const { value, message } = isMessage(required)
794
+ ? { value: !!required, message: required }
795
+ : getValueAndMessage(required);
796
+ if (value) {
797
+ error[name] = Object.assign({ type: INPUT_VALIDATION_RULES.required, message, ref: isRadioOrCheckbox ? (refs || [])[0] || {} : ref }, appendErrorsCurry(INPUT_VALIDATION_RULES.required, message));
798
+ if (!validateAllFieldCriteria) {
799
+ return error;
800
+ }
801
+ }
802
+ }
803
+ if ((!isNullOrUndefined(min) || !isNullOrUndefined(max)) &&
804
+ inputValue !== '') {
805
+ let exceedMax;
806
+ let exceedMin;
807
+ const maxOutput = getValueAndMessage(max);
808
+ const minOutput = getValueAndMessage(min);
809
+ if (!isNaN(inputValue)) {
810
+ const valueNumber = ref.valueAsNumber || parseFloat(inputValue);
811
+ if (!isNullOrUndefined(maxOutput.value)) {
812
+ exceedMax = valueNumber > maxOutput.value;
813
+ }
814
+ if (!isNullOrUndefined(minOutput.value)) {
815
+ exceedMin = valueNumber < minOutput.value;
816
+ }
817
+ }
818
+ else {
819
+ const valueDate = ref.valueAsDate || new Date(inputValue);
820
+ if (isString(maxOutput.value)) {
821
+ exceedMax = valueDate > new Date(maxOutput.value);
822
+ }
823
+ if (isString(minOutput.value)) {
824
+ exceedMin = valueDate < new Date(minOutput.value);
825
+ }
826
+ }
827
+ if (exceedMax || exceedMin) {
828
+ getMinMaxMessage(!!exceedMax, maxOutput.message, minOutput.message, INPUT_VALIDATION_RULES.max, INPUT_VALIDATION_RULES.min);
829
+ if (!validateAllFieldCriteria) {
830
+ return error;
831
+ }
832
+ }
833
+ }
834
+ if (isString(inputValue) && !isEmpty && (maxLength || minLength)) {
835
+ const maxLengthOutput = getValueAndMessage(maxLength);
836
+ const minLengthOutput = getValueAndMessage(minLength);
837
+ const exceedMax = !isNullOrUndefined(maxLengthOutput.value) &&
838
+ inputValue.length > maxLengthOutput.value;
839
+ const exceedMin = !isNullOrUndefined(minLengthOutput.value) &&
840
+ inputValue.length < minLengthOutput.value;
841
+ if (exceedMax || exceedMin) {
842
+ getMinMaxMessage(exceedMax, maxLengthOutput.message, minLengthOutput.message);
843
+ if (!validateAllFieldCriteria) {
844
+ return error;
845
+ }
846
+ }
847
+ }
848
+ if (isString(inputValue) && pattern && !isEmpty) {
849
+ const { value: patternValue, message } = getValueAndMessage(pattern);
850
+ if (isRegex(patternValue) && !patternValue.test(inputValue)) {
851
+ error[name] = Object.assign({ type: INPUT_VALIDATION_RULES.pattern, message,
852
+ ref }, appendErrorsCurry(INPUT_VALIDATION_RULES.pattern, message));
853
+ if (!validateAllFieldCriteria) {
854
+ return error;
855
+ }
856
+ }
857
+ }
858
+ if (validate) {
859
+ const validateRef = isRadioOrCheckbox && refs ? refs[0] : ref;
860
+ if (isFunction(validate)) {
861
+ const result = await validate(inputValue);
862
+ const validateError = getValidateError(result, validateRef);
863
+ if (validateError) {
864
+ error[name] = Object.assign(Object.assign({}, validateError), appendErrorsCurry(INPUT_VALIDATION_RULES.validate, validateError.message));
865
+ if (!validateAllFieldCriteria) {
866
+ return error;
867
+ }
868
+ }
869
+ }
870
+ else if (isObject(validate)) {
871
+ let validationResult = {};
872
+ for (const [key, validateFunction] of Object.entries(validate)) {
873
+ if (!isEmptyObject(validationResult) && !validateAllFieldCriteria) {
874
+ break;
875
+ }
876
+ const validateResult = await validateFunction(inputValue);
877
+ const validateError = getValidateError(validateResult, validateRef, key);
878
+ if (validateError) {
879
+ validationResult = Object.assign(Object.assign({}, validateError), appendErrorsCurry(key, validateError.message));
880
+ if (validateAllFieldCriteria) {
881
+ error[name] = validationResult;
882
+ }
883
+ }
884
+ }
885
+ if (!isEmptyObject(validationResult)) {
886
+ error[name] = Object.assign({ ref: validateRef }, validationResult);
887
+ if (!validateAllFieldCriteria) {
888
+ return error;
889
+ }
890
+ }
891
+ }
892
+ }
893
+ return error;
894
+ };
895
+
896
+ var getValidationModes = (mode) => ({
897
+ isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
898
+ isOnBlur: mode === VALIDATION_MODE.onBlur,
899
+ isOnChange: mode === VALIDATION_MODE.onChange,
900
+ isOnAll: mode === VALIDATION_MODE.all,
901
+ isOnTouch: mode === VALIDATION_MODE.onTouched,
902
+ });
903
+
904
+ var isHTMLElement = (value) => value instanceof HTMLElement;
905
+
906
+ var isRadioOrCheckboxFunction = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
907
+
908
+ class Subscription {
909
+ constructor() {
910
+ this.tearDowns = [];
911
+ }
912
+ add(tearDown) {
913
+ this.tearDowns.push(tearDown);
914
+ }
915
+ unsubscribe() {
916
+ for (const teardown of this.tearDowns) {
917
+ teardown();
918
+ }
919
+ this.tearDowns = [];
920
+ }
921
+ }
922
+ class Subscriber {
923
+ constructor(observer, subscription) {
924
+ this.observer = observer;
925
+ this.closed = false;
926
+ subscription.add(() => (this.closed = true));
927
+ }
928
+ next(value) {
929
+ if (!this.closed) {
930
+ this.observer.next(value);
931
+ }
932
+ }
933
+ }
934
+ class Subject {
935
+ constructor() {
936
+ this.observers = [];
937
+ }
938
+ next(value) {
939
+ for (const observer of this.observers) {
940
+ observer.next(value);
941
+ }
942
+ }
943
+ subscribe(observer) {
944
+ const subscription = new Subscription();
945
+ const subscriber = new Subscriber(observer, subscription);
946
+ this.observers.push(subscriber);
947
+ return subscription;
948
+ }
949
+ unsubscribe() {
950
+ this.observers = [];
951
+ }
952
+ }
953
+
954
+ const isWindowUndefined = typeof window === UNDEFINED;
955
+ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_MODE.onChange, resolver, context, defaultValues = {}, shouldFocusError = true, criteriaMode, } = {}) {
956
+ const fieldsRef = React.useRef({});
957
+ const fieldsNamesRef = React.useRef(new Set());
958
+ const formStateSubjectRef = React.useRef(new Subject());
959
+ const watchSubjectRef = React.useRef(new Subject());
960
+ const controllerSubjectRef = React.useRef(new Subject());
961
+ const fieldArraySubjectRef = React.useRef(new Subject());
962
+ const fieldArrayDefaultValuesRef = React.useRef({});
963
+ const watchFieldsRef = React.useRef(new Set());
964
+ const isMountedRef = React.useRef(false);
965
+ const fieldsWithValidationRef = React.useRef({});
966
+ const validFieldsRef = React.useRef({});
967
+ const defaultValuesRef = React.useRef(defaultValues);
968
+ const isWatchAllRef = React.useRef(false);
969
+ const contextRef = React.useRef(context);
970
+ const resolverRef = React.useRef(resolver);
971
+ const fieldArrayNamesRef = React.useRef(new Set());
972
+ const validationMode = getValidationModes(mode);
973
+ const isValidateAllFieldCriteria = criteriaMode === VALIDATION_MODE.all;
974
+ const [formState, setFormState] = React.useState({
975
+ isDirty: false,
976
+ isValidating: false,
977
+ dirtyFields: {},
978
+ isSubmitted: false,
622
979
  submitCount: 0,
623
980
  touchedFields: {},
624
981
  isSubmitting: false,
@@ -711,7 +1068,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
711
1068
  name,
712
1069
  });
713
1070
  }
714
- options.shouldDirty && updateAndGetDirtyState(name);
1071
+ options.shouldDirty && updateAndGetDirtyState(name, value);
715
1072
  options.shouldValidate && trigger(name);
716
1073
  }
717
1074
  }, []);
@@ -723,17 +1080,18 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
723
1080
  }
724
1081
  return false;
725
1082
  }, []);
726
- const updateAndGetDirtyState = React.useCallback((name, shouldRender = true) => {
1083
+ const updateAndGetDirtyState = React.useCallback((name, inputValue, shouldRender = true) => {
727
1084
  if (readFormStateRef.current.isDirty ||
728
1085
  readFormStateRef.current.dirtyFields) {
729
- const isFieldDirty = !deepEqual(get(defaultValuesRef.current, name), getFieldValue(get(fieldsRef.current, name)));
1086
+ const isFieldDirty = !deepEqual(get(defaultValuesRef.current, name), inputValue);
730
1087
  const isDirtyFieldExist = get(formStateRef.current.dirtyFields, name);
731
1088
  const previousIsDirty = formStateRef.current.isDirty;
732
1089
  isFieldDirty
733
1090
  ? set(formStateRef.current.dirtyFields, name, true)
734
1091
  : unset(formStateRef.current.dirtyFields, name);
1092
+ formStateRef.current.isDirty = getFormIsDirty();
735
1093
  const state = {
736
- isDirty: getFormIsDirty(),
1094
+ isDirty: formStateRef.current.isDirty,
737
1095
  dirtyFields: formStateRef.current.dirtyFields,
738
1096
  };
739
1097
  const isChanged = (readFormStateRef.current.isDirty &&
@@ -854,8 +1212,11 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
854
1212
  isDirty: getFormIsDirty(name, value),
855
1213
  });
856
1214
  }
1215
+ !value.length &&
1216
+ set(fieldsRef.current, name, []) &&
1217
+ set(fieldArrayDefaultValuesRef.current, name, []);
857
1218
  }
858
- field && !field._f
1219
+ (field && !field._f) || isFieldArray
859
1220
  ? setInternalValues(name, value, isFieldArray ? {} : options)
860
1221
  : setFieldValue(name, value, options, true, !field);
861
1222
  isFieldWatched(name) && formStateSubjectRef.current.next({});
@@ -876,7 +1237,7 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
876
1237
  if (!isUndefined(inputValue)) {
877
1238
  field._f.value = inputValue;
878
1239
  }
879
- const state = updateAndGetDirtyState(name, false);
1240
+ const state = updateAndGetDirtyState(name, field._f.value, false);
880
1241
  if (isBlurEvent && !get(formStateRef.current.touchedFields, name)) {
881
1242
  set(formStateRef.current.touchedFields, name, true);
882
1243
  state.touchedFields = formStateRef.current.touchedFields;
@@ -1033,7 +1394,8 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1033
1394
  ? Array.isArray(field._f.refs) &&
1034
1395
  compact(field._f.refs).find((option) => ref.value === option.value && option === ref)
1035
1396
  : ref === field._f.ref) ||
1036
- !field) {
1397
+ !field ||
1398
+ (isWeb && isHTMLElement(field._f.ref) && !isHTMLElement(ref))) {
1037
1399
  return;
1038
1400
  }
1039
1401
  field = {
@@ -1067,13 +1429,15 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1067
1429
  }
1068
1430
  };
1069
1431
  const register = React.useCallback((name, options) => {
1432
+ const isInitialRegister = !get(fieldsRef.current, name);
1070
1433
  set(fieldsRef.current, name, {
1071
- _f: Object.assign(Object.assign(Object.assign({}, (get(fieldsRef.current, name)
1072
- ? Object.assign({ ref: get(fieldsRef.current, name)._f.ref }, get(fieldsRef.current, name)._f) : { ref: { name } })), { name }), options),
1434
+ _f: Object.assign(Object.assign(Object.assign({}, (isInitialRegister
1435
+ ? { ref: { name } }
1436
+ : Object.assign({ ref: (get(fieldsRef.current, name)._f || {}).ref }, get(fieldsRef.current, name)._f))), { name }), options),
1073
1437
  });
1074
1438
  options && set(fieldsWithValidationRef.current, name, true);
1075
1439
  fieldsNamesRef.current.add(name);
1076
- updateValueAndGetDefault(name);
1440
+ isInitialRegister && updateValueAndGetDefault(name);
1077
1441
  return isWindowUndefined
1078
1442
  ? { name: name }
1079
1443
  : {
@@ -1113,487 +1477,135 @@ function useForm({ mode = VALIDATION_MODE.onSubmit, reValidateMode = VALIDATION_
1113
1477
  await onValid(fieldValues, e);
1114
1478
  }
1115
1479
  else {
1116
- onInvalid && (await onInvalid(formStateRef.current.errors, e));
1117
- shouldFocusError &&
1118
- focusFieldBy(fieldsRef.current, (key) => get(formStateRef.current.errors, key), fieldsNamesRef.current);
1119
- }
1120
- }
1121
- finally {
1122
- formStateRef.current.isSubmitted = true;
1123
- formStateSubjectRef.current.next({
1124
- isSubmitted: true,
1125
- isSubmitting: false,
1126
- isSubmitSuccessful: isEmptyObject(formStateRef.current.errors),
1127
- submitCount: formStateRef.current.submitCount + 1,
1128
- errors: formStateRef.current.errors,
1129
- });
1130
- }
1131
- }, [shouldFocusError, isValidateAllFieldCriteria, criteriaMode]);
1132
- const resetFromState = React.useCallback(({ keepErrors, keepDirty, keepIsSubmitted, keepTouched, keepIsValid, keepSubmitCount, }) => {
1133
- if (!keepIsValid) {
1134
- validFieldsRef.current = {};
1135
- fieldsWithValidationRef.current = {};
1136
- }
1137
- watchFieldsRef.current = new Set();
1138
- isWatchAllRef.current = false;
1139
- formStateSubjectRef.current.next({
1140
- submitCount: keepSubmitCount ? formStateRef.current.submitCount : 0,
1141
- isDirty: keepDirty ? formStateRef.current.isDirty : false,
1142
- isSubmitted: keepIsSubmitted ? formStateRef.current.isSubmitted : false,
1143
- isValid: keepIsValid
1144
- ? formStateRef.current.isValid
1145
- : !validationMode.isOnSubmit,
1146
- dirtyFields: keepDirty ? formStateRef.current.dirtyFields : {},
1147
- touchedFields: keepTouched ? formStateRef.current.touchedFields : {},
1148
- errors: keepErrors ? formStateRef.current.errors : {},
1149
- isSubmitting: false,
1150
- isSubmitSuccessful: false,
1151
- });
1152
- }, []);
1153
- const reset = (values, keepStateOptions = {}) => {
1154
- const updatedValues = values || defaultValuesRef.current;
1155
- if (isWeb && !keepStateOptions.keepValues) {
1156
- for (const field of Object.values(fieldsRef.current)) {
1157
- if (field && field._f) {
1158
- const inputRef = Array.isArray(field._f.refs)
1159
- ? field._f.refs[0]
1160
- : field._f.ref;
1161
- if (isHTMLElement(inputRef)) {
1162
- try {
1163
- inputRef.closest('form').reset();
1164
- break;
1165
- }
1166
- catch (_a) { }
1167
- }
1168
- }
1169
- }
1170
- }
1171
- !keepStateOptions.keepDefaultValues &&
1172
- (defaultValuesRef.current = Object.assign({}, updatedValues));
1173
- if (!keepStateOptions.keepValues) {
1174
- fieldsRef.current = {};
1175
- controllerSubjectRef.current.next({
1176
- values: Object.assign({}, updatedValues),
1177
- });
1178
- watchSubjectRef.current.next({
1179
- value: Object.assign({}, updatedValues),
1180
- });
1181
- fieldArraySubjectRef.current.next({
1182
- fields: Object.assign({}, updatedValues),
1183
- isReset: true,
1184
- });
1185
- }
1186
- resetFromState(keepStateOptions);
1187
- };
1188
- React.useEffect(() => {
1189
- isMountedRef.current = true;
1190
- const formStateSubscription = formStateSubjectRef.current.subscribe({
1191
- next(formState = {}) {
1192
- if (shouldRenderFormState(formState, readFormStateRef.current, true)) {
1193
- formStateRef.current = Object.assign(Object.assign({}, formStateRef.current), formState);
1194
- setFormState(formStateRef.current);
1195
- }
1196
- },
1197
- });
1198
- const useFieldArraySubscription = fieldArraySubjectRef.current.subscribe({
1199
- next(state) {
1200
- if (state.fields && state.name && readFormStateRef.current.isValid) {
1201
- const values = getFieldsValues(fieldsRef);
1202
- set(values, state.name, state.fields);
1203
- updateIsValid(values);
1204
- }
1205
- },
1206
- });
1207
- resolverRef.current && readFormStateRef.current.isValid && updateIsValid();
1208
- return () => {
1209
- watchSubjectRef.current.unsubscribe();
1210
- formStateSubscription.unsubscribe();
1211
- useFieldArraySubscription.unsubscribe();
1212
- };
1213
- }, []);
1214
- return {
1215
- control: React.useMemo(() => ({
1216
- register,
1217
- isWatchAllRef,
1218
- watchFieldsRef,
1219
- getFormIsDirty,
1220
- formStateSubjectRef,
1221
- fieldArraySubjectRef,
1222
- controllerSubjectRef,
1223
- watchSubjectRef,
1224
- watchInternal,
1225
- fieldsRef,
1226
- validFieldsRef,
1227
- fieldsWithValidationRef,
1228
- fieldArrayNamesRef,
1229
- readFormStateRef,
1230
- formStateRef,
1231
- defaultValuesRef,
1232
- fieldArrayDefaultValuesRef,
1233
- }), []),
1234
- formState: getProxyFormState(isProxyEnabled, formState, readFormStateRef),
1235
- trigger,
1236
- register,
1237
- handleSubmit,
1238
- watch: React.useCallback(watch, []),
1239
- setValue: React.useCallback(setValue, [setInternalValues]),
1240
- getValues: React.useCallback(getValues, []),
1241
- reset: React.useCallback(reset, []),
1242
- clearErrors: React.useCallback(clearErrors, []),
1243
- unregister: React.useCallback(unregister, []),
1244
- setError: React.useCallback(setError, []),
1245
- };
1246
- }
1247
-
1248
- const FormContext = React.createContext(null);
1249
- FormContext.displayName = 'RHFContext';
1250
- const useFormContext = () => React.useContext(FormContext);
1251
- const FormProvider = (props) => (React.createElement(FormContext.Provider, { value: omit(props, 'children') }, props.children));
1252
-
1253
- var generateId = () => {
1254
- const d = typeof performance === UNDEFINED ? Date.now() : performance.now() * 1000;
1255
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
1256
- const r = (Math.random() * 16 + d) % 16 | 0;
1257
- return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
1258
- });
1259
- };
1260
-
1261
- var mapIds = (values = [], keyName) => values.map((value) => (Object.assign({ [keyName]: (value && value[keyName]) || generateId() }, value)));
1262
-
1263
- function removeAtIndexes(data, indexes) {
1264
- let i = 0;
1265
- const temp = [...data];
1266
- for (const index of indexes) {
1267
- temp.splice(index - i, 1);
1268
- i++;
1269
- }
1270
- return compact(temp).length ? temp : [];
1271
- }
1272
- var removeArrayAt = (data, index) => isUndefined(index)
1273
- ? []
1274
- : removeAtIndexes(data, (Array.isArray(index) ? index : [index]).sort((a, b) => a - b));
1275
-
1276
- var moveArrayAt = (data, from, to) => {
1277
- if (Array.isArray(data)) {
1278
- if (isUndefined(data[to])) {
1279
- data[to] = undefined;
1280
- }
1281
- data.splice(to, 0, data.splice(from, 1)[0]);
1282
- return data;
1283
- }
1284
- return [];
1285
- };
1286
-
1287
- var swapArrayAt = (data, indexA, indexB) => {
1288
- data[indexA] = [data[indexB], (data[indexB] = data[indexA])][0];
1289
- };
1290
-
1291
- function prepend(data, value) {
1292
- return [...(Array.isArray(value) ? value : [value]), ...data];
1293
- }
1294
-
1295
- function append(data, value) {
1296
- return [...data, ...(Array.isArray(value) ? value : [value])];
1297
- }
1298
-
1299
- function insert(data, index, value) {
1300
- return [
1301
- ...data.slice(0, index),
1302
- ...(Array.isArray(value) ? value : [value]),
1303
- ...data.slice(index),
1304
- ];
1305
- }
1306
-
1307
- var fillEmptyArray = (value) => Array.isArray(value) ? Array(value.length).fill(undefined) : undefined;
1308
-
1309
- const useFieldArray = ({ control, name, keyName = 'id', }) => {
1310
- const methods = useFormContext();
1311
- const focusNameRef = React.useRef('');
1312
- const { isWatchAllRef, watchFieldsRef, getFormIsDirty, watchSubjectRef, fieldArraySubjectRef, fieldArrayNamesRef, fieldsRef, defaultValuesRef, formStateRef, formStateSubjectRef, readFormStateRef, validFieldsRef, fieldsWithValidationRef, fieldArrayDefaultValuesRef, } = control || methods.control;
1313
- const [fields, setFields] = React.useState(mapIds(get(fieldArrayDefaultValuesRef.current, getNodeParentName(name))
1314
- ? get(fieldArrayDefaultValuesRef.current, name, [])
1315
- : get(defaultValuesRef.current, name, []), keyName));
1316
- set(fieldArrayDefaultValuesRef.current, name, [...fields]);
1317
- fieldArrayNamesRef.current.add(name);
1318
- const omitKey = (fields) => fields.map((field) => omit((field || {}), keyName));
1319
- const getCurrentFieldsValues = () => {
1320
- const values = get(getFieldsValues(fieldsRef, defaultValuesRef), name, []);
1321
- return mapIds(get(fieldArrayDefaultValuesRef.current, name, []).map((item, index) => (Object.assign(Object.assign({}, item), values[index]))), keyName);
1322
- };
1323
- const getFocusDetail = (index, options) => options
1324
- ? !isUndefined(options.focusIndex)
1325
- ? `${name}.${options.focusIndex}`
1326
- : options.focusName
1327
- ? options.focusName
1328
- : !options.shouldFocus
1329
- ? ''
1330
- : `${name}.${index}`
1331
- : `${name}.${index}`;
1332
- const resetFields = (index) => (Array.isArray(index) ? index : [index]).forEach((currentIndex) => set(fieldsRef.current, `${name}${isUndefined(currentIndex) ? '' : `.${currentIndex}`}`, isUndefined(currentIndex) ? [] : undefined));
1333
- const setFieldsAndNotify = (fieldsValues = []) => setFields(mapIds(fieldsValues, keyName));
1334
- const cleanup = (ref) => !compact(get(ref, name, [])).length && unset(ref, name);
1335
- const updateDirtyFieldsWithDefaultValues = (updatedFieldArrayValues) => updatedFieldArrayValues &&
1336
- set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
1337
- const batchStateUpdate = (method, args, updatedFieldArrayValues = [], shouldSet = true) => {
1338
- if (get(fieldsRef.current, name)) {
1339
- const output = method(get(fieldsRef.current, name), args.argA, args.argB);
1340
- shouldSet && set(fieldsRef.current, name, output);
1341
- }
1342
- if (Array.isArray(get(formStateRef.current.errors, name))) {
1343
- const output = method(get(formStateRef.current.errors, name), args.argA, args.argB);
1344
- shouldSet && set(formStateRef.current.errors, name, output);
1345
- cleanup(formStateRef.current.errors);
1346
- }
1347
- if (readFormStateRef.current.touchedFields &&
1348
- get(formStateRef.current.touchedFields, name)) {
1349
- const output = method(get(formStateRef.current.touchedFields, name), args.argA, args.argB);
1350
- shouldSet && set(formStateRef.current.touchedFields, name, output);
1351
- cleanup(formStateRef.current.touchedFields);
1352
- }
1353
- if (readFormStateRef.current.dirtyFields ||
1354
- readFormStateRef.current.isDirty) {
1355
- set(formStateRef.current.dirtyFields, name, setFieldArrayDirtyFields(omitKey(updatedFieldArrayValues), get(defaultValuesRef.current, name, []), get(formStateRef.current.dirtyFields, name, [])));
1356
- updateDirtyFieldsWithDefaultValues(updatedFieldArrayValues);
1357
- cleanup(formStateRef.current.dirtyFields);
1358
- }
1359
- if (readFormStateRef.current.isValid) {
1360
- set(validFieldsRef.current, name, method(get(validFieldsRef.current, name, []), args.argA));
1361
- cleanup(validFieldsRef.current);
1362
- set(fieldsWithValidationRef.current, name, method(get(fieldsWithValidationRef.current, name, []), args.argA));
1363
- cleanup(fieldsWithValidationRef.current);
1364
- }
1365
- formStateSubjectRef.current.next({
1366
- isDirty: getFormIsDirty(name, omitKey(updatedFieldArrayValues)),
1367
- errors: formStateRef.current.errors,
1368
- isValid: formStateRef.current.isValid,
1369
- });
1370
- };
1371
- const registerFieldArray = (values, index = 0, parentName = '') => values.forEach((appendValueItem, valueIndex) => Object.entries(appendValueItem).forEach(([key, value]) => {
1372
- const inputName = `${parentName || name}.${parentName ? valueIndex : index + valueIndex}.${key}`;
1373
- Array.isArray(value)
1374
- ? registerFieldArray(value, valueIndex, inputName)
1375
- : set(fieldsRef.current, inputName, {
1376
- _f: {
1377
- ref: {
1378
- name: inputName,
1379
- },
1380
- name: inputName,
1381
- value,
1382
- },
1383
- });
1384
- }));
1385
- const append$1 = (value, options) => {
1386
- const appendValue = Array.isArray(value) ? value : [value];
1387
- const updatedFieldArrayValues = append(getCurrentFieldsValues(), appendValue);
1388
- const currentIndex = updatedFieldArrayValues.length - appendValue.length;
1389
- setFieldsAndNotify(updatedFieldArrayValues);
1390
- batchStateUpdate(append, {
1391
- argA: fillEmptyArray(value),
1392
- }, updatedFieldArrayValues, false);
1393
- registerFieldArray(appendValue, currentIndex);
1394
- focusNameRef.current = getFocusDetail(currentIndex, options);
1395
- };
1396
- const prepend$1 = (value, options) => {
1397
- const prependValue = Array.isArray(value) ? value : [value];
1398
- const updatedFieldArrayValues = prepend(getCurrentFieldsValues(), prependValue);
1399
- setFieldsAndNotify(updatedFieldArrayValues);
1400
- batchStateUpdate(prepend, {
1401
- argA: fillEmptyArray(value),
1402
- }, updatedFieldArrayValues);
1403
- registerFieldArray(prependValue);
1404
- focusNameRef.current = getFocusDetail(0, options);
1405
- };
1406
- const remove = (index) => {
1407
- const updatedFieldArrayValues = removeArrayAt(getCurrentFieldsValues(), index);
1408
- resetFields(index);
1409
- setFieldsAndNotify(updatedFieldArrayValues);
1410
- batchStateUpdate(removeArrayAt, {
1411
- argA: index,
1412
- }, updatedFieldArrayValues);
1413
- };
1414
- const insert$1 = (index, value, options) => {
1415
- const insertValue = Array.isArray(value) ? value : [value];
1416
- const updatedFieldArrayValues = insert(getCurrentFieldsValues(), index, insertValue);
1417
- setFieldsAndNotify(updatedFieldArrayValues);
1418
- batchStateUpdate(insert, {
1419
- argA: index,
1420
- argB: fillEmptyArray(value),
1421
- }, updatedFieldArrayValues);
1422
- registerFieldArray(insertValue, index);
1423
- focusNameRef.current = getFocusDetail(index, options);
1424
- };
1425
- const swap = (indexA, indexB) => {
1426
- const fieldValues = getCurrentFieldsValues();
1427
- swapArrayAt(fieldValues, indexA, indexB);
1428
- batchStateUpdate(swapArrayAt, {
1429
- argA: indexA,
1430
- argB: indexB,
1431
- }, fieldValues, false);
1432
- setFieldsAndNotify(fieldValues);
1433
- };
1434
- const move = (from, to) => {
1435
- const fieldValues = getCurrentFieldsValues();
1436
- moveArrayAt(fieldValues, from, to);
1437
- setFieldsAndNotify(fieldValues);
1438
- batchStateUpdate(moveArrayAt, {
1439
- argA: from,
1440
- argB: to,
1441
- }, fieldValues, false);
1442
- };
1443
- React.useEffect(() => {
1444
- if (isWatchAllRef.current) {
1445
- formStateSubjectRef.current.next({});
1480
+ onInvalid && (await onInvalid(formStateRef.current.errors, e));
1481
+ shouldFocusError &&
1482
+ focusFieldBy(fieldsRef.current, (key) => get(formStateRef.current.errors, key), fieldsNamesRef.current);
1483
+ }
1446
1484
  }
1447
- else {
1448
- for (const watchField of watchFieldsRef.current) {
1449
- if (name.startsWith(watchField)) {
1450
- formStateSubjectRef.current.next({});
1451
- break;
1485
+ finally {
1486
+ formStateRef.current.isSubmitted = true;
1487
+ formStateSubjectRef.current.next({
1488
+ isSubmitted: true,
1489
+ isSubmitting: false,
1490
+ isSubmitSuccessful: isEmptyObject(formStateRef.current.errors),
1491
+ submitCount: formStateRef.current.submitCount + 1,
1492
+ errors: formStateRef.current.errors,
1493
+ });
1494
+ }
1495
+ }, [shouldFocusError, isValidateAllFieldCriteria, criteriaMode]);
1496
+ const resetFromState = React.useCallback(({ keepErrors, keepDirty, keepIsSubmitted, keepTouched, keepIsValid, keepSubmitCount, }) => {
1497
+ if (!keepIsValid) {
1498
+ validFieldsRef.current = {};
1499
+ fieldsWithValidationRef.current = {};
1500
+ }
1501
+ watchFieldsRef.current = new Set();
1502
+ isWatchAllRef.current = false;
1503
+ formStateSubjectRef.current.next({
1504
+ submitCount: keepSubmitCount ? formStateRef.current.submitCount : 0,
1505
+ isDirty: keepDirty ? formStateRef.current.isDirty : false,
1506
+ isSubmitted: keepIsSubmitted ? formStateRef.current.isSubmitted : false,
1507
+ isValid: keepIsValid
1508
+ ? formStateRef.current.isValid
1509
+ : !validationMode.isOnSubmit,
1510
+ dirtyFields: keepDirty ? formStateRef.current.dirtyFields : {},
1511
+ touchedFields: keepTouched ? formStateRef.current.touchedFields : {},
1512
+ errors: keepErrors ? formStateRef.current.errors : {},
1513
+ isSubmitting: false,
1514
+ isSubmitSuccessful: false,
1515
+ });
1516
+ }, []);
1517
+ const reset = (values, keepStateOptions = {}) => {
1518
+ const updatedValues = values || defaultValuesRef.current;
1519
+ if (isWeb && !keepStateOptions.keepValues) {
1520
+ for (const field of Object.values(fieldsRef.current)) {
1521
+ if (field && field._f) {
1522
+ const inputRef = Array.isArray(field._f.refs)
1523
+ ? field._f.refs[0]
1524
+ : field._f.ref;
1525
+ if (isHTMLElement(inputRef)) {
1526
+ try {
1527
+ inputRef.closest('form').reset();
1528
+ break;
1529
+ }
1530
+ catch (_a) { }
1531
+ }
1452
1532
  }
1453
1533
  }
1454
1534
  }
1455
- watchSubjectRef.current.next({
1456
- name,
1457
- value: get(getFieldsValues(fieldsRef, defaultValuesRef), name, []),
1458
- });
1459
- focusNameRef.current &&
1460
- focusFieldBy(fieldsRef.current, (key) => key.startsWith(focusNameRef.current));
1461
- focusNameRef.current = '';
1462
- fieldArraySubjectRef.current.next({
1463
- name,
1464
- fields: omitKey([...fields]),
1465
- });
1466
- }, [fields, name]);
1535
+ !keepStateOptions.keepDefaultValues &&
1536
+ (defaultValuesRef.current = Object.assign({}, updatedValues));
1537
+ if (!keepStateOptions.keepValues) {
1538
+ fieldsRef.current = {};
1539
+ controllerSubjectRef.current.next({
1540
+ values: Object.assign({}, updatedValues),
1541
+ });
1542
+ watchSubjectRef.current.next({
1543
+ value: Object.assign({}, updatedValues),
1544
+ });
1545
+ fieldArraySubjectRef.current.next({
1546
+ fields: Object.assign({}, updatedValues),
1547
+ isReset: true,
1548
+ });
1549
+ }
1550
+ resetFromState(keepStateOptions);
1551
+ };
1467
1552
  React.useEffect(() => {
1468
- const fieldArraySubscription = fieldArraySubjectRef.current.subscribe({
1469
- next({ name: inputFieldArrayName, fields, isReset }) {
1470
- if (isReset) {
1471
- unset(fieldsRef.current, inputFieldArrayName || name);
1472
- inputFieldArrayName
1473
- ? set(fieldArrayDefaultValuesRef.current, inputFieldArrayName, fields)
1474
- : (fieldArrayDefaultValuesRef.current = fields);
1475
- setFieldsAndNotify(get(fieldArrayDefaultValuesRef.current, name));
1553
+ isMountedRef.current = true;
1554
+ const formStateSubscription = formStateSubjectRef.current.subscribe({
1555
+ next(formState = {}) {
1556
+ if (shouldRenderFormState(formState, readFormStateRef.current, true)) {
1557
+ formStateRef.current = Object.assign(Object.assign({}, formStateRef.current), formState);
1558
+ setFormState(formStateRef.current);
1476
1559
  }
1477
1560
  },
1478
1561
  });
1479
- !get(fieldsRef.current, name) && set(fieldsRef.current, name, []);
1480
- return () => {
1481
- fieldArrayDefaultValuesRef.current = getFieldsValues(fieldsRef);
1482
- fieldArraySubscription.unsubscribe();
1483
- };
1484
- }, []);
1485
- return {
1486
- swap: React.useCallback(swap, [name]),
1487
- move: React.useCallback(move, [name]),
1488
- prepend: React.useCallback(prepend$1, [name]),
1489
- append: React.useCallback(append$1, [name]),
1490
- remove: React.useCallback(remove, [name]),
1491
- insert: React.useCallback(insert$1, [name]),
1492
- fields: fields,
1493
- };
1494
- };
1495
-
1496
- function useFormState({ control, } = {}) {
1497
- const methods = useFormContext();
1498
- const { formStateRef, formStateSubjectRef, readFormStateRef } = control || methods.control;
1499
- const [formState, updateFormState] = React.useState(formStateRef.current);
1500
- const readFormState = React.useRef({
1501
- isDirty: false,
1502
- dirtyFields: false,
1503
- touchedFields: false,
1504
- isValidating: false,
1505
- isValid: false,
1506
- errors: false,
1507
- });
1508
- React.useEffect(() => {
1509
- const formStateSubscription = formStateSubjectRef.current.subscribe({
1510
- next: (formState) => {
1511
- shouldRenderFormState(formState, readFormState.current) &&
1512
- updateFormState(Object.assign(Object.assign({}, formStateRef.current), formState));
1562
+ const useFieldArraySubscription = fieldArraySubjectRef.current.subscribe({
1563
+ next(state) {
1564
+ if (state.fields && state.name && readFormStateRef.current.isValid) {
1565
+ const values = getFieldsValues(fieldsRef);
1566
+ set(values, state.name, state.fields);
1567
+ updateIsValid(values);
1568
+ }
1513
1569
  },
1514
1570
  });
1515
- return () => formStateSubscription.unsubscribe();
1571
+ resolverRef.current && readFormStateRef.current.isValid && updateIsValid();
1572
+ return () => {
1573
+ watchSubjectRef.current.unsubscribe();
1574
+ formStateSubscription.unsubscribe();
1575
+ useFieldArraySubscription.unsubscribe();
1576
+ };
1516
1577
  }, []);
1517
- return getProxyFormState(isProxyEnabled, formState, readFormStateRef, readFormState, false);
1518
- }
1519
-
1520
- var getControllerValue = (event) => isObject(event) && event.target
1521
- ? isCheckBoxInput(event.target)
1522
- ? event.target.checked
1523
- : event.target.value
1524
- : event;
1525
-
1526
- var isNameInFieldArray = (names, name) => [...names].some((current) => getNodeParentName(name) === current);
1527
-
1528
- function useController({ name, rules, defaultValue, control, }) {
1529
- const methods = useFormContext();
1530
- const { defaultValuesRef, register, fieldsRef, fieldArrayNamesRef, controllerSubjectRef, } = control || methods.control;
1531
- const { onChange, onBlur, ref } = register(name, rules);
1532
- const [value, setInputStateValue] = React.useState(isUndefined(get(fieldsRef.current, name)._f.value) ||
1533
- isNameInFieldArray(fieldArrayNamesRef.current, name)
1534
- ? isUndefined(defaultValue)
1535
- ? get(defaultValuesRef.current, name)
1536
- : defaultValue
1537
- : get(fieldsRef.current, name)._f.value);
1538
- const formState = useFormState({
1539
- control: control || methods.control,
1540
- });
1541
- get(fieldsRef.current, name)._f.value = value;
1542
- React.useEffect(() => {
1543
- const controllerSubscription = controllerSubjectRef.current.subscribe({
1544
- next: (data) => (!data.name || name === data.name) &&
1545
- setInputStateValue(get(data.values, name)),
1546
- });
1547
- return () => controllerSubscription.unsubscribe();
1548
- }, [name]);
1549
1578
  return {
1550
- field: {
1551
- onChange: (event) => {
1552
- const value = getControllerValue(event);
1553
- setInputStateValue(value);
1554
- onChange({
1555
- target: {
1556
- value,
1557
- name: name,
1558
- },
1559
- type: EVENTS.CHANGE,
1560
- });
1561
- },
1562
- onBlur: () => {
1563
- onBlur({
1564
- target: {
1565
- name: name,
1566
- },
1567
- type: EVENTS.BLUR,
1568
- });
1569
- },
1570
- name,
1571
- value,
1572
- ref,
1573
- },
1574
- formState,
1575
- fieldState: Object.defineProperties({}, {
1576
- invalid: {
1577
- get() {
1578
- return !!get(formState.errors, name);
1579
- },
1580
- },
1581
- isDirty: {
1582
- get() {
1583
- return !!get(formState.dirtyFields, name);
1584
- },
1585
- },
1586
- isTouched: {
1587
- get() {
1588
- return !!get(formState.touchedFields, name);
1589
- },
1590
- },
1591
- error: {
1592
- get() {
1593
- return get(formState.errors, name);
1594
- },
1595
- },
1596
- }),
1579
+ control: React.useMemo(() => ({
1580
+ register,
1581
+ isWatchAllRef,
1582
+ watchFieldsRef,
1583
+ getFormIsDirty,
1584
+ formStateSubjectRef,
1585
+ fieldArraySubjectRef,
1586
+ controllerSubjectRef,
1587
+ watchSubjectRef,
1588
+ watchInternal,
1589
+ fieldsRef,
1590
+ validFieldsRef,
1591
+ fieldsWithValidationRef,
1592
+ fieldArrayNamesRef,
1593
+ readFormStateRef,
1594
+ formStateRef,
1595
+ defaultValuesRef,
1596
+ fieldArrayDefaultValuesRef,
1597
+ }), []),
1598
+ formState: getProxyFormState(isProxyEnabled, formState, readFormStateRef),
1599
+ trigger,
1600
+ register,
1601
+ handleSubmit,
1602
+ watch: React.useCallback(watch, []),
1603
+ setValue: React.useCallback(setValue, [setInternalValues]),
1604
+ getValues: React.useCallback(getValues, []),
1605
+ reset: React.useCallback(reset, []),
1606
+ clearErrors: React.useCallback(clearErrors, []),
1607
+ unregister: React.useCallback(unregister, []),
1608
+ setError: React.useCallback(setError, []),
1597
1609
  };
1598
1610
  }
1599
1611
 
@@ -1623,7 +1635,5 @@ function useWatch(props) {
1623
1635
  return value;
1624
1636
  }
1625
1637
 
1626
- const Controller = (props) => props.render(useController(props));
1627
-
1628
1638
  export { Controller, FormProvider, appendErrors, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
1629
1639
  //# sourceMappingURL=index.esm.js.map