'use strict';

var jsxRuntime = require('react/jsx-runtime');
var React = require('react');
var react = require('@chakra-ui/react');
var reactHookForm = require('react-hook-form');
var devtools = require('@hookform/devtools');
var yup = require('@hookform/resolvers/yup');
var Yup = require('yup');
var useReactHookForm = require('../../hooks/useReactHookForm.cjs');
var FormField = require('../FormField/FormField.cjs');
var NumberInput = require('../Inputs/NumberInput/NumberInput.cjs');
var RadioGroup = require('../Inputs/RadioGroup/RadioGroup.cjs');
var Select = require('../Inputs/Select/Select.cjs');
var RPSlider = require('../Inputs/Slider/RPSlider.cjs');
var ColumnSelect = require('../Inputs/ColumnSelect/ColumnSelect.cjs');
var Button = require('../Button/Button.cjs');
var PasswordInput = require('../Inputs/PasswordInput/PasswordInput.cjs');

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 Yup__namespace = /*#__PURE__*/_interopNamespace(Yup);

var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
  for (var prop in b || (b = {}))
    if (__hasOwnProp.call(b, prop))
      __defNormalProp(a, prop, b[prop]);
  if (__getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(b)) {
      if (__propIsEnum.call(b, prop))
        __defNormalProp(a, prop, b[prop]);
    }
  return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __objRest = (source, exclude) => {
  var target = {};
  for (var prop in source)
    if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
      target[prop] = source[prop];
  if (source != null && __getOwnPropSymbols)
    for (var prop of __getOwnPropSymbols(source)) {
      if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
        target[prop] = source[prop];
    }
  return target;
};
function generateValidationSchemaObject(fields) {
  let schema = fields.filter((field) => field.fieldType !== "displaySection").map((field) => {
    if (field.fieldType === "custom" && "fields" in field) {
      return generateValidationSchemaObject(field.fields);
    } else {
      return { name: field.name, schema: field.schema };
    }
  });
  return schema.flat();
}
function generateInitialValuesObject(fields) {
  const initialValues = fields.filter((field) => field.fieldType !== "displaySection").map((field) => {
    if (field.fieldType === "custom" && "fields" in field) {
      return generateInitialValuesObject(field.fields);
    } else {
      if (field.fieldType === "select" && field.defaultValue) {
        const selectField = field;
        return {
          name: selectField.name,
          defaultValue: selectField.isMulti ? selectField.defaultValue : selectField.defaultValue.value
        };
      } else {
        return { name: field.name, defaultValue: field.defaultValue };
      }
    }
  });
  return initialValues.flat();
}
function Form({
  onValid,
  onInvalid,
  fields,
  button,
  autofocus,
  mode,
  developerView,
  isDisabled,
  isFetching,
  actions,
  onInvalidFormValidation
}) {
  var _a;
  const filteredFields = fields.filter((field) => !field.hide);
  const initialSchemaValues = Object.fromEntries(
    generateInitialValuesObject(filteredFields).map((fieldObj) => [
      fieldObj.name,
      fieldObj.defaultValue
    ])
  );
  const schema = Object.fromEntries(
    generateValidationSchemaObject(filteredFields).map((fieldObj) => [
      fieldObj.name,
      fieldObj.schema
    ])
  );
  const validationSchema = Yup__namespace.object().shape(schema);
  const [validationContext, setValidationContext] = React.useState({});
  const inputRef = React.useRef();
  React.useEffect(() => {
    var _a2;
    if (autofocus && inputRef)
      (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
  }, [inputRef, autofocus]);
  const { formValues, setFormMethods } = useReactHookForm();
  const defaultValues = formValues && Object.entries(formValues).length > 0 ? __spreadValues(__spreadValues({}, initialSchemaValues), formValues) : initialSchemaValues;
  const formMethods = reactHookForm.useForm({
    mode: mode || "all",
    defaultValues,
    resolver: yup.yupResolver(validationSchema),
    context: validationContext
  });
  React.useEffect(() => {
    setFormMethods(formMethods);
  }, []);
  const {
    register,
    handleSubmit,
    setValue,
    control,
    formState: { isSubmitting, errors }
  } = formMethods;
  const isFormDisabled = isSubmitting || isDisabled || isFetching;
  const isFormSubmissionDisabled = isFormDisabled || Object.keys(errors).length > 0;
  React.useEffect(() => {
    if (isFormSubmissionDisabled && onInvalidFormValidation !== void 0) {
      onInvalidFormValidation();
    }
  }, [isFormSubmissionDisabled]);
  const allActions = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      Button,
      {
        variant: (_a = button.variant) != null ? _a : "brand",
        "aria-label": button.label,
        "data-testid": button.label,
        type: "submit",
        isLoading: isSubmitting || isFetching,
        isDisabled: isFormSubmissionDisabled,
        children: button.text
      }
    ),
    actions
  ] });
  const mapFields = (fields2) => {
    const mappedFields = fields2.map(
      (_a2) => {
        var _b = _a2, {
          label,
          columns,
          help,
          description,
          footerDescription,
          tooltip,
          heading,
          showRequiredIndicator
        } = _b, field = __objRest(_b, [
          "label",
          "columns",
          "help",
          "description",
          "footerDescription",
          "tooltip",
          "heading",
          "showRequiredIndicator"
        ]);
        var _a3;
        if (field.fieldType === "displaySection") {
          return /* @__PURE__ */ jsxRuntime.jsxs(react.Box, { children: [
            heading && /* @__PURE__ */ jsxRuntime.jsx(react.Heading, { as: "h5", size: "md", children: heading }),
            description && /* @__PURE__ */ jsxRuntime.jsx(react.Text, { children: description })
          ] }, field.name);
        }
        if (field.fieldType === "repeater") {
          return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {});
        }
        if (field.fieldType === "custom") {
          let f = field;
          return /* @__PURE__ */ jsxRuntime.jsx(
            f.component,
            {
              form: formMethods,
              setValidationContext
            },
            field.name
          );
        }
        return /* @__PURE__ */ jsxRuntime.jsx(React.Fragment, { children: /* @__PURE__ */ jsxRuntime.jsx(
          FormField,
          {
            description,
            footerDescription,
            tooltip,
            isRequired: field.fieldType === "hidden" ? false : field.isRequired !== false,
            isDisabled: field.isDisabled || isFormDisabled,
            hidden: field.fieldType === "hidden",
            style: columns && { gridColumn: `span ${columns}` },
            label,
            isInvalid: !!errors[field.name],
            errorText: (_a3 = errors[field.name]) == null ? void 0 : _a3.message,
            helpText: help,
            showRequiredIndicator,
            children: {
              text: /* @__PURE__ */ jsxRuntime.jsx(
                react.Input,
                __spreadValues({
                  "data-testid": `${field.name}_field`,
                  placeholder: field.placeholder,
                  pattern: field.pattern,
                  type: field.inputMode
                }, register(field.name))
              ),
              password: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const _a4 = renderField, rest = __objRest(_a4, ["ref"]);
                    const passwordField = field;
                    return /* @__PURE__ */ jsxRuntime.jsx(
                      PasswordInput,
                      __spreadProps(__spreadValues({}, rest), {
                        name: passwordField.name,
                        placeholder: passwordField.placeholder,
                        pattern: passwordField.pattern,
                        type: passwordField.inputMode,
                        defaultShowPassword: passwordField.defaultShowPassword,
                        showEyeIndicator: passwordField.showEyeIndicator
                      })
                    );
                  }
                }
              ),
              toggle: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const toggleField = field;
                    return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${toggleField.name}_field`, children: /* @__PURE__ */ jsxRuntime.jsx(
                      react.Switch,
                      __spreadProps(__spreadValues({}, renderField), {
                        defaultChecked: toggleField.defaultValue === "true"
                      })
                    ) });
                  }
                }
              ),
              hidden: /* @__PURE__ */ jsxRuntime.jsx(
                react.Input,
                __spreadValues({
                  "data-testid": `${field.name}_field`,
                  hidden: true,
                  type: "none"
                }, register(field.name))
              ),
              number: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const _a4 = renderField, rest = __objRest(_a4, ["ref"]);
                    const numberField = field;
                    return /* @__PURE__ */ jsxRuntime.jsx(
                      NumberInput,
                      __spreadProps(__spreadValues({}, rest), {
                        name: numberField.name,
                        min: numberField.min,
                        max: numberField.max,
                        step: numberField.step,
                        placeholder: numberField.placeholder
                      })
                    );
                  }
                }
              ),
              radio: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const _a4 = renderField, rest = __objRest(_a4, ["ref"]);
                    const radioField = field;
                    if (radioField.radioVariant === "circle") {
                      return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${field.name}_field`, mt: 2, children: /* @__PURE__ */ jsxRuntime.jsx(
                        react.RadioGroup,
                        __spreadProps(__spreadValues({}, rest), {
                          defaultValue: field.defaultValue,
                          onChange: (nextValue) => {
                            setValue(radioField.name, nextValue);
                            setFormMethods(formMethods);
                          },
                          children: /* @__PURE__ */ jsxRuntime.jsx(react.Stack, { direction: radioField.radioStackDirection, children: radioField.options.map(
                            (_b2) => {
                              var _c = _b2, { label: label2, value, disabled, invalid } = _c, otherOptionProps = __objRest(_c, ["label", "value", "disabled", "invalid"]);
                              return /* @__PURE__ */ jsxRuntime.jsx(
                                react.Radio,
                                __spreadProps(__spreadValues({
                                  value: `${value}`,
                                  isDisabled: disabled,
                                  isInvalid: invalid
                                }, otherOptionProps), {
                                  children: /* @__PURE__ */ jsxRuntime.jsx(
                                    react.Text,
                                    {
                                      "aria-invalid": invalid,
                                      _invalid: {
                                        textColor: "red.500",
                                        borderColor: "red.500"
                                      },
                                      children: label2
                                    }
                                  )
                                }),
                                `${value}`
                              );
                            }
                          ) })
                        })
                      ) });
                    }
                    return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${field.name}_field`, children: /* @__PURE__ */ jsxRuntime.jsx(
                      RadioGroup,
                      __spreadProps(__spreadValues({}, rest), {
                        isAttached: radioField.isAttached,
                        options: radioField.options || [],
                        defaultValue: radioField.defaultValue,
                        onChange: (nextValue) => {
                          setValue(radioField.name, nextValue);
                          setFormMethods(formMethods);
                        }
                      })
                    ) });
                  }
                }
              ),
              select: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const _a4 = renderField, rest = __objRest(_a4, ["ref"]);
                    const selectField = field;
                    return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${selectField.name}_field`, children: /* @__PURE__ */ jsxRuntime.jsx(
                      Select["default"],
                      __spreadProps(__spreadValues({
                        menuPlacement: "auto"
                      }, rest), {
                        innerRef: selectField.innerRef,
                        placeholder: selectField.placeholder,
                        isLoading: selectField.isLoading,
                        isMulti: selectField.isMulti,
                        options: selectField.options,
                        defaultValue: selectField.defaultValue,
                        onChange: (nextValue) => {
                          setValue(selectField.name, nextValue);
                          setFormMethods(formMethods);
                        }
                      })
                    ) });
                  }
                }
              ),
              columnSelect: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const _a4 = renderField, rest = __objRest(_a4, ["ref"]);
                    const columnSelectField = field;
                    return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${columnSelectField.name}_field`, children: /* @__PURE__ */ jsxRuntime.jsx(
                      ColumnSelect,
                      __spreadProps(__spreadValues({
                        menuPlacement: "auto"
                      }, rest), {
                        innerRef: columnSelectField.innerRef,
                        placeholder: columnSelectField.placeholder,
                        isLoading: columnSelectField.isLoading,
                        options: columnSelectField.options,
                        defaultValue: columnSelectField.defaultValue,
                        firstTextPosition: columnSelectField.firstTextPosition,
                        headerColumns: columnSelectField.headerColumns,
                        footer: columnSelectField.footer,
                        singleValueText: columnSelectField.singleValueText,
                        onChange: (nextValue) => {
                          setValue(columnSelectField.name, nextValue);
                          setFormMethods(formMethods);
                        }
                      })
                    ) });
                  }
                }
              ),
              textarea: /* @__PURE__ */ jsxRuntime.jsx(
                react.Textarea,
                __spreadProps(__spreadValues({}, register(field.name)), {
                  "data-testid": `${field.name}_field`,
                  placeholder: field.placeholder
                })
              ),
              slider: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const _a4 = renderField, rest = __objRest(_a4, ["ref"]);
                    const sliderField = field;
                    const _b2 = sliderField, sliderRest = __objRest(_b2, ["fieldType"]);
                    return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${sliderField.name}_field`, children: /* @__PURE__ */ jsxRuntime.jsx(
                      RPSlider,
                      __spreadProps(__spreadValues(__spreadValues({}, sliderRest), rest), {
                        onChange: (nextValue) => {
                          setValue(sliderField.name, nextValue);
                          setFormMethods(formMethods);
                        }
                      })
                    ) });
                  }
                }
              ),
              displaySection: /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, {}),
              checkbox: /* @__PURE__ */ jsxRuntime.jsx(
                reactHookForm.Controller,
                {
                  name: field.name,
                  control,
                  render: ({ field: renderField }) => {
                    const checkboxField = field;
                    return /* @__PURE__ */ jsxRuntime.jsx(react.Box, { "data-testid": `${checkboxField.name}_field`, children: /* @__PURE__ */ jsxRuntime.jsx(react.Checkbox, __spreadProps(__spreadValues({}, renderField), { children: checkboxField.text })) });
                  }
                }
              )
            }[field.fieldType || "text"]
          },
          field.name
        ) }, field.name);
      }
    );
    return mappedFields.flat();
  };
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
    /* @__PURE__ */ jsxRuntime.jsx(
      react.chakra.form,
      {
        onChange: () => setFormMethods(formMethods),
        onSubmit: handleSubmit(onValid, onInvalid),
        children: /* @__PURE__ */ jsxRuntime.jsx(react.chakra.fieldset, { children: /* @__PURE__ */ jsxRuntime.jsxs(react.VStack, { alignItems: "left", gap: 6, children: [
          mapFields(fields),
          button.spanFullWidth ? allActions : /* @__PURE__ */ jsxRuntime.jsx(react.Box, { children: /* @__PURE__ */ jsxRuntime.jsx(react.ButtonGroup, { children: allActions }) })
        ] }) })
      }
    ),
    developerView ? /* @__PURE__ */ jsxRuntime.jsx(devtools.DevTool, { control }) : null
  ] });
}

module.exports = Form;
//# sourceMappingURL=Form.cjs.map
