grommet
Version:
focus on the essential experience
708 lines (693 loc) • 30 kB
JavaScript
;
exports.__esModule = true;
exports.Form = void 0;
var _react = _interopRequireWildcard(require("react"));
var _contexts = require("../../contexts");
var _MessageContext = require("../../contexts/MessageContext");
var _utils = require("../../utils");
var _FormContext = require("./FormContext");
var _propTypes = require("./propTypes");
var _excluded = ["children", "errors", "infos", "messages", "kind", "onChange", "onReset", "onSubmit", "onValidate", "validate", "value"];
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
var defaultValue = {};
var defaultTouched = {};
var defaultValidationResults = {
errors: {},
infos: {}
};
var defaultThreshold = 0.5;
var stringToArray = function stringToArray(string) {
var match = string == null ? void 0 : string.match(/^(.+)\[([0-9]+)\]\.(.*)$/);
if (match) {
var arrayName = match[1],
indexOfArray = match[2],
arrayObjName = match[3];
return {
indexOfArray: indexOfArray,
arrayName: arrayName,
arrayObjName: arrayObjName
};
}
return undefined;
};
var _getValueAt = function getValueAt(valueObject, pathArg) {
if (valueObject === undefined) return undefined;
var path = Array.isArray(pathArg) ? pathArg : pathArg.split('.');
if (path.length === 1) return valueObject[path];
return _getValueAt(valueObject[path.shift()], path);
};
var _setValueAt = function setValueAt(valueObject, pathArg, value) {
var object = valueObject;
var path = Array.isArray(pathArg) ? pathArg : pathArg.split('.');
if (path.length === 1) object[path] = value;else {
var key = path.shift();
if (!object[key]) object[key] = {};
_setValueAt(object[key], path, value);
}
};
var getFieldValue = function getFieldValue(name, value) {
var isArrayField = stringToArray(name);
if (isArrayField) {
var _value$arrayName;
var indexOfArray = isArrayField.indexOfArray,
arrayName = isArrayField.arrayName,
arrayObjName = isArrayField.arrayObjName;
var obj = (_value$arrayName = value[arrayName]) == null ? void 0 : _value$arrayName[indexOfArray];
return arrayObjName ? obj == null ? void 0 : obj[arrayObjName] : obj;
}
return _getValueAt(value, name);
};
var setFieldValue = function setFieldValue(name, componentValue, prevValue) {
var nextValue = _extends({}, prevValue);
var isArrayField = stringToArray(name);
if (isArrayField) {
var indexOfArray = isArrayField.indexOfArray,
arrayName = isArrayField.arrayName,
arrayObjName = isArrayField.arrayObjName;
if (!nextValue[arrayName]) nextValue[arrayName] = [];
if (arrayObjName) {
var _nextValue$arrayName$;
if (!nextValue[arrayName][indexOfArray]) nextValue[arrayName][indexOfArray] = (_nextValue$arrayName$ = {}, _nextValue$arrayName$[arrayObjName] = componentValue, _nextValue$arrayName$);
nextValue[arrayName][indexOfArray][arrayObjName] = componentValue;
} else nextValue[arrayName][indexOfArray] = componentValue;
} else {
_setValueAt(nextValue, name, componentValue);
}
return nextValue;
};
var validateCharacterCount = function validateCharacterCount(format, rule, value) {
var max = rule.max,
threshold = rule.threshold;
var getMessage = function getMessage() {
var charactersRemaining = function charactersRemaining(plural) {
return {
id: "formField.maxCharacters.remaining." + (plural ? 'plural' : 'singular'),
values: {
number: max - value.length
}
};
};
var charactersOverLimit = function charactersOverLimit(plural) {
return {
id: "formField.maxCharacters.overLimit." + (plural ? 'plural' : 'singular'),
values: {
number: value.length - max
}
};
};
if (max - value.length >= 0) {
return format(charactersRemaining(max - value.length > 1));
}
return format(charactersOverLimit(value.length - max > 1));
};
return value.length / max > (threshold != null ? threshold : defaultThreshold) ? {
status: max - value.length >= 0 ? 'info' : 'error',
message: getMessage()
} : undefined;
};
// Apply validation rule to field value and send correct messaging.
var validate = function validate(rule, fieldValue, formValue, format, messages) {
var result;
if (typeof rule === 'function') {
result = rule(fieldValue, formValue);
} else if (rule.regexp) {
if (!rule.regexp.test(fieldValue)) {
result = rule.message || format({
id: 'form.invalid',
messages: messages
});
if (rule.status) {
result = {
message: result,
status: rule.status
};
}
}
} else if (rule.max) {
result = validateCharacterCount(format, rule, fieldValue);
}
return result;
};
// Validates particular key in formValue
var validateName = function validateName(validationRules, required) {
return function (name, formValue, format, messages) {
var fieldValue = getFieldValue(name, formValue);
var validationResult;
if (required && (
// false is for CheckBox
fieldValue === undefined || fieldValue === '' || fieldValue === false || Array.isArray(fieldValue) && !fieldValue.length)) {
validationResult = format({
id: 'form.required',
messages: messages
});
} else if (validationRules) {
if (Array.isArray(validationRules)) {
validationRules.some(function (rule) {
validationResult = validate(rule, fieldValue, formValue, format, messages);
return !!validationResult;
});
} else {
validationResult = validate(validationRules, fieldValue, formValue, format, messages);
}
}
return validationResult;
};
};
// Validates all keys in formValue
var validateForm = function validateForm(validationRules, formValue, format, messages, omitValid) {
var nextErrors = {};
var nextInfos = {};
validationRules.forEach(function (_ref) {
var name = _ref[0],
_ref$ = _ref[1],
field = _ref$.field,
input = _ref$.input,
validateOn = _ref$.validateOn;
if (!omitValid) {
nextErrors[name] = undefined;
nextInfos[name] = undefined;
}
if (!validateOn) return;
var result;
if (input) {
// input() a validation function supplied through useFormInput()
result = input(name, formValue, format, messages);
}
if (field && !result) {
// field() a validation function supplied through useFormField()
result = field(name, formValue, format, messages);
}
// typeof error === 'object' is implied for both cases of error with
// a status message and for an error object that is a react node
if (typeof result === 'object') {
if (result.status === 'info') {
nextInfos[name] = result.message;
} else {
nextErrors[name] = result.message || result; // could be a node
}
} else if (typeof result === 'string') {
nextErrors[name] = result;
}
});
return [nextErrors, nextInfos];
};
var isInstantValidate = function isInstantValidate(validateOn) {
return ['blur', 'change'].includes(validateOn);
};
var Form = exports.Form = /*#__PURE__*/(0, _react.forwardRef)(function (_ref2, ref) {
var children = _ref2.children,
_ref2$errors = _ref2.errors,
errorsProp = _ref2$errors === void 0 ? defaultValidationResults.errors : _ref2$errors,
_ref2$infos = _ref2.infos,
infosProp = _ref2$infos === void 0 ? defaultValidationResults.infos : _ref2$infos,
messages = _ref2.messages,
kind = _ref2.kind,
onChange = _ref2.onChange,
_onReset = _ref2.onReset,
_onSubmit = _ref2.onSubmit,
onValidate = _ref2.onValidate,
_ref2$validate = _ref2.validate,
validateOnProp = _ref2$validate === void 0 ? 'submit' : _ref2$validate,
valueProp = _ref2.value,
rest = _objectWithoutPropertiesLoose(_ref2, _excluded);
var formRef = (0, _utils.useForwardedRef)(ref);
var _useContext = (0, _react.useContext)(_MessageContext.MessageContext),
format = _useContext.format;
var _useState = (0, _react.useState)(valueProp || defaultValue),
valueState = _useState[0],
setValueState = _useState[1];
var value = (0, _react.useMemo)(function () {
return valueProp || valueState;
}, [valueProp, valueState]);
var _useState2 = (0, _react.useState)(defaultTouched),
touched = _useState2[0],
setTouched = _useState2[1];
var _useState3 = (0, _react.useState)(validateOnProp),
validateOn = _useState3[0],
setValidateOn = _useState3[1];
var _useState4 = (0, _react.useState)({
errors: errorsProp,
infos: infosProp
}),
validationResults = _useState4[0],
setValidationResults = _useState4[1];
// maintain a copy of validationResults in a ref for useEffects
// which can't depend on validationResults directly without
// causing infinite renders.
var validationResultsRef = (0, _react.useRef)({});
// Simulated onMount state. Consider Form to be mounted once it has
// accounted for values originating from controlled inputs (available
// at second rendering).
var _useState5 = (0, _react.useState)('unmounted'),
mounted = _useState5[0],
setMounted = _useState5[1];
(0, _react.useEffect)(function () {
if (!mounted) setMounted('mounting');else if (mounted === 'mounting') setMounted('mounted');
}, [mounted]);
// `pendingValidation` is the name of the FormField awaiting validation.
var _useState6 = (0, _react.useState)(undefined),
pendingValidation = _useState6[0],
setPendingValidation = _useState6[1];
var validationRulesRef = (0, _react.useRef)({});
var requiredFields = (0, _react.useRef)([]);
var analyticsRef = (0, _react.useRef)({
start: new Date(),
errors: {}
});
var sendAnalytics = (0, _contexts.useAnalytics)();
var buildValid = (0, _react.useCallback)(function (nextErrors) {
var valid = false;
valid = requiredFields.current.filter(function (n) {
return Object.keys(validationRulesRef.current).includes(n);
}).every(function (field) {
return value[field] && (value[field] !== '' || value[field] !== false);
});
if (Object.keys(nextErrors).length > 0) valid = false;
return valid;
}, [value]);
// Only keep validation results for current form fields. In the case of a
// dynamic form, a field possessing an error may have been removed from the
// form; need to clean up any previous related validation results.
var filterRemovedFields = function filterRemovedFields(prevValidations) {
var nextValidations = prevValidations;
return Object.keys(nextValidations).filter(function (n) {
return !validationRulesRef.current[n] || nextValidations[n] === undefined;
}).forEach(function (n) {
return delete nextValidations[n];
});
};
var updateAnalytics = function updateAnalytics() {
var _validationResultsRef;
var errorFields = Object.keys((_validationResultsRef = validationResultsRef.current) == null ? void 0 : _validationResultsRef.errors);
var errorCounts = analyticsRef.current.errors;
if (errorFields.length > 0) {
errorFields.forEach(function (key) {
errorCounts[key] = (errorCounts[key] || 0) + 1;
});
}
};
var applyValidationRules = (0, _react.useCallback)(function (validationRules) {
var _validateForm = validateForm(validationRules, value, format, messages),
validatedErrors = _validateForm[0],
validatedInfos = _validateForm[1];
setValidationResults(function (prevValidationResults) {
// Keep any previous errors and infos for untouched keys,
// these may have come from a Submit.
var nextErrors = _extends({}, prevValidationResults.errors, validatedErrors);
var nextInfos = _extends({}, prevValidationResults.infos, validatedInfos);
// Remove previous errors and infos for keys no longer in the
// form, these may have been fields removed from a dynamic form.
filterRemovedFields(nextErrors);
filterRemovedFields(nextInfos);
var nextValidationResults = {
errors: nextErrors,
infos: nextInfos
};
if (onValidate) onValidate(_extends({}, nextValidationResults, {
valid: buildValid(nextErrors)
}));
validationResultsRef.current = nextValidationResults;
updateAnalytics();
return nextValidationResults;
});
}, [buildValid, format, messages, onValidate, value]);
// Validate all fields holding values onMount if set to
// validate when blur or change.
(0, _react.useEffect)(function () {
var validationRules = Object.entries(validationRulesRef.current);
// Use simulated onMount state to account for values provided by
// controlled inputs.
if (mounted !== 'mounted' && (isInstantValidate(validateOn) || validationRules.some(function (_ref3) {
var v = _ref3[1];
return isInstantValidate(v.validateOn);
})) && Object.keys(value).length > 0 && Object.keys(touched).length === 0) {
applyValidationRules(validationRules.filter(function (_ref4) {
var n = _ref4[0],
v = _ref4[1];
return getFieldValue(n, value) && v.validateOn;
})
// Exlude empty arrays which may be initial values in
// an input such as DateInput.
.filter(function (_ref5) {
var n = _ref5[0];
return !(Array.isArray(getFieldValue(n, value)) && getFieldValue(n, value).length === 0);
}));
}
}, [applyValidationRules, mounted, touched, validateOn, value]);
// Run validation against fields with pendingValidations from onBlur
// and/or onChange.
(0, _react.useEffect)(function () {
var validationRules = Object.entries(validationRulesRef.current);
var timer = setTimeout(function () {
if (pendingValidation && (isInstantValidate(validateOn) || validationRules.some(function (_ref6) {
var v = _ref6[1];
return isInstantValidate(v.validateOn);
}))) {
applyValidationRules(validationRules.filter(function (_ref7) {
var n = _ref7[0],
v = _ref7[1];
return (touched[n] || pendingValidation.includes(n)) && v.validateOn;
}));
setPendingValidation(undefined);
}
// Complete any potential click events before running onBlur validation.
// Otherwise, click events like reset, etc. may not be registered. For a
// detailed scenario/discussion, see: https://github.com/grommet/grommet/issues/4863
// Values empirically tested; 120 was selected because it is the largest
// Chrome: 100, Safari: 120, Firefox: 80
}, 120);
return function () {
return clearTimeout(timer);
};
}, [applyValidationRules, pendingValidation, touched, validateOn]);
// Re-run validation rules for all fields with prior errors.
// if validate=blur this helps re-validate if there are errors
// as the user fixes them (basically act like validate=change for that)
(0, _react.useEffect)(function () {
var _validationResultsRef2;
var validationRules = Object.entries(validationRulesRef.current);
if ((_validationResultsRef2 = validationResultsRef.current) != null && _validationResultsRef2.errors && Object.keys(validationResultsRef.current.errors).length > 0) {
applyValidationRules(validationRules.filter(function (_ref8) {
var n = _ref8[0];
return touched[n] && validationResultsRef.current.errors[n];
}));
}
}, [applyValidationRules, touched]);
(0, _react.useEffect)(function () {
var element = formRef.current;
analyticsRef.current = {
start: new Date(),
errors: {}
};
sendAnalytics({
type: 'formOpen',
element: element
});
return function () {
if (!analyticsRef.current.submitted) {
sendAnalytics({
type: 'formClose',
element: element,
errors: analyticsRef.current.errors,
elapsed: new Date().getTime() - analyticsRef.current.start.getTime()
});
}
};
}, [sendAnalytics, formRef]);
// There are three basic patterns of handling form input value state:
//
// 1 - form controlled
//
// In this model, the caller sets `value` and `onChange` properties
// on the Form component to supply the values used by the input fields.
// In useFormContext(), componentValue would be undefined and formValue
// is be set to whatever the form state has. Whenever the form state
// changes, we update the contextValue so the input component will use
// that. When the input component changes, we will call update() to
// update the form state.
//
// 2 - input controlled
//
// In this model, the caller sets `value` and `onChange` properties
// on the input components, like TextInput, to supply the value for it.
// In useFormContext(), componentValue is this value and we ensure to
// update the form state, via update(), and set the contextValue from
// the componentValue. When the input component changes, we will
// call update() to update the form state.
//
// 3 - uncontrolled
//
// In this model, the caller doesn't set a `value` or `onChange` property
// at either the form or input component levels.
// In useFormContext(), componentValue is undefined and valueProp is
// undefined and nothing much happens here. That is, unless the
// calling component needs to know the state in order to work, such
// as CheckBox or Select. In this case, those components supply
// an initialValue, which will trigger updating the contextValue so
// they can have access to it.
//
var formContextValue = (0, _react.useMemo)(function () {
var useFormInput = function useFormInput(_ref9) {
var name = _ref9.name,
componentValue = _ref9.value,
initialValue = _ref9.initialValue,
validateArg = _ref9.validate;
var _useState7 = (0, _react.useState)(initialValue),
inputValue = _useState7[0],
setInputValue = _useState7[1];
var formValue = name ? getFieldValue(name, value) : undefined;
// for dynamic forms, we need to track when an input has been added to
// the form value. if the input is unmounted, we will delete its
// key/value from the form value.
var keyCreated = (0, _react.useRef)(false);
// This effect is for pattern #2, where the controlled input
// component is driving the value via componentValue.
(0, _react.useEffect)(function () {
if (name &&
// we have somewhere to put this
componentValue !== undefined && (
// input driving
Array.isArray(componentValue) && Array.isArray(formValue) ? componentValue.toString() !== formValue.toString() : componentValue !== formValue) // don't already have it
) {
setValueState(function (prevValue) {
return setFieldValue(name, componentValue, prevValue);
});
// don't onChange on programmatic changes
}
}, [componentValue, formValue, name]);
// on unmount, if the form is uncontrolled, remove the key/value
// from the form value
(0, _react.useEffect)(function () {
return function () {
if (keyCreated.current) {
keyCreated.current = false;
setValueState(function (prevValue) {
var nextValue = _extends({}, prevValue);
var isArrayField = stringToArray(name);
if (isArrayField) {
var arrayName = isArrayField.arrayName;
delete nextValue[arrayName];
} else {
delete nextValue[name];
}
return nextValue;
});
}
};
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[] // only run onmount and unmount
);
// Create validation rules for fields
(0, _react.useEffect)(function () {
if (validateArg) {
if (!validationRulesRef.current[name]) {
validationRulesRef.current[name] = {};
}
validationRulesRef.current[name].input = validateName(validateArg);
return function () {
return delete validationRulesRef.current[name].input;
};
}
return undefined;
}, [validateArg, name]);
var useValue;
if (componentValue !== undefined)
// input component drives, pattern #2
useValue = componentValue;else if (valueProp && name && formValue !== undefined)
// form drives, pattern #1
useValue = formValue;else if (formValue === undefined && name)
// form has reset, so reset input value as well
useValue = initialValue;else useValue = inputValue;
return [useValue, function (nextComponentValue) {
if (name) {
// we have somewhere to put this
var nextTouched = _extends({}, touched);
nextTouched[name] = true;
if (!touched[name]) {
// don't update if not needed
setTouched(nextTouched);
}
// if nextValue doesn't have a key for name, this must be
// uncontrolled form. we will flag this field was added so
// we know to remove its value from the form if it is dynamically
// removed
if (!(name in value)) keyCreated.current = true;
var nextValue = setFieldValue(name, nextComponentValue, value);
setValueState(nextValue);
if (onChange) onChange(nextValue, {
touched: nextTouched
});
}
if (initialValue !== undefined) setInputValue(nextComponentValue);
}];
};
var useFormField = function useFormField(_ref0) {
var errorArg = _ref0.error,
infoArg = _ref0.info,
name = _ref0.name,
required = _ref0.required,
disabled = _ref0.disabled,
validateArg = _ref0.validate,
validateOnArg = _ref0.validateOn;
var error = disabled ? undefined : errorArg || validationResults.errors[name];
var info = infoArg || validationResults.infos[name];
(0, _react.useEffect)(function () {
setValidateOn(function (prevValues) {
var _extends2;
if (typeof prevValues === 'string') {
var _ref1;
return _ref1 = {}, _ref1[name] = validateOnArg || validateOnProp, _ref1;
}
return _extends({}, prevValues, (_extends2 = {}, _extends2[name] = validateOnArg || validateOnProp, _extends2));
});
}, [validateOnArg, name]);
// Create validation rules for field
(0, _react.useEffect)(function () {
var index = requiredFields.current.indexOf(name);
if (required) {
if (index === -1) requiredFields.current.push(name);
} else if (index !== -1) requiredFields.current.splice(index, 1);
if (validateArg || required) {
if (!validationRulesRef.current[name]) {
validationRulesRef.current[name] = {};
}
validationRulesRef.current[name].field = validateName(validateArg, required);
// priority is given to validateOn prop on formField, if it is
// undefined, then we will use the validate prop value of Form.
// The reason we don't want to add validateOn = "submit" here is
// because we don't want to trigger validation of "submit" field
// when the user is typing in the instant (blur, change)
// validation fields.
if (validateOnArg && validateOnArg !== 'submit') {
validationRulesRef.current[name].validateOn = validateOnArg;
} else if (!validateOnArg && validateOnProp !== 'submit') {
validationRulesRef.current[name].validateOn = validateOnProp;
}
return function () {
delete validationRulesRef.current[name].field;
delete validationRulesRef.current[name].validateOn;
var requiredFieldIndex = requiredFields.current.indexOf(name);
if (requiredFieldIndex !== -1) {
requiredFields.current.splice(requiredFieldIndex, 1);
}
};
}
return undefined;
}, [error, name, required, validateArg, disabled, validateOnArg]);
return {
error: error,
info: info,
inForm: true,
onBlur: validateOnArg === 'blur' || validateOn[name] === 'blur' ? function () {
return setPendingValidation(pendingValidation ? [].concat(pendingValidation, [name]) : [name]);
} : undefined,
onChange: validateOnArg === 'change' || validateOn[name] === 'change' ? function () {
return setPendingValidation(pendingValidation ? [].concat(pendingValidation, [name]) : [name]);
} : undefined
};
};
return {
useFormField: useFormField,
useFormInput: useFormInput,
kind: kind
};
}, [onChange, kind, pendingValidation, touched, validateOn, validationResults.errors, validationResults.infos, value, valueProp, validateOnProp]);
return /*#__PURE__*/_react["default"].createElement("form", _extends({
ref: formRef
}, rest, {
onReset: function onReset(event) {
sendAnalytics({
type: 'formReset',
element: formRef.current,
data: event,
errors: analyticsRef.current.errors,
elapsed: new Date().getTime() - analyticsRef.current.start.getTime()
});
setPendingValidation(undefined);
if (!valueProp) {
setValueState(defaultValue);
if (onChange) onChange(defaultValue, {
touched: defaultTouched
});
}
setTouched(defaultTouched);
setValidationResults(defaultValidationResults);
analyticsRef.current = {
start: new Date(),
errors: {}
};
if (_onReset) {
event.persist(); // extract from React's synthetic event pool
var adjustedEvent = event;
adjustedEvent.value = defaultValue;
_onReset(adjustedEvent);
}
},
onSubmit: function onSubmit(event) {
// Don't submit the form via browser form action. We don't want it
// if the validation fails. And, we assume a javascript action handler
// otherwise.
event.preventDefault();
// Prevent any "outer" forms from performing `onSubmit`.
// Nesting forms is not recommended in HTML. However, with React
// portals, if the portal (such as Grommet's Layer) contains a form
// and is nested within another form in the React tree, the event
// bubbles up to the "outer" form even though in the DOM the portal
// doesn't render as child of the "outer" form.
// https://legacy.reactjs.org/docs/portals.html#event-bubbling-through-portals
if (formRef.current && (event.target === formRef.current || event.target.form === formRef.current)) {
setPendingValidation(undefined);
// adding validateOn: "submit" prop to the undefined validateOn
// fields as we want to trigger "submit" validation once form
// is submitted
var newValidationRulesRef = Object.keys(validationRulesRef.current).reduce(function (acc, key) {
acc[key] = validationRulesRef.current[key];
if (!acc[key].validateOn) {
acc[key] = _extends({}, validationRulesRef.current[key], {
validateOn: 'submit'
});
}
return acc;
}, {});
var _validateForm2 = validateForm(Object.entries(newValidationRulesRef), value, format, messages, true),
nextErrors = _validateForm2[0],
nextInfos = _validateForm2[1];
setValidationResults(function () {
var nextValidationResults = {
errors: nextErrors,
infos: nextInfos,
// Show form's validity when clicking on Submit
valid: buildValid(nextErrors)
};
if (onValidate) onValidate(nextValidationResults);
validationResultsRef.current = nextValidationResults;
updateAnalytics();
return nextValidationResults;
});
if (Object.keys(nextErrors).length === 0 && _onSubmit) {
event.persist(); // extract from React's synthetic event pool
var adjustedEvent = event;
adjustedEvent.value = value;
adjustedEvent.touched = touched;
_onSubmit(adjustedEvent);
sendAnalytics({
type: 'formSubmit',
element: formRef.current,
data: adjustedEvent,
errors: analyticsRef.current.errors,
elapsed: new Date().getTime() - analyticsRef.current.start.getTime()
});
analyticsRef.current.errors = {};
analyticsRef.current.submitted = true;
}
}
}
}), /*#__PURE__*/_react["default"].createElement(_FormContext.FormContext.Provider, {
value: formContextValue
}, children));
});
Form.displayName = 'Form';
Form.propTypes = _propTypes.FormPropTypes;