UNPKG

informed

Version:

A lightweight framework and utility for building powerful forms in React applications

261 lines (244 loc) 10.7 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _rollupPluginBabelHelpers = require('../_virtual/_rollupPluginBabelHelpers.js'); var React = require('react'); var FormController = require('../FormController.js'); var Context = require('../Context.js'); var useUpdateEffect = require('./useUpdateEffect.js'); var useInformed = require('./useInformed.js'); var debug = require('../debug.js'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); var _excluded = ["onSubmit", "onReset", "onChange", "onSubmitFailure", "onValueChange", "onValueSet", "onValid", "onInvalid", "onValueModified", "initialValues", "validateFields", "autocomplete", "showErrorIfError", "showErrorIfTouched", "showErrorIfDirty", "validateOn", "validateOnMount", "formApiRef", "dontPreventDefault", "yupSchema", "allowEmptyStrings", "disabled", "preventEnter", "validateModified", "schema", "ajv", "ajvErrors", "components", "errorMessage", "fieldMap", "adapter", "name", "keepState", "keepStateIfRelevant", "focusOnInvalid", "scrollOnInvalid", "resetOnlyOnscreen", "debounceGather", "debounceError"]; var logger = debug.Debug('informed:useForm' + '\t'); var useForm = function useForm(_ref) { var _window; var onSubmit = _ref.onSubmit, onReset = _ref.onReset, onChange = _ref.onChange, onSubmitFailure = _ref.onSubmitFailure, onValueChange = _ref.onValueChange, onValueSet = _ref.onValueSet, onValid = _ref.onValid, onInvalid = _ref.onInvalid, onValueModified = _ref.onValueModified, userInitialValues = _ref.initialValues, validateFields = _ref.validateFields, autocomplete = _ref.autocomplete, showErrorIfError = _ref.showErrorIfError, showErrorIfTouched = _ref.showErrorIfTouched, showErrorIfDirty = _ref.showErrorIfDirty, validateOn = _ref.validateOn, validateOnMount = _ref.validateOnMount, formApiRef = _ref.formApiRef, dontPreventDefault = _ref.dontPreventDefault, yupSchema = _ref.yupSchema, allowEmptyStrings = _ref.allowEmptyStrings, disabled = _ref.disabled, preventEnter = _ref.preventEnter, validateModified = _ref.validateModified, schema = _ref.schema, ajv = _ref.ajv, ajvErrors = _ref.ajvErrors, components = _ref.components, errorMessage = _ref.errorMessage, fieldMap = _ref.fieldMap, adapter = _ref.adapter, name = _ref.name, keepState = _ref.keepState, keepStateIfRelevant = _ref.keepStateIfRelevant, focusOnInvalid = _ref.focusOnInvalid, scrollOnInvalid = _ref.scrollOnInvalid, resetOnlyOnscreen = _ref.resetOnlyOnscreen, debounceGather = _ref.debounceGather, debounceError = _ref.debounceError, userProps = _rollupPluginBabelHelpers.objectWithoutProperties(_ref, _excluded); // Register this controller by name if we are in global context var informed = useInformed.useInformed(); var initialValues = React.useMemo(function () { if (informed && name) { var _informed$getSavedVal; logger('Checking for saved values', informed.getSavedValues(name)); return (_informed$getSavedVal = informed.getSavedValues(name)) !== null && _informed$getSavedVal !== void 0 ? _informed$getSavedVal : userInitialValues; } return userInitialValues; }, [userInitialValues]); // If we have a schema allow user to add magic validation to the schema before passing it in!! if (typeof window !== 'undefined' && (_window = window) !== null && _window !== void 0 && (_window = _window.informed) !== null && _window !== void 0 && _window.properties) { var _window2; var properties = (_window2 = window) === null || _window2 === void 0 || (_window2 = _window2.informed) === null || _window2 === void 0 ? void 0 : _window2.properties; Object.keys(properties).forEach(function (key) { if (schema.properties[key]) { schema.properties[key]['ui:props'] = properties[key]; } }); } var formControllerOptions = { initialValues: initialValues, validateFields: validateFields, autocomplete: autocomplete, showErrorIfError: showErrorIfError, showErrorIfTouched: showErrorIfTouched !== null && showErrorIfTouched !== void 0 ? showErrorIfTouched : true, showErrorIfDirty: showErrorIfDirty, validateOn: validateOn, validateOnMount: validateOnMount, // NEW STUFF dontPreventDefault: dontPreventDefault, yupSchema: yupSchema, allowEmptyStrings: allowEmptyStrings, disabled: disabled, preventEnter: preventEnter, schema: schema, ajv: ajv, ajvErrors: ajvErrors, components: components, errorMessage: errorMessage, fieldMap: fieldMap, adapter: adapter, keepState: keepState, keepStateIfRelevant: keepStateIfRelevant, validateModified: validateModified, focusOnInvalid: focusOnInvalid, scrollOnInvalid: scrollOnInvalid, resetOnlyOnscreen: resetOnlyOnscreen, debounceGather: debounceGather, debounceError: debounceError }; var optionsRef = React.useRef(); optionsRef.current = formControllerOptions; // Create form controller var _useState = React.useState(function () { return new FormController.FormController(optionsRef); }), _useState2 = _rollupPluginBabelHelpers.slicedToArray(_useState, 1), formController = _useState2[0]; // Register for events React.useEffect(function () { var onChangeHandler = function onChangeHandler() { return onChange && onChange(formController.getFormState()); }; var onResetHandler = function onResetHandler() { return onReset && onReset(formController.getFormState()); }; var onSubmitHandler = function onSubmitHandler() { return onSubmit && onSubmit(formController.getFormState()); }; var onFailureHandler = function onFailureHandler() { return onSubmitFailure && onSubmitFailure(formController.getFormState()); }; var onValueChangeHandler = function onValueChangeHandler(n) { return onValueChange && onValueChange(formController.getFormState(), n); }; var onValueModifiedHandler = function onValueModifiedHandler(n) { return onValueModified && onValueModified(formController.getFormState(), n); }; var onValueSetHandler = function onValueSetHandler(n) { return onValueSet && onValueSet(formController.getFormState(), n); }; var onValidHandler = function onValidHandler() { return onValid && onValid(formController.getFormState()); }; var onInvalidHandler = function onInvalidHandler() { return onInvalid && onInvalid(formController.getFormState()); }; // Register for events formController.on('field', onChangeHandler); formController.on('reset', onResetHandler); formController.on('submit', onSubmitHandler); formController.on('failure', onFailureHandler); formController.on('field-value', onValueChangeHandler); formController.on('field-modified', onValueModifiedHandler); formController.on('field-value-set', onValueSetHandler); formController.on('valid', onValidHandler); formController.on('invalid', onInvalidHandler); // Unregister events return function () { formController.removeListener('field', onChangeHandler); formController.removeListener('reset', onResetHandler); formController.removeListener('submit', onSubmitHandler); formController.removeListener('failure', onFailureHandler); formController.removeListener('field-value', onValueChangeHandler); formController.removeListener('field-modified', onValueModifiedHandler); }; }, [onChange, onReset, onSubmit, onSubmitFailure, onValueChange, onValueModified]); // Form state will be used to trigger rerenders var _useState3 = React.useState(function () { return formController.getFormState(); }), _useState4 = _rollupPluginBabelHelpers.slicedToArray(_useState3, 2), formState = _useState4[0], setFormState = _useState4[1]; // Register for events for ALL fields! React.useEffect(function () { var listener = function listener(target) { setFormState(_rollupPluginBabelHelpers.objectSpread2({}, formController.getFormState())); if (informed) { informed.inform(name, target); } }; formController.emitter.on('field', listener); // Need initial state setFormState(_rollupPluginBabelHelpers.objectSpread2({}, formController.getFormState())); //Register this form if we need to if (name && informed) { informed.register(name, formController); } return function () { formController.emitter.removeListener('field', listener); if (name && informed) { // informed.deregister(name); informed.setSavedValues(name, formController.getFormState().values); } }; }, []); // YES! this is important! Otherwise it would get a new formApi object every render /// That would cause unessissarry re-renders! so do not remove useMemeo! var formApi = React.useMemo(function () { if (formApiRef) { formApiRef.current = formController.getFormApi(); } return formController.getFormApi(); }, []); useUpdateEffect.useUpdateEffect(function () { // If the form is pristine then reset it when we get new initial values ! var _formApi$getFormState = formApi.getFormState(), pristine = _formApi$getFormState.pristine; if (pristine) { logger('Resetting entire form as form is pristine and we got new initial values'); formApi.reset(); } }, [initialValues]); useUpdateEffect.useUpdateEffect(function () { if (disabled) { formApi.disable(); } else { formApi.enable(); } }, [disabled]); React.useEffect(function () { logger('Mount'); formController.lockRemoval(false); return function () { // Important so we dont clear values!!! formController.lockRemoval(true); logger('Un-Mount'); }; }, []); var render = function render(children) { return /*#__PURE__*/React__default["default"].createElement(Context.FormControllerContext.Provider, { value: formController }, /*#__PURE__*/React__default["default"].createElement(Context.FormApiContext.Provider, { value: formApi }, /*#__PURE__*/React__default["default"].createElement(Context.FormStateContext.Provider, { value: formState }, children))); }; return { formApi: formApi, formState: formState, formController: formController, render: render, userProps: userProps }; }; exports.useForm = useForm;