import { useCallback, useRef } from 'react';
import PropTypes from 'prop-types';
import { BREAKPOINTS } from '../../constants';
import { BUTTON_VARIANT_CLASSES as variantClasses } from './FormTheme';
import { clsm, noop } from '../../utils';
import { useResponsiveDevice } from '../../contexts/ResponsiveDevice';
import Button from '../../components/Button';
import Input from '../../components/Input';
import useForm from './useForm';
import useThrottledCallback from '../../hooks/useThrottledCallback';
const Form = ({
'data-testid': dataTestId,
className,
clearFormOnSuccess,
disableSubmit,
disableValidation,
errorHandler,
footer,
formVariant,
inputsData,
inputVariant,
onFailure,
onSuccess,
submitBtnVariant,
submitHandler,
submitText,
title,
validationCheck
}) => {
const [formProps, isLoading, onChange, onSubmit, presubmitValidation] =
useForm({
disableValidation,
errorHandler,
inputsData,
onFailure,
onSuccess,
submitHandler,
validationCheck
});
const isFormComplete = Object.values(formProps).every(({ value }) => value);
const { currentBreakpoint } = useResponsiveDevice();
const isMobileView = currentBreakpoint < BREAKPOINTS.sm;
const classes = clsm(variantClasses[formVariant], className);
const SubmitButton = useCallback(
() => (
{!!footer &&
{footer}
}
),
[
disableSubmit,
footer,
formProps,
formVariant,
inputVariant,
isFormComplete,
isLoading,
submitBtnVariant,
submitText,
dataTestId
]
);
const throttledPresubmitValidation = useThrottledCallback((name) => {
presubmitValidation(name);
initialFocusedInputValue.current = '';
}, 1000);
const initialFocusedInputValue = useRef('');
const onFocus = ({ target: { value } }) => {
initialFocusedInputValue.current = value;
};
const onBlur = ({ relatedTarget, target: { name, value } }) => {
if (relatedTarget?.type === 'submit') return;
if (value && initialFocusedInputValue.current !== value) {
// If onBlur causes a re-render, then onSubmit will not be called.
// So we wrap the presubmit validation inside a setTimeout to give onSubmit a chance to be called.
setTimeout(() => throttledPresubmitValidation(name));
}
};
return (
);
};
Form.defaultProps = {
'data-testid': undefined,
className: '',
clearFormOnSuccess: true,
disableSubmit: noop,
disableValidation: false,
errorHandler: noop,
footer: null,
formVariant: 'vertical',
inputsData: {},
inputVariant: 'vertical',
onFailure: noop,
onSuccess: noop,
submitBtnVariant: 'primary',
submitText: 'Submit',
title: '',
validationCheck: noop
};
Form.propTypes = {
'data-testid': PropTypes.string,
className: PropTypes.string,
clearFormOnSuccess: PropTypes.bool,
disableSubmit: PropTypes.func,
disableValidation: PropTypes.bool,
errorHandler: PropTypes.func,
footer: PropTypes.node,
formVariant: PropTypes.oneOf(['vertical', 'horizontal']),
inputsData: PropTypes.object,
inputVariant: PropTypes.oneOf(['vertical', 'horizontal']),
onFailure: PropTypes.func,
onSuccess: PropTypes.func,
submitBtnVariant: PropTypes.oneOf([
'primary',
'tertiary',
'secondary',
'destructive',
'link'
]),
submitHandler: PropTypes.func.isRequired,
submitText: PropTypes.string.isRequired,
title: PropTypes.string,
validationCheck: PropTypes.func
};
export default Form;