UNPKG

@appbuckets/react-ui-forms

Version:

An utilities package to manage and create Form using AppBuckets ReactUI

370 lines (363 loc) 11.1 kB
'use strict'; var _tslib = require('../_virtual/_tslib.js'); var React = require('react'); var clsx = require('clsx'); var reactHookForm = require('react-hook-form'); var Form = require('@appbuckets/react-ui/Form'); var HookedForm_context = require('../context/HookedForm.context.js'); var HookedFormActions = require('./HookedFormActions.js'); var HookedFormContent = require('./HookedFormContent.js'); function _interopDefaultLegacy(e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; } function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty( n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; }, } ); } }); } n['default'] = e; return Object.freeze(n); } var React__namespace = /*#__PURE__*/ _interopNamespace(React); var clsx__default = /*#__PURE__*/ _interopDefaultLegacy(clsx); var Form__default = /*#__PURE__*/ _interopDefaultLegacy(Form); var HookedForm = React__namespace.forwardRef(function (props, ref) { // ---- // Deconstruct Options // ---- var /** Hook form props */ autoFocusFirstError = props.autoFocusFirstError, breakOnFirstError = props.breakOnFirstError, context = props.context, defaultValues = props.defaultValues, resolver = props.resolver, reValidateOn = props.reValidateOn, validateOn = props.validateOn, /** Strict props */ actionsWrapper = props.actionsWrapper, cancelButton = props.cancelButton, children = props.children, className = props.className, contentWrapper = props.contentWrapper, disabled = props.disabled, resetOnCancel = props.resetOnCancel, restoreDefaultValuesIfChanged = props.restoreDefaultValuesIfChanged, submitButton = props.submitButton, /** UserDefined Handlers */ userDefinedOnCancelHandler = props.onCancel, userDefinedOnInvalidSubmitHandler = props.onInvalidSubmit, userDefinedOnSubmitHandler = props.onSubmit, userDefinedOnSubmitErrorHandler = props.onSubmitError, userDefinedOnSubmitSuccessHandler = props.onSubmitSuccess, /** Forwarded props to form component */ restFormComponent = _tslib.__rest(props, [ 'autoFocusFirstError', 'breakOnFirstError', 'context', 'defaultValues', 'resolver', 'reValidateOn', 'validateOn', 'actionsWrapper', 'cancelButton', 'children', 'className', 'contentWrapper', 'disabled', 'resetOnCancel', 'restoreDefaultValuesIfChanged', 'submitButton', 'onCancel', 'onInvalidSubmit', 'onSubmit', 'onSubmitError', 'onSubmitSuccess', ]); // ---- // Initialize HookedForm // ---- var hookFormCtx = reactHookForm.useForm({ mode: validateOn, reValidateMode: reValidateOn, defaultValues: defaultValues, context: context, shouldFocusError: autoFocusFirstError, criteriaMode: breakOnFirstError ? 'firstError' : 'all', resolver: resolver, }); // ---- // Build Classes // ---- var state = hookFormCtx.formState, getValues = hookFormCtx.getValues, setValue = hookFormCtx.setValue; var classes = clsx__default['default']( { disabled: disabled, dirty: state.isDirty, submitted: state.isSubmitted, submitting: state.isSubmitting, valid: state.isValid && !!state.submitCount, invalid: !state.isValid && !!state.submitCount, }, 'hooked-form', className ); // ---- // Default Values Restore // ---- var resetForm = hookFormCtx.reset; React__namespace.useEffect( function () { /** Check if must reset form state */ if (restoreDefaultValuesIfChanged) { resetForm(defaultValues); } }, [resetForm, defaultValues, restoreDefaultValuesIfChanged] ); // ---- // Handler & Submit Wrapper // ---- var handleValidFormSubmit = React__namespace.useCallback( function (values) { return _tslib.__awaiter(void 0, void 0, void 0, function () { var result, _a, error_1; return _tslib.__generator(this, function (_b) { switch (_b.label) { case 0: _b.trys.push([0, 6, , 7]); if (!(typeof userDefinedOnSubmitHandler === 'function')) return [3 /*break*/, 2]; return [ 4 /*yield*/, userDefinedOnSubmitHandler(values, hookFormCtx, context || {}), ]; case 1: _a = _b.sent(); return [3 /*break*/, 3]; case 2: _a = undefined; _b.label = 3; case 3: result = _a; if (!(typeof userDefinedOnSubmitSuccessHandler === 'function')) return [3 /*break*/, 5]; return [ 4 /*yield*/, userDefinedOnSubmitSuccessHandler( result, hookFormCtx, context || {} ), ]; case 4: return [2 /*return*/, _b.sent()]; case 5: return [3 /*break*/, 7]; case 6: error_1 = _b.sent(); /** Call error handler */ if (typeof userDefinedOnSubmitErrorHandler === 'function') { return [ 2 /*return*/, userDefinedOnSubmitErrorHandler( error_1, hookFormCtx, context || {} ), ]; } return [3 /*break*/, 7]; case 7: return [2 /*return*/]; } }); }); }, [ context, hookFormCtx, userDefinedOnSubmitErrorHandler, userDefinedOnSubmitHandler, userDefinedOnSubmitSuccessHandler, ] ); var handleInvalidFormSubmit = React__namespace.useCallback( function (errors) { return _tslib.__awaiter(void 0, void 0, void 0, function () { return _tslib.__generator(this, function (_a) { if (typeof userDefinedOnInvalidSubmitHandler === 'function') { userDefinedOnInvalidSubmitHandler( errors, hookFormCtx, context || {} ); } return [2 /*return*/]; }); }); }, [context, hookFormCtx, userDefinedOnInvalidSubmitHandler] ); var wrappedNativeSubmitHandler = React__namespace.useCallback( function () { return hookFormCtx.handleSubmit( handleValidFormSubmit, handleInvalidFormSubmit ); }, [handleInvalidFormSubmit, handleValidFormSubmit, hookFormCtx] ); var handleFormCancel = React__namespace.useCallback( function () { /** Check if form must be reset */ if (resetOnCancel) { hookFormCtx.reset(); } /** Call user defined onCancel handler */ if (typeof userDefinedOnCancelHandler === 'function') { userDefinedOnCancelHandler( hookFormCtx.getValues(), hookFormCtx, context || {} ); } }, [context, hookFormCtx, resetOnCancel, userDefinedOnCancelHandler] ); // ---- // Field Changed Handlers // ---- var changeHandlers = React__namespace.useRef({}); var registerChangeHandler = React__namespace.useCallback(function ( field, handler ) { /** Get current ref value */ var currentHandlers = changeHandlers.current; /** Create the handler array container if doesn't exists */ if (!Array.isArray(currentHandlers[field])) { currentHandlers[field] = []; } /** Add the new handler to handlers container */ currentHandlers[field].push(handler); /** Return a function to unregister field handler */ return function () { /** Assert current is not changed */ if (Array.isArray(currentHandlers[field])) { /** Remove the handler */ currentHandlers[field] = currentHandlers[field].filter(function ( changeHandler ) { return changeHandler !== handler; }); } }; }, []); var triggerFieldChanged = React__namespace.useCallback(function ( field, value ) { /** Get current handlers */ var currentHandlers = changeHandlers.current; /** Check if there are some registered handlers for field change */ if (currentHandlers[field] && Array.isArray(currentHandlers[field])) { /** Fire all change event handlers */ currentHandlers[field].forEach(function (handler) { return handler(value); }); } }, []); // ---- // Field Values Watched // ---- var _a = _tslib.__read(React__namespace.useState({}), 2), fieldValues = _a[0], setFieldValues = _a[1]; var useFieldValue = React__namespace.useCallback( function (field) { /** Register a new handler */ registerChangeHandler(field, function (newValue) { var _a; setFieldValues( _tslib.__assign( _tslib.__assign({}, fieldValues), ((_a = {}), (_a[field] = newValue), _a) ) ); }); /** Create a nested function to set the new value */ var setNewFieldValue = function (newValue, options) { setValue(field, newValue, options); }; /** Return data */ return [ field in fieldValues ? fieldValues[field] : getValues(field), setNewFieldValue, ]; }, [registerChangeHandler, fieldValues, getValues, setValue] ); // ---- // Context Value Builder // ---- var ctxValue = _tslib.__assign(_tslib.__assign({}, hookFormCtx), { handleSubmit: wrappedNativeSubmitHandler, actionsWrapper: actionsWrapper, cancelButton: cancelButton, contentWrapper: contentWrapper, defaultValues: defaultValues, disabled: !!disabled, handleCancel: handleFormCancel, registerChangeHandler: registerChangeHandler, submitButton: submitButton, triggerFieldChanged: triggerFieldChanged, useFieldValue: useFieldValue, }); // ---- // Render Component // ---- return React__namespace.createElement( HookedForm_context.HookedFormProvider, { value: ctxValue }, React__namespace.createElement( Form__default['default'], _tslib.__assign({}, restFormComponent, { ref: ref, className: classes, onSubmit: wrappedNativeSubmitHandler(), }), React__namespace.createElement(HookedFormContent, null, children), React__namespace.createElement(HookedFormActions, null) ) ); }); HookedForm.displayName = 'HookedForm'; HookedForm.defaultProps = { actionsWrapper: 'div', breakOnFirstError: false, contentWrapper: 'div', reValidateOn: 'onChange', validateOn: 'onSubmit', }; module.exports = HookedForm;