mirror of
https://github.com/idanoo/GoScrobble.git
synced 2024-11-23 00:45:16 +00:00
1984 lines
67 KiB
JavaScript
1984 lines
67 KiB
JavaScript
|
import { Children, createContext, useContext, useRef, useEffect, useReducer, useCallback, useMemo, useImperativeHandle, createElement, useLayoutEffect, forwardRef, Component } from 'react';
|
||
|
import isEqual from 'react-fast-compare';
|
||
|
import deepmerge from 'deepmerge';
|
||
|
import isPlainObject from 'lodash-es/isPlainObject';
|
||
|
import clone from 'lodash-es/clone';
|
||
|
import toPath from 'lodash-es/toPath';
|
||
|
import invariant from 'tiny-warning';
|
||
|
import hoistNonReactStatics from 'hoist-non-react-statics';
|
||
|
import cloneDeep from 'lodash-es/cloneDeep';
|
||
|
|
||
|
function _extends() {
|
||
|
_extends = Object.assign || function (target) {
|
||
|
for (var i = 1; i < arguments.length; i++) {
|
||
|
var source = arguments[i];
|
||
|
|
||
|
for (var key in source) {
|
||
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||
|
target[key] = source[key];
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return target;
|
||
|
};
|
||
|
|
||
|
return _extends.apply(this, arguments);
|
||
|
}
|
||
|
|
||
|
function _inheritsLoose(subClass, superClass) {
|
||
|
subClass.prototype = Object.create(superClass.prototype);
|
||
|
subClass.prototype.constructor = subClass;
|
||
|
subClass.__proto__ = superClass;
|
||
|
}
|
||
|
|
||
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
||
|
if (source == null) return {};
|
||
|
var target = {};
|
||
|
var sourceKeys = Object.keys(source);
|
||
|
var key, i;
|
||
|
|
||
|
for (i = 0; i < sourceKeys.length; i++) {
|
||
|
key = sourceKeys[i];
|
||
|
if (excluded.indexOf(key) >= 0) continue;
|
||
|
target[key] = source[key];
|
||
|
}
|
||
|
|
||
|
return target;
|
||
|
}
|
||
|
|
||
|
function _assertThisInitialized(self) {
|
||
|
if (self === void 0) {
|
||
|
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
|
||
|
}
|
||
|
|
||
|
return self;
|
||
|
}
|
||
|
|
||
|
/** @private is the value an empty array? */
|
||
|
|
||
|
var isEmptyArray = function isEmptyArray(value) {
|
||
|
return Array.isArray(value) && value.length === 0;
|
||
|
};
|
||
|
/** @private is the given object a Function? */
|
||
|
|
||
|
var isFunction = function isFunction(obj) {
|
||
|
return typeof obj === 'function';
|
||
|
};
|
||
|
/** @private is the given object an Object? */
|
||
|
|
||
|
var isObject = function isObject(obj) {
|
||
|
return obj !== null && typeof obj === 'object';
|
||
|
};
|
||
|
/** @private is the given object an integer? */
|
||
|
|
||
|
var isInteger = function isInteger(obj) {
|
||
|
return String(Math.floor(Number(obj))) === obj;
|
||
|
};
|
||
|
/** @private is the given object a string? */
|
||
|
|
||
|
var isString = function isString(obj) {
|
||
|
return Object.prototype.toString.call(obj) === '[object String]';
|
||
|
};
|
||
|
/** @private is the given object a NaN? */
|
||
|
// eslint-disable-next-line no-self-compare
|
||
|
|
||
|
var isNaN$1 = function isNaN(obj) {
|
||
|
return obj !== obj;
|
||
|
};
|
||
|
/** @private Does a React component have exactly 0 children? */
|
||
|
|
||
|
var isEmptyChildren = function isEmptyChildren(children) {
|
||
|
return Children.count(children) === 0;
|
||
|
};
|
||
|
/** @private is the given object/value a promise? */
|
||
|
|
||
|
var isPromise = function isPromise(value) {
|
||
|
return isObject(value) && isFunction(value.then);
|
||
|
};
|
||
|
/** @private is the given object/value a type of synthetic event? */
|
||
|
|
||
|
var isInputEvent = function isInputEvent(value) {
|
||
|
return value && isObject(value) && isObject(value.target);
|
||
|
};
|
||
|
/**
|
||
|
* Same as document.activeElement but wraps in a try-catch block. In IE it is
|
||
|
* not safe to call document.activeElement if there is nothing focused.
|
||
|
*
|
||
|
* The activeElement will be null only if the document or document body is not
|
||
|
* yet defined.
|
||
|
*
|
||
|
* @param {?Document} doc Defaults to current document.
|
||
|
* @return {Element | null}
|
||
|
* @see https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js
|
||
|
*/
|
||
|
|
||
|
function getActiveElement(doc) {
|
||
|
doc = doc || (typeof document !== 'undefined' ? document : undefined);
|
||
|
|
||
|
if (typeof doc === 'undefined') {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
return doc.activeElement || doc.body;
|
||
|
} catch (e) {
|
||
|
return doc.body;
|
||
|
}
|
||
|
}
|
||
|
/**
|
||
|
* Deeply get a value from an object via its path.
|
||
|
*/
|
||
|
|
||
|
function getIn(obj, key, def, p) {
|
||
|
if (p === void 0) {
|
||
|
p = 0;
|
||
|
}
|
||
|
|
||
|
var path = toPath(key);
|
||
|
|
||
|
while (obj && p < path.length) {
|
||
|
obj = obj[path[p++]];
|
||
|
}
|
||
|
|
||
|
return obj === undefined ? def : obj;
|
||
|
}
|
||
|
/**
|
||
|
* Deeply set a value from in object via it's path. If the value at `path`
|
||
|
* has changed, return a shallow copy of obj with `value` set at `path`.
|
||
|
* If `value` has not changed, return the original `obj`.
|
||
|
*
|
||
|
* Existing objects / arrays along `path` are also shallow copied. Sibling
|
||
|
* objects along path retain the same internal js reference. Since new
|
||
|
* objects / arrays are only created along `path`, we can test if anything
|
||
|
* changed in a nested structure by comparing the object's reference in
|
||
|
* the old and new object, similar to how russian doll cache invalidation
|
||
|
* works.
|
||
|
*
|
||
|
* In earlier versions of this function, which used cloneDeep, there were
|
||
|
* issues whereby settings a nested value would mutate the parent
|
||
|
* instead of creating a new object. `clone` avoids that bug making a
|
||
|
* shallow copy of the objects along the update path
|
||
|
* so no object is mutated in place.
|
||
|
*
|
||
|
* Before changing this function, please read through the following
|
||
|
* discussions.
|
||
|
*
|
||
|
* @see https://github.com/developit/linkstate
|
||
|
* @see https://github.com/jaredpalmer/formik/pull/123
|
||
|
*/
|
||
|
|
||
|
function setIn(obj, path, value) {
|
||
|
var res = clone(obj); // this keeps inheritance when obj is a class
|
||
|
|
||
|
var resVal = res;
|
||
|
var i = 0;
|
||
|
var pathArray = toPath(path);
|
||
|
|
||
|
for (; i < pathArray.length - 1; i++) {
|
||
|
var currentPath = pathArray[i];
|
||
|
var currentObj = getIn(obj, pathArray.slice(0, i + 1));
|
||
|
|
||
|
if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {
|
||
|
resVal = resVal[currentPath] = clone(currentObj);
|
||
|
} else {
|
||
|
var nextPath = pathArray[i + 1];
|
||
|
resVal = resVal[currentPath] = isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};
|
||
|
}
|
||
|
} // Return original object if new value is the same as current
|
||
|
|
||
|
|
||
|
if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {
|
||
|
return obj;
|
||
|
}
|
||
|
|
||
|
if (value === undefined) {
|
||
|
delete resVal[pathArray[i]];
|
||
|
} else {
|
||
|
resVal[pathArray[i]] = value;
|
||
|
} // If the path array has a single element, the loop did not run.
|
||
|
// Deleting on `resVal` had no effect in this scenario, so we delete on the result instead.
|
||
|
|
||
|
|
||
|
if (i === 0 && value === undefined) {
|
||
|
delete res[pathArray[i]];
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
/**
|
||
|
* Recursively a set the same value for all keys and arrays nested object, cloning
|
||
|
* @param object
|
||
|
* @param value
|
||
|
* @param visited
|
||
|
* @param response
|
||
|
*/
|
||
|
|
||
|
function setNestedObjectValues(object, value, visited, response) {
|
||
|
if (visited === void 0) {
|
||
|
visited = new WeakMap();
|
||
|
}
|
||
|
|
||
|
if (response === void 0) {
|
||
|
response = {};
|
||
|
}
|
||
|
|
||
|
for (var _i = 0, _Object$keys = Object.keys(object); _i < _Object$keys.length; _i++) {
|
||
|
var k = _Object$keys[_i];
|
||
|
var val = object[k];
|
||
|
|
||
|
if (isObject(val)) {
|
||
|
if (!visited.get(val)) {
|
||
|
visited.set(val, true); // In order to keep array values consistent for both dot path and
|
||
|
// bracket syntax, we need to check if this is an array so that
|
||
|
// this will output { friends: [true] } and not { friends: { "0": true } }
|
||
|
|
||
|
response[k] = Array.isArray(val) ? [] : {};
|
||
|
setNestedObjectValues(val, value, visited, response[k]);
|
||
|
}
|
||
|
} else {
|
||
|
response[k] = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return response;
|
||
|
}
|
||
|
|
||
|
var FormikContext = /*#__PURE__*/createContext(undefined);
|
||
|
FormikContext.displayName = 'FormikContext';
|
||
|
var FormikProvider = FormikContext.Provider;
|
||
|
var FormikConsumer = FormikContext.Consumer;
|
||
|
function useFormikContext() {
|
||
|
var formik = useContext(FormikContext);
|
||
|
!!!formik ? process.env.NODE_ENV !== "production" ? invariant(false, "Formik context is undefined, please verify you are calling useFormikContext() as child of a <Formik> component.") : invariant(false) : void 0;
|
||
|
return formik;
|
||
|
}
|
||
|
|
||
|
function formikReducer(state, msg) {
|
||
|
switch (msg.type) {
|
||
|
case 'SET_VALUES':
|
||
|
return _extends({}, state, {
|
||
|
values: msg.payload
|
||
|
});
|
||
|
|
||
|
case 'SET_TOUCHED':
|
||
|
return _extends({}, state, {
|
||
|
touched: msg.payload
|
||
|
});
|
||
|
|
||
|
case 'SET_ERRORS':
|
||
|
if (isEqual(state.errors, msg.payload)) {
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
return _extends({}, state, {
|
||
|
errors: msg.payload
|
||
|
});
|
||
|
|
||
|
case 'SET_STATUS':
|
||
|
return _extends({}, state, {
|
||
|
status: msg.payload
|
||
|
});
|
||
|
|
||
|
case 'SET_ISSUBMITTING':
|
||
|
return _extends({}, state, {
|
||
|
isSubmitting: msg.payload
|
||
|
});
|
||
|
|
||
|
case 'SET_ISVALIDATING':
|
||
|
return _extends({}, state, {
|
||
|
isValidating: msg.payload
|
||
|
});
|
||
|
|
||
|
case 'SET_FIELD_VALUE':
|
||
|
return _extends({}, state, {
|
||
|
values: setIn(state.values, msg.payload.field, msg.payload.value)
|
||
|
});
|
||
|
|
||
|
case 'SET_FIELD_TOUCHED':
|
||
|
return _extends({}, state, {
|
||
|
touched: setIn(state.touched, msg.payload.field, msg.payload.value)
|
||
|
});
|
||
|
|
||
|
case 'SET_FIELD_ERROR':
|
||
|
return _extends({}, state, {
|
||
|
errors: setIn(state.errors, msg.payload.field, msg.payload.value)
|
||
|
});
|
||
|
|
||
|
case 'RESET_FORM':
|
||
|
return _extends({}, state, msg.payload);
|
||
|
|
||
|
case 'SET_FORMIK_STATE':
|
||
|
return msg.payload(state);
|
||
|
|
||
|
case 'SUBMIT_ATTEMPT':
|
||
|
return _extends({}, state, {
|
||
|
touched: setNestedObjectValues(state.values, true),
|
||
|
isSubmitting: true,
|
||
|
submitCount: state.submitCount + 1
|
||
|
});
|
||
|
|
||
|
case 'SUBMIT_FAILURE':
|
||
|
return _extends({}, state, {
|
||
|
isSubmitting: false
|
||
|
});
|
||
|
|
||
|
case 'SUBMIT_SUCCESS':
|
||
|
return _extends({}, state, {
|
||
|
isSubmitting: false
|
||
|
});
|
||
|
|
||
|
default:
|
||
|
return state;
|
||
|
}
|
||
|
} // Initial empty states // objects
|
||
|
|
||
|
|
||
|
var emptyErrors = {};
|
||
|
var emptyTouched = {};
|
||
|
function useFormik(_ref) {
|
||
|
var _ref$validateOnChange = _ref.validateOnChange,
|
||
|
validateOnChange = _ref$validateOnChange === void 0 ? true : _ref$validateOnChange,
|
||
|
_ref$validateOnBlur = _ref.validateOnBlur,
|
||
|
validateOnBlur = _ref$validateOnBlur === void 0 ? true : _ref$validateOnBlur,
|
||
|
_ref$validateOnMount = _ref.validateOnMount,
|
||
|
validateOnMount = _ref$validateOnMount === void 0 ? false : _ref$validateOnMount,
|
||
|
isInitialValid = _ref.isInitialValid,
|
||
|
_ref$enableReinitiali = _ref.enableReinitialize,
|
||
|
enableReinitialize = _ref$enableReinitiali === void 0 ? false : _ref$enableReinitiali,
|
||
|
onSubmit = _ref.onSubmit,
|
||
|
rest = _objectWithoutPropertiesLoose(_ref, ["validateOnChange", "validateOnBlur", "validateOnMount", "isInitialValid", "enableReinitialize", "onSubmit"]);
|
||
|
|
||
|
var props = _extends({
|
||
|
validateOnChange: validateOnChange,
|
||
|
validateOnBlur: validateOnBlur,
|
||
|
validateOnMount: validateOnMount,
|
||
|
onSubmit: onSubmit
|
||
|
}, rest);
|
||
|
|
||
|
var initialValues = useRef(props.initialValues);
|
||
|
var initialErrors = useRef(props.initialErrors || emptyErrors);
|
||
|
var initialTouched = useRef(props.initialTouched || emptyTouched);
|
||
|
var initialStatus = useRef(props.initialStatus);
|
||
|
var isMounted = useRef(false);
|
||
|
var fieldRegistry = useRef({});
|
||
|
|
||
|
if (process.env.NODE_ENV !== "production") {
|
||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||
|
useEffect(function () {
|
||
|
!(typeof isInitialValid === 'undefined') ? process.env.NODE_ENV !== "production" ? invariant(false, 'isInitialValid has been deprecated and will be removed in future versions of Formik. Please use initialErrors or validateOnMount instead.') : invariant(false) : void 0; // eslint-disable-next-line
|
||
|
}, []);
|
||
|
}
|
||
|
|
||
|
useEffect(function () {
|
||
|
isMounted.current = true;
|
||
|
return function () {
|
||
|
isMounted.current = false;
|
||
|
};
|
||
|
}, []);
|
||
|
|
||
|
var _React$useReducer = useReducer(formikReducer, {
|
||
|
values: props.initialValues,
|
||
|
errors: props.initialErrors || emptyErrors,
|
||
|
touched: props.initialTouched || emptyTouched,
|
||
|
status: props.initialStatus,
|
||
|
isSubmitting: false,
|
||
|
isValidating: false,
|
||
|
submitCount: 0
|
||
|
}),
|
||
|
state = _React$useReducer[0],
|
||
|
dispatch = _React$useReducer[1];
|
||
|
|
||
|
var runValidateHandler = useCallback(function (values, field) {
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
var maybePromisedErrors = props.validate(values, field);
|
||
|
|
||
|
if (maybePromisedErrors == null) {
|
||
|
// use loose null check here on purpose
|
||
|
resolve(emptyErrors);
|
||
|
} else if (isPromise(maybePromisedErrors)) {
|
||
|
maybePromisedErrors.then(function (errors) {
|
||
|
resolve(errors || emptyErrors);
|
||
|
}, function (actualException) {
|
||
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
console.warn("Warning: An unhandled error was caught during validation in <Formik validate />", actualException);
|
||
|
}
|
||
|
|
||
|
reject(actualException);
|
||
|
});
|
||
|
} else {
|
||
|
resolve(maybePromisedErrors);
|
||
|
}
|
||
|
});
|
||
|
}, [props.validate]);
|
||
|
/**
|
||
|
* Run validation against a Yup schema and optionally run a function if successful
|
||
|
*/
|
||
|
|
||
|
var runValidationSchema = useCallback(function (values, field) {
|
||
|
var validationSchema = props.validationSchema;
|
||
|
var schema = isFunction(validationSchema) ? validationSchema(field) : validationSchema;
|
||
|
var promise = field && schema.validateAt ? schema.validateAt(field, values) : validateYupSchema(values, schema);
|
||
|
return new Promise(function (resolve, reject) {
|
||
|
promise.then(function () {
|
||
|
resolve(emptyErrors);
|
||
|
}, function (err) {
|
||
|
// Yup will throw a validation error if validation fails. We catch those and
|
||
|
// resolve them into Formik errors. We can sniff if something is a Yup error
|
||
|
// by checking error.name.
|
||
|
// @see https://github.com/jquense/yup#validationerrorerrors-string--arraystring-value-any-path-string
|
||
|
if (err.name === 'ValidationError') {
|
||
|
resolve(yupToFormErrors(err));
|
||
|
} else {
|
||
|
// We throw any other errors
|
||
|
if (process.env.NODE_ENV !== 'production') {
|
||
|
console.warn("Warning: An unhandled error was caught during validation in <Formik validationSchema />", err);
|
||
|
}
|
||
|
|
||
|
reject(err);
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
}, [props.validationSchema]);
|
||
|
var runSingleFieldLevelValidation = useCallback(function (field, value) {
|
||
|
return new Promise(function (resolve) {
|
||
|
return resolve(fieldRegistry.current[field].validate(value));
|
||
|
});
|
||
|
}, []);
|
||
|
var runFieldLevelValidations = useCallback(function (values) {
|
||
|
var fieldKeysWithValidation = Object.keys(fieldRegistry.current).filter(function (f) {
|
||
|
return isFunction(fieldRegistry.current[f].validate);
|
||
|
}); // Construct an array with all of the field validation functions
|
||
|
|
||
|
var fieldValidations = fieldKeysWithValidation.length > 0 ? fieldKeysWithValidation.map(function (f) {
|
||
|
return runSingleFieldLevelValidation(f, getIn(values, f));
|
||
|
}) : [Promise.resolve('DO_NOT_DELETE_YOU_WILL_BE_FIRED')]; // use special case ;)
|
||
|
|
||
|
return Promise.all(fieldValidations).then(function (fieldErrorsList) {
|
||
|
return fieldErrorsList.reduce(function (prev, curr, index) {
|
||
|
if (curr === 'DO_NOT_DELETE_YOU_WILL_BE_FIRED') {
|
||
|
return prev;
|
||
|
}
|
||
|
|
||
|
if (curr) {
|
||
|
prev = setIn(prev, fieldKeysWithValidation[index], curr);
|
||
|
}
|
||
|
|
||
|
return prev;
|
||
|
}, {});
|
||
|
});
|
||
|
}, [runSingleFieldLevelValidation]); // Run all validations and return the result
|
||
|
|
||
|
var runAllValidations = useCallback(function (values) {
|
||
|
return Promise.all([runFieldLevelValidations(values), props.validationSchema ? runValidationSchema(values) : {}, props.validate ? runValidateHandler(values) : {}]).then(function (_ref2) {
|
||
|
var fieldErrors = _ref2[0],
|
||
|
schemaErrors = _ref2[1],
|
||
|
validateErrors = _ref2[2];
|
||
|
var combinedErrors = deepmerge.all([fieldErrors, schemaErrors, validateErrors], {
|
||
|
arrayMerge: arrayMerge
|
||
|
});
|
||
|
return combinedErrors;
|
||
|
});
|
||
|
}, [props.validate, props.validationSchema, runFieldLevelValidations, runValidateHandler, runValidationSchema]); // Run all validations methods and update state accordingly
|
||
|
|
||
|
var validateFormWithHighPriority = useEventCallback(function (values) {
|
||
|
if (values === void 0) {
|
||
|
values = state.values;
|
||
|
}
|
||
|
|
||
|
dispatch({
|
||
|
type: 'SET_ISVALIDATING',
|
||
|
payload: true
|
||
|
});
|
||
|
return runAllValidations(values).then(function (combinedErrors) {
|
||
|
if (!!isMounted.current) {
|
||
|
dispatch({
|
||
|
type: 'SET_ISVALIDATING',
|
||
|
payload: false
|
||
|
});
|
||
|
dispatch({
|
||
|
type: 'SET_ERRORS',
|
||
|
payload: combinedErrors
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return combinedErrors;
|
||
|
});
|
||
|
});
|
||
|
useEffect(function () {
|
||
|
if (validateOnMount && isMounted.current === true && isEqual(initialValues.current, props.initialValues)) {
|
||
|
validateFormWithHighPriority(initialValues.current);
|
||
|
}
|
||
|
}, [validateOnMount, validateFormWithHighPriority]);
|
||
|
var resetForm = useCallback(function (nextState) {
|
||
|
var values = nextState && nextState.values ? nextState.values : initialValues.current;
|
||
|
var errors = nextState && nextState.errors ? nextState.errors : initialErrors.current ? initialErrors.current : props.initialErrors || {};
|
||
|
var touched = nextState && nextState.touched ? nextState.touched : initialTouched.current ? initialTouched.current : props.initialTouched || {};
|
||
|
var status = nextState && nextState.status ? nextState.status : initialStatus.current ? initialStatus.current : props.initialStatus;
|
||
|
initialValues.current = values;
|
||
|
initialErrors.current = errors;
|
||
|
initialTouched.current = touched;
|
||
|
initialStatus.current = status;
|
||
|
|
||
|
var dispatchFn = function dispatchFn() {
|
||
|
dispatch({
|
||
|
type: 'RESET_FORM',
|
||
|
payload: {
|
||
|
isSubmitting: !!nextState && !!nextState.isSubmitting,
|
||
|
errors: errors,
|
||
|
touched: touched,
|
||
|
status: status,
|
||
|
values: values,
|
||
|
isValidating: !!nextState && !!nextState.isValidating,
|
||
|
submitCount: !!nextState && !!nextState.submitCount && typeof nextState.submitCount === 'number' ? nextState.submitCount : 0
|
||
|
}
|
||
|
});
|
||
|
};
|
||
|
|
||
|
if (props.onReset) {
|
||
|
var maybePromisedOnReset = props.onReset(state.values, imperativeMethods);
|
||
|
|
||
|
if (isPromise(maybePromisedOnReset)) {
|
||
|
maybePromisedOnReset.then(dispatchFn);
|
||
|
} else {
|
||
|
dispatchFn();
|
||
|
}
|
||
|
} else {
|
||
|
dispatchFn();
|
||
|
}
|
||
|
}, [props.initialErrors, props.initialStatus, props.initialTouched]);
|
||
|
useEffect(function () {
|
||
|
if (isMounted.current === true && !isEqual(initialValues.current, props.initialValues)) {
|
||
|
if (enableReinitialize) {
|
||
|
initialValues.current = props.initialValues;
|
||
|
resetForm();
|
||
|
}
|
||
|
|
||
|
if (validateOnMount) {
|
||
|
validateFormWithHighPriority(initialValues.current);
|
||
|
}
|
||
|
}
|
||
|
}, [enableReinitialize, props.initialValues, resetForm, validateOnMount, validateFormWithHighPriority]);
|
||
|
useEffect(function () {
|
||
|
if (enableReinitialize && isMounted.current === true && !isEqual(initialErrors.current, props.initialErrors)) {
|
||
|
initialErrors.current = props.initialErrors || emptyErrors;
|
||
|
dispatch({
|
||
|
type: 'SET_ERRORS',
|
||
|
payload: props.initialErrors || emptyErrors
|
||
|
});
|
||
|
}
|
||
|
}, [enableReinitialize, props.initialErrors]);
|
||
|
useEffect(function () {
|
||
|
if (enableReinitialize && isMounted.current === true && !isEqual(initialTouched.current, props.initialTouched)) {
|
||
|
initialTouched.current = props.initialTouched || emptyTouched;
|
||
|
dispatch({
|
||
|
type: 'SET_TOUCHED',
|
||
|
payload: props.initialTouched || emptyTouched
|
||
|
});
|
||
|
}
|
||
|
}, [enableReinitialize, props.initialTouched]);
|
||
|
useEffect(function () {
|
||
|
if (enableReinitialize && isMounted.current === true && !isEqual(initialStatus.current, props.initialStatus)) {
|
||
|
initialStatus.current = props.initialStatus;
|
||
|
dispatch({
|
||
|
type: 'SET_STATUS',
|
||
|
payload: props.initialStatus
|
||
|
});
|
||
|
}
|
||
|
}, [enableReinitialize, props.initialStatus, props.initialTouched]);
|
||
|
var validateField = useEventCallback(function (name) {
|
||
|
// This will efficiently validate a single field by avoiding state
|
||
|
// changes if the validation function is synchronous. It's different from
|
||
|
// what is called when using validateForm.
|
||
|
if (fieldRegistry.current[name] && isFunction(fieldRegistry.current[name].validate)) {
|
||
|
var value = getIn(state.values, name);
|
||
|
var maybePromise = fieldRegistry.current[name].validate(value);
|
||
|
|
||
|
if (isPromise(maybePromise)) {
|
||
|
// Only flip isValidating if the function is async.
|
||
|
dispatch({
|
||
|
type: 'SET_ISVALIDATING',
|
||
|
payload: true
|
||
|
});
|
||
|
return maybePromise.then(function (x) {
|
||
|
return x;
|
||
|
}).then(function (error) {
|
||
|
dispatch({
|
||
|
type: 'SET_FIELD_ERROR',
|
||
|
payload: {
|
||
|
field: name,
|
||
|
value: error
|
||
|
}
|
||
|
});
|
||
|
dispatch({
|
||
|
type: 'SET_ISVALIDATING',
|
||
|
payload: false
|
||
|
});
|
||
|
});
|
||
|
} else {
|
||
|
dispatch({
|
||
|
type: 'SET_FIELD_ERROR',
|
||
|
payload: {
|
||
|
field: name,
|
||
|
value: maybePromise
|
||
|
}
|
||
|
});
|
||
|
return Promise.resolve(maybePromise);
|
||
|
}
|
||
|
} else if (props.validationSchema) {
|
||
|
dispatch({
|
||
|
type: 'SET_ISVALIDATING',
|
||
|
payload: true
|
||
|
});
|
||
|
return runValidationSchema(state.values, name).then(function (x) {
|
||
|
return x;
|
||
|
}).then(function (error) {
|
||
|
dispatch({
|
||
|
type: 'SET_FIELD_ERROR',
|
||
|
payload: {
|
||
|
field: name,
|
||
|
value: error[name]
|
||
|
}
|
||
|
});
|
||
|
dispatch({
|
||
|
type: 'SET_ISVALIDATING',
|
||
|
payload: false
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return Promise.resolve();
|
||
|
});
|
||
|
var registerField = useCallback(function (name, _ref3) {
|
||
|
var validate = _ref3.validate;
|
||
|
fieldRegistry.current[name] = {
|
||
|
validate: validate
|
||
|
};
|
||
|
}, []);
|
||
|
var unregisterField = useCallback(function (name) {
|
||
|
delete fieldRegistry.current[name];
|
||
|
}, []);
|
||
|
var setTouched = useEventCallback(function (touched, shouldValidate) {
|
||
|
dispatch({
|
||
|
type: 'SET_TOUCHED',
|
||
|
payload: touched
|
||
|
});
|
||
|
var willValidate = shouldValidate === undefined ? validateOnBlur : shouldValidate;
|
||
|
return willValidate ? validateFormWithHighPriority(state.values) : Promise.resolve();
|
||
|
});
|
||
|
var setErrors = useCallback(function (errors) {
|
||
|
dispatch({
|
||
|
type: 'SET_ERRORS',
|
||
|
payload: errors
|
||
|
});
|
||
|
}, []);
|
||
|
var setValues = useEventCallback(function (values, shouldValidate) {
|
||
|
var resolvedValues = isFunction(values) ? values(state.values) : values;
|
||
|
dispatch({
|
||
|
type: 'SET_VALUES',
|
||
|
payload: resolvedValues
|
||
|
});
|
||
|
var willValidate = shouldValidate === undefined ? validateOnChange : shouldValidate;
|
||
|
return willValidate ? validateFormWithHighPriority(resolvedValues) : Promise.resolve();
|
||
|
});
|
||
|
var setFieldError = useCallback(function (field, value) {
|
||
|
dispatch({
|
||
|
type: 'SET_FIELD_ERROR',
|
||
|
payload: {
|
||
|
field: field,
|
||
|
value: value
|
||
|
}
|
||
|
});
|
||
|
}, []);
|
||
|
var setFieldValue = useEventCallback(function (field, value, shouldValidate) {
|
||
|
dispatch({
|
||
|
type: 'SET_FIELD_VALUE',
|
||
|
payload: {
|
||
|
field: field,
|
||
|
value: value
|
||
|
}
|
||
|
});
|
||
|
var willValidate = shouldValidate === undefined ? validateOnChange : shouldValidate;
|
||
|
return willValidate ? validateFormWithHighPriority(setIn(state.values, field, value)) : Promise.resolve();
|
||
|
});
|
||
|
var executeChange = useCallback(function (eventOrTextValue, maybePath) {
|
||
|
// By default, assume that the first argument is a string. This allows us to use
|
||
|
// handleChange with React Native and React Native Web's onChangeText prop which
|
||
|
// provides just the value of the input.
|
||
|
var field = maybePath;
|
||
|
var val = eventOrTextValue;
|
||
|
var parsed; // If the first argument is not a string though, it has to be a synthetic React Event (or a fake one),
|
||
|
// so we handle like we would a normal HTML change event.
|
||
|
|
||
|
if (!isString(eventOrTextValue)) {
|
||
|
// If we can, persist the event
|
||
|
// @see https://reactjs.org/docs/events.html#event-pooling
|
||
|
if (eventOrTextValue.persist) {
|
||
|
eventOrTextValue.persist();
|
||
|
}
|
||
|
|
||
|
var target = eventOrTextValue.target ? eventOrTextValue.target : eventOrTextValue.currentTarget;
|
||
|
var type = target.type,
|
||
|
name = target.name,
|
||
|
id = target.id,
|
||
|
value = target.value,
|
||
|
checked = target.checked,
|
||
|
outerHTML = target.outerHTML,
|
||
|
options = target.options,
|
||
|
multiple = target.multiple;
|
||
|
field = maybePath ? maybePath : name ? name : id;
|
||
|
|
||
|
if (!field && process.env.NODE_ENV !== "production") {
|
||
|
warnAboutMissingIdentifier({
|
||
|
htmlContent: outerHTML,
|
||
|
documentationAnchorLink: 'handlechange-e-reactchangeeventany--void',
|
||
|
handlerName: 'handleChange'
|
||
|
});
|
||
|
}
|
||
|
|
||
|
val = /number|range/.test(type) ? (parsed = parseFloat(value), isNaN(parsed) ? '' : parsed) : /checkbox/.test(type) // checkboxes
|
||
|
? getValueForCheckbox(getIn(state.values, field), checked, value) : options && multiple // <select multiple>
|
||
|
? getSelectedValues(options) : value;
|
||
|
}
|
||
|
|
||
|
if (field) {
|
||
|
// Set form fields by name
|
||
|
setFieldValue(field, val);
|
||
|
}
|
||
|
}, [setFieldValue, state.values]);
|
||
|
var handleChange = useEventCallback(function (eventOrPath) {
|
||
|
if (isString(eventOrPath)) {
|
||
|
return function (event) {
|
||
|
return executeChange(event, eventOrPath);
|
||
|
};
|
||
|
} else {
|
||
|
executeChange(eventOrPath);
|
||
|
}
|
||
|
});
|
||
|
var setFieldTouched = useEventCallback(function (field, touched, shouldValidate) {
|
||
|
if (touched === void 0) {
|
||
|
touched = true;
|
||
|
}
|
||
|
|
||
|
dispatch({
|
||
|
type: 'SET_FIELD_TOUCHED',
|
||
|
payload: {
|
||
|
field: field,
|
||
|
value: touched
|
||
|
}
|
||
|
});
|
||
|
var willValidate = shouldValidate === undefined ? validateOnBlur : shouldValidate;
|
||
|
return willValidate ? validateFormWithHighPriority(state.values) : Promise.resolve();
|
||
|
});
|
||
|
var executeBlur = useCallback(function (e, path) {
|
||
|
if (e.persist) {
|
||
|
e.persist();
|
||
|
}
|
||
|
|
||
|
var _e$target = e.target,
|
||
|
name = _e$target.name,
|
||
|
id = _e$target.id,
|
||
|
outerHTML = _e$target.outerHTML;
|
||
|
var field = path ? path : name ? name : id;
|
||
|
|
||
|
if (!field && process.env.NODE_ENV !== "production") {
|
||
|
warnAboutMissingIdentifier({
|
||
|
htmlContent: outerHTML,
|
||
|
documentationAnchorLink: 'handleblur-e-any--void',
|
||
|
handlerName: 'handleBlur'
|
||
|
});
|
||
|
}
|
||
|
|
||
|
setFieldTouched(field, true);
|
||
|
}, [setFieldTouched]);
|
||
|
var handleBlur = useEventCallback(function (eventOrString) {
|
||
|
if (isString(eventOrString)) {
|
||
|
return function (event) {
|
||
|
return executeBlur(event, eventOrString);
|
||
|
};
|
||
|
} else {
|
||
|
executeBlur(eventOrString);
|
||
|
}
|
||
|
});
|
||
|
var setFormikState = useCallback(function (stateOrCb) {
|
||
|
if (isFunction(stateOrCb)) {
|
||
|
dispatch({
|
||
|
type: 'SET_FORMIK_STATE',
|
||
|
payload: stateOrCb
|
||
|
});
|
||
|
} else {
|
||
|
dispatch({
|
||
|
type: 'SET_FORMIK_STATE',
|
||
|
payload: function payload() {
|
||
|
return stateOrCb;
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
}, []);
|
||
|
var setStatus = useCallback(function (status) {
|
||
|
dispatch({
|
||
|
type: 'SET_STATUS',
|
||
|
payload: status
|
||
|
});
|
||
|
}, []);
|
||
|
var setSubmitting = useCallback(function (isSubmitting) {
|
||
|
dispatch({
|
||
|
type: 'SET_ISSUBMITTING',
|
||
|
payload: isSubmitting
|
||
|
});
|
||
|
}, []);
|
||
|
var submitForm = useEventCallback(function () {
|
||
|
dispatch({
|
||
|
type: 'SUBMIT_ATTEMPT'
|
||
|
});
|
||
|
return validateFormWithHighPriority().then(function (combinedErrors) {
|
||
|
// In case an error was thrown and passed to the resolved Promise,
|
||
|
// `combinedErrors` can be an instance of an Error. We need to check
|
||
|
// that and abort the submit.
|
||
|
// If we don't do that, calling `Object.keys(new Error())` yields an
|
||
|
// empty array, which causes the validation to pass and the form
|
||
|
// to be submitted.
|
||
|
var isInstanceOfError = combinedErrors instanceof Error;
|
||
|
var isActuallyValid = !isInstanceOfError && Object.keys(combinedErrors).length === 0;
|
||
|
|
||
|
if (isActuallyValid) {
|
||
|
// Proceed with submit...
|
||
|
//
|
||
|
// To respect sync submit fns, we can't simply wrap executeSubmit in a promise and
|
||
|
// _always_ dispatch SUBMIT_SUCCESS because isSubmitting would then always be false.
|
||
|
// This would be fine in simple cases, but make it impossible to disable submit
|
||
|
// buttons where people use callbacks or promises as side effects (which is basically
|
||
|
// all of v1 Formik code). Instead, recall that we are inside of a promise chain already,
|
||
|
// so we can try/catch executeSubmit(), if it returns undefined, then just bail.
|
||
|
// If there are errors, throw em. Otherwise, wrap executeSubmit in a promise and handle
|
||
|
// cleanup of isSubmitting on behalf of the consumer.
|
||
|
var promiseOrUndefined;
|
||
|
|
||
|
try {
|
||
|
promiseOrUndefined = executeSubmit(); // Bail if it's sync, consumer is responsible for cleaning up
|
||
|
// via setSubmitting(false)
|
||
|
|
||
|
if (promiseOrUndefined === undefined) {
|
||
|
return;
|
||
|
}
|
||
|
} catch (error) {
|
||
|
throw error;
|
||
|
}
|
||
|
|
||
|
return Promise.resolve(promiseOrUndefined).then(function (result) {
|
||
|
if (!!isMounted.current) {
|
||
|
dispatch({
|
||
|
type: 'SUBMIT_SUCCESS'
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
})["catch"](function (_errors) {
|
||
|
if (!!isMounted.current) {
|
||
|
dispatch({
|
||
|
type: 'SUBMIT_FAILURE'
|
||
|
}); // This is a legit error rejected by the onSubmit fn
|
||
|
// so we don't want to break the promise chain
|
||
|
|
||
|
throw _errors;
|
||
|
}
|
||
|
});
|
||
|
} else if (!!isMounted.current) {
|
||
|
// ^^^ Make sure Formik is still mounted before updating state
|
||
|
dispatch({
|
||
|
type: 'SUBMIT_FAILURE'
|
||
|
}); // throw combinedErrors;
|
||
|
|
||
|
if (isInstanceOfError) {
|
||
|
throw combinedErrors;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
});
|
||
|
});
|
||
|
var handleSubmit = useEventCallback(function (e) {
|
||
|
if (e && e.preventDefault && isFunction(e.preventDefault)) {
|
||
|
e.preventDefault();
|
||
|
}
|
||
|
|
||
|
if (e && e.stopPropagation && isFunction(e.stopPropagation)) {
|
||
|
e.stopPropagation();
|
||
|
} // Warn if form submission is triggered by a <button> without a
|
||
|
// specified `type` attribute during development. This mitigates
|
||
|
// a common gotcha in forms with both reset and submit buttons,
|
||
|
// where the dev forgets to add type="button" to the reset button.
|
||
|
|
||
|
|
||
|
if (process.env.NODE_ENV !== "production" && typeof document !== 'undefined') {
|
||
|
// Safely get the active element (works with IE)
|
||
|
var activeElement = getActiveElement();
|
||
|
|
||
|
if (activeElement !== null && activeElement instanceof HTMLButtonElement) {
|
||
|
!(activeElement.attributes && activeElement.attributes.getNamedItem('type')) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You submitted a Formik form using a button with an unspecified `type` attribute. Most browsers default button elements to `type="submit"`. If this is not a submit button, please add `type="button"`.') : invariant(false) : void 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
submitForm()["catch"](function (reason) {
|
||
|
console.warn("Warning: An unhandled error was caught from submitForm()", reason);
|
||
|
});
|
||
|
});
|
||
|
var imperativeMethods = {
|
||
|
resetForm: resetForm,
|
||
|
validateForm: validateFormWithHighPriority,
|
||
|
validateField: validateField,
|
||
|
setErrors: setErrors,
|
||
|
setFieldError: setFieldError,
|
||
|
setFieldTouched: setFieldTouched,
|
||
|
setFieldValue: setFieldValue,
|
||
|
setStatus: setStatus,
|
||
|
setSubmitting: setSubmitting,
|
||
|
setTouched: setTouched,
|
||
|
setValues: setValues,
|
||
|
setFormikState: setFormikState,
|
||
|
submitForm: submitForm
|
||
|
};
|
||
|
var executeSubmit = useEventCallback(function () {
|
||
|
return onSubmit(state.values, imperativeMethods);
|
||
|
});
|
||
|
var handleReset = useEventCallback(function (e) {
|
||
|
if (e && e.preventDefault && isFunction(e.preventDefault)) {
|
||
|
e.preventDefault();
|
||
|
}
|
||
|
|
||
|
if (e && e.stopPropagation && isFunction(e.stopPropagation)) {
|
||
|
e.stopPropagation();
|
||
|
}
|
||
|
|
||
|
resetForm();
|
||
|
});
|
||
|
var getFieldMeta = useCallback(function (name) {
|
||
|
return {
|
||
|
value: getIn(state.values, name),
|
||
|
error: getIn(state.errors, name),
|
||
|
touched: !!getIn(state.touched, name),
|
||
|
initialValue: getIn(initialValues.current, name),
|
||
|
initialTouched: !!getIn(initialTouched.current, name),
|
||
|
initialError: getIn(initialErrors.current, name)
|
||
|
};
|
||
|
}, [state.errors, state.touched, state.values]);
|
||
|
var getFieldHelpers = useCallback(function (name) {
|
||
|
return {
|
||
|
setValue: function setValue(value, shouldValidate) {
|
||
|
return setFieldValue(name, value, shouldValidate);
|
||
|
},
|
||
|
setTouched: function setTouched(value, shouldValidate) {
|
||
|
return setFieldTouched(name, value, shouldValidate);
|
||
|
},
|
||
|
setError: function setError(value) {
|
||
|
return setFieldError(name, value);
|
||
|
}
|
||
|
};
|
||
|
}, [setFieldValue, setFieldTouched, setFieldError]);
|
||
|
var getFieldProps = useCallback(function (nameOrOptions) {
|
||
|
var isAnObject = isObject(nameOrOptions);
|
||
|
var name = isAnObject ? nameOrOptions.name : nameOrOptions;
|
||
|
var valueState = getIn(state.values, name);
|
||
|
var field = {
|
||
|
name: name,
|
||
|
value: valueState,
|
||
|
onChange: handleChange,
|
||
|
onBlur: handleBlur
|
||
|
};
|
||
|
|
||
|
if (isAnObject) {
|
||
|
var type = nameOrOptions.type,
|
||
|
valueProp = nameOrOptions.value,
|
||
|
is = nameOrOptions.as,
|
||
|
multiple = nameOrOptions.multiple;
|
||
|
|
||
|
if (type === 'checkbox') {
|
||
|
if (valueProp === undefined) {
|
||
|
field.checked = !!valueState;
|
||
|
} else {
|
||
|
field.checked = !!(Array.isArray(valueState) && ~valueState.indexOf(valueProp));
|
||
|
field.value = valueProp;
|
||
|
}
|
||
|
} else if (type === 'radio') {
|
||
|
field.checked = valueState === valueProp;
|
||
|
field.value = valueProp;
|
||
|
} else if (is === 'select' && multiple) {
|
||
|
field.value = field.value || [];
|
||
|
field.multiple = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return field;
|
||
|
}, [handleBlur, handleChange, state.values]);
|
||
|
var dirty = useMemo(function () {
|
||
|
return !isEqual(initialValues.current, state.values);
|
||
|
}, [initialValues.current, state.values]);
|
||
|
var isValid = useMemo(function () {
|
||
|
return typeof isInitialValid !== 'undefined' ? dirty ? state.errors && Object.keys(state.errors).length === 0 : isInitialValid !== false && isFunction(isInitialValid) ? isInitialValid(props) : isInitialValid : state.errors && Object.keys(state.errors).length === 0;
|
||
|
}, [isInitialValid, dirty, state.errors, props]);
|
||
|
|
||
|
var ctx = _extends({}, state, {
|
||
|
initialValues: initialValues.current,
|
||
|
initialErrors: initialErrors.current,
|
||
|
initialTouched: initialTouched.current,
|
||
|
initialStatus: initialStatus.current,
|
||
|
handleBlur: handleBlur,
|
||
|
handleChange: handleChange,
|
||
|
handleReset: handleReset,
|
||
|
handleSubmit: handleSubmit,
|
||
|
resetForm: resetForm,
|
||
|
setErrors: setErrors,
|
||
|
setFormikState: setFormikState,
|
||
|
setFieldTouched: setFieldTouched,
|
||
|
setFieldValue: setFieldValue,
|
||
|
setFieldError: setFieldError,
|
||
|
setStatus: setStatus,
|
||
|
setSubmitting: setSubmitting,
|
||
|
setTouched: setTouched,
|
||
|
setValues: setValues,
|
||
|
submitForm: submitForm,
|
||
|
validateForm: validateFormWithHighPriority,
|
||
|
validateField: validateField,
|
||
|
isValid: isValid,
|
||
|
dirty: dirty,
|
||
|
unregisterField: unregisterField,
|
||
|
registerField: registerField,
|
||
|
getFieldProps: getFieldProps,
|
||
|
getFieldMeta: getFieldMeta,
|
||
|
getFieldHelpers: getFieldHelpers,
|
||
|
validateOnBlur: validateOnBlur,
|
||
|
validateOnChange: validateOnChange,
|
||
|
validateOnMount: validateOnMount
|
||
|
});
|
||
|
|
||
|
return ctx;
|
||
|
}
|
||
|
function Formik(props) {
|
||
|
var formikbag = useFormik(props);
|
||
|
var component = props.component,
|
||
|
children = props.children,
|
||
|
render = props.render,
|
||
|
innerRef = props.innerRef; // This allows folks to pass a ref to <Formik />
|
||
|
|
||
|
useImperativeHandle(innerRef, function () {
|
||
|
return formikbag;
|
||
|
});
|
||
|
|
||
|
if (process.env.NODE_ENV !== "production") {
|
||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||
|
useEffect(function () {
|
||
|
!!props.render ? process.env.NODE_ENV !== "production" ? invariant(false, "<Formik render> has been deprecated and will be removed in future versions of Formik. Please use a child callback function instead. To get rid of this warning, replace <Formik render={(props) => ...} /> with <Formik>{(props) => ...}</Formik>") : invariant(false) : void 0; // eslint-disable-next-line
|
||
|
}, []);
|
||
|
}
|
||
|
|
||
|
return createElement(FormikProvider, {
|
||
|
value: formikbag
|
||
|
}, component ? createElement(component, formikbag) : render ? render(formikbag) : children // children come last, always called
|
||
|
? isFunction(children) ? children(formikbag) : !isEmptyChildren(children) ? Children.only(children) : null : null);
|
||
|
}
|
||
|
|
||
|
function warnAboutMissingIdentifier(_ref4) {
|
||
|
var htmlContent = _ref4.htmlContent,
|
||
|
documentationAnchorLink = _ref4.documentationAnchorLink,
|
||
|
handlerName = _ref4.handlerName;
|
||
|
console.warn("Warning: Formik called `" + handlerName + "`, but you forgot to pass an `id` or `name` attribute to your input:\n " + htmlContent + "\n Formik cannot determine which value to update. For more info see https://formik.org/docs/api/formik#" + documentationAnchorLink + "\n ");
|
||
|
}
|
||
|
/**
|
||
|
* Transform Yup ValidationError to a more usable object
|
||
|
*/
|
||
|
|
||
|
|
||
|
function yupToFormErrors(yupError) {
|
||
|
var errors = {};
|
||
|
|
||
|
if (yupError.inner) {
|
||
|
if (yupError.inner.length === 0) {
|
||
|
return setIn(errors, yupError.path, yupError.message);
|
||
|
}
|
||
|
|
||
|
for (var _iterator = yupError.inner, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
|
||
|
var _ref5;
|
||
|
|
||
|
if (_isArray) {
|
||
|
if (_i >= _iterator.length) break;
|
||
|
_ref5 = _iterator[_i++];
|
||
|
} else {
|
||
|
_i = _iterator.next();
|
||
|
if (_i.done) break;
|
||
|
_ref5 = _i.value;
|
||
|
}
|
||
|
|
||
|
var err = _ref5;
|
||
|
|
||
|
if (!getIn(errors, err.path)) {
|
||
|
errors = setIn(errors, err.path, err.message);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return errors;
|
||
|
}
|
||
|
/**
|
||
|
* Validate a yup schema.
|
||
|
*/
|
||
|
|
||
|
function validateYupSchema(values, schema, sync, context) {
|
||
|
if (sync === void 0) {
|
||
|
sync = false;
|
||
|
}
|
||
|
|
||
|
if (context === void 0) {
|
||
|
context = {};
|
||
|
}
|
||
|
|
||
|
var validateData = prepareDataForValidation(values);
|
||
|
return schema[sync ? 'validateSync' : 'validate'](validateData, {
|
||
|
abortEarly: false,
|
||
|
context: context
|
||
|
});
|
||
|
}
|
||
|
/**
|
||
|
* Recursively prepare values.
|
||
|
*/
|
||
|
|
||
|
function prepareDataForValidation(values) {
|
||
|
var data = Array.isArray(values) ? [] : {};
|
||
|
|
||
|
for (var k in values) {
|
||
|
if (Object.prototype.hasOwnProperty.call(values, k)) {
|
||
|
var key = String(k);
|
||
|
|
||
|
if (Array.isArray(values[key]) === true) {
|
||
|
data[key] = values[key].map(function (value) {
|
||
|
if (Array.isArray(value) === true || isPlainObject(value)) {
|
||
|
return prepareDataForValidation(value);
|
||
|
} else {
|
||
|
return value !== '' ? value : undefined;
|
||
|
}
|
||
|
});
|
||
|
} else if (isPlainObject(values[key])) {
|
||
|
data[key] = prepareDataForValidation(values[key]);
|
||
|
} else {
|
||
|
data[key] = values[key] !== '' ? values[key] : undefined;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return data;
|
||
|
}
|
||
|
/**
|
||
|
* deepmerge array merging algorithm
|
||
|
* https://github.com/KyleAMathews/deepmerge#combine-array
|
||
|
*/
|
||
|
|
||
|
function arrayMerge(target, source, options) {
|
||
|
var destination = target.slice();
|
||
|
source.forEach(function merge(e, i) {
|
||
|
if (typeof destination[i] === 'undefined') {
|
||
|
var cloneRequested = options.clone !== false;
|
||
|
var shouldClone = cloneRequested && options.isMergeableObject(e);
|
||
|
destination[i] = shouldClone ? deepmerge(Array.isArray(e) ? [] : {}, e, options) : e;
|
||
|
} else if (options.isMergeableObject(e)) {
|
||
|
destination[i] = deepmerge(target[i], e, options);
|
||
|
} else if (target.indexOf(e) === -1) {
|
||
|
destination.push(e);
|
||
|
}
|
||
|
});
|
||
|
return destination;
|
||
|
}
|
||
|
/** Return multi select values based on an array of options */
|
||
|
|
||
|
|
||
|
function getSelectedValues(options) {
|
||
|
return Array.from(options).filter(function (el) {
|
||
|
return el.selected;
|
||
|
}).map(function (el) {
|
||
|
return el.value;
|
||
|
});
|
||
|
}
|
||
|
/** Return the next value for a checkbox */
|
||
|
|
||
|
|
||
|
function getValueForCheckbox(currentValue, checked, valueProp) {
|
||
|
// If the current value was a boolean, return a boolean
|
||
|
if (typeof currentValue === 'boolean') {
|
||
|
return Boolean(checked);
|
||
|
} // If the currentValue was not a boolean we want to return an array
|
||
|
|
||
|
|
||
|
var currentArrayOfValues = [];
|
||
|
var isValueInArray = false;
|
||
|
var index = -1;
|
||
|
|
||
|
if (!Array.isArray(currentValue)) {
|
||
|
// eslint-disable-next-line eqeqeq
|
||
|
if (!valueProp || valueProp == 'true' || valueProp == 'false') {
|
||
|
return Boolean(checked);
|
||
|
}
|
||
|
} else {
|
||
|
// If the current value is already an array, use it
|
||
|
currentArrayOfValues = currentValue;
|
||
|
index = currentValue.indexOf(valueProp);
|
||
|
isValueInArray = index >= 0;
|
||
|
} // If the checkbox was checked and the value is not already present in the aray we want to add the new value to the array of values
|
||
|
|
||
|
|
||
|
if (checked && valueProp && !isValueInArray) {
|
||
|
return currentArrayOfValues.concat(valueProp);
|
||
|
} // If the checkbox was unchecked and the value is not in the array, simply return the already existing array of values
|
||
|
|
||
|
|
||
|
if (!isValueInArray) {
|
||
|
return currentArrayOfValues;
|
||
|
} // If the checkbox was unchecked and the value is in the array, remove the value and return the array
|
||
|
|
||
|
|
||
|
return currentArrayOfValues.slice(0, index).concat(currentArrayOfValues.slice(index + 1));
|
||
|
} // React currently throws a warning when using useLayoutEffect on the server.
|
||
|
// To get around it, we can conditionally useEffect on the server (no-op) and
|
||
|
// useLayoutEffect in the browser.
|
||
|
// @see https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
|
||
|
|
||
|
|
||
|
var useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? useLayoutEffect : useEffect;
|
||
|
|
||
|
function useEventCallback(fn) {
|
||
|
var ref = useRef(fn); // we copy a ref to the callback scoped to the current state/props on each render
|
||
|
|
||
|
useIsomorphicLayoutEffect(function () {
|
||
|
ref.current = fn;
|
||
|
});
|
||
|
return useCallback(function () {
|
||
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
||
|
args[_key] = arguments[_key];
|
||
|
}
|
||
|
|
||
|
return ref.current.apply(void 0, args);
|
||
|
}, []);
|
||
|
}
|
||
|
|
||
|
function useField(propsOrFieldName) {
|
||
|
var formik = useFormikContext();
|
||
|
var getFieldProps = formik.getFieldProps,
|
||
|
getFieldMeta = formik.getFieldMeta,
|
||
|
getFieldHelpers = formik.getFieldHelpers,
|
||
|
registerField = formik.registerField,
|
||
|
unregisterField = formik.unregisterField;
|
||
|
var isAnObject = isObject(propsOrFieldName); // Normalize propsOrFieldName to FieldHookConfig<Val>
|
||
|
|
||
|
var props = isAnObject ? propsOrFieldName : {
|
||
|
name: propsOrFieldName
|
||
|
};
|
||
|
var fieldName = props.name,
|
||
|
validateFn = props.validate;
|
||
|
useEffect(function () {
|
||
|
if (fieldName) {
|
||
|
registerField(fieldName, {
|
||
|
validate: validateFn
|
||
|
});
|
||
|
}
|
||
|
|
||
|
return function () {
|
||
|
if (fieldName) {
|
||
|
unregisterField(fieldName);
|
||
|
}
|
||
|
};
|
||
|
}, [registerField, unregisterField, fieldName, validateFn]);
|
||
|
|
||
|
if (process.env.NODE_ENV !== "production") {
|
||
|
!formik ? process.env.NODE_ENV !== "production" ? invariant(false, 'useField() / <Field /> must be used underneath a <Formik> component or withFormik() higher order component') : invariant(false) : void 0;
|
||
|
}
|
||
|
|
||
|
!fieldName ? process.env.NODE_ENV !== "production" ? invariant(false, 'Invalid field name. Either pass `useField` a string or an object containing a `name` key.') : invariant(false) : void 0;
|
||
|
return [getFieldProps(props), getFieldMeta(fieldName), getFieldHelpers(fieldName)];
|
||
|
}
|
||
|
function Field(_ref) {
|
||
|
var validate = _ref.validate,
|
||
|
name = _ref.name,
|
||
|
render = _ref.render,
|
||
|
children = _ref.children,
|
||
|
is = _ref.as,
|
||
|
component = _ref.component,
|
||
|
props = _objectWithoutPropertiesLoose(_ref, ["validate", "name", "render", "children", "as", "component"]);
|
||
|
|
||
|
var _useFormikContext = useFormikContext(),
|
||
|
formik = _objectWithoutPropertiesLoose(_useFormikContext, ["validate", "validationSchema"]);
|
||
|
|
||
|
if (process.env.NODE_ENV !== "production") {
|
||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||
|
useEffect(function () {
|
||
|
!!render ? process.env.NODE_ENV !== "production" ? invariant(false, "<Field render> has been deprecated and will be removed in future versions of Formik. Please use a child callback function instead. To get rid of this warning, replace <Field name=\"" + name + "\" render={({field, form}) => ...} /> with <Field name=\"" + name + "\">{({field, form, meta}) => ...}</Field>") : invariant(false) : void 0;
|
||
|
!!(is && children && isFunction(children)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <Field as> and <Field children> as a function in the same <Field> component; <Field as> will be ignored.') : invariant(false) : void 0;
|
||
|
!!(component && children && isFunction(children)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <Field component> and <Field children> as a function in the same <Field> component; <Field component> will be ignored.') : invariant(false) : void 0;
|
||
|
!!(render && children && !isEmptyChildren(children)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <Field render> and <Field children> in the same <Field> component; <Field children> will be ignored') : invariant(false) : void 0; // eslint-disable-next-line
|
||
|
}, []);
|
||
|
} // Register field and field-level validation with parent <Formik>
|
||
|
|
||
|
|
||
|
var registerField = formik.registerField,
|
||
|
unregisterField = formik.unregisterField;
|
||
|
useEffect(function () {
|
||
|
registerField(name, {
|
||
|
validate: validate
|
||
|
});
|
||
|
return function () {
|
||
|
unregisterField(name);
|
||
|
};
|
||
|
}, [registerField, unregisterField, name, validate]);
|
||
|
var field = formik.getFieldProps(_extends({
|
||
|
name: name
|
||
|
}, props));
|
||
|
var meta = formik.getFieldMeta(name);
|
||
|
var legacyBag = {
|
||
|
field: field,
|
||
|
form: formik
|
||
|
};
|
||
|
|
||
|
if (render) {
|
||
|
return render(_extends({}, legacyBag, {
|
||
|
meta: meta
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
if (isFunction(children)) {
|
||
|
return children(_extends({}, legacyBag, {
|
||
|
meta: meta
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
if (component) {
|
||
|
// This behavior is backwards compat with earlier Formik 0.9 to 1.x
|
||
|
if (typeof component === 'string') {
|
||
|
var innerRef = props.innerRef,
|
||
|
rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
|
||
|
|
||
|
return createElement(component, _extends({
|
||
|
ref: innerRef
|
||
|
}, field, rest), children);
|
||
|
} // We don't pass `meta` for backwards compat
|
||
|
|
||
|
|
||
|
return createElement(component, _extends({
|
||
|
field: field,
|
||
|
form: formik
|
||
|
}, props), children);
|
||
|
} // default to input here so we can check for both `as` and `children` above
|
||
|
|
||
|
|
||
|
var asElement = is || 'input';
|
||
|
|
||
|
if (typeof asElement === 'string') {
|
||
|
var _innerRef = props.innerRef,
|
||
|
_rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
|
||
|
|
||
|
return createElement(asElement, _extends({
|
||
|
ref: _innerRef
|
||
|
}, field, _rest), children);
|
||
|
}
|
||
|
|
||
|
return createElement(asElement, _extends({}, field, props), children);
|
||
|
}
|
||
|
|
||
|
var Form = /*#__PURE__*/forwardRef(function (props, ref) {
|
||
|
// iOS needs an "action" attribute for nice input: https://stackoverflow.com/a/39485162/406725
|
||
|
// We default the action to "#" in case the preventDefault fails (just updates the URL hash)
|
||
|
var action = props.action,
|
||
|
rest = _objectWithoutPropertiesLoose(props, ["action"]);
|
||
|
|
||
|
var _action = action != null ? action : '#';
|
||
|
|
||
|
var _useFormikContext = useFormikContext(),
|
||
|
handleReset = _useFormikContext.handleReset,
|
||
|
handleSubmit = _useFormikContext.handleSubmit;
|
||
|
|
||
|
return createElement("form", Object.assign({
|
||
|
onSubmit: handleSubmit,
|
||
|
ref: ref,
|
||
|
onReset: handleReset,
|
||
|
action: _action
|
||
|
}, rest));
|
||
|
});
|
||
|
Form.displayName = 'Form';
|
||
|
|
||
|
/**
|
||
|
* A public higher-order component to access the imperative API
|
||
|
*/
|
||
|
|
||
|
function withFormik(_ref) {
|
||
|
var _ref$mapPropsToValues = _ref.mapPropsToValues,
|
||
|
mapPropsToValues = _ref$mapPropsToValues === void 0 ? function (vanillaProps) {
|
||
|
var val = {};
|
||
|
|
||
|
for (var k in vanillaProps) {
|
||
|
if (vanillaProps.hasOwnProperty(k) && typeof vanillaProps[k] !== 'function') {
|
||
|
// @todo TypeScript fix
|
||
|
val[k] = vanillaProps[k];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return val;
|
||
|
} : _ref$mapPropsToValues,
|
||
|
config = _objectWithoutPropertiesLoose(_ref, ["mapPropsToValues"]);
|
||
|
|
||
|
return function createFormik(Component$1) {
|
||
|
var componentDisplayName = Component$1.displayName || Component$1.name || Component$1.constructor && Component$1.constructor.name || 'Component';
|
||
|
/**
|
||
|
* We need to use closures here for to provide the wrapped component's props to
|
||
|
* the respective withFormik config methods.
|
||
|
*/
|
||
|
|
||
|
var C = /*#__PURE__*/function (_React$Component) {
|
||
|
_inheritsLoose(C, _React$Component);
|
||
|
|
||
|
function C() {
|
||
|
var _this;
|
||
|
|
||
|
_this = _React$Component.apply(this, arguments) || this;
|
||
|
|
||
|
_this.validate = function (values) {
|
||
|
return config.validate(values, _this.props);
|
||
|
};
|
||
|
|
||
|
_this.validationSchema = function () {
|
||
|
return isFunction(config.validationSchema) ? config.validationSchema(_this.props) : config.validationSchema;
|
||
|
};
|
||
|
|
||
|
_this.handleSubmit = function (values, actions) {
|
||
|
return config.handleSubmit(values, _extends({}, actions, {
|
||
|
props: _this.props
|
||
|
}));
|
||
|
};
|
||
|
/**
|
||
|
* Just avoiding a render callback for perf here
|
||
|
*/
|
||
|
|
||
|
|
||
|
_this.renderFormComponent = function (formikProps) {
|
||
|
return createElement(Component$1, Object.assign({}, _this.props, formikProps));
|
||
|
};
|
||
|
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
var _proto = C.prototype;
|
||
|
|
||
|
_proto.render = function render() {
|
||
|
var _this$props = this.props,
|
||
|
props = _objectWithoutPropertiesLoose(_this$props, ["children"]);
|
||
|
|
||
|
return createElement(Formik, Object.assign({}, props, config, {
|
||
|
validate: config.validate && this.validate,
|
||
|
validationSchema: config.validationSchema && this.validationSchema,
|
||
|
initialValues: mapPropsToValues(this.props),
|
||
|
initialStatus: config.mapPropsToStatus && config.mapPropsToStatus(this.props),
|
||
|
initialErrors: config.mapPropsToErrors && config.mapPropsToErrors(this.props),
|
||
|
initialTouched: config.mapPropsToTouched && config.mapPropsToTouched(this.props),
|
||
|
onSubmit: this.handleSubmit,
|
||
|
children: this.renderFormComponent
|
||
|
}));
|
||
|
};
|
||
|
|
||
|
return C;
|
||
|
}(Component);
|
||
|
|
||
|
C.displayName = "WithFormik(" + componentDisplayName + ")";
|
||
|
return hoistNonReactStatics(C, Component$1 // cast type to ComponentClass (even if SFC)
|
||
|
);
|
||
|
};
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Connect any component to Formik context, and inject as a prop called `formik`;
|
||
|
* @param Comp React Component
|
||
|
*/
|
||
|
|
||
|
function connect(Comp) {
|
||
|
var C = function C(props) {
|
||
|
return createElement(FormikConsumer, null, function (formik) {
|
||
|
!!!formik ? process.env.NODE_ENV !== "production" ? invariant(false, "Formik context is undefined, please verify you are rendering <Form>, <Field>, <FastField>, <FieldArray>, or your custom context-using component as a child of a <Formik> component. Component name: " + Comp.name) : invariant(false) : void 0;
|
||
|
return createElement(Comp, Object.assign({}, props, {
|
||
|
formik: formik
|
||
|
}));
|
||
|
});
|
||
|
};
|
||
|
|
||
|
var componentDisplayName = Comp.displayName || Comp.name || Comp.constructor && Comp.constructor.name || 'Component'; // Assign Comp to C.WrappedComponent so we can access the inner component in tests
|
||
|
// For example, <Field.WrappedComponent /> gets us <FieldInner/>
|
||
|
|
||
|
C.WrappedComponent = Comp;
|
||
|
C.displayName = "FormikConnect(" + componentDisplayName + ")";
|
||
|
return hoistNonReactStatics(C, Comp // cast type to ComponentClass (even if SFC)
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Some array helpers!
|
||
|
*/
|
||
|
|
||
|
var move = function move(array, from, to) {
|
||
|
var copy = copyArrayLike(array);
|
||
|
var value = copy[from];
|
||
|
copy.splice(from, 1);
|
||
|
copy.splice(to, 0, value);
|
||
|
return copy;
|
||
|
};
|
||
|
var swap = function swap(arrayLike, indexA, indexB) {
|
||
|
var copy = copyArrayLike(arrayLike);
|
||
|
var a = copy[indexA];
|
||
|
copy[indexA] = copy[indexB];
|
||
|
copy[indexB] = a;
|
||
|
return copy;
|
||
|
};
|
||
|
var insert = function insert(arrayLike, index, value) {
|
||
|
var copy = copyArrayLike(arrayLike);
|
||
|
copy.splice(index, 0, value);
|
||
|
return copy;
|
||
|
};
|
||
|
var replace = function replace(arrayLike, index, value) {
|
||
|
var copy = copyArrayLike(arrayLike);
|
||
|
copy[index] = value;
|
||
|
return copy;
|
||
|
};
|
||
|
|
||
|
var copyArrayLike = function copyArrayLike(arrayLike) {
|
||
|
if (!arrayLike) {
|
||
|
return [];
|
||
|
} else if (Array.isArray(arrayLike)) {
|
||
|
return [].concat(arrayLike);
|
||
|
} else {
|
||
|
var maxIndex = Object.keys(arrayLike).map(function (key) {
|
||
|
return parseInt(key);
|
||
|
}).reduce(function (max, el) {
|
||
|
return el > max ? el : max;
|
||
|
}, 0);
|
||
|
return Array.from(_extends({}, arrayLike, {
|
||
|
length: maxIndex + 1
|
||
|
}));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var FieldArrayInner = /*#__PURE__*/function (_React$Component) {
|
||
|
_inheritsLoose(FieldArrayInner, _React$Component);
|
||
|
|
||
|
function FieldArrayInner(props) {
|
||
|
var _this;
|
||
|
|
||
|
_this = _React$Component.call(this, props) || this;
|
||
|
|
||
|
_this.updateArrayField = function (fn, alterTouched, alterErrors) {
|
||
|
var _this$props = _this.props,
|
||
|
name = _this$props.name,
|
||
|
setFormikState = _this$props.formik.setFormikState;
|
||
|
setFormikState(function (prevState) {
|
||
|
var updateErrors = typeof alterErrors === 'function' ? alterErrors : fn;
|
||
|
var updateTouched = typeof alterTouched === 'function' ? alterTouched : fn; // values fn should be executed before updateErrors and updateTouched,
|
||
|
// otherwise it causes an error with unshift.
|
||
|
|
||
|
var values = setIn(prevState.values, name, fn(getIn(prevState.values, name)));
|
||
|
var fieldError = alterErrors ? updateErrors(getIn(prevState.errors, name)) : undefined;
|
||
|
var fieldTouched = alterTouched ? updateTouched(getIn(prevState.touched, name)) : undefined;
|
||
|
|
||
|
if (isEmptyArray(fieldError)) {
|
||
|
fieldError = undefined;
|
||
|
}
|
||
|
|
||
|
if (isEmptyArray(fieldTouched)) {
|
||
|
fieldTouched = undefined;
|
||
|
}
|
||
|
|
||
|
return _extends({}, prevState, {
|
||
|
values: values,
|
||
|
errors: alterErrors ? setIn(prevState.errors, name, fieldError) : prevState.errors,
|
||
|
touched: alterTouched ? setIn(prevState.touched, name, fieldTouched) : prevState.touched
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
_this.push = function (value) {
|
||
|
return _this.updateArrayField(function (arrayLike) {
|
||
|
return [].concat(copyArrayLike(arrayLike), [cloneDeep(value)]);
|
||
|
}, false, false);
|
||
|
};
|
||
|
|
||
|
_this.handlePush = function (value) {
|
||
|
return function () {
|
||
|
return _this.push(value);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.swap = function (indexA, indexB) {
|
||
|
return _this.updateArrayField(function (array) {
|
||
|
return swap(array, indexA, indexB);
|
||
|
}, true, true);
|
||
|
};
|
||
|
|
||
|
_this.handleSwap = function (indexA, indexB) {
|
||
|
return function () {
|
||
|
return _this.swap(indexA, indexB);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.move = function (from, to) {
|
||
|
return _this.updateArrayField(function (array) {
|
||
|
return move(array, from, to);
|
||
|
}, true, true);
|
||
|
};
|
||
|
|
||
|
_this.handleMove = function (from, to) {
|
||
|
return function () {
|
||
|
return _this.move(from, to);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.insert = function (index, value) {
|
||
|
return _this.updateArrayField(function (array) {
|
||
|
return insert(array, index, value);
|
||
|
}, function (array) {
|
||
|
return insert(array, index, null);
|
||
|
}, function (array) {
|
||
|
return insert(array, index, null);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
_this.handleInsert = function (index, value) {
|
||
|
return function () {
|
||
|
return _this.insert(index, value);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.replace = function (index, value) {
|
||
|
return _this.updateArrayField(function (array) {
|
||
|
return replace(array, index, value);
|
||
|
}, false, false);
|
||
|
};
|
||
|
|
||
|
_this.handleReplace = function (index, value) {
|
||
|
return function () {
|
||
|
return _this.replace(index, value);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.unshift = function (value) {
|
||
|
var length = -1;
|
||
|
|
||
|
_this.updateArrayField(function (array) {
|
||
|
var arr = array ? [value].concat(array) : [value];
|
||
|
|
||
|
if (length < 0) {
|
||
|
length = arr.length;
|
||
|
}
|
||
|
|
||
|
return arr;
|
||
|
}, function (array) {
|
||
|
var arr = array ? [null].concat(array) : [null];
|
||
|
|
||
|
if (length < 0) {
|
||
|
length = arr.length;
|
||
|
}
|
||
|
|
||
|
return arr;
|
||
|
}, function (array) {
|
||
|
var arr = array ? [null].concat(array) : [null];
|
||
|
|
||
|
if (length < 0) {
|
||
|
length = arr.length;
|
||
|
}
|
||
|
|
||
|
return arr;
|
||
|
});
|
||
|
|
||
|
return length;
|
||
|
};
|
||
|
|
||
|
_this.handleUnshift = function (value) {
|
||
|
return function () {
|
||
|
return _this.unshift(value);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.handleRemove = function (index) {
|
||
|
return function () {
|
||
|
return _this.remove(index);
|
||
|
};
|
||
|
};
|
||
|
|
||
|
_this.handlePop = function () {
|
||
|
return function () {
|
||
|
return _this.pop();
|
||
|
};
|
||
|
}; // We need TypeScript generics on these, so we'll bind them in the constructor
|
||
|
// @todo Fix TS 3.2.1
|
||
|
|
||
|
|
||
|
_this.remove = _this.remove.bind(_assertThisInitialized(_this));
|
||
|
_this.pop = _this.pop.bind(_assertThisInitialized(_this));
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
var _proto = FieldArrayInner.prototype;
|
||
|
|
||
|
_proto.componentDidUpdate = function componentDidUpdate(prevProps) {
|
||
|
if (this.props.validateOnChange && this.props.formik.validateOnChange && !isEqual(getIn(prevProps.formik.values, prevProps.name), getIn(this.props.formik.values, this.props.name))) {
|
||
|
this.props.formik.validateForm(this.props.formik.values);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
_proto.remove = function remove(index) {
|
||
|
// We need to make sure we also remove relevant pieces of `touched` and `errors`
|
||
|
var result;
|
||
|
this.updateArrayField( // so this gets call 3 times
|
||
|
function (array) {
|
||
|
var copy = array ? copyArrayLike(array) : [];
|
||
|
|
||
|
if (!result) {
|
||
|
result = copy[index];
|
||
|
}
|
||
|
|
||
|
if (isFunction(copy.splice)) {
|
||
|
copy.splice(index, 1);
|
||
|
}
|
||
|
|
||
|
return copy;
|
||
|
}, true, true);
|
||
|
return result;
|
||
|
};
|
||
|
|
||
|
_proto.pop = function pop() {
|
||
|
// Remove relevant pieces of `touched` and `errors` too!
|
||
|
var result;
|
||
|
this.updateArrayField( // so this gets call 3 times
|
||
|
function (array) {
|
||
|
var tmp = array;
|
||
|
|
||
|
if (!result) {
|
||
|
result = tmp && tmp.pop && tmp.pop();
|
||
|
}
|
||
|
|
||
|
return tmp;
|
||
|
}, true, true);
|
||
|
return result;
|
||
|
};
|
||
|
|
||
|
_proto.render = function render() {
|
||
|
var arrayHelpers = {
|
||
|
push: this.push,
|
||
|
pop: this.pop,
|
||
|
swap: this.swap,
|
||
|
move: this.move,
|
||
|
insert: this.insert,
|
||
|
replace: this.replace,
|
||
|
unshift: this.unshift,
|
||
|
remove: this.remove,
|
||
|
handlePush: this.handlePush,
|
||
|
handlePop: this.handlePop,
|
||
|
handleSwap: this.handleSwap,
|
||
|
handleMove: this.handleMove,
|
||
|
handleInsert: this.handleInsert,
|
||
|
handleReplace: this.handleReplace,
|
||
|
handleUnshift: this.handleUnshift,
|
||
|
handleRemove: this.handleRemove
|
||
|
};
|
||
|
|
||
|
var _this$props2 = this.props,
|
||
|
component = _this$props2.component,
|
||
|
render = _this$props2.render,
|
||
|
children = _this$props2.children,
|
||
|
name = _this$props2.name,
|
||
|
_this$props2$formik = _this$props2.formik,
|
||
|
restOfFormik = _objectWithoutPropertiesLoose(_this$props2$formik, ["validate", "validationSchema"]);
|
||
|
|
||
|
var props = _extends({}, arrayHelpers, {
|
||
|
form: restOfFormik,
|
||
|
name: name
|
||
|
});
|
||
|
|
||
|
return component ? createElement(component, props) : render ? render(props) : children // children come last, always called
|
||
|
? typeof children === 'function' ? children(props) : !isEmptyChildren(children) ? Children.only(children) : null : null;
|
||
|
};
|
||
|
|
||
|
return FieldArrayInner;
|
||
|
}(Component);
|
||
|
|
||
|
FieldArrayInner.defaultProps = {
|
||
|
validateOnChange: true
|
||
|
};
|
||
|
var FieldArray = /*#__PURE__*/connect(FieldArrayInner);
|
||
|
|
||
|
var ErrorMessageImpl = /*#__PURE__*/function (_React$Component) {
|
||
|
_inheritsLoose(ErrorMessageImpl, _React$Component);
|
||
|
|
||
|
function ErrorMessageImpl() {
|
||
|
return _React$Component.apply(this, arguments) || this;
|
||
|
}
|
||
|
|
||
|
var _proto = ErrorMessageImpl.prototype;
|
||
|
|
||
|
_proto.shouldComponentUpdate = function shouldComponentUpdate(props) {
|
||
|
if (getIn(this.props.formik.errors, this.props.name) !== getIn(props.formik.errors, this.props.name) || getIn(this.props.formik.touched, this.props.name) !== getIn(props.formik.touched, this.props.name) || Object.keys(this.props).length !== Object.keys(props).length) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
_proto.render = function render() {
|
||
|
var _this$props = this.props,
|
||
|
component = _this$props.component,
|
||
|
formik = _this$props.formik,
|
||
|
render = _this$props.render,
|
||
|
children = _this$props.children,
|
||
|
name = _this$props.name,
|
||
|
rest = _objectWithoutPropertiesLoose(_this$props, ["component", "formik", "render", "children", "name"]);
|
||
|
|
||
|
var touch = getIn(formik.touched, name);
|
||
|
var error = getIn(formik.errors, name);
|
||
|
return !!touch && !!error ? render ? isFunction(render) ? render(error) : null : children ? isFunction(children) ? children(error) : null : component ? createElement(component, rest, error) : error : null;
|
||
|
};
|
||
|
|
||
|
return ErrorMessageImpl;
|
||
|
}(Component);
|
||
|
|
||
|
var ErrorMessage = /*#__PURE__*/connect(ErrorMessageImpl);
|
||
|
|
||
|
/**
|
||
|
* Custom Field component for quickly hooking into Formik
|
||
|
* context and wiring up forms.
|
||
|
*/
|
||
|
|
||
|
var FastFieldInner = /*#__PURE__*/function (_React$Component) {
|
||
|
_inheritsLoose(FastFieldInner, _React$Component);
|
||
|
|
||
|
function FastFieldInner(props) {
|
||
|
var _this;
|
||
|
|
||
|
_this = _React$Component.call(this, props) || this;
|
||
|
var render = props.render,
|
||
|
children = props.children,
|
||
|
component = props.component,
|
||
|
is = props.as,
|
||
|
name = props.name;
|
||
|
!!render ? process.env.NODE_ENV !== "production" ? invariant(false, "<FastField render> has been deprecated. Please use a child callback function instead: <FastField name={" + name + "}>{props => ...}</FastField> instead.") : invariant(false) : void 0;
|
||
|
!!(component && render) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <FastField component> and <FastField render> in the same <FastField> component; <FastField component> will be ignored') : invariant(false) : void 0;
|
||
|
!!(is && children && isFunction(children)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <FastField as> and <FastField children> as a function in the same <FastField> component; <FastField as> will be ignored.') : invariant(false) : void 0;
|
||
|
!!(component && children && isFunction(children)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <FastField component> and <FastField children> as a function in the same <FastField> component; <FastField component> will be ignored.') : invariant(false) : void 0;
|
||
|
!!(render && children && !isEmptyChildren(children)) ? process.env.NODE_ENV !== "production" ? invariant(false, 'You should not use <FastField render> and <FastField children> in the same <FastField> component; <FastField children> will be ignored') : invariant(false) : void 0;
|
||
|
return _this;
|
||
|
}
|
||
|
|
||
|
var _proto = FastFieldInner.prototype;
|
||
|
|
||
|
_proto.shouldComponentUpdate = function shouldComponentUpdate(props) {
|
||
|
if (this.props.shouldUpdate) {
|
||
|
return this.props.shouldUpdate(props, this.props);
|
||
|
} else if (props.name !== this.props.name || getIn(props.formik.values, this.props.name) !== getIn(this.props.formik.values, this.props.name) || getIn(props.formik.errors, this.props.name) !== getIn(this.props.formik.errors, this.props.name) || getIn(props.formik.touched, this.props.name) !== getIn(this.props.formik.touched, this.props.name) || Object.keys(this.props).length !== Object.keys(props).length || props.formik.isSubmitting !== this.props.formik.isSubmitting) {
|
||
|
return true;
|
||
|
} else {
|
||
|
return false;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
_proto.componentDidMount = function componentDidMount() {
|
||
|
// Register the Field with the parent Formik. Parent will cycle through
|
||
|
// registered Field's validate fns right prior to submit
|
||
|
this.props.formik.registerField(this.props.name, {
|
||
|
validate: this.props.validate
|
||
|
});
|
||
|
};
|
||
|
|
||
|
_proto.componentDidUpdate = function componentDidUpdate(prevProps) {
|
||
|
if (this.props.name !== prevProps.name) {
|
||
|
this.props.formik.unregisterField(prevProps.name);
|
||
|
this.props.formik.registerField(this.props.name, {
|
||
|
validate: this.props.validate
|
||
|
});
|
||
|
}
|
||
|
|
||
|
if (this.props.validate !== prevProps.validate) {
|
||
|
this.props.formik.registerField(this.props.name, {
|
||
|
validate: this.props.validate
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
_proto.componentWillUnmount = function componentWillUnmount() {
|
||
|
this.props.formik.unregisterField(this.props.name);
|
||
|
};
|
||
|
|
||
|
_proto.render = function render() {
|
||
|
var _this$props = this.props,
|
||
|
name = _this$props.name,
|
||
|
render = _this$props.render,
|
||
|
is = _this$props.as,
|
||
|
children = _this$props.children,
|
||
|
component = _this$props.component,
|
||
|
formik = _this$props.formik,
|
||
|
props = _objectWithoutPropertiesLoose(_this$props, ["validate", "name", "render", "as", "children", "component", "shouldUpdate", "formik"]);
|
||
|
|
||
|
var restOfFormik = _objectWithoutPropertiesLoose(formik, ["validate", "validationSchema"]);
|
||
|
|
||
|
var field = formik.getFieldProps(_extends({
|
||
|
name: name
|
||
|
}, props));
|
||
|
var meta = {
|
||
|
value: getIn(formik.values, name),
|
||
|
error: getIn(formik.errors, name),
|
||
|
touched: !!getIn(formik.touched, name),
|
||
|
initialValue: getIn(formik.initialValues, name),
|
||
|
initialTouched: !!getIn(formik.initialTouched, name),
|
||
|
initialError: getIn(formik.initialErrors, name)
|
||
|
};
|
||
|
var bag = {
|
||
|
field: field,
|
||
|
meta: meta,
|
||
|
form: restOfFormik
|
||
|
};
|
||
|
|
||
|
if (render) {
|
||
|
return render(bag);
|
||
|
}
|
||
|
|
||
|
if (isFunction(children)) {
|
||
|
return children(bag);
|
||
|
}
|
||
|
|
||
|
if (component) {
|
||
|
// This behavior is backwards compat with earlier Formik 0.9 to 1.x
|
||
|
if (typeof component === 'string') {
|
||
|
var innerRef = props.innerRef,
|
||
|
rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
|
||
|
|
||
|
return createElement(component, _extends({
|
||
|
ref: innerRef
|
||
|
}, field, rest), children);
|
||
|
} // We don't pass `meta` for backwards compat
|
||
|
|
||
|
|
||
|
return createElement(component, _extends({
|
||
|
field: field,
|
||
|
form: formik
|
||
|
}, props), children);
|
||
|
} // default to input here so we can check for both `as` and `children` above
|
||
|
|
||
|
|
||
|
var asElement = is || 'input';
|
||
|
|
||
|
if (typeof asElement === 'string') {
|
||
|
var _innerRef = props.innerRef,
|
||
|
_rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
|
||
|
|
||
|
return createElement(asElement, _extends({
|
||
|
ref: _innerRef
|
||
|
}, field, _rest), children);
|
||
|
}
|
||
|
|
||
|
return createElement(asElement, _extends({}, field, props), children);
|
||
|
};
|
||
|
|
||
|
return FastFieldInner;
|
||
|
}(Component);
|
||
|
|
||
|
var FastField = /*#__PURE__*/connect(FastFieldInner);
|
||
|
|
||
|
export { ErrorMessage, FastField, Field, FieldArray, Form, Formik, FormikConsumer, FormikContext, FormikProvider, connect, getActiveElement, getIn, insert, isEmptyArray, isEmptyChildren, isFunction, isInputEvent, isInteger, isNaN$1 as isNaN, isObject, isPromise, isString, move, prepareDataForValidation, replace, setIn, setNestedObjectValues, swap, useField, useFormik, useFormikContext, validateYupSchema, withFormik, yupToFormErrors };
|
||
|
//# sourceMappingURL=formik.esm.js.map
|