@appbuckets/react-ui-forms
Version:
An utilities package to manage and create Form using AppBuckets ReactUI
370 lines (363 loc) • 11.1 kB
JavaScript
;
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;