UNPKG

@appbuckets/react-ui-forms

Version:

An utilities package to manage and create Form using AppBuckets ReactUI

332 lines (329 loc) 9.97 kB
import { __rest, __awaiter, __read, __assign, __generator, } from '../_virtual/_tslib.js'; import * as React from 'react'; import clsx from 'clsx'; import { useForm } from 'react-hook-form'; import Form from '@appbuckets/react-ui/Form'; import { HookedFormProvider } from '../context/HookedForm.context.js'; import HookedFormActions from './HookedFormActions.js'; import HookedFormContent from './HookedFormContent.js'; var HookedForm = React.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 = __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 = 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( { 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.useEffect( function () { /** Check if must reset form state */ if (restoreDefaultValuesIfChanged) { resetForm(defaultValues); } }, [resetForm, defaultValues, restoreDefaultValuesIfChanged] ); // ---- // Handler & Submit Wrapper // ---- var handleValidFormSubmit = React.useCallback( function (values) { return __awaiter(void 0, void 0, void 0, function () { var result, _a, error_1; return __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.useCallback( function (errors) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) { if (typeof userDefinedOnInvalidSubmitHandler === 'function') { userDefinedOnInvalidSubmitHandler( errors, hookFormCtx, context || {} ); } return [2 /*return*/]; }); }); }, [context, hookFormCtx, userDefinedOnInvalidSubmitHandler] ); var wrappedNativeSubmitHandler = React.useCallback( function () { return hookFormCtx.handleSubmit( handleValidFormSubmit, handleInvalidFormSubmit ); }, [handleInvalidFormSubmit, handleValidFormSubmit, hookFormCtx] ); var handleFormCancel = React.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.useRef({}); var registerChangeHandler = React.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.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 = __read(React.useState({}), 2), fieldValues = _a[0], setFieldValues = _a[1]; var useFieldValue = React.useCallback( function (field) { /** Register a new handler */ registerChangeHandler(field, function (newValue) { var _a; setFieldValues( __assign( __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 = __assign(__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.createElement( HookedFormProvider, { value: ctxValue }, React.createElement( Form, __assign({}, restFormComponent, { ref: ref, className: classes, onSubmit: wrappedNativeSubmitHandler(), }), React.createElement(HookedFormContent, null, children), React.createElement(HookedFormActions, null) ) ); }); HookedForm.displayName = 'HookedForm'; HookedForm.defaultProps = { actionsWrapper: 'div', breakOnFirstError: false, contentWrapper: 'div', reValidateOn: 'onChange', validateOn: 'onSubmit', }; export { HookedForm as default };