UNPKG

mobx-hooks-form

Version:

React form package using mobX, React hooks and context

545 lines (441 loc) 16.8 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } var tslib = require('tslib'); var React = require('react'); var React__default = _interopDefault(React); var mobx = require('mobx'); var mobxUtils = require('mobx-utils'); var mobxReactLite = require('mobx-react-lite'); var lodash = require('lodash'); var yup = require('yup'); function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } 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); } var isObject = function isObject(obj) { return typeof obj === 'object' && obj !== null; }; var pathToArr = function pathToArr(path) { var output = []; path.split('.').forEach(function (item) { item.split(/\[([^}]+)\]/g).forEach(function (key) { if (key.length > 0) { output.push(key); } }); }); return output; }; var get = function get(path) { return function (obj) { var ar = pathToArr(path); if (ar[5]) { throw Error('mobx form path is too deep'); } else if (ar[4]) { var _obj$ar$, _obj$ar$$ar$, _obj$ar$$ar$$ar$, _obj$ar$$ar$$ar$$ar$; return (_obj$ar$ = obj[ar[0]]) === null || _obj$ar$ === void 0 ? void 0 : (_obj$ar$$ar$ = _obj$ar$[ar[1]]) === null || _obj$ar$$ar$ === void 0 ? void 0 : (_obj$ar$$ar$$ar$ = _obj$ar$$ar$[ar[2]]) === null || _obj$ar$$ar$$ar$ === void 0 ? void 0 : (_obj$ar$$ar$$ar$$ar$ = _obj$ar$$ar$$ar$[ar[3]]) === null || _obj$ar$$ar$$ar$$ar$ === void 0 ? void 0 : _obj$ar$$ar$$ar$$ar$[ar[4]]; } else if (ar[3]) { var _obj$ar$2, _obj$ar$2$ar$, _obj$ar$2$ar$$ar$; return (_obj$ar$2 = obj[ar[0]]) === null || _obj$ar$2 === void 0 ? void 0 : (_obj$ar$2$ar$ = _obj$ar$2[ar[1]]) === null || _obj$ar$2$ar$ === void 0 ? void 0 : (_obj$ar$2$ar$$ar$ = _obj$ar$2$ar$[ar[2]]) === null || _obj$ar$2$ar$$ar$ === void 0 ? void 0 : _obj$ar$2$ar$$ar$[ar[3]]; } else if (ar[2]) { var _obj$ar$3, _obj$ar$3$ar$; return (_obj$ar$3 = obj[ar[0]]) === null || _obj$ar$3 === void 0 ? void 0 : (_obj$ar$3$ar$ = _obj$ar$3[ar[1]]) === null || _obj$ar$3$ar$ === void 0 ? void 0 : _obj$ar$3$ar$[ar[2]]; } else if (ar[1]) { var _obj$ar$4; return (_obj$ar$4 = obj[ar[0]]) === null || _obj$ar$4 === void 0 ? void 0 : _obj$ar$4[ar[1]]; } else { return obj[ar[0]]; } }; }; var set = function set(path) { return function (value) { return function (obj) { var ar = pathToArr(path); if (ar[5]) { throw Error('mobx form path is too deep'); } else if (ar[4]) { var _obj$ar$5, _obj$ar$5$ar$, _obj$ar$5$ar$$ar$; var base = (_obj$ar$5 = obj[ar[0]]) === null || _obj$ar$5 === void 0 ? void 0 : (_obj$ar$5$ar$ = _obj$ar$5[ar[1]]) === null || _obj$ar$5$ar$ === void 0 ? void 0 : (_obj$ar$5$ar$$ar$ = _obj$ar$5$ar$[ar[2]]) === null || _obj$ar$5$ar$$ar$ === void 0 ? void 0 : _obj$ar$5$ar$$ar$[ar[3]]; if (isObject(base)) { base[ar[4]] = value; } } else if (ar[3]) { var _obj$ar$6, _obj$ar$6$ar$; var _base = (_obj$ar$6 = obj[ar[0]]) === null || _obj$ar$6 === void 0 ? void 0 : (_obj$ar$6$ar$ = _obj$ar$6[ar[1]]) === null || _obj$ar$6$ar$ === void 0 ? void 0 : _obj$ar$6$ar$[ar[2]]; if (isObject(_base)) { _base[ar[3]] = value; } } else if (ar[2]) { var _obj$ar$7; var _base2 = (_obj$ar$7 = obj[ar[0]]) === null || _obj$ar$7 === void 0 ? void 0 : _obj$ar$7[ar[1]]; if (isObject(_base2)) { _base2[ar[2]] = value; } } else if (ar[1]) { var _base3 = obj[ar[0]]; if (isObject(_base3)) { _base3[ar[1]] = value; } } else { obj[ar[0]] = value; } }; }; }; function getErrorsFromValidationError(validationError) { var FIRST_ERROR = 0; return validationError.inner.reduce(function (errors, error) { var _extends2; return _extends({}, errors, (_extends2 = {}, _extends2[error.path] = error.errors[FIRST_ERROR], _extends2)); }, {}); } function validate(schema, values) { try { schema.validateSync(values, { abortEarly: false, recursive: true }); return {}; } catch (error) { return getErrorsFromValidationError(error); } } var Store = /*#__PURE__*/ function () { function Store(props) { var _this = this; this.debug = false; this.DEBOUNCE_MS = 0; this.isTouchedAll = false; this.touched = {}; this.submitting = false; this.error = undefined; this.setError = function (error) { _this.error = error; }; this.setSubmitting = function (submitting) { _this.submitting = submitting; }; this.values = {}; this.debouncedValues = {}; this.getValue = mobxUtils.computedFn(function getValue(path) { var _get; return (_get = get(path)(this.values)) !== null && _get !== void 0 ? _get : ''; }); this.getDebouncedValue = mobxUtils.computedFn(function getDebouncedValue(path) { var _get2; return (_get2 = get(path)(this.debouncedValues)) !== null && _get2 !== void 0 ? _get2 : ''; }); this.getValueLength = mobxUtils.computedFn(function getValueLength(path) { var _ref, _this$getValue; return (_ref = (_this$getValue = this.getValue(path)) === null || _this$getValue === void 0 ? void 0 : _this$getValue.length) !== null && _ref !== void 0 ? _ref : 0; }); this.setDebouncedValue = lodash.debounce(function (path, value) { set(path)(value)(_this.debouncedValues); }, this.DEBOUNCE_MS); this.pushDebouncedValue = lodash.debounce(function (path, value) { get(path)(_this.debouncedValues).push(value); }, this.DEBOUNCE_MS); this.removeDebouncedValue = lodash.debounce(function (path, index) { get(path)(_this.debouncedValues).splice(index, 1); }, this.DEBOUNCE_MS); this.pushValue = function (path, value) { get(path)(_this.values).push(value); _this.pushDebouncedValue(path, value); }; this.removeValue = function (path, index) { get(path)(_this.values).splice(index, 1); _this.removeDebouncedValue(path, index); }; this.setValue = function (path) { return function (value) { set(path)(value)(_this.values); _this.setDebouncedValue(path, value); }; }; this.setValues = function (values) { _this.values = values; _this.debouncedValues = values; }; this.isRequired = mobxUtils.computedFn(function isRequired(path) { try { var _ref2; var _yup$reach$describe = yup.reach(this.schema, path, this.debouncedValues, this.debouncedValues).describe(), tests = _yup$reach$describe.tests; return (_ref2 = !!(tests === null || tests === void 0 ? void 0 : tests.find(function (test) { return test.name === 'required'; }))) !== null && _ref2 !== void 0 ? _ref2 : false; } catch (error) { return false; } }); this.reset = function () { _this.setValues(_this.defaultValues); _this.touched = {}; _this.isTouchedAll = false; }; this.handleSubmit = function (submit) { return mobx.action('handleSubmit', function (e) { try { e.preventDefault(); _this.touchAll(); var _temp2 = function () { if (_this.isValid) { var _submit; _this.setSubmitting(true); return Promise.resolve((_submit = submit(_this.values)) === null || _submit === void 0 ? void 0 : _submit["catch"](function (e) { return _this.setError(e); })).then(function () { _this.setSubmitting(false); }); } }(); return Promise.resolve(_temp2 && _temp2.then ? _temp2.then(function () {}) : void 0); } catch (e) { return Promise.reject(e); } }); }; this.touch = function (path) { _this.touched[path] = true; }; this.touchAll = function () { _this.isTouchedAll = true; }; this.getError = mobxUtils.computedFn(function getError(key) { return this.errors[key]; }); this.getId = function (path) { return _this.formName + "_" + path; }; this.getField = mobxUtils.computedFn(function getField(path) { var store = this; return { path: path, submitting: store.submitting, get value() { return store.getValue(path); }, get error() { return store.getError(path); }, id: store.getId(path), setValue: store.setValue(path), onBlur: mobx.action('onBlur', function () { store.touch(path); }), onChange: mobx.action('onChange', function (e) { store.setValue(path)(e.target.value); }), onCheckedChange: mobx.action('onCheckedChange', function (e) { store.setValue(path)(e.target.checked); }), isRequired: store.isRequired(path) }; }); this.getFieldArray = mobxUtils.computedFn(function getFieldArray(path) { var store = this; return { path: path, get error() { return store.getError(path); }, get indexes() { return Array.from(Array(store.getValueLength(path)).keys()); }, id: store.getId(path), isRequired: store.isRequired(path), add: mobx.action('add', function (value) { var ar = store.getValue(path); if (!Array.isArray(ar)) { store.setValue(path)([]); } if (value === undefined) { var defaultAr = get(path)(store.defaultValues); if (Array.isArray(defaultAr)) { value = defaultAr.length ? defaultAr[defaultAr.length - 1] : ''; } else if (defaultAr !== undefined) { value = defaultAr; } else { value = ar.length ? ar[ar.length - 1] : ''; } } store.pushValue(path, value); }), remove: mobx.action('remove', function (index) { var ar = store.getValue(path); if (!Array.isArray(ar) || index >= ar.length) { console.error('trying to remove item from non array or at wrong index'); } else { store.removeValue(path, index); if (ar.length === 0) { var d = get(path)(store.defaultValues); if (!Array.isArray(d)) { store.setValue(path)(d); } } } }) }; }); var schema = props.schema, defaultValues = props.defaultValues, _props$formName = props.formName, formName = _props$formName === void 0 ? '' : _props$formName, _props$debug = props.debug, debug = _props$debug === void 0 ? false : _props$debug, _props$debugMobx = props.debugMobx, debugMobx = _props$debugMobx === void 0 ? false : _props$debugMobx, _props$DEBOUNCE_MS = props.DEBOUNCE_MS, DEBOUNCE_MS = _props$DEBOUNCE_MS === void 0 ? 0 : _props$DEBOUNCE_MS; this.defaultValues = defaultValues || {}; this.schema = schema; this.debug = debug; this.formName = formName; this.DEBOUNCE_MS = DEBOUNCE_MS; this.setValues(defaultValues || {}); var resetError = function resetError() { _this.error = undefined; }; mobx.observe(this.values, function () { return resetError(); }); if (debug) { mobx.autorun(function () { console.log('values', mobx.toJS(_this.values)); console.log('validations', mobx.toJS(_this.validations)); console.log('error', mobx.toJS(_this.error)); }); if (debugMobx) { mobx.spy(function (event) { if (event.type === 'action') { console.log("%c" + event.name + " %c[ " + event.arguments + " ]", 'color: #bad', 'color: #bada55'); } else { if (event.type || event.name) { console.log("%c " + event.type + " | " + event.name, 'color: #f9d299'); } } }); } } } _createClass(Store, [{ key: "validations", get: function get() { return validate(this.schema, this.debouncedValues); } }, { key: "isValid", get: function get() { return lodash.isEmpty(this.validations); } }, { key: "errors", get: function get() { var _this2 = this; return this.isTouchedAll ? this.validations : Object.fromEntries(Object.entries(this.validations).filter(function (_ref3) { var key = _ref3[0]; return _this2.touched[key]; })); } }]); return Store; }(); tslib.__decorate([mobx.observable], Store.prototype, "isTouchedAll", void 0); tslib.__decorate([mobx.observable], Store.prototype, "touched", void 0); tslib.__decorate([mobx.observable], Store.prototype, "submitting", void 0); tslib.__decorate([mobx.observable], Store.prototype, "error", void 0); tslib.__decorate([mobx.action], Store.prototype, "setError", void 0); tslib.__decorate([mobx.action], Store.prototype, "setSubmitting", void 0); tslib.__decorate([mobx.observable], Store.prototype, "values", void 0); tslib.__decorate([mobx.observable], Store.prototype, "debouncedValues", void 0); tslib.__decorate([mobx.action], Store.prototype, "setDebouncedValue", void 0); tslib.__decorate([mobx.action], Store.prototype, "pushDebouncedValue", void 0); tslib.__decorate([mobx.action], Store.prototype, "removeDebouncedValue", void 0); tslib.__decorate([mobx.action], Store.prototype, "pushValue", void 0); tslib.__decorate([mobx.action], Store.prototype, "removeValue", void 0); tslib.__decorate([mobx.action], Store.prototype, "setValue", void 0); tslib.__decorate([mobx.action], Store.prototype, "setValues", void 0); tslib.__decorate([mobx.computed], Store.prototype, "validations", null); tslib.__decorate([mobx.computed], Store.prototype, "isValid", null); tslib.__decorate([mobx.action], Store.prototype, "reset", void 0); tslib.__decorate([mobx.action], Store.prototype, "touch", void 0); tslib.__decorate([mobx.action], Store.prototype, "touchAll", void 0); tslib.__decorate([mobx.computed], Store.prototype, "errors", null); var useForm = function useForm(props) { return mobxReactLite.useLocalStore(function (source) { return new Store(source); }, props); }; var FormContext = /*#__PURE__*/ React__default.createContext({}, function () { return 0; }); var useFormContext = function useFormContext() { return React.useContext(FormContext); }; var FormContextProvider = function FormContextProvider(_ref4) { var children = _ref4.children, formStore = _ref4.formStore; return React__default.createElement(FormContext.Provider, { value: formStore }, children); }; var useField = function useField(path) { return React.useContext(FormContext).getField(path); }; var useFieldArray = function useFieldArray(path) { return React.useContext(FormContext).getFieldArray(path); }; var FieldContext = /*#__PURE__*/ React__default.createContext({}); var useFieldContext = function useFieldContext() { return React.useContext(FieldContext); }; var FieldContextProvider = /*#__PURE__*/ mobxReactLite.observer(function (_ref5) { var children = _ref5.children, path = _ref5.path; var field = React.useContext(FormContext).getField(path); return React__default.createElement(FieldContext.Provider, { value: field }, typeof children === 'function' ? children(field) : children); }); exports.FieldContextProvider = FieldContextProvider; exports.FormContextProvider = FormContextProvider; exports.useField = useField; exports.useFieldArray = useFieldArray; exports.useFieldContext = useFieldContext; exports.useForm = useForm; exports.useFormContext = useFormContext; //# sourceMappingURL=mobx-hooks-form.cjs.development.js.map