import { jsxs, jsx } from 'react/jsx-runtime';
import { useEffect, forwardRef, useRef, useCallback } from 'react';
import { useFormikContext, Form as Form$1, Formik } from 'formik';
import { is } from 'ramda';

const transformObjectToDotNotation = (object, prefix = "") => {
    const result = [];
    Object.entries(object).forEach(([key, value]) => {
        if (!value)
            return;
        const nextKey = prefix ? `${prefix}.${key}` : key;
        if (is(Object, value)) {
            result.push(...transformObjectToDotNotation(value, nextKey));
        }
        else {
            result.push(nextKey);
        }
    });
    return result;
};
const getErrorFieldName = (formikErrors) => transformObjectToDotNotation(formikErrors)?.[0];
const getFieldsWithServerError = (status = {}) => Object.keys(status).filter(fieldName => status[fieldName] != null && status[fieldName] !== "");
const scrollToError = (formRef, errors, status) => {
    const fieldErrorName = getErrorFieldName(errors);
    const [fieldWithServerError] = getFieldsWithServerError(status);
    if (!fieldErrorName && !fieldWithServerError)
        return;
    const errorFieldName = fieldErrorName || fieldWithServerError;
    const errorFormElement = formRef.current?.querySelector(`[name="${errorFieldName}"]`);
    errorFormElement?.scrollIntoView({
        behavior: "smooth",
        block: "center",
    });
};

const ScrollToErrorField = ({ formRef }) => {
    const { submitCount, isValid, errors, status } = useFormikContext();
    useEffect(() => {
        const fieldsWithServerError = getFieldsWithServerError(status);
        if (!formRef.current || (isValid && fieldsWithServerError.length === 0)) {
            return;
        }
        scrollToError(formRef, errors, status);
    }, [submitCount]);
    return null;
};

const FormWrapper = forwardRef(({ className, formProps, children, scrollToErrorField }, ref) => {
    const { validateForm, setErrors, setTouched, submitForm, ...formikBag } = useFormikContext();
    const { dirty: isFormDirty, isSubmitting, status } = formikBag;
    const formRefForScrollToErrorField = useRef(null);
    const formRef = ref ||
        formRefForScrollToErrorField;
    const handleKeyDown = useCallback(async (event) => {
        const target = event.target;
        const isEventFromEditorOrTextarea = target.tagName === "TEXTAREA" || target.editor;
        if (event.key !== "Enter")
            return;
        if (isEventFromEditorOrTextarea && !event.metaKey)
            return;
        event.preventDefault();
        if (event.shiftKey)
            return;
        if (!isFormDirty || isSubmitting)
            return;
        try {
            const errors = await validateForm();
            const fieldStatuses = getFieldsWithServerError(status);
            if (Object.keys(errors).length > 0 ||
                Object.keys(fieldStatuses).length > 0) {
                setErrors(errors);
                setTouched({ ...errors, ...status });
                if (scrollToErrorField) {
                    scrollToError(formRef, errors, status);
                }
            }
            else {
                submitForm();
            }
        }
        catch (error) {
            console.error("An unhandled error was caught from validateForm()", error);
        }
    }, [
        validateForm,
        setErrors,
        setTouched,
        isFormDirty,
        isSubmitting,
        submitForm,
        status,
        scrollToErrorField,
        formRef,
    ]);
    return (jsxs(Form$1, { className, noValidate: true, ref: formRef, onKeyDown: handleKeyDown, ...formProps, children: [scrollToErrorField && jsx(ScrollToErrorField, { formRef }), children] }));
});
FormWrapper.displayName = "FormWrapper";

const Form = forwardRef(({ className, children, formikProps, formProps, scrollToErrorField = false }, ref) => {
    const formikRef = useRef(null);
    const handleSubmit = (values, actions) => {
        const fieldsWithServerError = getFieldsWithServerError(formikRef.current?.status);
        if (fieldsWithServerError.length > 0) {
            actions.setSubmitting(false);
            return undefined;
        }
        return formikProps.onSubmit(values, actions);
    };
    return (jsx(Formik, { innerRef: formikRef, ...formikProps, onSubmit: handleSubmit, children: props => (jsx(FormWrapper, { className, formProps, ref, scrollToErrorField, children: typeof children === "function" ? children(props) : children })) }));
});
Form.displayName = "Form";

export { Form };
//# sourceMappingURL=Form.js.map
