UEA-PRODEM

This commit is contained in:
2026-06-10 12:14:46 -03:00
parent f54126b9d8
commit 9947565694
5319 changed files with 148520 additions and 129332 deletions
+371 -98
View File
@@ -10,7 +10,11 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
const EVENTS = {
BLUR: 'blur',
FOCUS_OUT: 'focusout'};
FOCUS_OUT: 'focusout',
SUBMIT: 'submit',
TRIGGER: 'trigger',
VALID: 'valid',
};
const VALIDATION_MODE = {
onBlur: 'onBlur',
onChange: 'onChange',
@@ -27,6 +31,9 @@ const INPUT_VALIDATION_RULES = {
required: 'required',
validate: 'validate',
};
const FORM_ERROR_TYPE = 'form';
const ROOT_ERROR_TYPE = 'root';
const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
var isDateObject = (value) => value instanceof Date;
@@ -102,7 +109,11 @@ var createSubject = () => {
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
function deepEqual(object1, object2, visited = new WeakSet()) {
if (object1 === object2) {
return true;
}
if (isPrimitive(object1) || isPrimitive(object2)) {
return Object.is(object1, object2);
}
@@ -114,22 +125,26 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
if (keys1.length !== keys2.length) {
return false;
}
if (_internal_visited.has(object1) || _internal_visited.has(object2)) {
if (isEmptyObjectWithCustomPrototype(object1, keys1) ||
isEmptyObjectWithCustomPrototype(object2, keys2)) {
return Object.is(object1, object2);
}
if (visited.has(object1) || visited.has(object2)) {
return true;
}
_internal_visited.add(object1);
_internal_visited.add(object2);
visited.add(object1);
visited.add(object2);
for (const key of keys1) {
const val1 = object1[key];
if (!keys2.includes(key)) {
if (!(key in object2)) {
return false;
}
if (key !== 'ref') {
const val2 = object2[key];
if ((isDateObject(val1) && isDateObject(val2)) ||
(isObject(val1) && isObject(val2)) ||
(Array.isArray(val1) && Array.isArray(val2))
? !deepEqual(val1, val2, _internal_visited)
((isObject(val1) || Array.isArray(val1)) &&
(isObject(val2) || Array.isArray(val2)))
? !deepEqual(val1, val2, visited)
: !Object.is(val1, val2)) {
return false;
}
@@ -162,13 +177,19 @@ var isKey = (value) => /^\w*$/.test(value);
var isUndefined = (val) => val === undefined;
var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
var stringToPath = (input) => input.split(/[.[\]'"]/g).filter(Boolean);
var get = (object, path, defaultValue) => {
if (!path || !isObject(object)) {
return defaultValue;
}
const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object);
const paths = isKey(path) ? [path] : stringToPath(path);
if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
return defaultValue;
}
const result = paths.reduce((result, key) => {
return isNullOrUndefined(result) ? undefined : result[key];
}, object);
return isUndefined(result) || result === object
? isUndefined(object[path])
? defaultValue
@@ -222,7 +243,7 @@ var set = (object, path, value) => {
? []
: {};
}
if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
if (PROTOTYPE_KEYWORDS.includes(key)) {
return;
}
object[key] = newValue;
@@ -234,7 +255,12 @@ function baseGet(object, updatePath) {
const length = updatePath.slice(0, -1).length;
let index = 0;
while (index < length) {
object = isUndefined(object) ? index++ : object[updatePath[index++]];
if (isNullOrUndefined(object)) {
object = undefined;
break;
}
object = object[updatePath[index]];
index++;
}
return object;
}
@@ -247,6 +273,10 @@ function isEmptyArray(obj) {
return true;
}
function unset(object, path) {
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
delete object[path];
return object;
}
const paths = Array.isArray(path)
? path
: isKey(path)
@@ -304,6 +334,29 @@ function markFieldsDirty(data, fields = {}) {
}
return fields;
}
function pruneDirtyFields(value) {
if (value === false) {
return undefined;
}
if (value === true) {
return true;
}
if (Array.isArray(value)) {
const result = value.map((value) => pruneDirtyFields(value));
return (result.some((value) => value !== undefined) ? result : undefined);
}
if (isObject(value)) {
const result = {};
for (const key in value) {
const pruned = pruneDirtyFields(value[key]);
if (!isUndefined(pruned)) {
result[key] = pruned;
}
}
return (Object.keys(result).length ? result : undefined);
}
return undefined;
}
function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
if (!dirtyFieldsFromValues) {
dirtyFieldsFromValues = markFieldsDirty(formValues);
@@ -323,7 +376,7 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
}
}
return dirtyFieldsFromValues;
return pruneDirtyFields(dirtyFieldsFromValues) || {};
}
var getEventValue = (event) => isObject(event) && event.target
@@ -452,15 +505,14 @@ var hasValidation = (options) => options.mount &&
options.pattern ||
options.validate);
var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
var isNameInFieldArray = (names, name) => name
.split('.')
.some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
(_names.watchAll ||
_names.watch.has(name) ||
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
/^\.\w+/.test(name.slice(watchName.length))));
[..._names.watch].some((watchName) => name.startsWith(`${watchName}.`)));
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
for (const key of fieldsNames || Object.keys(fields)) {
@@ -529,7 +581,8 @@ var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, is
updateFormState(formStateData);
const { name, ...formState } = formStateData;
return (isEmptyObject(formState) ||
Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
(isRoot &&
Object.keys(formState).length >= Object.keys(_proxyFormState).length) ||
Object.keys(formState).find((key) => _proxyFormState[key] ===
(!isRoot || VALIDATION_MODE.all)));
};
@@ -562,8 +615,9 @@ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode)
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
var updateFieldArrayRootError = (errors, error, name) => {
const fieldArrayErrors = convertToArrayPayload(get(errors, name));
set(fieldArrayErrors, 'root', error[name]);
const existingErrors = get(errors, name);
const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
set(errors, name, fieldArrayErrors);
return errors;
};
@@ -771,24 +825,27 @@ const defaultOptions = {
reValidateMode: VALIDATION_MODE.onChange,
shouldFocusError: true,
};
const DEFAULT_FORM_STATE = {
submitCount: 0,
isDirty: false,
isReady: false,
isValidating: false,
isSubmitted: false,
isSubmitting: false,
isSubmitSuccessful: false,
isValid: false,
touchedFields: {},
dirtyFields: {},
validatingFields: {},
};
function createFormControl(props = {}) {
let _options = {
...defaultOptions,
...props,
};
let _formState = {
submitCount: 0,
isDirty: false,
isReady: false,
...cloneObject(DEFAULT_FORM_STATE),
isLoading: isFunction(_options.defaultValues),
isValidating: false,
isSubmitted: false,
isSubmitting: false,
isSubmitSuccessful: false,
isValid: false,
touchedFields: {},
dirtyFields: {},
validatingFields: {},
errors: _options.errors || {},
disabled: _options.disabled || false,
};
@@ -811,6 +868,7 @@ function createFormControl(props = {}) {
unMount: new Set(),
array: new Set(),
watch: new Set(),
registerName: new Set(),
};
let delayErrorCallback;
let timer = 0;
@@ -852,7 +910,11 @@ function createFormControl(props = {}) {
_updateIsValidating();
}
else {
isValid = await executeBuiltInValidation(_fields, true);
isValid = await executeBuiltInValidation({
fields: _fields,
onlyCheckValid: true,
eventType: EVENTS.VALID,
});
}
if (isValid !== _formState.isValid) {
_subjects.state.next({
@@ -880,6 +942,9 @@ function createFormControl(props = {}) {
});
}
};
const _updateDirtyFields = () => {
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
};
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
if (args && method && !_options.disabled) {
_state.action = true;
@@ -901,7 +966,7 @@ function createFormControl(props = {}) {
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
}
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
_updateDirtyFields();
}
_subjects.state.next({
name,
@@ -928,16 +993,53 @@ function createFormControl(props = {}) {
isValid: false,
});
};
const hasExplicitNullIntermediate = (name) => {
const segments = isKey(name) ? [name] : stringToPath(name);
let formValues = _formValues;
let defaultValues = _defaultValues;
for (let i = 0; i < segments.length - 1; i++) {
const key = segments[i];
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
defaultValues = isNullOrUndefined(defaultValues)
? defaultValues
: defaultValues[key];
if (formValues === null && defaultValues !== null) {
return true;
}
}
return false;
};
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
const field = get(_fields, name);
if (field) {
if (hasExplicitNullIntermediate(name)) {
return;
}
const wasUnsetInFormValues = isUndefined(get(_formValues, name));
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
isUndefined(defaultValue) ||
(ref && ref.defaultChecked) ||
shouldSkipSetValueAs
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
: setFieldValue(name, defaultValue);
_state.mount && !_state.action && _setValid();
if (_state.mount && !_state.action) {
_setValid();
// Re-registering a field after a prior unregister puts its key back
// into _formValues, which can flip isDirty back to false (#13397).
// Only run when we are currently dirty, otherwise an initial register
// for a field with no defaultValue would flip isDirty to true. Reset
// paths repopulate _formValues before re-register, so the key is
// present then and this branch is skipped (preserves keepDirty).
if (wasUnsetInFormValues &&
_formState.isDirty &&
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
const isDirty = _getDirty();
if (!isDirty) {
_formState.isDirty = false;
_subjects.state.next({ ..._formState });
}
}
}
}
};
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
@@ -955,9 +1057,14 @@ function createFormControl(props = {}) {
}
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
isPreviousDirty = !!get(_formState.dirtyFields, name);
isCurrentFieldPristine
? unset(_formState.dirtyFields, name)
: set(_formState.dirtyFields, name, true);
if (isCurrentFieldPristine !== _formState.isDirty) {
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
}
else {
isCurrentFieldPristine
? unset(_formState.dirtyFields, name)
: set(_formState.dirtyFields, name, true);
}
output.dirtyFields = _formState.dirtyFields;
shouldUpdateField =
shouldUpdateField ||
@@ -1015,8 +1122,7 @@ function createFormControl(props = {}) {
};
const _runSchema = async (name) => {
_updateIsValidating(name, true);
const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
return result;
return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
};
const executeSchemaAndUpdateState = async (names) => {
const { errors } = await _runSchema(names);
@@ -1025,7 +1131,11 @@ function createFormControl(props = {}) {
for (const name of names) {
const error = get(errors, name);
error
? set(_formState.errors, name, error)
? _names.array.has(name) &&
isObject(error) &&
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
: set(_formState.errors, name, error)
: unset(_formState.errors, name);
}
}
@@ -1034,9 +1144,55 @@ function createFormControl(props = {}) {
}
return errors;
};
const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
const validateForm = async ({ name, eventType, }) => {
if (props.validate) {
const result = await props.validate({
formValues: _formValues,
formState: _formState,
name,
eventType,
});
if (isObject(result)) {
for (const key in result) {
const error = result[key];
if (error) {
setError(`${FORM_ERROR_TYPE}.${key}`, {
message: isString(error.message) ? error.message : '',
type: error.type || INPUT_VALIDATION_RULES.validate,
});
}
}
}
else if (isString(result) || !result) {
setError(FORM_ERROR_TYPE, {
message: result || '',
type: INPUT_VALIDATION_RULES.validate,
});
}
else {
clearErrors(FORM_ERROR_TYPE);
}
return result;
}
return true;
};
const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
valid: true,
}) => {
runRootValidation: false,
}, }) => {
if (props.validate) {
context.runRootValidation = true;
const result = await validateForm({
name,
eventType,
});
if (!result) {
context.valid = false;
if (onlyCheckValid) {
return context.valid;
}
}
}
for (const name in fields) {
const field = fields[name];
if (field) {
@@ -1044,28 +1200,41 @@ function createFormControl(props = {}) {
if (_f) {
const isFieldArrayRoot = _names.array.has(_f.name);
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
if (isPromiseFunction && _proxyFormState.validatingFields) {
const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
_proxyFormState.isValidating ||
_proxySubscribeFormState.validatingFields ||
_proxySubscribeFormState.isValidating;
if (isPromiseFunction && shouldTrackIsValidatingState) {
_updateIsValidating([_f.name], true);
}
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
if (isPromiseFunction && _proxyFormState.validatingFields) {
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
if (isPromiseFunction && shouldTrackIsValidatingState) {
_updateIsValidating([_f.name]);
}
if (fieldError[_f.name]) {
context.valid = false;
if (shouldOnlyCheckValid || props.shouldUseNativeValidation) {
if (onlyCheckValid) {
break;
}
}
!shouldOnlyCheckValid &&
!onlyCheckValid &&
(get(fieldError, _f.name)
? isFieldArrayRoot
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
: set(_formState.errors, _f.name, fieldError[_f.name])
: unset(_formState.errors, _f.name));
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
break;
}
}
!isEmptyObject(fieldValue) &&
(await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
(await executeBuiltInValidation({
context,
onlyCheckValid,
fields: fieldValue,
name: name,
eventType,
}));
}
}
return context.valid;
@@ -1094,7 +1263,7 @@ function createFormControl(props = {}) {
: defaultValue),
}, isGlobal, defaultValue);
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
const setFieldValue = (name, value, options = {}) => {
const setFieldValue = (name, value, options = {}, skipClone = false) => {
const field = get(_fields, name);
let fieldValue = value;
if (field) {
@@ -1135,7 +1304,7 @@ function createFormControl(props = {}) {
if (!fieldReference.ref.type) {
_subjects.state.next({
name,
values: cloneObject(_formValues),
values: skipClone ? _formValues : cloneObject(_formValues),
});
}
}
@@ -1145,7 +1314,7 @@ function createFormControl(props = {}) {
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
options.shouldValidate && trigger(name);
};
const setValues = (name, value, options) => {
const setFieldValues = (name, value, options, skipClone = false) => {
for (const fieldKey in value) {
if (!value.hasOwnProperty(fieldKey)) {
return;
@@ -1157,49 +1326,79 @@ function createFormControl(props = {}) {
isObject(fieldValue) ||
(field && !field._f)) &&
!isDateObject(fieldValue)
? setValues(fieldName, fieldValue, options)
: setFieldValue(fieldName, fieldValue, options);
? setFieldValues(fieldName, fieldValue, options, skipClone)
: setFieldValue(fieldName, fieldValue, options, skipClone);
}
};
const setValue = (name, value, options = {}) => {
const _setValue = (name, value, options, skipClone) => {
const field = get(_fields, name);
const isFieldArray = _names.array.has(name);
const cloneValue = cloneObject(value);
set(_formValues, name, cloneValue);
const cloneValue = skipClone ? value : cloneObject(value);
const previousValue = get(_formValues, name);
const isValueUnchanged = deepEqual(previousValue, cloneValue);
if (!isValueUnchanged) {
set(_formValues, name, cloneValue);
}
if (isFieldArray) {
_subjects.array.next({
name,
values: cloneObject(_formValues),
values: skipClone ? _formValues : cloneObject(_formValues),
});
if ((_proxyFormState.isDirty ||
_proxyFormState.dirtyFields ||
_proxySubscribeFormState.isDirty ||
_proxySubscribeFormState.dirtyFields) &&
options.shouldDirty) {
_updateDirtyFields();
_subjects.state.next({
name,
dirtyFields: getDirtyFields(_defaultValues, _formValues),
dirtyFields: _formState.dirtyFields,
isDirty: _getDirty(name, cloneValue),
});
}
}
else {
field && !field._f && !isNullOrUndefined(cloneValue)
? setValues(name, cloneValue, options)
: setFieldValue(name, cloneValue, options);
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
isEmptyObject(cloneValue);
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
setFieldValue(name, cloneValue, options, skipClone);
}
else {
setFieldValues(name, cloneValue, options, skipClone);
}
}
if (isWatched(name, _names)) {
if (!isValueUnchanged) {
const watched = isWatched(name, _names);
const values = skipClone ? _formValues : cloneObject(_formValues);
_subjects.state.next({
...(watched && _formState),
name: _state.mount || watched ? name : undefined,
values,
});
}
};
const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
const setValues = (formValues, options = {}) => {
const updatedFormValues = isFunction(formValues)
? formValues(_formValues)
: formValues;
if (!deepEqual(_formValues, updatedFormValues)) {
_formValues = {
..._formValues,
...updatedFormValues,
};
for (const fieldName of _names.mount) {
_setValue(fieldName, get(updatedFormValues, fieldName), options, true);
}
_subjects.state.next({
..._formState,
name,
values: cloneObject(_formValues),
});
}
else {
_subjects.state.next({
name: _state.mount ? name : undefined,
values: cloneObject(_formValues),
name: undefined,
type: undefined,
values: _formValues,
});
if (options.shouldValidate) {
_setValid();
}
}
};
const onChange = async (event) => {
@@ -1224,6 +1423,7 @@ function createFormControl(props = {}) {
: getEventValue(event);
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
const shouldSkipValidation = (!hasValidation(field._f) &&
!props.validate &&
!_options.resolver &&
!get(_formState.errors, name) &&
!field._f.deps) ||
@@ -1261,18 +1461,26 @@ function createFormControl(props = {}) {
return (shouldRender &&
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
}
if (!_options.resolver && props.validate) {
await validateForm({
name: name,
eventType: event.type,
});
}
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
if (_options.resolver) {
const { errors } = await _runSchema([name]);
_updateIsValidating([name]);
_updateIsFieldValueUpdated(fieldValue);
if (isFieldValueUpdated) {
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
error = errorLookupResult.error;
name = errorLookupResult.name;
isValid = isEmptyObject(errors);
if (!isFieldValueUpdated) {
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
return;
}
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
error = errorLookupResult.error;
name = errorLookupResult.name;
isValid = isEmptyObject(errors);
}
else {
_updateIsValidating([name], true);
@@ -1285,7 +1493,12 @@ function createFormControl(props = {}) {
}
else if (_proxyFormState.isValid ||
_proxySubscribeFormState.isValid) {
isValid = await executeBuiltInValidation(_fields, true);
isValid = await executeBuiltInValidation({
fields: _fields,
onlyCheckValid: true,
name: name,
eventType: event.type,
});
}
}
}
@@ -1318,12 +1531,19 @@ function createFormControl(props = {}) {
else if (name) {
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
const field = get(_fields, fieldName);
return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
return await executeBuiltInValidation({
fields: field && field._f ? { [fieldName]: field } : field,
eventType: EVENTS.TRIGGER,
});
}))).every(Boolean);
!(!validationResult && !_formState.isValid) && _setValid();
}
else {
validationResult = isValid = await executeBuiltInValidation(_fields);
validationResult = isValid = await executeBuiltInValidation({
fields: _fields,
name,
eventType: EVENTS.TRIGGER,
});
}
_subjects.state.next({
...(!isString(name) ||
@@ -1360,11 +1580,24 @@ function createFormControl(props = {}) {
isTouched: !!get((formState || _formState).touchedFields, name),
});
const clearErrors = (name) => {
name &&
convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
_subjects.state.next({
errors: name ? _formState.errors : {},
});
const names = name ? convertToArrayPayload(name) : undefined;
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
if (names) {
// Emit for each cleared field with the field name so that
// shouldSubscribeByName can filter and avoid broad re-renders
names.forEach((inputName) => {
_subjects.state.next({
name: inputName,
errors: _formState.errors,
});
});
}
else {
// Clear all errors - emit without name to notify all subscribers
_subjects.state.next({
errors: {},
});
}
};
const setError = (name, error, options) => {
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
@@ -1386,15 +1619,16 @@ function createFormControl(props = {}) {
const watch = (name, defaultValue) => isFunction(name)
? _subjects.state.subscribe({
next: (payload) => 'values' in payload &&
name(_getWatch(undefined, defaultValue), payload),
name(payload.values || _getWatch(undefined, defaultValue), payload),
})
: _getWatch(name, defaultValue, true);
const _subscribe = (props) => _subjects.state.subscribe({
next: (formState) => {
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
const snapshot = { ..._formValues };
props.callback({
values: { ..._formValues },
values: snapshot,
..._formState,
...formState,
defaultValues: _defaultValues,
@@ -1446,12 +1680,17 @@ function createFormControl(props = {}) {
if ((isBoolean(disabled) && _state.mount) ||
!!disabled ||
_names.disabled.has(name)) {
const wasDisabled = _names.disabled.has(name);
const isDisabled = !!disabled;
const disabledStateChanged = wasDisabled !== isDisabled;
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
disabledStateChanged && _state.mount && !_state.action && _setValid();
}
};
const register = (name, options = {}) => {
let field = get(_fields, name);
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
set(_fields, name, {
...(field || {}),
_f: {
@@ -1462,7 +1701,7 @@ function createFormControl(props = {}) {
},
});
_names.mount.add(name);
if (field) {
if (field && !shouldRevalidateRemount) {
_setDisabledField({
disabled: isBoolean(options.disabled)
? options.disabled
@@ -1492,7 +1731,9 @@ function createFormControl(props = {}) {
onBlur: onChange,
ref: (ref) => {
if (ref) {
_names.registerName.add(name);
register(name, options);
_names.registerName.delete(name);
field = get(_fields, name);
const fieldRef = isUndefined(ref.value)
? ref.querySelectorAll
@@ -1536,6 +1777,7 @@ function createFormControl(props = {}) {
};
};
const _focusError = () => _options.shouldFocusError &&
!_options.shouldUseNativeValidation &&
iterateFieldsByAction(_fields, _focusInput, _names.mount);
const _disableForm = (disabled) => {
if (isBoolean(disabled)) {
@@ -1571,14 +1813,17 @@ function createFormControl(props = {}) {
fieldValues = cloneObject(values);
}
else {
await executeBuiltInValidation(_fields);
await executeBuiltInValidation({
fields: _fields,
eventType: EVENTS.SUBMIT,
});
}
if (_names.disabled.size) {
for (const name of _names.disabled) {
unset(fieldValues, name);
}
}
unset(_formState.errors, 'root');
unset(_formState.errors, ROOT_ERROR_TYPE);
if (isEmptyObject(_formState.errors)) {
_subjects.state.next({
errors: {},
@@ -1637,7 +1882,7 @@ function createFormControl(props = {}) {
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
const cloneUpdatedValues = cloneObject(updatedValues);
const isEmptyResetValues = isEmptyObject(formValues);
const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues;
const values = cloneUpdatedValues;
if (!keepStateOptions.keepDefaultValues) {
_defaultValues = updatedValues;
}
@@ -1686,11 +1931,19 @@ function createFormControl(props = {}) {
_fields = {};
}
}
_formValues = _options.shouldUnregister
? keepStateOptions.keepDefaultValues
if (_options.shouldUnregister) {
_formValues = keepStateOptions.keepDefaultValues
? cloneObject(_defaultValues)
: {}
: cloneObject(values);
: {};
if (keepStateOptions.keepFieldsRef) {
for (const fieldName of _names.mount) {
set(_formValues, fieldName, get(values, fieldName));
}
}
}
else {
_formValues = cloneObject(values);
}
_subjects.array.next({
values: { ...values },
});
@@ -1702,6 +1955,7 @@ function createFormControl(props = {}) {
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
unMount: new Set(),
array: new Set(),
registerName: new Set(),
disabled: new Set(),
watch: new Set(),
watchAll: false,
@@ -1729,8 +1983,10 @@ function createFormControl(props = {}) {
? false
: keepStateOptions.keepDirty
? _formState.isDirty
: !!(keepStateOptions.keepDefaultValues &&
!deepEqual(formValues, _defaultValues)),
: keepStateOptions.keepValues
? _getDirty()
: !!(keepStateOptions.keepDefaultValues &&
!deepEqual(formValues, _defaultValues)),
isSubmitted: keepStateOptions.keepIsSubmitted
? _formState.isSubmitted
: false,
@@ -1791,6 +2047,21 @@ function createFormControl(props = {}) {
isLoading: false,
});
});
const resetDefaultValues = (values, options = {}) => {
_defaultValues = cloneObject(values);
if (!options.keepDirty) {
const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
_formState.dirtyFields = newDirtyFields;
_formState.isDirty = !isEmptyObject(newDirtyFields);
}
if (!options.keepIsValid) {
_setValid();
}
_subjects.state.next({
..._formState,
defaultValues: _defaultValues,
});
};
const methods = {
control: {
register,
@@ -1855,9 +2126,11 @@ function createFormControl(props = {}) {
handleSubmit,
watch,
setValue,
setValues,
getValues,
reset,
resetField,
resetDefaultValues,
clearErrors,
unregister,
setError,