Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-form

Package Overview
Dependencies
Maintainers
2
Versions
122
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-form - npm Package Compare versions

Comparing version 4.0.0-alpha.11 to 4.0.0-alpha.12

868

dist/index.es.js

@@ -282,4 +282,190 @@ import React from 'react';

var formContext = React.createContext();
function FormContextProvider(_ref) {
var value = _ref.value,
children = _ref.children;
return React.createElement(formContext.Provider, {
value: value
}, children);
}
function useFormContext(manualFormContext) {
var formApi = React.useContext(formContext);
if (manualFormContext) {
return manualFormContext;
}
if (!formApi) {
throw new Error("You are trying to use the form API outside of a form!");
}
return formApi;
}
function useFormElement(contextValue) {
var FormRef = React.useRef();
var FormApiRef = React.useRef();
FormApiRef.current = contextValue; // Create a new form element
if (!FormRef.current) {
FormRef.current = function Form(_ref) {
var children = _ref.children,
noFormElement = _ref.noFormElement,
rest = _objectWithoutProperties(_ref, ["children", "noFormElement"]);
var _FormApiRef$current = FormApiRef.current,
handleSubmit = _FormApiRef$current.handleSubmit,
isSubmitting = _FormApiRef$current.meta.isSubmitting,
debugForm = _FormApiRef$current.debugForm;
return React.createElement(FormContextProvider, {
value: FormApiRef.current
}, noFormElement ? children : React.createElement("form", _extends({
onSubmit: handleSubmit,
disabled: isSubmitting
}, rest), children, debugForm ? React.createElement("div", {
style: {
margin: '2rem 0'
}
}, React.createElement("div", {
style: {
fontWeight: 'bolder'
}
}, "Form State"), React.createElement("pre", null, React.createElement("code", null, JSON.stringify(_objectSpread({}, FormApiRef.current, {
formContext: undefined
}), safeStringifyReplace(new Set()), 2)))) : null));
};
} // Return the form element
return FormRef.current;
}
function safeStringifyReplace(set) {
return function (key, value) {
if (_typeof(value) === 'object' || Array.isArray(value)) {
if (set.has(value)) {
return '(circular value)';
}
set.add(value);
}
return typeof value === 'function' ? undefined : value;
};
}
function splitFormProps(_ref) {
var field = _ref.field,
defaultValue = _ref.defaultValue,
defaultIsTouched = _ref.defaultIsTouched,
defaultError = _ref.defaultError,
defaultMeta = _ref.defaultMeta,
validatePristine = _ref.validatePristine,
validate = _ref.validate,
onSubmit = _ref.onSubmit,
defaultValues = _ref.defaultValues,
filterValue = _ref.filterValue,
debugForm = _ref.debugForm,
rest = _objectWithoutProperties(_ref, ["field", "defaultValue", "defaultIsTouched", "defaultError", "defaultMeta", "validatePristine", "validate", "onSubmit", "defaultValues", "filterValue", "debugForm"]);
return [field, {
defaultValue: defaultValue,
defaultIsTouched: defaultIsTouched,
defaultError: defaultError,
defaultMeta: defaultMeta,
validatePristine: validatePristine,
validate: validate,
onSubmit: onSubmit,
defaultValues: defaultValues,
filterValue: filterValue,
debugForm: debugForm
}, rest];
} // Utils
function getBy(obj, path) {
if (!path) {
throw new Error('A path string is required to use getBy');
}
var pathArray = makePathArray(path);
var pathObj = pathArray;
return pathObj.reduce(function (current, pathPart) {
if (typeof current !== 'undefined') {
return current[pathPart];
}
return undefined;
}, obj);
}
function setBy(obj, path, updater) {
path = makePathArray(path);
function doSet(parent) {
if (!path.length) {
return typeof updater === 'function' ? updater(parent) : updater;
}
var key = path.shift();
if (typeof key === 'string') {
if (_typeof(parent) === 'object') {
return _objectSpread({}, parent, _defineProperty({}, key, doSet(parent[key])));
}
return _defineProperty({}, key, doSet());
}
if (typeof key === 'number') {
if (Array.isArray(parent)) {
var prefix = parent.slice(0, key);
return [].concat(_toConsumableArray(prefix.length ? prefix : new Array(key)), [doSet(parent[key])], _toConsumableArray(parent.slice(key + 1)));
}
return [].concat(_toConsumableArray(new Array(key)), [doSet()]);
}
throw new Error('Uh oh!');
}
return doSet(obj);
}
function getFieldID(str) {
return makePathArray(str).join('_');
}
var reFindNumbers0 = /^(\d*)$/gm;
var reFindNumbers1 = /\.(\d*)\./gm;
var reFindNumbers2 = /^(\d*)\./gm;
var reFindNumbers3 = /\.(\d*$)/gm;
var reFindMultiplePeriods = /\.{2,}/gm;
function makePathArray(str) {
return str.replace('[', '').replace(']', '.').replace(reFindNumbers0, '__int__$1').replace(reFindNumbers1, '.__int__$1.').replace(reFindNumbers2, '__int__$1.').replace(reFindNumbers3, '.__int__$1').replace(reFindMultiplePeriods, '.').split('.').map(function (d) {
if (d.indexOf('__int__') === 0) {
return parseInt(d.substring('__int__'.length), 10);
}
return d;
});
}
function loopObject(obj, fn, callback) {
Object.keys(obj).forEach(function (key) {
callback(fn(obj[key], key), key);
});
}
function someObject(obj, fn) {
var found = false;
loopObject(obj, fn, function (result, key) {
if (found) {
return;
}
if (result) {
found = true;
}
});
return found;
}
var defaultDefaultValue = {};
var uid = 0;

@@ -322,18 +508,22 @@ function makeState(decor) {

var _React$useState3 = React.useState(false),
_React$useState4 = _slicedToArray(_React$useState3, 2),
shouldResubmit = _React$useState4[0],
setShouldResubmit = _React$useState4[1];
var apiRef = React.useRef();
var metaRef = React.useRef({});
var __fieldMetaRefsRef = React.useRef({});
var __fieldMetaRefsRef = React.useRef({}); // Keep validate up to date with the latest version
var validateRef = React.useRef(); // Keep validate up to date with the latest version
validateRef.current = validate;
var allFieldsTouched = !someObject(__fieldMeta, function (field) {
return field && !field.isTouched;
metaRef.current.validate = validate;
var fieldsAreValidating = someObject(__fieldMeta, function (field) {
return field && field.isValidating;
});
var allFieldsValid = !someObject(__fieldMeta, function (field) {
var fieldsAreValid = !someObject(__fieldMeta, function (field) {
return field && field.error;
}); // Can we submit this form?
var isValid = isTouched && allFieldsValid && !meta.error;
var isValid = !fieldsAreValidating && fieldsAreValid && !meta.error;
var canSubmit = isValid && !isSubmitting; // Decorate form meta

@@ -343,8 +533,8 @@

return _objectSpread({}, meta, {
fieldsAreValidating: fieldsAreValidating,
fieldsAreValid: fieldsAreValid,
isValid: isValid,
canSubmit: canSubmit,
allFieldsTouched: allFieldsTouched,
allFieldsValid: allFieldsValid
canSubmit: canSubmit
});
}, [meta, isValid, canSubmit, allFieldsTouched, allFieldsValid]); // We want the apiRef to change every time state updates
}, [meta, fieldsAreValidating, fieldsAreValid, isValid, canSubmit]); // We want the apiRef to change every time state updates

@@ -371,95 +561,141 @@ var api = React.useMemo(function () {

/*#__PURE__*/
function () {
var _ref2 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(e) {
var needTouchedAndValidation;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
e.persist();
e.preventDefault(); // This lets sub-forms with form elements (despite them being invalid HTML)
// handle submissions without triggering parent forms
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee() {
var e,
needsResubmit,
fieldValidationPromises,
_args = arguments;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
e = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
if (e.persist) e.persist();
if (e.preventDefault) e.preventDefault(); // This lets sub-forms with form elements (despite them being invalid HTML)
// handle submissions without triggering parent forms
if (!e.__handled) {
_context.next = 4;
break;
}
if (!e.__handled) {
_context.next = 5;
break;
}
return _context.abrupt("return");
return _context.abrupt("return");
case 4:
e.__handled = true;
Object.keys(apiRef.current.__fieldMetaRefs).forEach(function (key) {
var fieldMeta = apiRef.current.__fieldMetaRefs[key].current;
Object.keys(fieldMeta.instanceRefs).forEach(function (key) {
var fieldInstance = fieldMeta.instanceRefs[key].current;
case 5:
e.__handled = true; // Don't let invalid forms submit
if (fieldInstance.__validate && !fieldInstance.meta.isTouched) {
needTouchedAndValidation = true;
fieldInstance.setMeta({
isTouched: true
});
if (apiRef.current.meta.isValid) {
_context.next = 9;
break;
}
// If the form can't submit, let's trigger all of the fields
// to be touched. Thus, their validations will run
apiRef.current.setMeta({
isSubmitting: false
});
return _context.abrupt("return");
case 9:
apiRef.current.setMeta({
isSubmitting: true
});
needsResubmit = false;
fieldValidationPromises = [];
Object.keys(apiRef.current.__fieldMetaRefs).forEach(function (key) {
var fieldMeta = apiRef.current.__fieldMetaRefs[key].current;
Object.keys(fieldMeta.instanceRefs).forEach(function (key) {
var fieldInstance = fieldMeta.instanceRefs[key].current; // If any fields are not touched
if (!fieldInstance.meta.isTouched) {
// Mark them as touched
fieldInstance.setMeta({
isTouched: true
}); // Likewise, if they need validation
if (fieldInstance.__validate) {
// Run their validation and keep track of the
// promise
fieldValidationPromises.push(fieldInstance.runValidation());
}
});
}); // Don't let invalid forms submit
}
});
}); // If any validation needed to be run
if (!(!apiRef.current.meta.canSubmit || needTouchedAndValidation)) {
_context.next = 8;
break;
}
if (fieldValidationPromises.length) {
// Mark for resubmission
needsResubmit = true;
}
return _context.abrupt("return");
if (!apiRef.current.meta.isTouched) {
// Mark for resubmission
needsResubmit = true; // Mark the form as touched
case 8:
apiRef.current.setMeta(function (old) {
return _objectSpread({}, old, {
// Submission attempts make the form dirty
isTouched: true,
// Submittion attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1
isTouched: true
});
});
apiRef.current.setMeta({
isSubmitting: true
});
_context.prev = 10;
_context.next = 13;
return apiRef.current.onSubmit(apiRef.current.values, apiRef.current);
}
case 13:
apiRef.current.setMeta({
isSubmitted: true
});
_context.next = 19;
if (!needsResubmit) {
_context.next = 23;
break;
}
case 16:
_context.prev = 16;
_context.t0 = _context["catch"](10);
throw _context.t0;
_context.next = 18;
return Promise.all(fieldValidationPromises);
case 19:
_context.prev = 19;
apiRef.current.setMeta({
isSubmitting: false
case 18:
_context.next = 20;
return apiRef.current.runValidation();
case 20:
// Then rerun the submission attempt
e.__handled = false;
setShouldResubmit(e || true); // Do not continue
return _context.abrupt("return");
case 23:
apiRef.current.setMeta(function (old) {
return _objectSpread({}, old, {
// Submittion attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1
});
return _context.finish(19);
});
_context.prev = 24;
_context.next = 27;
return apiRef.current.onSubmit(apiRef.current.values, apiRef.current);
case 22:
case "end":
return _context.stop();
}
case 27:
apiRef.current.setMeta({
isSubmitted: true
});
_context.next = 33;
break;
case 30:
_context.prev = 30;
_context.t0 = _context["catch"](24);
throw _context.t0;
case 33:
_context.prev = 33;
apiRef.current.setMeta({
isSubmitting: false
});
return _context.finish(33);
case 36:
case "end":
return _context.stop();
}
}, _callee, null, [[10, 16, 19, 22]]);
}));
}
}, _callee, null, [[24, 30, 33, 36]]);
})), []); // Create a debounce for this field hook instance (not all instances)
return function (_x) {
return _ref2.apply(this, arguments);
};
}(), []); // Create a debounce for this field hook instance (not all instances)
var debounce = useAsyncDebounce();

@@ -473,65 +709,98 @@ var setMeta = React.useCallback(function (updater) {

}, [setState]);
var runValidation = React.useCallback(
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2() {
var id, checkLatest, error;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (validateRef.current) {
_context2.next = 2;
break;
}
var runValidation = React.useCallback(function () {
if (!metaRef.current.validate) {
return;
}
return _context2.abrupt("return");
apiRef.current.setMeta({
isValidating: true
}); // Use the validationCount for all field instances to
// track freshness of the validation
case 2:
apiRef.current.setMeta({
isValidating: true
}); // Use the validationCount for all field instances to
// track freshness of the validation
var id = (metaRef.current.validationCount || 0) + 1;
metaRef.current.validationCount = id;
id = (metaRef.current.validationCount || 0) + 1;
metaRef.current.validationCount = id;
var checkLatest = function checkLatest() {
return id === metaRef.current.validationCount;
};
checkLatest = function checkLatest() {
return id === metaRef.current.validationCount;
};
if (!metaRef.current.validationPromise) {
metaRef.current.validationPromise = new Promise(function (resolve, reject) {
metaRef.current.validationResolve = resolve;
metaRef.current.validationReject = reject;
});
}
_context2.next = 8;
return validateRef.current(apiRef.current.values, apiRef.current);
var doValidation =
/*#__PURE__*/
function () {
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2() {
var error;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
_context2.next = 3;
return metaRef.current.validate(apiRef.current.values, apiRef.current);
case 8:
error = _context2.sent;
case 3:
error = _context2.sent;
if (checkLatest()) {
apiRef.current.setMeta({
isValidating: false
});
if (checkLatest()) {
apiRef.current.setMeta({
isValidating: false
});
if (typeof error !== 'undefined') {
if (error) {
if (typeof error === 'string') {
apiRef.current.setMeta({
error: error
});
if (typeof error !== 'undefined') {
if (error) {
if (typeof error === 'string') {
apiRef.current.setMeta({
error: error
});
}
} else {
apiRef.current.setMeta({
error: null
});
}
}
} else {
apiRef.current.setMeta({
error: null
});
metaRef.current.validationResolve();
}
}
_context2.next = 10;
break;
case 7:
_context2.prev = 7;
_context2.t0 = _context2["catch"](0);
if (checkLatest()) {
metaRef.current.validationReject(_context2.t0);
}
case 10:
_context2.prev = 10;
delete metaRef.current.validationPromise;
return _context2.finish(10);
case 13:
case "end":
return _context2.stop();
}
}
}, _callee2, null, [[0, 7, 10, 13]]);
}));
case 10:
case "end":
return _context2.stop();
}
}
}, _callee2);
})), []);
return function doValidation() {
return _ref3.apply(this, arguments);
};
}();
doValidation();
return metaRef.current.validationPromise;
}, []);
var getFieldValue = React.useCallback(function (field) {

@@ -562,4 +831,10 @@ return getBy(apiRef.current.values, field);

setState(function (old) {
var newFieldMeta = typeof updater === 'function' ? updater(old.__fieldMeta[fieldID]) : _objectSpread({}, old.__fieldMeta[fieldID], updater);
return _objectSpread({}, old, {
__fieldMeta: _objectSpread({}, old.__fieldMeta, _defineProperty({}, fieldID, typeof updater === 'function' ? updater(old.__fieldMeta[fieldID]) : _objectSpread({}, old.__fieldMeta[fieldID], updater)))
// Any errors in fields should visually stop
// form.isSubmitting
meta: newFieldMeta && newFieldMeta.error ? _objectSpread({}, old.meta, {
isSubmitting: false
}) : old.meta,
__fieldMeta: _objectSpread({}, old.__fieldMeta, _defineProperty({}, fieldID, newFieldMeta))
});

@@ -607,7 +882,3 @@ });

apiRef.current.setFieldValue(field, function (old) {
if (Array.isArray(old)) {
return [].concat(_toConsumableArray(old), [value]);
} else {
throw Error("Cannot push a field value into a non-array field. Check that this field's existing value is an array: ".concat(field, "."));
}
return [].concat(_toConsumableArray(Array.isArray(old) ? old : []), [value]);
}, options);

@@ -678,3 +949,10 @@ }, []);

formContext: api
}); // When the form gets dirty and when the value changes
}); // If shouldResubmit is true, do yo thang
React.useEffect(function () {
if (shouldResubmit) {
handleSubmit(shouldResubmit);
setShouldResubmit(false);
}
}, [handleSubmit, shouldResubmit]); // When the form gets dirty and when the value changes
// validate

@@ -702,15 +980,21 @@

}
function useFormContext(manualFormContext) {
var formApi = React.useContext(formContext);
if (manualFormContext) {
return manualFormContext;
}
function useFieldScope(contextValue) {
var FieldScopeRef = React.useRef();
var FieldScopeApiRef = React.useRef();
FieldScopeApiRef.current = contextValue; // Create a new form element
if (!formApi) {
throw new Error("You are trying to use the form API outside of a form!");
if (!FieldScopeRef.current) {
FieldScopeRef.current = function Field(_ref) {
var children = _ref.children;
return React.createElement(FormContextProvider, {
value: FieldScopeApiRef.current
}, children);
};
}
return formApi;
return FieldScopeRef.current;
}
var uid = 0;
var methodMap = ['setFieldValue', 'setFieldMeta', 'pushFieldValue', 'insertFieldValue', 'removeFieldValue', 'swapFieldValues'];

@@ -723,14 +1007,14 @@ var defaultDefaultMeta = {

function useField(fieldName) {
var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
defaultValue = _ref5.defaultValue,
_ref5$defaultIsTouche = _ref5.defaultIsTouched,
defaultIsTouched = _ref5$defaultIsTouche === void 0 ? false : _ref5$defaultIsTouche,
_ref5$defaultError = _ref5.defaultError,
defaultError = _ref5$defaultError === void 0 ? null : _ref5$defaultError,
_ref5$defaultMeta = _ref5.defaultMeta,
defaultMeta = _ref5$defaultMeta === void 0 ? defaultDefaultMeta : _ref5$defaultMeta,
validatePristine = _ref5.validatePristine,
validate = _ref5.validate,
filterValue = _ref5.filterValue,
manualFormContext = _ref5.formContext;
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
defaultValue = _ref.defaultValue,
_ref$defaultIsTouched = _ref.defaultIsTouched,
defaultIsTouched = _ref$defaultIsTouched === void 0 ? false : _ref$defaultIsTouched,
_ref$defaultError = _ref.defaultError,
defaultError = _ref$defaultError === void 0 ? null : _ref$defaultError,
_ref$defaultMeta = _ref.defaultMeta,
defaultMeta = _ref$defaultMeta === void 0 ? defaultDefaultMeta : _ref$defaultMeta,
validatePristine = _ref.validatePristine,
validate = _ref.validate,
filterValue = _ref.filterValue,
manualFormContext = _ref.formContext;

@@ -841,14 +1125,14 @@ if (!fieldName) {

/*#__PURE__*/
regeneratorRuntime.mark(function _callee4() {
regeneratorRuntime.mark(function _callee2() {
var id, checkLatest, doValidate;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context4.prev = _context4.next) {
switch (_context2.prev = _context2.next) {
case 0:
if (fieldApiRef.current.__validate) {
_context4.next = 2;
_context2.next = 2;
break;
}
return _context4.abrupt("return");
return _context2.abrupt("return");

@@ -878,16 +1162,16 @@ case 2:

function () {
var _ref7 = _asyncToGenerator(
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee3() {
regeneratorRuntime.mark(function _callee() {
var error;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context3.prev = _context3.next) {
switch (_context.prev = _context.next) {
case 0:
_context3.prev = 0;
_context3.next = 3;
_context.prev = 0;
_context.next = 3;
return fieldApiRef.current.__validate(fieldApiRef.current.value, fieldApiRef.current);
case 3:
error = _context3.sent;
error = _context.sent;

@@ -916,20 +1200,20 @@ if (checkLatest()) {

_context3.next = 12;
_context.next = 12;
break;
case 7:
_context3.prev = 7;
_context3.t0 = _context3["catch"](0);
_context.prev = 7;
_context.t0 = _context["catch"](0);
if (!checkLatest()) {
_context3.next = 12;
_context.next = 12;
break;
}
__metaRef.current.validationReject(_context3.t0);
__metaRef.current.validationReject(_context.t0);
throw _context3.t0;
throw _context.t0;
case 12:
_context3.prev = 12;
_context.prev = 12;

@@ -943,14 +1227,14 @@ if (checkLatest()) {

return _context3.finish(12);
return _context.finish(12);
case 15:
case "end":
return _context3.stop();
return _context.stop();
}
}
}, _callee3, null, [[0, 7, 12, 15]]);
}, _callee, null, [[0, 7, 12, 15]]);
}));
return function doValidate() {
return _ref7.apply(this, arguments);
return _ref3.apply(this, arguments);
};

@@ -960,16 +1244,16 @@ }();

doValidate();
return _context4.abrupt("return", __metaRef.current.validationPromise);
return _context2.abrupt("return", __metaRef.current.validationPromise);
case 10:
case "end":
return _context4.stop();
return _context2.stop();
}
}
}, _callee4);
}, _callee2);
})), [__metaRef, setMeta]);
var getInputProps = React.useCallback(function () {
var _ref8 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_onChange = _ref8.onChange,
_onBlur = _ref8.onBlur,
rest = _objectWithoutProperties(_ref8, ["onChange", "onBlur"]);
var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_onChange = _ref4.onChange,
_onBlur = _ref4.onBlur,
rest = _objectWithoutProperties(_ref4, ["onChange", "onBlur"]);

@@ -1018,3 +1302,4 @@ return _objectSpread({

React.useEffect(function () {
var metaRef = __metaRef.current;
var fieldID = getFieldID(fieldName);
var metaRef = formApiRef.current.__fieldMetaRefs[fieldID].current;
metaRef.instanceRefs = metaRef.instanceRefs || {};

@@ -1024,4 +1309,11 @@ metaRef.instanceRefs[instanceID] = fieldApiRef;

delete metaRef.instanceRefs[instanceID];
if (!Object.keys(metaRef.instanceRefs).length) {
fieldApiRef.current.setMeta(function () {
return undefined;
});
delete formApiRef.current.__fieldMetaRefs[fieldID];
}
};
}, [__metaRef, fieldApiRef, instanceID]); // The default value effect handler
}, [fieldName, instanceID]); // The default value effect handler

@@ -1056,189 +1348,3 @@ React.useEffect(function () {

function useFormElement(contextValue) {
var FormRef = React.useRef();
var FormApiRef = React.useRef();
FormApiRef.current = contextValue; // Create a new form element
if (!FormRef.current) {
FormRef.current = function Form(_ref9) {
var children = _ref9.children,
noFormElement = _ref9.noFormElement,
rest = _objectWithoutProperties(_ref9, ["children", "noFormElement"]);
var _FormApiRef$current = FormApiRef.current,
handleSubmit = _FormApiRef$current.handleSubmit,
isSubmitting = _FormApiRef$current.meta.isSubmitting,
debugForm = _FormApiRef$current.debugForm;
return React.createElement(formContext.Provider, {
value: FormApiRef.current
}, noFormElement ? children : React.createElement("form", _extends({
onSubmit: handleSubmit,
disabled: isSubmitting
}, rest), children, debugForm ? React.createElement("div", {
style: {
margin: '2rem 0'
}
}, React.createElement("div", {
style: {
fontWeight: 'bolder'
}
}, "Form State"), React.createElement("pre", null, React.createElement("code", null, JSON.stringify(_objectSpread({}, FormApiRef.current, {
formContext: undefined
}), safeStringifyReplace(new Set()), 2)))) : null));
};
} // Return the form element
return FormRef.current;
}
function useFieldScope(contextValue) {
var FieldScopeRef = React.useRef();
var FieldScopeApiRef = React.useRef();
FieldScopeApiRef.current = contextValue; // Create a new form element
if (!FieldScopeRef.current) {
FieldScopeRef.current = function Field(_ref10) {
var children = _ref10.children;
return React.createElement(formContext.Provider, {
value: FieldScopeApiRef.current
}, children);
};
}
return FieldScopeRef.current;
}
function splitFormProps(_ref11) {
var field = _ref11.field,
defaultValue = _ref11.defaultValue,
defaultIsTouched = _ref11.defaultIsTouched,
defaultError = _ref11.defaultError,
defaultMeta = _ref11.defaultMeta,
validatePristine = _ref11.validatePristine,
validate = _ref11.validate,
onSubmit = _ref11.onSubmit,
defaultValues = _ref11.defaultValues,
filterValue = _ref11.filterValue,
debugForm = _ref11.debugForm,
rest = _objectWithoutProperties(_ref11, ["field", "defaultValue", "defaultIsTouched", "defaultError", "defaultMeta", "validatePristine", "validate", "onSubmit", "defaultValues", "filterValue", "debugForm"]);
return [field, {
defaultValue: defaultValue,
defaultIsTouched: defaultIsTouched,
defaultError: defaultError,
defaultMeta: defaultMeta,
validatePristine: validatePristine,
validate: validate,
onSubmit: onSubmit,
defaultValues: defaultValues,
filterValue: filterValue,
debugForm: debugForm
}, rest];
} // Utils
function getBy(obj, path) {
if (!path) {
throw new Error('A path string is required to use getBy');
}
var pathArray = makePathArray(path);
var pathObj = pathArray;
return pathObj.reduce(function (current, pathPart) {
if (typeof current !== 'undefined') {
return current[pathPart];
}
return undefined;
}, obj);
}
function setBy(obj, path, updater) {
path = makePathArray(path);
function doSet(parent) {
if (!path.length) {
return typeof updater === 'function' ? updater(parent) : updater;
}
var key = path.shift();
if (typeof key === 'string') {
if (_typeof(parent) === 'object') {
return _objectSpread({}, parent, _defineProperty({}, key, doSet(parent[key])));
}
return _defineProperty({}, key, doSet());
}
if (typeof key === 'number') {
if (Array.isArray(parent)) {
var prefix = parent.slice(0, key);
return [].concat(_toConsumableArray(prefix.length ? prefix : new Array(key)), [doSet(parent[key])], _toConsumableArray(parent.slice(key + 1)));
}
return [].concat(_toConsumableArray(new Array(key)), [doSet()]);
}
throw new Error('Uh oh!');
}
return doSet(obj);
}
function getFieldID(str) {
return makePathArray(str).join('_');
}
var reFindNumbers0 = /^(\d*)$/gm;
var reFindNumbers1 = /\.(\d*)\./gm;
var reFindNumbers2 = /^(\d*)\./gm;
var reFindNumbers3 = /\.(\d*$)/gm;
var reFindMultiplePeriods = /\.{2,}/gm;
function makePathArray(str) {
return str.replace('[', '').replace(']', '.').replace(reFindNumbers0, '__int__$1').replace(reFindNumbers1, '.__int__$1.').replace(reFindNumbers2, '__int__$1.').replace(reFindNumbers3, '.__int__$1').replace(reFindMultiplePeriods, '.').split('.').map(function (d) {
if (d.indexOf('__int__') === 0) {
return parseInt(d.substring('__int__'.length), 10);
}
return d;
});
}
function loopObject(obj, fn, callback) {
Object.keys(obj).forEach(function (key) {
callback(fn(obj[key], key), key);
});
}
function someObject(obj, fn) {
var found = false;
loopObject(obj, fn, function (result, key) {
if (found) {
return;
}
if (result) {
found = true;
}
});
return found;
}
function safeStringifyReplace(set) {
return function (key, value) {
if (_typeof(value) === 'object' || Array.isArray(value)) {
if (set.has(value)) {
return '(circular value)';
}
set.add(value);
}
return typeof value === 'function' ? undefined : value;
};
}
export { splitFormProps, useField, useForm, useFormContext };
//# sourceMappingURL=index.es.js.map

@@ -288,4 +288,190 @@ 'use strict';

var formContext = React.createContext();
function FormContextProvider(_ref) {
var value = _ref.value,
children = _ref.children;
return React.createElement(formContext.Provider, {
value: value
}, children);
}
function useFormContext(manualFormContext) {
var formApi = React.useContext(formContext);
if (manualFormContext) {
return manualFormContext;
}
if (!formApi) {
throw new Error("You are trying to use the form API outside of a form!");
}
return formApi;
}
function useFormElement(contextValue) {
var FormRef = React.useRef();
var FormApiRef = React.useRef();
FormApiRef.current = contextValue; // Create a new form element
if (!FormRef.current) {
FormRef.current = function Form(_ref) {
var children = _ref.children,
noFormElement = _ref.noFormElement,
rest = _objectWithoutProperties(_ref, ["children", "noFormElement"]);
var _FormApiRef$current = FormApiRef.current,
handleSubmit = _FormApiRef$current.handleSubmit,
isSubmitting = _FormApiRef$current.meta.isSubmitting,
debugForm = _FormApiRef$current.debugForm;
return React.createElement(FormContextProvider, {
value: FormApiRef.current
}, noFormElement ? children : React.createElement("form", _extends({
onSubmit: handleSubmit,
disabled: isSubmitting
}, rest), children, debugForm ? React.createElement("div", {
style: {
margin: '2rem 0'
}
}, React.createElement("div", {
style: {
fontWeight: 'bolder'
}
}, "Form State"), React.createElement("pre", null, React.createElement("code", null, JSON.stringify(_objectSpread({}, FormApiRef.current, {
formContext: undefined
}), safeStringifyReplace(new Set()), 2)))) : null));
};
} // Return the form element
return FormRef.current;
}
function safeStringifyReplace(set) {
return function (key, value) {
if (_typeof(value) === 'object' || Array.isArray(value)) {
if (set.has(value)) {
return '(circular value)';
}
set.add(value);
}
return typeof value === 'function' ? undefined : value;
};
}
function splitFormProps(_ref) {
var field = _ref.field,
defaultValue = _ref.defaultValue,
defaultIsTouched = _ref.defaultIsTouched,
defaultError = _ref.defaultError,
defaultMeta = _ref.defaultMeta,
validatePristine = _ref.validatePristine,
validate = _ref.validate,
onSubmit = _ref.onSubmit,
defaultValues = _ref.defaultValues,
filterValue = _ref.filterValue,
debugForm = _ref.debugForm,
rest = _objectWithoutProperties(_ref, ["field", "defaultValue", "defaultIsTouched", "defaultError", "defaultMeta", "validatePristine", "validate", "onSubmit", "defaultValues", "filterValue", "debugForm"]);
return [field, {
defaultValue: defaultValue,
defaultIsTouched: defaultIsTouched,
defaultError: defaultError,
defaultMeta: defaultMeta,
validatePristine: validatePristine,
validate: validate,
onSubmit: onSubmit,
defaultValues: defaultValues,
filterValue: filterValue,
debugForm: debugForm
}, rest];
} // Utils
function getBy(obj, path) {
if (!path) {
throw new Error('A path string is required to use getBy');
}
var pathArray = makePathArray(path);
var pathObj = pathArray;
return pathObj.reduce(function (current, pathPart) {
if (typeof current !== 'undefined') {
return current[pathPart];
}
return undefined;
}, obj);
}
function setBy(obj, path, updater) {
path = makePathArray(path);
function doSet(parent) {
if (!path.length) {
return typeof updater === 'function' ? updater(parent) : updater;
}
var key = path.shift();
if (typeof key === 'string') {
if (_typeof(parent) === 'object') {
return _objectSpread({}, parent, _defineProperty({}, key, doSet(parent[key])));
}
return _defineProperty({}, key, doSet());
}
if (typeof key === 'number') {
if (Array.isArray(parent)) {
var prefix = parent.slice(0, key);
return [].concat(_toConsumableArray(prefix.length ? prefix : new Array(key)), [doSet(parent[key])], _toConsumableArray(parent.slice(key + 1)));
}
return [].concat(_toConsumableArray(new Array(key)), [doSet()]);
}
throw new Error('Uh oh!');
}
return doSet(obj);
}
function getFieldID(str) {
return makePathArray(str).join('_');
}
var reFindNumbers0 = /^(\d*)$/gm;
var reFindNumbers1 = /\.(\d*)\./gm;
var reFindNumbers2 = /^(\d*)\./gm;
var reFindNumbers3 = /\.(\d*$)/gm;
var reFindMultiplePeriods = /\.{2,}/gm;
function makePathArray(str) {
return str.replace('[', '').replace(']', '.').replace(reFindNumbers0, '__int__$1').replace(reFindNumbers1, '.__int__$1.').replace(reFindNumbers2, '__int__$1.').replace(reFindNumbers3, '.__int__$1').replace(reFindMultiplePeriods, '.').split('.').map(function (d) {
if (d.indexOf('__int__') === 0) {
return parseInt(d.substring('__int__'.length), 10);
}
return d;
});
}
function loopObject(obj, fn, callback) {
Object.keys(obj).forEach(function (key) {
callback(fn(obj[key], key), key);
});
}
function someObject(obj, fn) {
var found = false;
loopObject(obj, fn, function (result, key) {
if (found) {
return;
}
if (result) {
found = true;
}
});
return found;
}
var defaultDefaultValue = {};
var uid = 0;

@@ -328,18 +514,22 @@ function makeState(decor) {

var _React$useState3 = React.useState(false),
_React$useState4 = _slicedToArray(_React$useState3, 2),
shouldResubmit = _React$useState4[0],
setShouldResubmit = _React$useState4[1];
var apiRef = React.useRef();
var metaRef = React.useRef({});
var __fieldMetaRefsRef = React.useRef({});
var __fieldMetaRefsRef = React.useRef({}); // Keep validate up to date with the latest version
var validateRef = React.useRef(); // Keep validate up to date with the latest version
validateRef.current = validate;
var allFieldsTouched = !someObject(__fieldMeta, function (field) {
return field && !field.isTouched;
metaRef.current.validate = validate;
var fieldsAreValidating = someObject(__fieldMeta, function (field) {
return field && field.isValidating;
});
var allFieldsValid = !someObject(__fieldMeta, function (field) {
var fieldsAreValid = !someObject(__fieldMeta, function (field) {
return field && field.error;
}); // Can we submit this form?
var isValid = isTouched && allFieldsValid && !meta.error;
var isValid = !fieldsAreValidating && fieldsAreValid && !meta.error;
var canSubmit = isValid && !isSubmitting; // Decorate form meta

@@ -349,8 +539,8 @@

return _objectSpread({}, meta, {
fieldsAreValidating: fieldsAreValidating,
fieldsAreValid: fieldsAreValid,
isValid: isValid,
canSubmit: canSubmit,
allFieldsTouched: allFieldsTouched,
allFieldsValid: allFieldsValid
canSubmit: canSubmit
});
}, [meta, isValid, canSubmit, allFieldsTouched, allFieldsValid]); // We want the apiRef to change every time state updates
}, [meta, fieldsAreValidating, fieldsAreValid, isValid, canSubmit]); // We want the apiRef to change every time state updates

@@ -377,95 +567,141 @@ var api = React.useMemo(function () {

/*#__PURE__*/
function () {
var _ref2 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(e) {
var needTouchedAndValidation;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
e.persist();
e.preventDefault(); // This lets sub-forms with form elements (despite them being invalid HTML)
// handle submissions without triggering parent forms
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee() {
var e,
needsResubmit,
fieldValidationPromises,
_args = arguments;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
e = _args.length > 0 && _args[0] !== undefined ? _args[0] : {};
if (e.persist) e.persist();
if (e.preventDefault) e.preventDefault(); // This lets sub-forms with form elements (despite them being invalid HTML)
// handle submissions without triggering parent forms
if (!e.__handled) {
_context.next = 4;
break;
}
if (!e.__handled) {
_context.next = 5;
break;
}
return _context.abrupt("return");
return _context.abrupt("return");
case 4:
e.__handled = true;
Object.keys(apiRef.current.__fieldMetaRefs).forEach(function (key) {
var fieldMeta = apiRef.current.__fieldMetaRefs[key].current;
Object.keys(fieldMeta.instanceRefs).forEach(function (key) {
var fieldInstance = fieldMeta.instanceRefs[key].current;
case 5:
e.__handled = true; // Don't let invalid forms submit
if (fieldInstance.__validate && !fieldInstance.meta.isTouched) {
needTouchedAndValidation = true;
fieldInstance.setMeta({
isTouched: true
});
if (apiRef.current.meta.isValid) {
_context.next = 9;
break;
}
// If the form can't submit, let's trigger all of the fields
// to be touched. Thus, their validations will run
apiRef.current.setMeta({
isSubmitting: false
});
return _context.abrupt("return");
case 9:
apiRef.current.setMeta({
isSubmitting: true
});
needsResubmit = false;
fieldValidationPromises = [];
Object.keys(apiRef.current.__fieldMetaRefs).forEach(function (key) {
var fieldMeta = apiRef.current.__fieldMetaRefs[key].current;
Object.keys(fieldMeta.instanceRefs).forEach(function (key) {
var fieldInstance = fieldMeta.instanceRefs[key].current; // If any fields are not touched
if (!fieldInstance.meta.isTouched) {
// Mark them as touched
fieldInstance.setMeta({
isTouched: true
}); // Likewise, if they need validation
if (fieldInstance.__validate) {
// Run their validation and keep track of the
// promise
fieldValidationPromises.push(fieldInstance.runValidation());
}
});
}); // Don't let invalid forms submit
}
});
}); // If any validation needed to be run
if (!(!apiRef.current.meta.canSubmit || needTouchedAndValidation)) {
_context.next = 8;
break;
}
if (fieldValidationPromises.length) {
// Mark for resubmission
needsResubmit = true;
}
return _context.abrupt("return");
if (!apiRef.current.meta.isTouched) {
// Mark for resubmission
needsResubmit = true; // Mark the form as touched
case 8:
apiRef.current.setMeta(function (old) {
return _objectSpread({}, old, {
// Submission attempts make the form dirty
isTouched: true,
// Submittion attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1
isTouched: true
});
});
apiRef.current.setMeta({
isSubmitting: true
});
_context.prev = 10;
_context.next = 13;
return apiRef.current.onSubmit(apiRef.current.values, apiRef.current);
}
case 13:
apiRef.current.setMeta({
isSubmitted: true
});
_context.next = 19;
if (!needsResubmit) {
_context.next = 23;
break;
}
case 16:
_context.prev = 16;
_context.t0 = _context["catch"](10);
throw _context.t0;
_context.next = 18;
return Promise.all(fieldValidationPromises);
case 19:
_context.prev = 19;
apiRef.current.setMeta({
isSubmitting: false
case 18:
_context.next = 20;
return apiRef.current.runValidation();
case 20:
// Then rerun the submission attempt
e.__handled = false;
setShouldResubmit(e || true); // Do not continue
return _context.abrupt("return");
case 23:
apiRef.current.setMeta(function (old) {
return _objectSpread({}, old, {
// Submittion attempts mark the form as not submitted
isSubmitted: false,
// Count submission attempts
submissionAttempts: old.submissionAttempts + 1
});
return _context.finish(19);
});
_context.prev = 24;
_context.next = 27;
return apiRef.current.onSubmit(apiRef.current.values, apiRef.current);
case 22:
case "end":
return _context.stop();
}
case 27:
apiRef.current.setMeta({
isSubmitted: true
});
_context.next = 33;
break;
case 30:
_context.prev = 30;
_context.t0 = _context["catch"](24);
throw _context.t0;
case 33:
_context.prev = 33;
apiRef.current.setMeta({
isSubmitting: false
});
return _context.finish(33);
case 36:
case "end":
return _context.stop();
}
}, _callee, null, [[10, 16, 19, 22]]);
}));
}
}, _callee, null, [[24, 30, 33, 36]]);
})), []); // Create a debounce for this field hook instance (not all instances)
return function (_x) {
return _ref2.apply(this, arguments);
};
}(), []); // Create a debounce for this field hook instance (not all instances)
var debounce = useAsyncDebounce();

@@ -479,65 +715,98 @@ var setMeta = React.useCallback(function (updater) {

}, [setState]);
var runValidation = React.useCallback(
/*#__PURE__*/
_asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2() {
var id, checkLatest, error;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (validateRef.current) {
_context2.next = 2;
break;
}
var runValidation = React.useCallback(function () {
if (!metaRef.current.validate) {
return;
}
return _context2.abrupt("return");
apiRef.current.setMeta({
isValidating: true
}); // Use the validationCount for all field instances to
// track freshness of the validation
case 2:
apiRef.current.setMeta({
isValidating: true
}); // Use the validationCount for all field instances to
// track freshness of the validation
var id = (metaRef.current.validationCount || 0) + 1;
metaRef.current.validationCount = id;
id = (metaRef.current.validationCount || 0) + 1;
metaRef.current.validationCount = id;
var checkLatest = function checkLatest() {
return id === metaRef.current.validationCount;
};
checkLatest = function checkLatest() {
return id === metaRef.current.validationCount;
};
if (!metaRef.current.validationPromise) {
metaRef.current.validationPromise = new Promise(function (resolve, reject) {
metaRef.current.validationResolve = resolve;
metaRef.current.validationReject = reject;
});
}
_context2.next = 8;
return validateRef.current(apiRef.current.values, apiRef.current);
var doValidation =
/*#__PURE__*/
function () {
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee2() {
var error;
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
_context2.next = 3;
return metaRef.current.validate(apiRef.current.values, apiRef.current);
case 8:
error = _context2.sent;
case 3:
error = _context2.sent;
if (checkLatest()) {
apiRef.current.setMeta({
isValidating: false
});
if (checkLatest()) {
apiRef.current.setMeta({
isValidating: false
});
if (typeof error !== 'undefined') {
if (error) {
if (typeof error === 'string') {
apiRef.current.setMeta({
error: error
});
if (typeof error !== 'undefined') {
if (error) {
if (typeof error === 'string') {
apiRef.current.setMeta({
error: error
});
}
} else {
apiRef.current.setMeta({
error: null
});
}
}
} else {
apiRef.current.setMeta({
error: null
});
metaRef.current.validationResolve();
}
}
_context2.next = 10;
break;
case 7:
_context2.prev = 7;
_context2.t0 = _context2["catch"](0);
if (checkLatest()) {
metaRef.current.validationReject(_context2.t0);
}
case 10:
_context2.prev = 10;
delete metaRef.current.validationPromise;
return _context2.finish(10);
case 13:
case "end":
return _context2.stop();
}
}
}, _callee2, null, [[0, 7, 10, 13]]);
}));
case 10:
case "end":
return _context2.stop();
}
}
}, _callee2);
})), []);
return function doValidation() {
return _ref3.apply(this, arguments);
};
}();
doValidation();
return metaRef.current.validationPromise;
}, []);
var getFieldValue = React.useCallback(function (field) {

@@ -568,4 +837,10 @@ return getBy(apiRef.current.values, field);

setState(function (old) {
var newFieldMeta = typeof updater === 'function' ? updater(old.__fieldMeta[fieldID]) : _objectSpread({}, old.__fieldMeta[fieldID], updater);
return _objectSpread({}, old, {
__fieldMeta: _objectSpread({}, old.__fieldMeta, _defineProperty({}, fieldID, typeof updater === 'function' ? updater(old.__fieldMeta[fieldID]) : _objectSpread({}, old.__fieldMeta[fieldID], updater)))
// Any errors in fields should visually stop
// form.isSubmitting
meta: newFieldMeta && newFieldMeta.error ? _objectSpread({}, old.meta, {
isSubmitting: false
}) : old.meta,
__fieldMeta: _objectSpread({}, old.__fieldMeta, _defineProperty({}, fieldID, newFieldMeta))
});

@@ -613,7 +888,3 @@ });

apiRef.current.setFieldValue(field, function (old) {
if (Array.isArray(old)) {
return [].concat(_toConsumableArray(old), [value]);
} else {
throw Error("Cannot push a field value into a non-array field. Check that this field's existing value is an array: ".concat(field, "."));
}
return [].concat(_toConsumableArray(Array.isArray(old) ? old : []), [value]);
}, options);

@@ -684,3 +955,10 @@ }, []);

formContext: api
}); // When the form gets dirty and when the value changes
}); // If shouldResubmit is true, do yo thang
React.useEffect(function () {
if (shouldResubmit) {
handleSubmit(shouldResubmit);
setShouldResubmit(false);
}
}, [handleSubmit, shouldResubmit]); // When the form gets dirty and when the value changes
// validate

@@ -708,15 +986,21 @@

}
function useFormContext(manualFormContext) {
var formApi = React.useContext(formContext);
if (manualFormContext) {
return manualFormContext;
}
function useFieldScope(contextValue) {
var FieldScopeRef = React.useRef();
var FieldScopeApiRef = React.useRef();
FieldScopeApiRef.current = contextValue; // Create a new form element
if (!formApi) {
throw new Error("You are trying to use the form API outside of a form!");
if (!FieldScopeRef.current) {
FieldScopeRef.current = function Field(_ref) {
var children = _ref.children;
return React.createElement(FormContextProvider, {
value: FieldScopeApiRef.current
}, children);
};
}
return formApi;
return FieldScopeRef.current;
}
var uid = 0;
var methodMap = ['setFieldValue', 'setFieldMeta', 'pushFieldValue', 'insertFieldValue', 'removeFieldValue', 'swapFieldValues'];

@@ -729,14 +1013,14 @@ var defaultDefaultMeta = {

function useField(fieldName) {
var _ref5 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
defaultValue = _ref5.defaultValue,
_ref5$defaultIsTouche = _ref5.defaultIsTouched,
defaultIsTouched = _ref5$defaultIsTouche === void 0 ? false : _ref5$defaultIsTouche,
_ref5$defaultError = _ref5.defaultError,
defaultError = _ref5$defaultError === void 0 ? null : _ref5$defaultError,
_ref5$defaultMeta = _ref5.defaultMeta,
defaultMeta = _ref5$defaultMeta === void 0 ? defaultDefaultMeta : _ref5$defaultMeta,
validatePristine = _ref5.validatePristine,
validate = _ref5.validate,
filterValue = _ref5.filterValue,
manualFormContext = _ref5.formContext;
var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
defaultValue = _ref.defaultValue,
_ref$defaultIsTouched = _ref.defaultIsTouched,
defaultIsTouched = _ref$defaultIsTouched === void 0 ? false : _ref$defaultIsTouched,
_ref$defaultError = _ref.defaultError,
defaultError = _ref$defaultError === void 0 ? null : _ref$defaultError,
_ref$defaultMeta = _ref.defaultMeta,
defaultMeta = _ref$defaultMeta === void 0 ? defaultDefaultMeta : _ref$defaultMeta,
validatePristine = _ref.validatePristine,
validate = _ref.validate,
filterValue = _ref.filterValue,
manualFormContext = _ref.formContext;

@@ -847,14 +1131,14 @@ if (!fieldName) {

/*#__PURE__*/
regeneratorRuntime.mark(function _callee4() {
regeneratorRuntime.mark(function _callee2() {
var id, checkLatest, doValidate;
return regeneratorRuntime.wrap(function _callee4$(_context4) {
return regeneratorRuntime.wrap(function _callee2$(_context2) {
while (1) {
switch (_context4.prev = _context4.next) {
switch (_context2.prev = _context2.next) {
case 0:
if (fieldApiRef.current.__validate) {
_context4.next = 2;
_context2.next = 2;
break;
}
return _context4.abrupt("return");
return _context2.abrupt("return");

@@ -884,16 +1168,16 @@ case 2:

function () {
var _ref7 = _asyncToGenerator(
var _ref3 = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee3() {
regeneratorRuntime.mark(function _callee() {
var error;
return regeneratorRuntime.wrap(function _callee3$(_context3) {
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context3.prev = _context3.next) {
switch (_context.prev = _context.next) {
case 0:
_context3.prev = 0;
_context3.next = 3;
_context.prev = 0;
_context.next = 3;
return fieldApiRef.current.__validate(fieldApiRef.current.value, fieldApiRef.current);
case 3:
error = _context3.sent;
error = _context.sent;

@@ -922,20 +1206,20 @@ if (checkLatest()) {

_context3.next = 12;
_context.next = 12;
break;
case 7:
_context3.prev = 7;
_context3.t0 = _context3["catch"](0);
_context.prev = 7;
_context.t0 = _context["catch"](0);
if (!checkLatest()) {
_context3.next = 12;
_context.next = 12;
break;
}
__metaRef.current.validationReject(_context3.t0);
__metaRef.current.validationReject(_context.t0);
throw _context3.t0;
throw _context.t0;
case 12:
_context3.prev = 12;
_context.prev = 12;

@@ -949,14 +1233,14 @@ if (checkLatest()) {

return _context3.finish(12);
return _context.finish(12);
case 15:
case "end":
return _context3.stop();
return _context.stop();
}
}
}, _callee3, null, [[0, 7, 12, 15]]);
}, _callee, null, [[0, 7, 12, 15]]);
}));
return function doValidate() {
return _ref7.apply(this, arguments);
return _ref3.apply(this, arguments);
};

@@ -966,16 +1250,16 @@ }();

doValidate();
return _context4.abrupt("return", __metaRef.current.validationPromise);
return _context2.abrupt("return", __metaRef.current.validationPromise);
case 10:
case "end":
return _context4.stop();
return _context2.stop();
}
}
}, _callee4);
}, _callee2);
})), [__metaRef, setMeta]);
var getInputProps = React.useCallback(function () {
var _ref8 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_onChange = _ref8.onChange,
_onBlur = _ref8.onBlur,
rest = _objectWithoutProperties(_ref8, ["onChange", "onBlur"]);
var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
_onChange = _ref4.onChange,
_onBlur = _ref4.onBlur,
rest = _objectWithoutProperties(_ref4, ["onChange", "onBlur"]);

@@ -1024,3 +1308,4 @@ return _objectSpread({

React.useEffect(function () {
var metaRef = __metaRef.current;
var fieldID = getFieldID(fieldName);
var metaRef = formApiRef.current.__fieldMetaRefs[fieldID].current;
metaRef.instanceRefs = metaRef.instanceRefs || {};

@@ -1030,4 +1315,11 @@ metaRef.instanceRefs[instanceID] = fieldApiRef;

delete metaRef.instanceRefs[instanceID];
if (!Object.keys(metaRef.instanceRefs).length) {
fieldApiRef.current.setMeta(function () {
return undefined;
});
delete formApiRef.current.__fieldMetaRefs[fieldID];
}
};
}, [__metaRef, fieldApiRef, instanceID]); // The default value effect handler
}, [fieldName, instanceID]); // The default value effect handler

@@ -1062,188 +1354,2 @@ React.useEffect(function () {

function useFormElement(contextValue) {
var FormRef = React.useRef();
var FormApiRef = React.useRef();
FormApiRef.current = contextValue; // Create a new form element
if (!FormRef.current) {
FormRef.current = function Form(_ref9) {
var children = _ref9.children,
noFormElement = _ref9.noFormElement,
rest = _objectWithoutProperties(_ref9, ["children", "noFormElement"]);
var _FormApiRef$current = FormApiRef.current,
handleSubmit = _FormApiRef$current.handleSubmit,
isSubmitting = _FormApiRef$current.meta.isSubmitting,
debugForm = _FormApiRef$current.debugForm;
return React.createElement(formContext.Provider, {
value: FormApiRef.current
}, noFormElement ? children : React.createElement("form", _extends({
onSubmit: handleSubmit,
disabled: isSubmitting
}, rest), children, debugForm ? React.createElement("div", {
style: {
margin: '2rem 0'
}
}, React.createElement("div", {
style: {
fontWeight: 'bolder'
}
}, "Form State"), React.createElement("pre", null, React.createElement("code", null, JSON.stringify(_objectSpread({}, FormApiRef.current, {
formContext: undefined
}), safeStringifyReplace(new Set()), 2)))) : null));
};
} // Return the form element
return FormRef.current;
}
function useFieldScope(contextValue) {
var FieldScopeRef = React.useRef();
var FieldScopeApiRef = React.useRef();
FieldScopeApiRef.current = contextValue; // Create a new form element
if (!FieldScopeRef.current) {
FieldScopeRef.current = function Field(_ref10) {
var children = _ref10.children;
return React.createElement(formContext.Provider, {
value: FieldScopeApiRef.current
}, children);
};
}
return FieldScopeRef.current;
}
function splitFormProps(_ref11) {
var field = _ref11.field,
defaultValue = _ref11.defaultValue,
defaultIsTouched = _ref11.defaultIsTouched,
defaultError = _ref11.defaultError,
defaultMeta = _ref11.defaultMeta,
validatePristine = _ref11.validatePristine,
validate = _ref11.validate,
onSubmit = _ref11.onSubmit,
defaultValues = _ref11.defaultValues,
filterValue = _ref11.filterValue,
debugForm = _ref11.debugForm,
rest = _objectWithoutProperties(_ref11, ["field", "defaultValue", "defaultIsTouched", "defaultError", "defaultMeta", "validatePristine", "validate", "onSubmit", "defaultValues", "filterValue", "debugForm"]);
return [field, {
defaultValue: defaultValue,
defaultIsTouched: defaultIsTouched,
defaultError: defaultError,
defaultMeta: defaultMeta,
validatePristine: validatePristine,
validate: validate,
onSubmit: onSubmit,
defaultValues: defaultValues,
filterValue: filterValue,
debugForm: debugForm
}, rest];
} // Utils
function getBy(obj, path) {
if (!path) {
throw new Error('A path string is required to use getBy');
}
var pathArray = makePathArray(path);
var pathObj = pathArray;
return pathObj.reduce(function (current, pathPart) {
if (typeof current !== 'undefined') {
return current[pathPart];
}
return undefined;
}, obj);
}
function setBy(obj, path, updater) {
path = makePathArray(path);
function doSet(parent) {
if (!path.length) {
return typeof updater === 'function' ? updater(parent) : updater;
}
var key = path.shift();
if (typeof key === 'string') {
if (_typeof(parent) === 'object') {
return _objectSpread({}, parent, _defineProperty({}, key, doSet(parent[key])));
}
return _defineProperty({}, key, doSet());
}
if (typeof key === 'number') {
if (Array.isArray(parent)) {
var prefix = parent.slice(0, key);
return [].concat(_toConsumableArray(prefix.length ? prefix : new Array(key)), [doSet(parent[key])], _toConsumableArray(parent.slice(key + 1)));
}
return [].concat(_toConsumableArray(new Array(key)), [doSet()]);
}
throw new Error('Uh oh!');
}
return doSet(obj);
}
function getFieldID(str) {
return makePathArray(str).join('_');
}
var reFindNumbers0 = /^(\d*)$/gm;
var reFindNumbers1 = /\.(\d*)\./gm;
var reFindNumbers2 = /^(\d*)\./gm;
var reFindNumbers3 = /\.(\d*$)/gm;
var reFindMultiplePeriods = /\.{2,}/gm;
function makePathArray(str) {
return str.replace('[', '').replace(']', '.').replace(reFindNumbers0, '__int__$1').replace(reFindNumbers1, '.__int__$1.').replace(reFindNumbers2, '__int__$1.').replace(reFindNumbers3, '.__int__$1').replace(reFindMultiplePeriods, '.').split('.').map(function (d) {
if (d.indexOf('__int__') === 0) {
return parseInt(d.substring('__int__'.length), 10);
}
return d;
});
}
function loopObject(obj, fn, callback) {
Object.keys(obj).forEach(function (key) {
callback(fn(obj[key], key), key);
});
}
function someObject(obj, fn) {
var found = false;
loopObject(obj, fn, function (result, key) {
if (found) {
return;
}
if (result) {
found = true;
}
});
return found;
}
function safeStringifyReplace(set) {
return function (key, value) {
if (_typeof(value) === 'object' || Array.isArray(value)) {
if (set.has(value)) {
return '(circular value)';
}
set.add(value);
}
return typeof value === 'function' ? undefined : value;
};
}
exports.splitFormProps = splitFormProps;

@@ -1250,0 +1356,0 @@ exports.useField = useField;

{
"name": "react-form",
"version": "4.0.0-alpha.11",
"version": "4.0.0-alpha.12",
"description": "⚛️ 💼 React hooks for managing form state and lifecycle",

@@ -5,0 +5,0 @@ "author": "tannerlinsley",

@@ -28,3 +28,3 @@ # ⚛️ 💼 React Form

- Highly practical validation API with 1st-class asynchronous support
- Built-in validation debouncing with auto cancellation for stale promises
- Built-in validation debouncing with auto cancellation for stale validations
- Field Scoping for deeply nested form values

@@ -406,2 +406,47 @@ - No nonsense meta management for both forms and form fields

Validation in React Form supports validation both individual fields and the entire form.
A form submission can be attempted when either:
- The form has not been touched `!instance.meta.isTouched`
**OR**
- All fields **with a validation option**
- Have been touched (`field.meta.isTouched`)
- Are not validating (`!field.meta.isValidating`)
- Do not have an error (`field.meta.error`)
- The form has been touched `instance.meta.isTouched`
- The form is not validating `!instance.meta.isValidating`
- The form does not have an error `instance.meta.error`
To simplify handling this state, the following additional booleans are available on the `instance.meta`:
- `instance.meta.fieldsAreValidating`
- Will be `true` if there are any fields validating
- `instance.meta.fieldsAreValid`
- Will be `true` if there are no fields with an error (`field.meta.error`)
- `instance.meta.isValid`
- Will be `true` if every field is valid and there is no form error (`allFieldsValid && !meta.error`)
- `instance.meta.canSubmit`
- Will be `true` if the form is valid and not in the middle of a submission attempt (`instance.meta.isValid && !instance.meta.isSubmitting`)
### Submission Attempt Flow
Every time a submission attempt is made, the following submission flow will takes place:
- If there are fields that have not been touched or the form has not been touched:
- All fields will be touched (`field.meta.isTouched === true`)
- The form is touched (`instance.meta.isTouched === true`)
- All fields with a `validate` option that have not been touched will be validated
- If the form `validate` option is set and has not been touched, the form will be validated
- The submission attempt will wait for any field and form validations to resolve
- If any field validations or the form validation throw a runtime error
- The submission attempt will abort 🛑
- Once all validations settle
- A new submission will be attempted with the new post-validation state 🔁
- If there are any field or form validation(s) errors
- The current submission will abort 🛑
- The form's `onSubmit` function will be called
### Synchronous Validation

@@ -408,0 +453,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc