UNPKG

68.4 kBJavaScriptView Raw
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; }
6
7var React = require('react');
8var isEqual = _interopDefault(require('react-fast-compare'));
9var deepmerge = _interopDefault(require('deepmerge'));
10var isPlainObject = _interopDefault(require('lodash/isPlainObject'));
11var clone = _interopDefault(require('lodash/clone'));
12var toPath = _interopDefault(require('lodash/toPath'));
13var invariant = _interopDefault(require('tiny-warning'));
14var hoistNonReactStatics = _interopDefault(require('hoist-non-react-statics'));
15var cloneDeep = _interopDefault(require('lodash/cloneDeep'));
16
17function _extends() {
18 _extends = Object.assign || function (target) {
19 for (var i = 1; i < arguments.length; i++) {
20 var source = arguments[i];
21
22 for (var key in source) {
23 if (Object.prototype.hasOwnProperty.call(source, key)) {
24 target[key] = source[key];
25 }
26 }
27 }
28
29 return target;
30 };
31
32 return _extends.apply(this, arguments);
33}
34
35function _inheritsLoose(subClass, superClass) {
36 subClass.prototype = Object.create(superClass.prototype);
37 subClass.prototype.constructor = subClass;
38 subClass.__proto__ = superClass;
39}
40
41function _objectWithoutPropertiesLoose(source, excluded) {
42 if (source == null) return {};
43 var target = {};
44 var sourceKeys = Object.keys(source);
45 var key, i;
46
47 for (i = 0; i < sourceKeys.length; i++) {
48 key = sourceKeys[i];
49 if (excluded.indexOf(key) >= 0) continue;
50 target[key] = source[key];
51 }
52
53 return target;
54}
55
56function _assertThisInitialized(self) {
57 if (self === void 0) {
58 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
59 }
60
61 return self;
62}
63
64/** @private is the value an empty array? */
65
66var isEmptyArray = function isEmptyArray(value) {
67 return Array.isArray(value) && value.length === 0;
68};
69/** @private is the given object a Function? */
70
71var isFunction = function isFunction(obj) {
72 return typeof obj === 'function';
73};
74/** @private is the given object an Object? */
75
76var isObject = function isObject(obj) {
77 return obj !== null && typeof obj === 'object';
78};
79/** @private is the given object an integer? */
80
81var isInteger = function isInteger(obj) {
82 return String(Math.floor(Number(obj))) === obj;
83};
84/** @private is the given object a string? */
85
86var isString = function isString(obj) {
87 return Object.prototype.toString.call(obj) === '[object String]';
88};
89/** @private is the given object a NaN? */
90// eslint-disable-next-line no-self-compare
91
92var isNaN$1 = function isNaN(obj) {
93 return obj !== obj;
94};
95/** @private Does a React component have exactly 0 children? */
96
97var isEmptyChildren = function isEmptyChildren(children) {
98 return React.Children.count(children) === 0;
99};
100/** @private is the given object/value a promise? */
101
102var isPromise = function isPromise(value) {
103 return isObject(value) && isFunction(value.then);
104};
105/** @private is the given object/value a type of synthetic event? */
106
107var isInputEvent = function isInputEvent(value) {
108 return value && isObject(value) && isObject(value.target);
109};
110/**
111 * Same as document.activeElement but wraps in a try-catch block. In IE it is
112 * not safe to call document.activeElement if there is nothing focused.
113 *
114 * The activeElement will be null only if the document or document body is not
115 * yet defined.
116 *
117 * @param {?Document} doc Defaults to current document.
118 * @return {Element | null}
119 * @see https://github.com/facebook/fbjs/blob/master/packages/fbjs/src/core/dom/getActiveElement.js
120 */
121
122function getActiveElement(doc) {
123 doc = doc || (typeof document !== 'undefined' ? document : undefined);
124
125 if (typeof doc === 'undefined') {
126 return null;
127 }
128
129 try {
130 return doc.activeElement || doc.body;
131 } catch (e) {
132 return doc.body;
133 }
134}
135/**
136 * Deeply get a value from an object via its path.
137 */
138
139function getIn(obj, key, def, p) {
140 if (p === void 0) {
141 p = 0;
142 }
143
144 var path = toPath(key);
145
146 while (obj && p < path.length) {
147 obj = obj[path[p++]];
148 }
149
150 return obj === undefined ? def : obj;
151}
152/**
153 * Deeply set a value from in object via it's path. If the value at `path`
154 * has changed, return a shallow copy of obj with `value` set at `path`.
155 * If `value` has not changed, return the original `obj`.
156 *
157 * Existing objects / arrays along `path` are also shallow copied. Sibling
158 * objects along path retain the same internal js reference. Since new
159 * objects / arrays are only created along `path`, we can test if anything
160 * changed in a nested structure by comparing the object's reference in
161 * the old and new object, similar to how russian doll cache invalidation
162 * works.
163 *
164 * In earlier versions of this function, which used cloneDeep, there were
165 * issues whereby settings a nested value would mutate the parent
166 * instead of creating a new object. `clone` avoids that bug making a
167 * shallow copy of the objects along the update path
168 * so no object is mutated in place.
169 *
170 * Before changing this function, please read through the following
171 * discussions.
172 *
173 * @see https://github.com/developit/linkstate
174 * @see https://github.com/jaredpalmer/formik/pull/123
175 */
176
177function setIn(obj, path, value) {
178 var res = clone(obj); // this keeps inheritance when obj is a class
179
180 var resVal = res;
181 var i = 0;
182 var pathArray = toPath(path);
183
184 for (; i < pathArray.length - 1; i++) {
185 var currentPath = pathArray[i];
186 var currentObj = getIn(obj, pathArray.slice(0, i + 1));
187
188 if (currentObj && (isObject(currentObj) || Array.isArray(currentObj))) {
189 resVal = resVal[currentPath] = clone(currentObj);
190 } else {
191 var nextPath = pathArray[i + 1];
192 resVal = resVal[currentPath] = isInteger(nextPath) && Number(nextPath) >= 0 ? [] : {};
193 }
194 } // Return original object if new value is the same as current
195
196
197 if ((i === 0 ? obj : resVal)[pathArray[i]] === value) {
198 return obj;
199 }
200
201 if (value === undefined) {
202 delete resVal[pathArray[i]];
203 } else {
204 resVal[pathArray[i]] = value;
205 } // If the path array has a single element, the loop did not run.
206 // Deleting on `resVal` had no effect in this scenario, so we delete on the result instead.
207
208
209 if (i === 0 && value === undefined) {
210 delete res[pathArray[i]];
211 }
212
213 return res;
214}
215/**
216 * Recursively a set the same value for all keys and arrays nested object, cloning
217 * @param object
218 * @param value
219 * @param visited
220 * @param response
221 */
222
223function setNestedObjectValues(object, value, visited, response) {
224 if (visited === void 0) {
225 visited = new WeakMap();
226 }
227
228 if (response === void 0) {
229 response = {};
230 }
231
232 for (var _i = 0, _Object$keys = Object.keys(object); _i < _Object$keys.length; _i++) {
233 var k = _Object$keys[_i];
234 var val = object[k];
235
236 if (isObject(val)) {
237 if (!visited.get(val)) {
238 visited.set(val, true); // In order to keep array values consistent for both dot path and
239 // bracket syntax, we need to check if this is an array so that
240 // this will output { friends: [true] } and not { friends: { "0": true } }
241
242 response[k] = Array.isArray(val) ? [] : {};
243 setNestedObjectValues(val, value, visited, response[k]);
244 }
245 } else {
246 response[k] = value;
247 }
248 }
249
250 return response;
251}
252
253var FormikContext = /*#__PURE__*/React.createContext(undefined);
254FormikContext.displayName = 'FormikContext';
255var FormikProvider = FormikContext.Provider;
256var FormikConsumer = FormikContext.Consumer;
257function useFormikContext() {
258 var formik = React.useContext(FormikContext);
259 !!!formik ? invariant(false, "Formik context is undefined, please verify you are calling useFormikContext() as child of a <Formik> component.") : void 0;
260 return formik;
261}
262
263function formikReducer(state, msg) {
264 switch (msg.type) {
265 case 'SET_VALUES':
266 return _extends({}, state, {
267 values: msg.payload
268 });
269
270 case 'SET_TOUCHED':
271 return _extends({}, state, {
272 touched: msg.payload
273 });
274
275 case 'SET_ERRORS':
276 if (isEqual(state.errors, msg.payload)) {
277 return state;
278 }
279
280 return _extends({}, state, {
281 errors: msg.payload
282 });
283
284 case 'SET_STATUS':
285 return _extends({}, state, {
286 status: msg.payload
287 });
288
289 case 'SET_ISSUBMITTING':
290 return _extends({}, state, {
291 isSubmitting: msg.payload
292 });
293
294 case 'SET_ISVALIDATING':
295 return _extends({}, state, {
296 isValidating: msg.payload
297 });
298
299 case 'SET_FIELD_VALUE':
300 return _extends({}, state, {
301 values: setIn(state.values, msg.payload.field, msg.payload.value)
302 });
303
304 case 'SET_FIELD_TOUCHED':
305 return _extends({}, state, {
306 touched: setIn(state.touched, msg.payload.field, msg.payload.value)
307 });
308
309 case 'SET_FIELD_ERROR':
310 return _extends({}, state, {
311 errors: setIn(state.errors, msg.payload.field, msg.payload.value)
312 });
313
314 case 'RESET_FORM':
315 return _extends({}, state, msg.payload);
316
317 case 'SET_FORMIK_STATE':
318 return msg.payload(state);
319
320 case 'SUBMIT_ATTEMPT':
321 return _extends({}, state, {
322 touched: setNestedObjectValues(state.values, true),
323 isSubmitting: true,
324 submitCount: state.submitCount + 1
325 });
326
327 case 'SUBMIT_FAILURE':
328 return _extends({}, state, {
329 isSubmitting: false
330 });
331
332 case 'SUBMIT_SUCCESS':
333 return _extends({}, state, {
334 isSubmitting: false
335 });
336
337 default:
338 return state;
339 }
340} // Initial empty states // objects
341
342
343var emptyErrors = {};
344var emptyTouched = {};
345function useFormik(_ref) {
346 var _ref$validateOnChange = _ref.validateOnChange,
347 validateOnChange = _ref$validateOnChange === void 0 ? true : _ref$validateOnChange,
348 _ref$validateOnBlur = _ref.validateOnBlur,
349 validateOnBlur = _ref$validateOnBlur === void 0 ? true : _ref$validateOnBlur,
350 _ref$validateOnMount = _ref.validateOnMount,
351 validateOnMount = _ref$validateOnMount === void 0 ? false : _ref$validateOnMount,
352 isInitialValid = _ref.isInitialValid,
353 _ref$enableReinitiali = _ref.enableReinitialize,
354 enableReinitialize = _ref$enableReinitiali === void 0 ? false : _ref$enableReinitiali,
355 onSubmit = _ref.onSubmit,
356 rest = _objectWithoutPropertiesLoose(_ref, ["validateOnChange", "validateOnBlur", "validateOnMount", "isInitialValid", "enableReinitialize", "onSubmit"]);
357
358 var props = _extends({
359 validateOnChange: validateOnChange,
360 validateOnBlur: validateOnBlur,
361 validateOnMount: validateOnMount,
362 onSubmit: onSubmit
363 }, rest);
364
365 var initialValues = React.useRef(props.initialValues);
366 var initialErrors = React.useRef(props.initialErrors || emptyErrors);
367 var initialTouched = React.useRef(props.initialTouched || emptyTouched);
368 var initialStatus = React.useRef(props.initialStatus);
369 var isMounted = React.useRef(false);
370 var fieldRegistry = React.useRef({});
371
372 {
373 // eslint-disable-next-line react-hooks/rules-of-hooks
374 React.useEffect(function () {
375 !(typeof isInitialValid === 'undefined') ? invariant(false, 'isInitialValid has been deprecated and will be removed in future versions of Formik. Please use initialErrors or validateOnMount instead.') : void 0; // eslint-disable-next-line
376 }, []);
377 }
378
379 React.useEffect(function () {
380 isMounted.current = true;
381 return function () {
382 isMounted.current = false;
383 };
384 }, []);
385
386 var _React$useReducer = React.useReducer(formikReducer, {
387 values: props.initialValues,
388 errors: props.initialErrors || emptyErrors,
389 touched: props.initialTouched || emptyTouched,
390 status: props.initialStatus,
391 isSubmitting: false,
392 isValidating: false,
393 submitCount: 0
394 }),
395 state = _React$useReducer[0],
396 dispatch = _React$useReducer[1];
397
398 var runValidateHandler = React.useCallback(function (values, field) {
399 return new Promise(function (resolve, reject) {
400 var maybePromisedErrors = props.validate(values, field);
401
402 if (maybePromisedErrors == null) {
403 // use loose null check here on purpose
404 resolve(emptyErrors);
405 } else if (isPromise(maybePromisedErrors)) {
406 maybePromisedErrors.then(function (errors) {
407 resolve(errors || emptyErrors);
408 }, function (actualException) {
409 {
410 console.warn("Warning: An unhandled error was caught during validation in <Formik validate />", actualException);
411 }
412
413 reject(actualException);
414 });
415 } else {
416 resolve(maybePromisedErrors);
417 }
418 });
419 }, [props.validate]);
420 /**
421 * Run validation against a Yup schema and optionally run a function if successful
422 */
423
424 var runValidationSchema = React.useCallback(function (values, field) {
425 var validationSchema = props.validationSchema;
426 var schema = isFunction(validationSchema) ? validationSchema(field) : validationSchema;
427 var promise = field && schema.validateAt ? schema.validateAt(field, values) : validateYupSchema(values, schema);
428 return new Promise(function (resolve, reject) {
429 promise.then(function () {
430 resolve(emptyErrors);
431 }, function (err) {
432 // Yup will throw a validation error if validation fails. We catch those and
433 // resolve them into Formik errors. We can sniff if something is a Yup error
434 // by checking error.name.
435 // @see https://github.com/jquense/yup#validationerrorerrors-string--arraystring-value-any-path-string
436 if (err.name === 'ValidationError') {
437 resolve(yupToFormErrors(err));
438 } else {
439 // We throw any other errors
440 {
441 console.warn("Warning: An unhandled error was caught during validation in <Formik validationSchema />", err);
442 }
443
444 reject(err);
445 }
446 });
447 });
448 }, [props.validationSchema]);
449 var runSingleFieldLevelValidation = React.useCallback(function (field, value) {
450 return new Promise(function (resolve) {
451 return resolve(fieldRegistry.current[field].validate(value));
452 });
453 }, []);
454 var runFieldLevelValidations = React.useCallback(function (values) {
455 var fieldKeysWithValidation = Object.keys(fieldRegistry.current).filter(function (f) {
456 return isFunction(fieldRegistry.current[f].validate);
457 }); // Construct an array with all of the field validation functions
458
459 var fieldValidations = fieldKeysWithValidation.length > 0 ? fieldKeysWithValidation.map(function (f) {
460 return runSingleFieldLevelValidation(f, getIn(values, f));
461 }) : [Promise.resolve('DO_NOT_DELETE_YOU_WILL_BE_FIRED')]; // use special case ;)
462
463 return Promise.all(fieldValidations).then(function (fieldErrorsList) {
464 return fieldErrorsList.reduce(function (prev, curr, index) {
465 if (curr === 'DO_NOT_DELETE_YOU_WILL_BE_FIRED') {
466 return prev;
467 }
468
469 if (curr) {
470 prev = setIn(prev, fieldKeysWithValidation[index], curr);
471 }
472
473 return prev;
474 }, {});
475 });
476 }, [runSingleFieldLevelValidation]); // Run all validations and return the result
477
478 var runAllValidations = React.useCallback(function (values) {
479 return Promise.all([runFieldLevelValidations(values), props.validationSchema ? runValidationSchema(values) : {}, props.validate ? runValidateHandler(values) : {}]).then(function (_ref2) {
480 var fieldErrors = _ref2[0],
481 schemaErrors = _ref2[1],
482 validateErrors = _ref2[2];
483 var combinedErrors = deepmerge.all([fieldErrors, schemaErrors, validateErrors], {
484 arrayMerge: arrayMerge
485 });
486 return combinedErrors;
487 });
488 }, [props.validate, props.validationSchema, runFieldLevelValidations, runValidateHandler, runValidationSchema]); // Run all validations methods and update state accordingly
489
490 var validateFormWithHighPriority = useEventCallback(function (values) {
491 if (values === void 0) {
492 values = state.values;
493 }
494
495 dispatch({
496 type: 'SET_ISVALIDATING',
497 payload: true
498 });
499 return runAllValidations(values).then(function (combinedErrors) {
500 if (!!isMounted.current) {
501 dispatch({
502 type: 'SET_ISVALIDATING',
503 payload: false
504 });
505 dispatch({
506 type: 'SET_ERRORS',
507 payload: combinedErrors
508 });
509 }
510
511 return combinedErrors;
512 });
513 });
514 React.useEffect(function () {
515 if (validateOnMount && isMounted.current === true && isEqual(initialValues.current, props.initialValues)) {
516 validateFormWithHighPriority(initialValues.current);
517 }
518 }, [validateOnMount, validateFormWithHighPriority]);
519 var resetForm = React.useCallback(function (nextState) {
520 var values = nextState && nextState.values ? nextState.values : initialValues.current;
521 var errors = nextState && nextState.errors ? nextState.errors : initialErrors.current ? initialErrors.current : props.initialErrors || {};
522 var touched = nextState && nextState.touched ? nextState.touched : initialTouched.current ? initialTouched.current : props.initialTouched || {};
523 var status = nextState && nextState.status ? nextState.status : initialStatus.current ? initialStatus.current : props.initialStatus;
524 initialValues.current = values;
525 initialErrors.current = errors;
526 initialTouched.current = touched;
527 initialStatus.current = status;
528
529 var dispatchFn = function dispatchFn() {
530 dispatch({
531 type: 'RESET_FORM',
532 payload: {
533 isSubmitting: !!nextState && !!nextState.isSubmitting,
534 errors: errors,
535 touched: touched,
536 status: status,
537 values: values,
538 isValidating: !!nextState && !!nextState.isValidating,
539 submitCount: !!nextState && !!nextState.submitCount && typeof nextState.submitCount === 'number' ? nextState.submitCount : 0
540 }
541 });
542 };
543
544 if (props.onReset) {
545 var maybePromisedOnReset = props.onReset(state.values, imperativeMethods);
546
547 if (isPromise(maybePromisedOnReset)) {
548 maybePromisedOnReset.then(dispatchFn);
549 } else {
550 dispatchFn();
551 }
552 } else {
553 dispatchFn();
554 }
555 }, [props.initialErrors, props.initialStatus, props.initialTouched]);
556 React.useEffect(function () {
557 if (isMounted.current === true && !isEqual(initialValues.current, props.initialValues)) {
558 if (enableReinitialize) {
559 initialValues.current = props.initialValues;
560 resetForm();
561 }
562
563 if (validateOnMount) {
564 validateFormWithHighPriority(initialValues.current);
565 }
566 }
567 }, [enableReinitialize, props.initialValues, resetForm, validateOnMount, validateFormWithHighPriority]);
568 React.useEffect(function () {
569 if (enableReinitialize && isMounted.current === true && !isEqual(initialErrors.current, props.initialErrors)) {
570 initialErrors.current = props.initialErrors || emptyErrors;
571 dispatch({
572 type: 'SET_ERRORS',
573 payload: props.initialErrors || emptyErrors
574 });
575 }
576 }, [enableReinitialize, props.initialErrors]);
577 React.useEffect(function () {
578 if (enableReinitialize && isMounted.current === true && !isEqual(initialTouched.current, props.initialTouched)) {
579 initialTouched.current = props.initialTouched || emptyTouched;
580 dispatch({
581 type: 'SET_TOUCHED',
582 payload: props.initialTouched || emptyTouched
583 });
584 }
585 }, [enableReinitialize, props.initialTouched]);
586 React.useEffect(function () {
587 if (enableReinitialize && isMounted.current === true && !isEqual(initialStatus.current, props.initialStatus)) {
588 initialStatus.current = props.initialStatus;
589 dispatch({
590 type: 'SET_STATUS',
591 payload: props.initialStatus
592 });
593 }
594 }, [enableReinitialize, props.initialStatus, props.initialTouched]);
595 var validateField = useEventCallback(function (name) {
596 // This will efficiently validate a single field by avoiding state
597 // changes if the validation function is synchronous. It's different from
598 // what is called when using validateForm.
599 if (fieldRegistry.current[name] && isFunction(fieldRegistry.current[name].validate)) {
600 var value = getIn(state.values, name);
601 var maybePromise = fieldRegistry.current[name].validate(value);
602
603 if (isPromise(maybePromise)) {
604 // Only flip isValidating if the function is async.
605 dispatch({
606 type: 'SET_ISVALIDATING',
607 payload: true
608 });
609 return maybePromise.then(function (x) {
610 return x;
611 }).then(function (error) {
612 dispatch({
613 type: 'SET_FIELD_ERROR',
614 payload: {
615 field: name,
616 value: error
617 }
618 });
619 dispatch({
620 type: 'SET_ISVALIDATING',
621 payload: false
622 });
623 });
624 } else {
625 dispatch({
626 type: 'SET_FIELD_ERROR',
627 payload: {
628 field: name,
629 value: maybePromise
630 }
631 });
632 return Promise.resolve(maybePromise);
633 }
634 } else if (props.validationSchema) {
635 dispatch({
636 type: 'SET_ISVALIDATING',
637 payload: true
638 });
639 return runValidationSchema(state.values, name).then(function (x) {
640 return x;
641 }).then(function (error) {
642 dispatch({
643 type: 'SET_FIELD_ERROR',
644 payload: {
645 field: name,
646 value: error[name]
647 }
648 });
649 dispatch({
650 type: 'SET_ISVALIDATING',
651 payload: false
652 });
653 });
654 }
655
656 return Promise.resolve();
657 });
658 var registerField = React.useCallback(function (name, _ref3) {
659 var validate = _ref3.validate;
660 fieldRegistry.current[name] = {
661 validate: validate
662 };
663 }, []);
664 var unregisterField = React.useCallback(function (name) {
665 delete fieldRegistry.current[name];
666 }, []);
667 var setTouched = useEventCallback(function (touched, shouldValidate) {
668 dispatch({
669 type: 'SET_TOUCHED',
670 payload: touched
671 });
672 var willValidate = shouldValidate === undefined ? validateOnBlur : shouldValidate;
673 return willValidate ? validateFormWithHighPriority(state.values) : Promise.resolve();
674 });
675 var setErrors = React.useCallback(function (errors) {
676 dispatch({
677 type: 'SET_ERRORS',
678 payload: errors
679 });
680 }, []);
681 var setValues = useEventCallback(function (values, shouldValidate) {
682 var resolvedValues = isFunction(values) ? values(state.values) : values;
683 dispatch({
684 type: 'SET_VALUES',
685 payload: resolvedValues
686 });
687 var willValidate = shouldValidate === undefined ? validateOnChange : shouldValidate;
688 return willValidate ? validateFormWithHighPriority(resolvedValues) : Promise.resolve();
689 });
690 var setFieldError = React.useCallback(function (field, value) {
691 dispatch({
692 type: 'SET_FIELD_ERROR',
693 payload: {
694 field: field,
695 value: value
696 }
697 });
698 }, []);
699 var setFieldValue = useEventCallback(function (field, value, shouldValidate) {
700 dispatch({
701 type: 'SET_FIELD_VALUE',
702 payload: {
703 field: field,
704 value: value
705 }
706 });
707 var willValidate = shouldValidate === undefined ? validateOnChange : shouldValidate;
708 return willValidate ? validateFormWithHighPriority(setIn(state.values, field, value)) : Promise.resolve();
709 });
710 var executeChange = React.useCallback(function (eventOrTextValue, maybePath) {
711 // By default, assume that the first argument is a string. This allows us to use
712 // handleChange with React Native and React Native Web's onChangeText prop which
713 // provides just the value of the input.
714 var field = maybePath;
715 var val = eventOrTextValue;
716 var parsed; // If the first argument is not a string though, it has to be a synthetic React Event (or a fake one),
717 // so we handle like we would a normal HTML change event.
718
719 if (!isString(eventOrTextValue)) {
720 // If we can, persist the event
721 // @see https://reactjs.org/docs/events.html#event-pooling
722 if (eventOrTextValue.persist) {
723 eventOrTextValue.persist();
724 }
725
726 var target = eventOrTextValue.target ? eventOrTextValue.target : eventOrTextValue.currentTarget;
727 var type = target.type,
728 name = target.name,
729 id = target.id,
730 value = target.value,
731 checked = target.checked,
732 outerHTML = target.outerHTML,
733 options = target.options,
734 multiple = target.multiple;
735 field = maybePath ? maybePath : name ? name : id;
736
737 if (!field && "development" !== "production") {
738 warnAboutMissingIdentifier({
739 htmlContent: outerHTML,
740 documentationAnchorLink: 'handlechange-e-reactchangeeventany--void',
741 handlerName: 'handleChange'
742 });
743 }
744
745 val = /number|range/.test(type) ? (parsed = parseFloat(value), isNaN(parsed) ? '' : parsed) : /checkbox/.test(type) // checkboxes
746 ? getValueForCheckbox(getIn(state.values, field), checked, value) : options && multiple // <select multiple>
747 ? getSelectedValues(options) : value;
748 }
749
750 if (field) {
751 // Set form fields by name
752 setFieldValue(field, val);
753 }
754 }, [setFieldValue, state.values]);
755 var handleChange = useEventCallback(function (eventOrPath) {
756 if (isString(eventOrPath)) {
757 return function (event) {
758 return executeChange(event, eventOrPath);
759 };
760 } else {
761 executeChange(eventOrPath);
762 }
763 });
764 var setFieldTouched = useEventCallback(function (field, touched, shouldValidate) {
765 if (touched === void 0) {
766 touched = true;
767 }
768
769 dispatch({
770 type: 'SET_FIELD_TOUCHED',
771 payload: {
772 field: field,
773 value: touched
774 }
775 });
776 var willValidate = shouldValidate === undefined ? validateOnBlur : shouldValidate;
777 return willValidate ? validateFormWithHighPriority(state.values) : Promise.resolve();
778 });
779 var executeBlur = React.useCallback(function (e, path) {
780 if (e.persist) {
781 e.persist();
782 }
783
784 var _e$target = e.target,
785 name = _e$target.name,
786 id = _e$target.id,
787 outerHTML = _e$target.outerHTML;
788 var field = path ? path : name ? name : id;
789
790 if (!field && "development" !== "production") {
791 warnAboutMissingIdentifier({
792 htmlContent: outerHTML,
793 documentationAnchorLink: 'handleblur-e-any--void',
794 handlerName: 'handleBlur'
795 });
796 }
797
798 setFieldTouched(field, true);
799 }, [setFieldTouched]);
800 var handleBlur = useEventCallback(function (eventOrString) {
801 if (isString(eventOrString)) {
802 return function (event) {
803 return executeBlur(event, eventOrString);
804 };
805 } else {
806 executeBlur(eventOrString);
807 }
808 });
809 var setFormikState = React.useCallback(function (stateOrCb) {
810 if (isFunction(stateOrCb)) {
811 dispatch({
812 type: 'SET_FORMIK_STATE',
813 payload: stateOrCb
814 });
815 } else {
816 dispatch({
817 type: 'SET_FORMIK_STATE',
818 payload: function payload() {
819 return stateOrCb;
820 }
821 });
822 }
823 }, []);
824 var setStatus = React.useCallback(function (status) {
825 dispatch({
826 type: 'SET_STATUS',
827 payload: status
828 });
829 }, []);
830 var setSubmitting = React.useCallback(function (isSubmitting) {
831 dispatch({
832 type: 'SET_ISSUBMITTING',
833 payload: isSubmitting
834 });
835 }, []);
836 var submitForm = useEventCallback(function () {
837 dispatch({
838 type: 'SUBMIT_ATTEMPT'
839 });
840 return validateFormWithHighPriority().then(function (combinedErrors) {
841 // In case an error was thrown and passed to the resolved Promise,
842 // `combinedErrors` can be an instance of an Error. We need to check
843 // that and abort the submit.
844 // If we don't do that, calling `Object.keys(new Error())` yields an
845 // empty array, which causes the validation to pass and the form
846 // to be submitted.
847 var isInstanceOfError = combinedErrors instanceof Error;
848 var isActuallyValid = !isInstanceOfError && Object.keys(combinedErrors).length === 0;
849
850 if (isActuallyValid) {
851 // Proceed with submit...
852 //
853 // To respect sync submit fns, we can't simply wrap executeSubmit in a promise and
854 // _always_ dispatch SUBMIT_SUCCESS because isSubmitting would then always be false.
855 // This would be fine in simple cases, but make it impossible to disable submit
856 // buttons where people use callbacks or promises as side effects (which is basically
857 // all of v1 Formik code). Instead, recall that we are inside of a promise chain already,
858 // so we can try/catch executeSubmit(), if it returns undefined, then just bail.
859 // If there are errors, throw em. Otherwise, wrap executeSubmit in a promise and handle
860 // cleanup of isSubmitting on behalf of the consumer.
861 var promiseOrUndefined;
862
863 try {
864 promiseOrUndefined = executeSubmit(); // Bail if it's sync, consumer is responsible for cleaning up
865 // via setSubmitting(false)
866
867 if (promiseOrUndefined === undefined) {
868 return;
869 }
870 } catch (error) {
871 throw error;
872 }
873
874 return Promise.resolve(promiseOrUndefined).then(function (result) {
875 if (!!isMounted.current) {
876 dispatch({
877 type: 'SUBMIT_SUCCESS'
878 });
879 }
880
881 return result;
882 })["catch"](function (_errors) {
883 if (!!isMounted.current) {
884 dispatch({
885 type: 'SUBMIT_FAILURE'
886 }); // This is a legit error rejected by the onSubmit fn
887 // so we don't want to break the promise chain
888
889 throw _errors;
890 }
891 });
892 } else if (!!isMounted.current) {
893 // ^^^ Make sure Formik is still mounted before updating state
894 dispatch({
895 type: 'SUBMIT_FAILURE'
896 }); // throw combinedErrors;
897
898 if (isInstanceOfError) {
899 throw combinedErrors;
900 }
901 }
902
903 return;
904 });
905 });
906 var handleSubmit = useEventCallback(function (e) {
907 if (e && e.preventDefault && isFunction(e.preventDefault)) {
908 e.preventDefault();
909 }
910
911 if (e && e.stopPropagation && isFunction(e.stopPropagation)) {
912 e.stopPropagation();
913 } // Warn if form submission is triggered by a <button> without a
914 // specified `type` attribute during development. This mitigates
915 // a common gotcha in forms with both reset and submit buttons,
916 // where the dev forgets to add type="button" to the reset button.
917
918
919 if ( typeof document !== 'undefined') {
920 // Safely get the active element (works with IE)
921 var activeElement = getActiveElement();
922
923 if (activeElement !== null && activeElement instanceof HTMLButtonElement) {
924 !(activeElement.attributes && activeElement.attributes.getNamedItem('type')) ? 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"`.') : void 0;
925 }
926 }
927
928 submitForm()["catch"](function (reason) {
929 console.warn("Warning: An unhandled error was caught from submitForm()", reason);
930 });
931 });
932 var imperativeMethods = {
933 resetForm: resetForm,
934 validateForm: validateFormWithHighPriority,
935 validateField: validateField,
936 setErrors: setErrors,
937 setFieldError: setFieldError,
938 setFieldTouched: setFieldTouched,
939 setFieldValue: setFieldValue,
940 setStatus: setStatus,
941 setSubmitting: setSubmitting,
942 setTouched: setTouched,
943 setValues: setValues,
944 setFormikState: setFormikState,
945 submitForm: submitForm
946 };
947 var executeSubmit = useEventCallback(function () {
948 return onSubmit(state.values, imperativeMethods);
949 });
950 var handleReset = useEventCallback(function (e) {
951 if (e && e.preventDefault && isFunction(e.preventDefault)) {
952 e.preventDefault();
953 }
954
955 if (e && e.stopPropagation && isFunction(e.stopPropagation)) {
956 e.stopPropagation();
957 }
958
959 resetForm();
960 });
961 var getFieldMeta = React.useCallback(function (name) {
962 return {
963 value: getIn(state.values, name),
964 error: getIn(state.errors, name),
965 touched: !!getIn(state.touched, name),
966 initialValue: getIn(initialValues.current, name),
967 initialTouched: !!getIn(initialTouched.current, name),
968 initialError: getIn(initialErrors.current, name)
969 };
970 }, [state.errors, state.touched, state.values]);
971 var getFieldHelpers = React.useCallback(function (name) {
972 return {
973 setValue: function setValue(value, shouldValidate) {
974 return setFieldValue(name, value, shouldValidate);
975 },
976 setTouched: function setTouched(value, shouldValidate) {
977 return setFieldTouched(name, value, shouldValidate);
978 },
979 setError: function setError(value) {
980 return setFieldError(name, value);
981 }
982 };
983 }, [setFieldValue, setFieldTouched, setFieldError]);
984 var getFieldProps = React.useCallback(function (nameOrOptions) {
985 var isAnObject = isObject(nameOrOptions);
986 var name = isAnObject ? nameOrOptions.name : nameOrOptions;
987 var valueState = getIn(state.values, name);
988 var field = {
989 name: name,
990 value: valueState,
991 onChange: handleChange,
992 onBlur: handleBlur
993 };
994
995 if (isAnObject) {
996 var type = nameOrOptions.type,
997 valueProp = nameOrOptions.value,
998 is = nameOrOptions.as,
999 multiple = nameOrOptions.multiple;
1000
1001 if (type === 'checkbox') {
1002 if (valueProp === undefined) {
1003 field.checked = !!valueState;
1004 } else {
1005 field.checked = !!(Array.isArray(valueState) && ~valueState.indexOf(valueProp));
1006 field.value = valueProp;
1007 }
1008 } else if (type === 'radio') {
1009 field.checked = valueState === valueProp;
1010 field.value = valueProp;
1011 } else if (is === 'select' && multiple) {
1012 field.value = field.value || [];
1013 field.multiple = true;
1014 }
1015 }
1016
1017 return field;
1018 }, [handleBlur, handleChange, state.values]);
1019 var dirty = React.useMemo(function () {
1020 return !isEqual(initialValues.current, state.values);
1021 }, [initialValues.current, state.values]);
1022 var isValid = React.useMemo(function () {
1023 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;
1024 }, [isInitialValid, dirty, state.errors, props]);
1025
1026 var ctx = _extends({}, state, {
1027 initialValues: initialValues.current,
1028 initialErrors: initialErrors.current,
1029 initialTouched: initialTouched.current,
1030 initialStatus: initialStatus.current,
1031 handleBlur: handleBlur,
1032 handleChange: handleChange,
1033 handleReset: handleReset,
1034 handleSubmit: handleSubmit,
1035 resetForm: resetForm,
1036 setErrors: setErrors,
1037 setFormikState: setFormikState,
1038 setFieldTouched: setFieldTouched,
1039 setFieldValue: setFieldValue,
1040 setFieldError: setFieldError,
1041 setStatus: setStatus,
1042 setSubmitting: setSubmitting,
1043 setTouched: setTouched,
1044 setValues: setValues,
1045 submitForm: submitForm,
1046 validateForm: validateFormWithHighPriority,
1047 validateField: validateField,
1048 isValid: isValid,
1049 dirty: dirty,
1050 unregisterField: unregisterField,
1051 registerField: registerField,
1052 getFieldProps: getFieldProps,
1053 getFieldMeta: getFieldMeta,
1054 getFieldHelpers: getFieldHelpers,
1055 validateOnBlur: validateOnBlur,
1056 validateOnChange: validateOnChange,
1057 validateOnMount: validateOnMount
1058 });
1059
1060 return ctx;
1061}
1062function Formik(props) {
1063 var formikbag = useFormik(props);
1064 var component = props.component,
1065 children = props.children,
1066 render = props.render,
1067 innerRef = props.innerRef; // This allows folks to pass a ref to <Formik />
1068
1069 React.useImperativeHandle(innerRef, function () {
1070 return formikbag;
1071 });
1072
1073 {
1074 // eslint-disable-next-line react-hooks/rules-of-hooks
1075 React.useEffect(function () {
1076 !!props.render ? 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>") : void 0; // eslint-disable-next-line
1077 }, []);
1078 }
1079
1080 return React.createElement(FormikProvider, {
1081 value: formikbag
1082 }, component ? React.createElement(component, formikbag) : render ? render(formikbag) : children // children come last, always called
1083 ? isFunction(children) ? children(formikbag) : !isEmptyChildren(children) ? React.Children.only(children) : null : null);
1084}
1085
1086function warnAboutMissingIdentifier(_ref4) {
1087 var htmlContent = _ref4.htmlContent,
1088 documentationAnchorLink = _ref4.documentationAnchorLink,
1089 handlerName = _ref4.handlerName;
1090 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 ");
1091}
1092/**
1093 * Transform Yup ValidationError to a more usable object
1094 */
1095
1096
1097function yupToFormErrors(yupError) {
1098 var errors = {};
1099
1100 if (yupError.inner) {
1101 if (yupError.inner.length === 0) {
1102 return setIn(errors, yupError.path, yupError.message);
1103 }
1104
1105 for (var _iterator = yupError.inner, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
1106 var _ref5;
1107
1108 if (_isArray) {
1109 if (_i >= _iterator.length) break;
1110 _ref5 = _iterator[_i++];
1111 } else {
1112 _i = _iterator.next();
1113 if (_i.done) break;
1114 _ref5 = _i.value;
1115 }
1116
1117 var err = _ref5;
1118
1119 if (!getIn(errors, err.path)) {
1120 errors = setIn(errors, err.path, err.message);
1121 }
1122 }
1123 }
1124
1125 return errors;
1126}
1127/**
1128 * Validate a yup schema.
1129 */
1130
1131function validateYupSchema(values, schema, sync, context) {
1132 if (sync === void 0) {
1133 sync = false;
1134 }
1135
1136 if (context === void 0) {
1137 context = {};
1138 }
1139
1140 var validateData = prepareDataForValidation(values);
1141 return schema[sync ? 'validateSync' : 'validate'](validateData, {
1142 abortEarly: false,
1143 context: context
1144 });
1145}
1146/**
1147 * Recursively prepare values.
1148 */
1149
1150function prepareDataForValidation(values) {
1151 var data = Array.isArray(values) ? [] : {};
1152
1153 for (var k in values) {
1154 if (Object.prototype.hasOwnProperty.call(values, k)) {
1155 var key = String(k);
1156
1157 if (Array.isArray(values[key]) === true) {
1158 data[key] = values[key].map(function (value) {
1159 if (Array.isArray(value) === true || isPlainObject(value)) {
1160 return prepareDataForValidation(value);
1161 } else {
1162 return value !== '' ? value : undefined;
1163 }
1164 });
1165 } else if (isPlainObject(values[key])) {
1166 data[key] = prepareDataForValidation(values[key]);
1167 } else {
1168 data[key] = values[key] !== '' ? values[key] : undefined;
1169 }
1170 }
1171 }
1172
1173 return data;
1174}
1175/**
1176 * deepmerge array merging algorithm
1177 * https://github.com/KyleAMathews/deepmerge#combine-array
1178 */
1179
1180function arrayMerge(target, source, options) {
1181 var destination = target.slice();
1182 source.forEach(function merge(e, i) {
1183 if (typeof destination[i] === 'undefined') {
1184 var cloneRequested = options.clone !== false;
1185 var shouldClone = cloneRequested && options.isMergeableObject(e);
1186 destination[i] = shouldClone ? deepmerge(Array.isArray(e) ? [] : {}, e, options) : e;
1187 } else if (options.isMergeableObject(e)) {
1188 destination[i] = deepmerge(target[i], e, options);
1189 } else if (target.indexOf(e) === -1) {
1190 destination.push(e);
1191 }
1192 });
1193 return destination;
1194}
1195/** Return multi select values based on an array of options */
1196
1197
1198function getSelectedValues(options) {
1199 return Array.from(options).filter(function (el) {
1200 return el.selected;
1201 }).map(function (el) {
1202 return el.value;
1203 });
1204}
1205/** Return the next value for a checkbox */
1206
1207
1208function getValueForCheckbox(currentValue, checked, valueProp) {
1209 // If the current value was a boolean, return a boolean
1210 if (typeof currentValue === 'boolean') {
1211 return Boolean(checked);
1212 } // If the currentValue was not a boolean we want to return an array
1213
1214
1215 var currentArrayOfValues = [];
1216 var isValueInArray = false;
1217 var index = -1;
1218
1219 if (!Array.isArray(currentValue)) {
1220 // eslint-disable-next-line eqeqeq
1221 if (!valueProp || valueProp == 'true' || valueProp == 'false') {
1222 return Boolean(checked);
1223 }
1224 } else {
1225 // If the current value is already an array, use it
1226 currentArrayOfValues = currentValue;
1227 index = currentValue.indexOf(valueProp);
1228 isValueInArray = index >= 0;
1229 } // 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
1230
1231
1232 if (checked && valueProp && !isValueInArray) {
1233 return currentArrayOfValues.concat(valueProp);
1234 } // If the checkbox was unchecked and the value is not in the array, simply return the already existing array of values
1235
1236
1237 if (!isValueInArray) {
1238 return currentArrayOfValues;
1239 } // If the checkbox was unchecked and the value is in the array, remove the value and return the array
1240
1241
1242 return currentArrayOfValues.slice(0, index).concat(currentArrayOfValues.slice(index + 1));
1243} // React currently throws a warning when using useLayoutEffect on the server.
1244// To get around it, we can conditionally useEffect on the server (no-op) and
1245// useLayoutEffect in the browser.
1246// @see https://gist.github.com/gaearon/e7d97cdf38a2907924ea12e4ebdf3c85
1247
1248
1249var useIsomorphicLayoutEffect = typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined' ? React.useLayoutEffect : React.useEffect;
1250
1251function useEventCallback(fn) {
1252 var ref = React.useRef(fn); // we copy a ref to the callback scoped to the current state/props on each render
1253
1254 useIsomorphicLayoutEffect(function () {
1255 ref.current = fn;
1256 });
1257 return React.useCallback(function () {
1258 for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
1259 args[_key] = arguments[_key];
1260 }
1261
1262 return ref.current.apply(void 0, args);
1263 }, []);
1264}
1265
1266function useField(propsOrFieldName) {
1267 var formik = useFormikContext();
1268 var getFieldProps = formik.getFieldProps,
1269 getFieldMeta = formik.getFieldMeta,
1270 getFieldHelpers = formik.getFieldHelpers,
1271 registerField = formik.registerField,
1272 unregisterField = formik.unregisterField;
1273 var isAnObject = isObject(propsOrFieldName); // Normalize propsOrFieldName to FieldHookConfig<Val>
1274
1275 var props = isAnObject ? propsOrFieldName : {
1276 name: propsOrFieldName
1277 };
1278 var fieldName = props.name,
1279 validateFn = props.validate;
1280 React.useEffect(function () {
1281 if (fieldName) {
1282 registerField(fieldName, {
1283 validate: validateFn
1284 });
1285 }
1286
1287 return function () {
1288 if (fieldName) {
1289 unregisterField(fieldName);
1290 }
1291 };
1292 }, [registerField, unregisterField, fieldName, validateFn]);
1293
1294 {
1295 !formik ? invariant(false, 'useField() / <Field /> must be used underneath a <Formik> component or withFormik() higher order component') : void 0;
1296 }
1297
1298 !fieldName ? invariant(false, 'Invalid field name. Either pass `useField` a string or an object containing a `name` key.') : void 0;
1299 return [getFieldProps(props), getFieldMeta(fieldName), getFieldHelpers(fieldName)];
1300}
1301function Field(_ref) {
1302 var validate = _ref.validate,
1303 name = _ref.name,
1304 render = _ref.render,
1305 children = _ref.children,
1306 is = _ref.as,
1307 component = _ref.component,
1308 props = _objectWithoutPropertiesLoose(_ref, ["validate", "name", "render", "children", "as", "component"]);
1309
1310 var _useFormikContext = useFormikContext(),
1311 formik = _objectWithoutPropertiesLoose(_useFormikContext, ["validate", "validationSchema"]);
1312
1313 {
1314 // eslint-disable-next-line react-hooks/rules-of-hooks
1315 React.useEffect(function () {
1316 !!render ? 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>") : void 0;
1317 !!(is && children && isFunction(children)) ? invariant(false, 'You should not use <Field as> and <Field children> as a function in the same <Field> component; <Field as> will be ignored.') : void 0;
1318 !!(component && children && isFunction(children)) ? invariant(false, 'You should not use <Field component> and <Field children> as a function in the same <Field> component; <Field component> will be ignored.') : void 0;
1319 !!(render && children && !isEmptyChildren(children)) ? invariant(false, 'You should not use <Field render> and <Field children> in the same <Field> component; <Field children> will be ignored') : void 0; // eslint-disable-next-line
1320 }, []);
1321 } // Register field and field-level validation with parent <Formik>
1322
1323
1324 var registerField = formik.registerField,
1325 unregisterField = formik.unregisterField;
1326 React.useEffect(function () {
1327 registerField(name, {
1328 validate: validate
1329 });
1330 return function () {
1331 unregisterField(name);
1332 };
1333 }, [registerField, unregisterField, name, validate]);
1334 var field = formik.getFieldProps(_extends({
1335 name: name
1336 }, props));
1337 var meta = formik.getFieldMeta(name);
1338 var legacyBag = {
1339 field: field,
1340 form: formik
1341 };
1342
1343 if (render) {
1344 return render(_extends({}, legacyBag, {
1345 meta: meta
1346 }));
1347 }
1348
1349 if (isFunction(children)) {
1350 return children(_extends({}, legacyBag, {
1351 meta: meta
1352 }));
1353 }
1354
1355 if (component) {
1356 // This behavior is backwards compat with earlier Formik 0.9 to 1.x
1357 if (typeof component === 'string') {
1358 var innerRef = props.innerRef,
1359 rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
1360
1361 return React.createElement(component, _extends({
1362 ref: innerRef
1363 }, field, rest), children);
1364 } // We don't pass `meta` for backwards compat
1365
1366
1367 return React.createElement(component, _extends({
1368 field: field,
1369 form: formik
1370 }, props), children);
1371 } // default to input here so we can check for both `as` and `children` above
1372
1373
1374 var asElement = is || 'input';
1375
1376 if (typeof asElement === 'string') {
1377 var _innerRef = props.innerRef,
1378 _rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
1379
1380 return React.createElement(asElement, _extends({
1381 ref: _innerRef
1382 }, field, _rest), children);
1383 }
1384
1385 return React.createElement(asElement, _extends({}, field, props), children);
1386}
1387
1388var Form = /*#__PURE__*/React.forwardRef(function (props, ref) {
1389 // iOS needs an "action" attribute for nice input: https://stackoverflow.com/a/39485162/406725
1390 // We default the action to "#" in case the preventDefault fails (just updates the URL hash)
1391 var action = props.action,
1392 rest = _objectWithoutPropertiesLoose(props, ["action"]);
1393
1394 var _action = action != null ? action : '#';
1395
1396 var _useFormikContext = useFormikContext(),
1397 handleReset = _useFormikContext.handleReset,
1398 handleSubmit = _useFormikContext.handleSubmit;
1399
1400 return React.createElement("form", Object.assign({
1401 onSubmit: handleSubmit,
1402 ref: ref,
1403 onReset: handleReset,
1404 action: _action
1405 }, rest));
1406});
1407Form.displayName = 'Form';
1408
1409/**
1410 * A public higher-order component to access the imperative API
1411 */
1412
1413function withFormik(_ref) {
1414 var _ref$mapPropsToValues = _ref.mapPropsToValues,
1415 mapPropsToValues = _ref$mapPropsToValues === void 0 ? function (vanillaProps) {
1416 var val = {};
1417
1418 for (var k in vanillaProps) {
1419 if (vanillaProps.hasOwnProperty(k) && typeof vanillaProps[k] !== 'function') {
1420 // @todo TypeScript fix
1421 val[k] = vanillaProps[k];
1422 }
1423 }
1424
1425 return val;
1426 } : _ref$mapPropsToValues,
1427 config = _objectWithoutPropertiesLoose(_ref, ["mapPropsToValues"]);
1428
1429 return function createFormik(Component) {
1430 var componentDisplayName = Component.displayName || Component.name || Component.constructor && Component.constructor.name || 'Component';
1431 /**
1432 * We need to use closures here for to provide the wrapped component's props to
1433 * the respective withFormik config methods.
1434 */
1435
1436 var C = /*#__PURE__*/function (_React$Component) {
1437 _inheritsLoose(C, _React$Component);
1438
1439 function C() {
1440 var _this;
1441
1442 _this = _React$Component.apply(this, arguments) || this;
1443
1444 _this.validate = function (values) {
1445 return config.validate(values, _this.props);
1446 };
1447
1448 _this.validationSchema = function () {
1449 return isFunction(config.validationSchema) ? config.validationSchema(_this.props) : config.validationSchema;
1450 };
1451
1452 _this.handleSubmit = function (values, actions) {
1453 return config.handleSubmit(values, _extends({}, actions, {
1454 props: _this.props
1455 }));
1456 };
1457 /**
1458 * Just avoiding a render callback for perf here
1459 */
1460
1461
1462 _this.renderFormComponent = function (formikProps) {
1463 return React.createElement(Component, Object.assign({}, _this.props, formikProps));
1464 };
1465
1466 return _this;
1467 }
1468
1469 var _proto = C.prototype;
1470
1471 _proto.render = function render() {
1472 var _this$props = this.props,
1473 props = _objectWithoutPropertiesLoose(_this$props, ["children"]);
1474
1475 return React.createElement(Formik, Object.assign({}, props, config, {
1476 validate: config.validate && this.validate,
1477 validationSchema: config.validationSchema && this.validationSchema,
1478 initialValues: mapPropsToValues(this.props),
1479 initialStatus: config.mapPropsToStatus && config.mapPropsToStatus(this.props),
1480 initialErrors: config.mapPropsToErrors && config.mapPropsToErrors(this.props),
1481 initialTouched: config.mapPropsToTouched && config.mapPropsToTouched(this.props),
1482 onSubmit: this.handleSubmit,
1483 children: this.renderFormComponent
1484 }));
1485 };
1486
1487 return C;
1488 }(React.Component);
1489
1490 C.displayName = "WithFormik(" + componentDisplayName + ")";
1491 return hoistNonReactStatics(C, Component // cast type to ComponentClass (even if SFC)
1492 );
1493 };
1494}
1495
1496/**
1497 * Connect any component to Formik context, and inject as a prop called `formik`;
1498 * @param Comp React Component
1499 */
1500
1501function connect(Comp) {
1502 var C = function C(props) {
1503 return React.createElement(FormikConsumer, null, function (formik) {
1504 !!!formik ? 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) : void 0;
1505 return React.createElement(Comp, Object.assign({}, props, {
1506 formik: formik
1507 }));
1508 });
1509 };
1510
1511 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
1512 // For example, <Field.WrappedComponent /> gets us <FieldInner/>
1513
1514 C.WrappedComponent = Comp;
1515 C.displayName = "FormikConnect(" + componentDisplayName + ")";
1516 return hoistNonReactStatics(C, Comp // cast type to ComponentClass (even if SFC)
1517 );
1518}
1519
1520/**
1521 * Some array helpers!
1522 */
1523
1524var move = function move(array, from, to) {
1525 var copy = copyArrayLike(array);
1526 var value = copy[from];
1527 copy.splice(from, 1);
1528 copy.splice(to, 0, value);
1529 return copy;
1530};
1531var swap = function swap(arrayLike, indexA, indexB) {
1532 var copy = copyArrayLike(arrayLike);
1533 var a = copy[indexA];
1534 copy[indexA] = copy[indexB];
1535 copy[indexB] = a;
1536 return copy;
1537};
1538var insert = function insert(arrayLike, index, value) {
1539 var copy = copyArrayLike(arrayLike);
1540 copy.splice(index, 0, value);
1541 return copy;
1542};
1543var replace = function replace(arrayLike, index, value) {
1544 var copy = copyArrayLike(arrayLike);
1545 copy[index] = value;
1546 return copy;
1547};
1548
1549var copyArrayLike = function copyArrayLike(arrayLike) {
1550 if (!arrayLike) {
1551 return [];
1552 } else if (Array.isArray(arrayLike)) {
1553 return [].concat(arrayLike);
1554 } else {
1555 var maxIndex = Object.keys(arrayLike).map(function (key) {
1556 return parseInt(key);
1557 }).reduce(function (max, el) {
1558 return el > max ? el : max;
1559 }, 0);
1560 return Array.from(_extends({}, arrayLike, {
1561 length: maxIndex + 1
1562 }));
1563 }
1564};
1565
1566var FieldArrayInner = /*#__PURE__*/function (_React$Component) {
1567 _inheritsLoose(FieldArrayInner, _React$Component);
1568
1569 function FieldArrayInner(props) {
1570 var _this;
1571
1572 _this = _React$Component.call(this, props) || this;
1573
1574 _this.updateArrayField = function (fn, alterTouched, alterErrors) {
1575 var _this$props = _this.props,
1576 name = _this$props.name,
1577 setFormikState = _this$props.formik.setFormikState;
1578 setFormikState(function (prevState) {
1579 var updateErrors = typeof alterErrors === 'function' ? alterErrors : fn;
1580 var updateTouched = typeof alterTouched === 'function' ? alterTouched : fn; // values fn should be executed before updateErrors and updateTouched,
1581 // otherwise it causes an error with unshift.
1582
1583 var values = setIn(prevState.values, name, fn(getIn(prevState.values, name)));
1584 var fieldError = alterErrors ? updateErrors(getIn(prevState.errors, name)) : undefined;
1585 var fieldTouched = alterTouched ? updateTouched(getIn(prevState.touched, name)) : undefined;
1586
1587 if (isEmptyArray(fieldError)) {
1588 fieldError = undefined;
1589 }
1590
1591 if (isEmptyArray(fieldTouched)) {
1592 fieldTouched = undefined;
1593 }
1594
1595 return _extends({}, prevState, {
1596 values: values,
1597 errors: alterErrors ? setIn(prevState.errors, name, fieldError) : prevState.errors,
1598 touched: alterTouched ? setIn(prevState.touched, name, fieldTouched) : prevState.touched
1599 });
1600 });
1601 };
1602
1603 _this.push = function (value) {
1604 return _this.updateArrayField(function (arrayLike) {
1605 return [].concat(copyArrayLike(arrayLike), [cloneDeep(value)]);
1606 }, false, false);
1607 };
1608
1609 _this.handlePush = function (value) {
1610 return function () {
1611 return _this.push(value);
1612 };
1613 };
1614
1615 _this.swap = function (indexA, indexB) {
1616 return _this.updateArrayField(function (array) {
1617 return swap(array, indexA, indexB);
1618 }, true, true);
1619 };
1620
1621 _this.handleSwap = function (indexA, indexB) {
1622 return function () {
1623 return _this.swap(indexA, indexB);
1624 };
1625 };
1626
1627 _this.move = function (from, to) {
1628 return _this.updateArrayField(function (array) {
1629 return move(array, from, to);
1630 }, true, true);
1631 };
1632
1633 _this.handleMove = function (from, to) {
1634 return function () {
1635 return _this.move(from, to);
1636 };
1637 };
1638
1639 _this.insert = function (index, value) {
1640 return _this.updateArrayField(function (array) {
1641 return insert(array, index, value);
1642 }, function (array) {
1643 return insert(array, index, null);
1644 }, function (array) {
1645 return insert(array, index, null);
1646 });
1647 };
1648
1649 _this.handleInsert = function (index, value) {
1650 return function () {
1651 return _this.insert(index, value);
1652 };
1653 };
1654
1655 _this.replace = function (index, value) {
1656 return _this.updateArrayField(function (array) {
1657 return replace(array, index, value);
1658 }, false, false);
1659 };
1660
1661 _this.handleReplace = function (index, value) {
1662 return function () {
1663 return _this.replace(index, value);
1664 };
1665 };
1666
1667 _this.unshift = function (value) {
1668 var length = -1;
1669
1670 _this.updateArrayField(function (array) {
1671 var arr = array ? [value].concat(array) : [value];
1672
1673 if (length < 0) {
1674 length = arr.length;
1675 }
1676
1677 return arr;
1678 }, function (array) {
1679 var arr = array ? [null].concat(array) : [null];
1680
1681 if (length < 0) {
1682 length = arr.length;
1683 }
1684
1685 return arr;
1686 }, function (array) {
1687 var arr = array ? [null].concat(array) : [null];
1688
1689 if (length < 0) {
1690 length = arr.length;
1691 }
1692
1693 return arr;
1694 });
1695
1696 return length;
1697 };
1698
1699 _this.handleUnshift = function (value) {
1700 return function () {
1701 return _this.unshift(value);
1702 };
1703 };
1704
1705 _this.handleRemove = function (index) {
1706 return function () {
1707 return _this.remove(index);
1708 };
1709 };
1710
1711 _this.handlePop = function () {
1712 return function () {
1713 return _this.pop();
1714 };
1715 }; // We need TypeScript generics on these, so we'll bind them in the constructor
1716 // @todo Fix TS 3.2.1
1717
1718
1719 _this.remove = _this.remove.bind(_assertThisInitialized(_this));
1720 _this.pop = _this.pop.bind(_assertThisInitialized(_this));
1721 return _this;
1722 }
1723
1724 var _proto = FieldArrayInner.prototype;
1725
1726 _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
1727 if (this.props.validateOnChange && this.props.formik.validateOnChange && !isEqual(getIn(prevProps.formik.values, prevProps.name), getIn(this.props.formik.values, this.props.name))) {
1728 this.props.formik.validateForm(this.props.formik.values);
1729 }
1730 };
1731
1732 _proto.remove = function remove(index) {
1733 // We need to make sure we also remove relevant pieces of `touched` and `errors`
1734 var result;
1735 this.updateArrayField( // so this gets call 3 times
1736 function (array) {
1737 var copy = array ? copyArrayLike(array) : [];
1738
1739 if (!result) {
1740 result = copy[index];
1741 }
1742
1743 if (isFunction(copy.splice)) {
1744 copy.splice(index, 1);
1745 }
1746
1747 return copy;
1748 }, true, true);
1749 return result;
1750 };
1751
1752 _proto.pop = function pop() {
1753 // Remove relevant pieces of `touched` and `errors` too!
1754 var result;
1755 this.updateArrayField( // so this gets call 3 times
1756 function (array) {
1757 var tmp = array;
1758
1759 if (!result) {
1760 result = tmp && tmp.pop && tmp.pop();
1761 }
1762
1763 return tmp;
1764 }, true, true);
1765 return result;
1766 };
1767
1768 _proto.render = function render() {
1769 var arrayHelpers = {
1770 push: this.push,
1771 pop: this.pop,
1772 swap: this.swap,
1773 move: this.move,
1774 insert: this.insert,
1775 replace: this.replace,
1776 unshift: this.unshift,
1777 remove: this.remove,
1778 handlePush: this.handlePush,
1779 handlePop: this.handlePop,
1780 handleSwap: this.handleSwap,
1781 handleMove: this.handleMove,
1782 handleInsert: this.handleInsert,
1783 handleReplace: this.handleReplace,
1784 handleUnshift: this.handleUnshift,
1785 handleRemove: this.handleRemove
1786 };
1787
1788 var _this$props2 = this.props,
1789 component = _this$props2.component,
1790 render = _this$props2.render,
1791 children = _this$props2.children,
1792 name = _this$props2.name,
1793 _this$props2$formik = _this$props2.formik,
1794 restOfFormik = _objectWithoutPropertiesLoose(_this$props2$formik, ["validate", "validationSchema"]);
1795
1796 var props = _extends({}, arrayHelpers, {
1797 form: restOfFormik,
1798 name: name
1799 });
1800
1801 return component ? React.createElement(component, props) : render ? render(props) : children // children come last, always called
1802 ? typeof children === 'function' ? children(props) : !isEmptyChildren(children) ? React.Children.only(children) : null : null;
1803 };
1804
1805 return FieldArrayInner;
1806}(React.Component);
1807
1808FieldArrayInner.defaultProps = {
1809 validateOnChange: true
1810};
1811var FieldArray = /*#__PURE__*/connect(FieldArrayInner);
1812
1813var ErrorMessageImpl = /*#__PURE__*/function (_React$Component) {
1814 _inheritsLoose(ErrorMessageImpl, _React$Component);
1815
1816 function ErrorMessageImpl() {
1817 return _React$Component.apply(this, arguments) || this;
1818 }
1819
1820 var _proto = ErrorMessageImpl.prototype;
1821
1822 _proto.shouldComponentUpdate = function shouldComponentUpdate(props) {
1823 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) {
1824 return true;
1825 } else {
1826 return false;
1827 }
1828 };
1829
1830 _proto.render = function render() {
1831 var _this$props = this.props,
1832 component = _this$props.component,
1833 formik = _this$props.formik,
1834 render = _this$props.render,
1835 children = _this$props.children,
1836 name = _this$props.name,
1837 rest = _objectWithoutPropertiesLoose(_this$props, ["component", "formik", "render", "children", "name"]);
1838
1839 var touch = getIn(formik.touched, name);
1840 var error = getIn(formik.errors, name);
1841 return !!touch && !!error ? render ? isFunction(render) ? render(error) : null : children ? isFunction(children) ? children(error) : null : component ? React.createElement(component, rest, error) : error : null;
1842 };
1843
1844 return ErrorMessageImpl;
1845}(React.Component);
1846
1847var ErrorMessage = /*#__PURE__*/connect(ErrorMessageImpl);
1848
1849/**
1850 * Custom Field component for quickly hooking into Formik
1851 * context and wiring up forms.
1852 */
1853
1854var FastFieldInner = /*#__PURE__*/function (_React$Component) {
1855 _inheritsLoose(FastFieldInner, _React$Component);
1856
1857 function FastFieldInner(props) {
1858 var _this;
1859
1860 _this = _React$Component.call(this, props) || this;
1861 var render = props.render,
1862 children = props.children,
1863 component = props.component,
1864 is = props.as,
1865 name = props.name;
1866 !!render ? invariant(false, "<FastField render> has been deprecated. Please use a child callback function instead: <FastField name={" + name + "}>{props => ...}</FastField> instead.") : void 0;
1867 !!(component && render) ? invariant(false, 'You should not use <FastField component> and <FastField render> in the same <FastField> component; <FastField component> will be ignored') : void 0;
1868 !!(is && children && isFunction(children)) ? invariant(false, 'You should not use <FastField as> and <FastField children> as a function in the same <FastField> component; <FastField as> will be ignored.') : void 0;
1869 !!(component && children && isFunction(children)) ? invariant(false, 'You should not use <FastField component> and <FastField children> as a function in the same <FastField> component; <FastField component> will be ignored.') : void 0;
1870 !!(render && children && !isEmptyChildren(children)) ? invariant(false, 'You should not use <FastField render> and <FastField children> in the same <FastField> component; <FastField children> will be ignored') : void 0;
1871 return _this;
1872 }
1873
1874 var _proto = FastFieldInner.prototype;
1875
1876 _proto.shouldComponentUpdate = function shouldComponentUpdate(props) {
1877 if (this.props.shouldUpdate) {
1878 return this.props.shouldUpdate(props, this.props);
1879 } 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) {
1880 return true;
1881 } else {
1882 return false;
1883 }
1884 };
1885
1886 _proto.componentDidMount = function componentDidMount() {
1887 // Register the Field with the parent Formik. Parent will cycle through
1888 // registered Field's validate fns right prior to submit
1889 this.props.formik.registerField(this.props.name, {
1890 validate: this.props.validate
1891 });
1892 };
1893
1894 _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
1895 if (this.props.name !== prevProps.name) {
1896 this.props.formik.unregisterField(prevProps.name);
1897 this.props.formik.registerField(this.props.name, {
1898 validate: this.props.validate
1899 });
1900 }
1901
1902 if (this.props.validate !== prevProps.validate) {
1903 this.props.formik.registerField(this.props.name, {
1904 validate: this.props.validate
1905 });
1906 }
1907 };
1908
1909 _proto.componentWillUnmount = function componentWillUnmount() {
1910 this.props.formik.unregisterField(this.props.name);
1911 };
1912
1913 _proto.render = function render() {
1914 var _this$props = this.props,
1915 name = _this$props.name,
1916 render = _this$props.render,
1917 is = _this$props.as,
1918 children = _this$props.children,
1919 component = _this$props.component,
1920 formik = _this$props.formik,
1921 props = _objectWithoutPropertiesLoose(_this$props, ["validate", "name", "render", "as", "children", "component", "shouldUpdate", "formik"]);
1922
1923 var restOfFormik = _objectWithoutPropertiesLoose(formik, ["validate", "validationSchema"]);
1924
1925 var field = formik.getFieldProps(_extends({
1926 name: name
1927 }, props));
1928 var meta = {
1929 value: getIn(formik.values, name),
1930 error: getIn(formik.errors, name),
1931 touched: !!getIn(formik.touched, name),
1932 initialValue: getIn(formik.initialValues, name),
1933 initialTouched: !!getIn(formik.initialTouched, name),
1934 initialError: getIn(formik.initialErrors, name)
1935 };
1936 var bag = {
1937 field: field,
1938 meta: meta,
1939 form: restOfFormik
1940 };
1941
1942 if (render) {
1943 return render(bag);
1944 }
1945
1946 if (isFunction(children)) {
1947 return children(bag);
1948 }
1949
1950 if (component) {
1951 // This behavior is backwards compat with earlier Formik 0.9 to 1.x
1952 if (typeof component === 'string') {
1953 var innerRef = props.innerRef,
1954 rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
1955
1956 return React.createElement(component, _extends({
1957 ref: innerRef
1958 }, field, rest), children);
1959 } // We don't pass `meta` for backwards compat
1960
1961
1962 return React.createElement(component, _extends({
1963 field: field,
1964 form: formik
1965 }, props), children);
1966 } // default to input here so we can check for both `as` and `children` above
1967
1968
1969 var asElement = is || 'input';
1970
1971 if (typeof asElement === 'string') {
1972 var _innerRef = props.innerRef,
1973 _rest = _objectWithoutPropertiesLoose(props, ["innerRef"]);
1974
1975 return React.createElement(asElement, _extends({
1976 ref: _innerRef
1977 }, field, _rest), children);
1978 }
1979
1980 return React.createElement(asElement, _extends({}, field, props), children);
1981 };
1982
1983 return FastFieldInner;
1984}(React.Component);
1985
1986var FastField = /*#__PURE__*/connect(FastFieldInner);
1987
1988exports.ErrorMessage = ErrorMessage;
1989exports.FastField = FastField;
1990exports.Field = Field;
1991exports.FieldArray = FieldArray;
1992exports.Form = Form;
1993exports.Formik = Formik;
1994exports.FormikConsumer = FormikConsumer;
1995exports.FormikContext = FormikContext;
1996exports.FormikProvider = FormikProvider;
1997exports.connect = connect;
1998exports.getActiveElement = getActiveElement;
1999exports.getIn = getIn;
2000exports.insert = insert;
2001exports.isEmptyArray = isEmptyArray;
2002exports.isEmptyChildren = isEmptyChildren;
2003exports.isFunction = isFunction;
2004exports.isInputEvent = isInputEvent;
2005exports.isInteger = isInteger;
2006exports.isNaN = isNaN$1;
2007exports.isObject = isObject;
2008exports.isPromise = isPromise;
2009exports.isString = isString;
2010exports.move = move;
2011exports.prepareDataForValidation = prepareDataForValidation;
2012exports.replace = replace;
2013exports.setIn = setIn;
2014exports.setNestedObjectValues = setNestedObjectValues;
2015exports.swap = swap;
2016exports.useField = useField;
2017exports.useFormik = useFormik;
2018exports.useFormikContext = useFormikContext;
2019exports.validateYupSchema = validateYupSchema;
2020exports.withFormik = withFormik;
2021exports.yupToFormErrors = yupToFormErrors;
2022//# sourceMappingURL=formik.cjs.development.js.map