"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.Form = void 0;

var _react = _interopRequireWildcard(require("react"));

var _yup = require("@hookform/resolvers/yup");

var _classnames = _interopRequireDefault(require("classnames"));

var _reactFeather = require("react-feather");

var _reactHookForm = require("react-hook-form");

var _reactRainbowComponents = require("react-rainbow-components");

var _reactTooltip = _interopRequireDefault(require("react-tooltip"));

var _uuid = require("uuid");

var yup = _interopRequireWildcard(require("yup"));

var _styleContext = require("./styleContext");

var _type = require("./type");

var _format = require("./format");

var _index = require("./inputs/index");

var _index2 = require("./resolvers/index");

var _Option = require("./Option");

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || _typeof(obj) !== "object" && typeof obj !== "function") { return { "default": obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj["default"] = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }

function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }

function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }

function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) { symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); } keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }

function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }

var usePrevious = function usePrevious(value) {
  // The ref object is a generic container whose current property is mutable ...
  // ... and can hold any value, similar to an instance property on a class
  var ref = (0, _react.useRef)(); // Store current value in ref

  (0, _react.useEffect)(function () {
    ref.current = JSON.parse(JSON.stringify(value));
  }, [value]); // Only re-run if value changes
  // Return previous value (happens before update in useEffect above)

  return ref.current;
};

var BasicWrapper = function BasicWrapper(_ref) {
  var entry = _ref.entry,
      className = _ref.className,
      label = _ref.label,
      error = _ref.error,
      help = _ref.help,
      children = _ref.children,
      render = _ref.render;
  var classes = (0, _styleContext.useCustomStyle)();
  var id = (0, _uuid.v4)();

  if (_typeof(entry) === 'object') {
    return children;
  }

  if (render) {
    return render({
      entry: entry,
      label: label,
      error: error,
      help: help,
      children: children
    });
  }

  return /*#__PURE__*/_react["default"].createElement("div", {
    className: "form-group mt-3 ".concat(className)
  }, label && /*#__PURE__*/_react["default"].createElement("label", {
    className: "form-label d-flex align-content-center",
    htmlFor: entry
  }, /*#__PURE__*/_react["default"].createElement("span", {
    className: "mr-2"
  }, label), help && /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, /*#__PURE__*/_react["default"].createElement(_reactTooltip["default"], {
    html: true,
    place: 'bottom',
    id: id
  }), /*#__PURE__*/_react["default"].createElement("span", {
    "data-html": true,
    "data-tip": help,
    "data-for": id
  }, /*#__PURE__*/_react["default"].createElement(_reactFeather.HelpCircle, {
    style: {
      color: 'gray',
      width: 17,
      marginLeft: '.5rem',
      cursor: 'help'
    }
  })))), children, error && /*#__PURE__*/_react["default"].createElement("div", {
    className: classes.invalid_feedback
  }, error.message));
};

var CustomizableInput = function CustomizableInput(props) {
  if (props.render) {
    return props.render(_objectSpread(_objectSpread({}, props.field), {}, {
      error: props.error
    }));
  }

  return props.children;
};

var defaultVal = function defaultVal(t, array, defaultValue) {
  if (!!defaultValue) return defaultValue;
  if (!!array) return [];

  switch (t) {
    case _type.type.bool:
      return false;

    case _type.type.number:
      return 0;

    case _type.type.object:
      return undefined;
    //todo: passur de moi

    case _type.type.string:
      return "";

    default:
      return undefined;
  }
};

var getDefaultValues = function getDefaultValues(flow, schema) {
  return flow.reduce(function (acc, key) {
    var entry = schema[key];

    if (_typeof(key) === 'object') {
      return _objectSpread(_objectSpread({}, acc), getDefaultValues(key.flow, schema));
    }

    return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, defaultVal(entry.type, entry.array || entry.isMulti, entry.defaultValue)));
  }, {});
};

var Form = /*#__PURE__*/_react["default"].forwardRef(function (_ref2, ref) {
  var schema = _ref2.schema,
      flow = _ref2.flow,
      value = _ref2.value,
      inputWrapper = _ref2.inputWrapper,
      onSubmit = _ref2.onSubmit,
      _ref2$onError = _ref2.onError,
      onError = _ref2$onError === void 0 ? function () {} : _ref2$onError,
      footer = _ref2.footer,
      _ref2$style = _ref2.style,
      style = _ref2$style === void 0 ? {} : _ref2$style,
      className = _ref2.className,
      _ref2$options = _ref2.options,
      options = _ref2$options === void 0 ? {} : _ref2$options;
  var classes = (0, _styleContext.useCustomStyle)(style);
  var formFlow = flow || Object.keys(schema);

  var maybeCustomHttpClient = function maybeCustomHttpClient(url, method) {
    //todo: if present props.resolve()
    if (options.httpClient) {
      return options.httpClient(url, method);
    }

    return fetch(url, {
      method: method,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json'
      }
    });
  };

  var defaultValues = getDefaultValues(formFlow, schema); //FIXME: get real schema through the switch

  var _resolver = function resolver(rawData) {
    var _getShapeAndDependenc = (0, _index2.getShapeAndDependencies)(formFlow, schema, [], rawData),
        shape = _getShapeAndDependenc.shape,
        dependencies = _getShapeAndDependenc.dependencies;

    var resolver = yup.object().shape(shape, dependencies);
    return resolver;
  };

  var cleanInputArray = function cleanInputArray(obj, subSchema) {
    return Object.entries(obj).reduce(function (acc, curr) {
      var _curr = _slicedToArray(curr, 2),
          key = _curr[0],
          v = _curr[1];

      if (Array.isArray(v)) {
        var isArray = (0, _Option.option)(subSchema).orElse(schema).map(function (s) {
          return s[key];
        }).map(function (entry) {
          return !!entry.array;
        }).getOrElse(false);

        if (isArray) {
          return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, v.map(function (value) {
            return {
              value: value
            };
          })));
        }

        return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, v));
      } else if (!!v && _typeof(v) === 'object') {
        var _subSchema$key;

        return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, cleanInputArray(v, ((_subSchema$key = subSchema[key]) === null || _subSchema$key === void 0 ? void 0 : _subSchema$key.schema) || {})));
      } else {
        return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, v));
      }
    }, {});
  };

  var cleanOutputArray = function cleanOutputArray(obj, subSchema) {
    return Object.entries(obj).reduce(function (acc, curr) {
      var _curr2 = _slicedToArray(curr, 2),
          key = _curr2[0],
          v = _curr2[1];

      if (Array.isArray(v)) {
        var isArray = (0, _Option.option)(subSchema).orElse(schema).map(function (s) {
          return s[key];
        }).map(function (entry) {
          return !!entry.array;
        }).getOrElse(false);

        if (isArray) {
          return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, v.map(function (_ref3) {
            var value = _ref3.value;
            return value;
          })));
        }

        return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, v));
      } else if (!!v && _typeof(v) === 'object') {
        var _subSchema$key2;

        return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, cleanOutputArray(v, ((_subSchema$key2 = subSchema[key]) === null || _subSchema$key2 === void 0 ? void 0 : _subSchema$key2.schema) || {})));
      } else {
        return _objectSpread(_objectSpread({}, acc), {}, _defineProperty({}, key, v));
      }
    }, {});
  };

  var methods = (0, _reactHookForm.useForm)({
    resolver: function resolver(data, context, options) {
      return (0, _yup.yupResolver)(_resolver(data))(data, context, options);
    },
    defaultValues: cleanInputArray(value || defaultValues, schema),
    shouldFocusError: !options.autosubmit
  });
  var register = methods.register,
      _handleSubmit = methods.handleSubmit,
      errors = methods.formState.errors,
      control = methods.control,
      _reset = methods.reset,
      watch = methods.watch,
      trigger = methods.trigger,
      getValues = methods.getValues,
      setValue = methods.setValue;
  (0, _react.useEffect)(function () {
    if (value) {
      _reset(cleanInputArray(value, schema));
    }
  }, [value, _reset]);
  (0, _react.useEffect)(function () {
    _reset(cleanInputArray(value || defaultValues, schema));
  }, [schema]);
  var data = watch();
  var prevData = usePrevious(data);
  (0, _react.useEffect)(function () {
    //todo: with debounce
    if (!!options.autosubmit && JSON.stringify(data) !== JSON.stringify(prevData)) {
      _handleSubmit(function (data) {
        var clean = cleanOutputArray(data, schema);
        onSubmit(clean);
      }, onError)();
    }
  }, [data]);

  if (options.watch) {
    console.group('react-form watch');
    console.log(watch());
    console.groupEnd();
  }

  (0, _react.useImperativeHandle)(ref, function () {
    return {
      handleSubmit: function handleSubmit() {
        return _handleSubmit(function (data) {
          var clean = cleanOutputArray(data, schema);
          onSubmit(clean);
        }, onError)();
      }
    };
  });
  return /*#__PURE__*/_react["default"].createElement(_reactHookForm.FormProvider, methods, /*#__PURE__*/_react["default"].createElement("form", {
    className: className || "".concat(classes.pr_15, " ").concat(classes.full_width),
    onSubmit: _handleSubmit(function (data) {
      var clean = cleanOutputArray(data, schema);
      onSubmit(clean);
    }, onError)
  }, formFlow.map(function (entry, idx) {
    var step = schema[entry];
    var error = _typeof(entry) === 'object' ? undefined : entry.split('.').reduce(function (object, key) {
      return object && object[key];
    }, errors);
    var visibleStep = (0, _Option.option)(step).map(function (s) {
      return s.visible;
    }).map(function (visible) {
      switch (_typeof(visible)) {
        case 'object':
          var _value = watch(step.visible.ref);

          return (0, _Option.option)(step.visible.test).map(function (test) {
            return test(_value);
          }).getOrElse(_value);

        case 'boolean':
          return visible;

        default:
          return true;
      }
    }).getOrElse(true);

    if (!visibleStep) {
      return null;
    }

    return /*#__PURE__*/_react["default"].createElement(BasicWrapper, {
      key: "".concat(entry, "-").concat(idx),
      entry: entry,
      error: error,
      label: (step === null || step === void 0 ? void 0 : step.label) === null ? null : (step === null || step === void 0 ? void 0 : step.label) || entry,
      help: step === null || step === void 0 ? void 0 : step.help,
      render: inputWrapper
    }, /*#__PURE__*/_react["default"].createElement(Step, {
      key: idx,
      entry: entry,
      step: step,
      error: error,
      errors: errors,
      register: register,
      schema: schema,
      control: control,
      trigger: trigger,
      getValues: getValues,
      setValue: setValue,
      watch: watch,
      inputWrapper: inputWrapper,
      httpClient: maybeCustomHttpClient
    }));
  }), /*#__PURE__*/_react["default"].createElement(Footer, {
    render: footer,
    reset: function reset() {
      return _reset(defaultValues);
    },
    valid: _handleSubmit(function (data) {
      return onSubmit(cleanOutputArray(data, schema));
    }, onError),
    actions: options.actions
  })));
});

exports.Form = Form;

var Footer = function Footer(props) {
  var _props$actions, _props$actions$submit, _props$actions2, _props$actions2$submi, _props$actions3, _props$actions3$cance, _props$actions5, _props$actions5$cance, _props$actions6, _props$actions6$reset, _props$actions7, _props$actions7$reset, _props$actions8, _props$actions8$submi;

  var classes = (0, _styleContext.useCustomStyle)();

  if (props.render) {
    return props.render({
      reset: props.reset,
      valid: props.valid
    });
  }

  var isSubmitDisplayed = ((_props$actions = props.actions) === null || _props$actions === void 0 ? void 0 : (_props$actions$submit = _props$actions.submit) === null || _props$actions$submit === void 0 ? void 0 : _props$actions$submit.display) === undefined ? true : !!((_props$actions2 = props.actions) !== null && _props$actions2 !== void 0 && (_props$actions2$submi = _props$actions2.submit) !== null && _props$actions2$submi !== void 0 && _props$actions2$submi.display);
  return /*#__PURE__*/_react["default"].createElement("div", {
    className: "".concat(classes.flex, " ").concat(classes.jc_end, " ").concat(classes.mt_5)
  }, ((_props$actions3 = props.actions) === null || _props$actions3 === void 0 ? void 0 : (_props$actions3$cance = _props$actions3.cancel) === null || _props$actions3$cance === void 0 ? void 0 : _props$actions3$cance.display) && /*#__PURE__*/_react["default"].createElement("button", {
    className: "".concat(classes.btn, " ").concat(classes.btn_red),
    type: "button",
    onClick: function onClick() {
      var _props$actions4;

      return (_props$actions4 = props.actions) === null || _props$actions4 === void 0 ? void 0 : _props$actions4.cancel.action();
    }
  }, ((_props$actions5 = props.actions) === null || _props$actions5 === void 0 ? void 0 : (_props$actions5$cance = _props$actions5.cancel) === null || _props$actions5$cance === void 0 ? void 0 : _props$actions5$cance.label) || 'Cancel'), ((_props$actions6 = props.actions) === null || _props$actions6 === void 0 ? void 0 : (_props$actions6$reset = _props$actions6.reset) === null || _props$actions6$reset === void 0 ? void 0 : _props$actions6$reset.display) && /*#__PURE__*/_react["default"].createElement("button", {
    className: "".concat(classes.btn, " ").concat(classes.btn_red),
    type: "button",
    onClick: props.reset
  }, ((_props$actions7 = props.actions) === null || _props$actions7 === void 0 ? void 0 : (_props$actions7$reset = _props$actions7.reset) === null || _props$actions7$reset === void 0 ? void 0 : _props$actions7$reset.label) || 'Reset'), isSubmitDisplayed && /*#__PURE__*/_react["default"].createElement("button", {
    className: "".concat(classes.btn, " ").concat(classes.btn_green, " ").concat(classes.ml_10),
    type: "submit"
  }, ((_props$actions8 = props.actions) === null || _props$actions8 === void 0 ? void 0 : (_props$actions8$submi = _props$actions8.submit) === null || _props$actions8$submi === void 0 ? void 0 : _props$actions8$submi.label) || 'Save'));
};

var Step = function Step(_ref4) {
  var entry = _ref4.entry,
      realEntry = _ref4.realEntry,
      step = _ref4.step,
      error = _ref4.error,
      errors = _ref4.errors,
      register = _ref4.register,
      schema = _ref4.schema,
      control = _ref4.control,
      trigger = _ref4.trigger,
      getValues = _ref4.getValues,
      _setValue = _ref4.setValue,
      watch = _ref4.watch,
      inputWrapper = _ref4.inputWrapper,
      httpClient = _ref4.httpClient,
      defaultValue = _ref4.defaultValue,
      index = _ref4.index;
  var classes = (0, _styleContext.useCustomStyle)();

  if (entry && _typeof(entry) === 'object') {
    var errored = entry.flow.some(function (step) {
      return !!errors[step];
    });
    return /*#__PURE__*/_react["default"].createElement(_index.Collapse, _extends({}, entry, {
      errored: errored
    }), entry.flow.map(function (en, entryIdx) {
      var stp = schema[en];
      var err = _typeof(en) === 'object' ? undefined : en.split('.').reduce(function (object, key) {
        return object && object[key];
      }, errors);
      var visibleStep = (0, _Option.option)(stp).map(function (s) {
        return s.visible;
      }).map(function (visible) {
        switch (_typeof(visible)) {
          case 'object':
            var value = watch(visible.ref);
            return (0, _Option.option)(visible.test).map(function (test) {
              return test(value);
            }).getOrElse(value);

          case 'boolean':
            return visible;

          default:
            return true;
        }
      }).getOrElse(true);

      if (!visibleStep) {
        return null;
      }

      return /*#__PURE__*/_react["default"].createElement(BasicWrapper, {
        key: "collapse-".concat(en, "-").concat(entryIdx),
        className: classes.collapseInline,
        entry: en,
        error: err,
        label: (stp === null || stp === void 0 ? void 0 : stp.label) === null ? null : (stp === null || stp === void 0 ? void 0 : stp.label) || en,
        help: stp === null || stp === void 0 ? void 0 : stp.help,
        render: inputWrapper
      }, /*#__PURE__*/_react["default"].createElement(Step, {
        entry: en,
        step: stp,
        error: err,
        errors: errors,
        register: register,
        schema: schema,
        control: control,
        trigger: trigger,
        getValues: getValues,
        setValue: _setValue,
        watch: watch,
        inputWrapper: inputWrapper,
        httpClient: httpClient,
        defaultValue: stp.defaultValue
      }));
    }));
  }

  if (step.array) {
    return /*#__PURE__*/_react["default"].createElement(ArrayStep, {
      entry: entry,
      step: step,
      trigger: trigger,
      register: register,
      control: control,
      error: error,
      setValue: _setValue,
      values: getValues(entry),
      defaultValue: step.defaultValue || defaultVal(step.type),
      component: function component(props, idx) {
        var _error$idx;

        return /*#__PURE__*/_react["default"].createElement(Step, {
          entry: "".concat(entry, "[").concat(idx, "].value"),
          step: _objectSpread(_objectSpread({}, schema[realEntry || entry]), {}, {
            array: false
          }),
          error: error && ((_error$idx = error[idx]) === null || _error$idx === void 0 ? void 0 : _error$idx.value),
          register: register,
          schema: schema,
          control: control,
          trigger: trigger,
          getValues: getValues,
          setValue: _setValue,
          watch: watch,
          inputWrapper: inputWrapper,
          httpClient: httpClient,
          defaultValue: props.defaultValue,
          value: props.value,
          index: idx
        });
      }
    });
  }

  switch (step.type) {
    case _type.type.string:
      switch (step.format) {
        case _format.format.text:
          return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
            render: step.render,
            field: {
              setValue: function setValue(key, value) {
                return _setValue(key, value);
              },
              rawValues: getValues(),
              value: getValues(entry),
              onChange: function onChange(v) {
                return _setValue(entry, v);
              }
            },
            error: error
          }, /*#__PURE__*/_react["default"].createElement("textarea", _extends({
            type: "text",
            id: entry,
            className: (0, _classnames["default"])(classes.input, _defineProperty({}, classes.input__invalid, error)),
            readOnly: step.disabled ? 'readOnly' : null
          }, step.props, {
            name: entry,
            defaultValue: defaultValue,
            placeholder: step.placeholder
          }, register(entry))));

        case _format.format.code:
          return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
            name: entry,
            control: control,
            render: function render(_ref5) {
              var field = _ref5.field;
              return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
                render: step.render,
                field: _objectSpread({
                  setValue: function setValue(key, value) {
                    return _setValue(key, value);
                  },
                  rawValues: getValues()
                }, field),
                error: error
              }, /*#__PURE__*/_react["default"].createElement(_index.CodeInput, _extends({
                className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
                readOnly: step.disabled ? true : false,
                onChange: field.onChange,
                value: field.value,
                defaultValue: defaultValue
              }, step.props)));
            }
          });

        case _format.format.markdown:
          return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
            name: entry,
            control: control,
            render: function render(_ref6) {
              var field = _ref6.field;
              return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
                render: step.render,
                field: _objectSpread({
                  setValue: function setValue(key, value) {
                    return _setValue(key, value);
                  },
                  rawValues: getValues()
                }, field),
                error: error
              }, /*#__PURE__*/_react["default"].createElement(_index.MarkdownInput, _extends({}, step.props, {
                className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
                readOnly: step.disabled ? 'readOnly' : null,
                onChange: field.onChange,
                value: field.value,
                defaultValue: defaultValue
              }, step)));
            }
          });

        case _format.format.buttonsSelect:
        case _format.format.select:
          return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
            name: entry,
            control: control,
            render: function render(_ref7) {
              var field = _ref7.field;
              return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
                render: step.render,
                field: _objectSpread({
                  setValue: function setValue(key, value) {
                    return _setValue(key, value);
                  },
                  rawValues: getValues()
                }, field),
                error: error
              }, /*#__PURE__*/_react["default"].createElement(_index.SelectInput, _extends({}, step.props, {
                className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
                readOnly: step.disabled ? 'readOnly' : null,
                onChange: field.onChange,
                value: field.value,
                possibleValues: step.options,
                defaultValue: defaultValue,
                httpClient: httpClient
              }, step)));
            }
          });

        default:
          return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
            render: step.render,
            field: {
              setValue: function setValue(key, value) {
                return _setValue(key, value);
              },
              rawValues: getValues(),
              value: getValues(entry),
              onChange: function onChange(v) {
                return _setValue(entry, v, {
                  shouldValidate: true
                });
              }
            },
            error: error
          }, /*#__PURE__*/_react["default"].createElement("input", _extends({
            // {...step.props}
            type: step.format || 'text',
            id: entry,
            className: (0, _classnames["default"])(classes.input, _defineProperty({}, classes.input__invalid, error)),
            readOnly: step.disabled ? 'readOnly' : null // defaultValue={defaultValue}
            ,
            placeholder: step.placeholder
          }, register(entry))));
      }

    case _type.type.number:
      switch (step.format) {
        case _format.format.buttonsSelect:
        case _format.format.select:
          return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
            name: entry,
            control: control,
            render: function render(_ref8) {
              var field = _ref8.field;
              return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
                render: step.render,
                field: _objectSpread({
                  setValue: function setValue(key, value) {
                    return _setValue(key, value);
                  },
                  rawValues: getValues()
                }, field),
                error: error
              }, /*#__PURE__*/_react["default"].createElement(_index.SelectInput, _extends({}, step.props, {
                className: (0, _classnames["default"])(classes.content, _defineProperty({}, classes.input__invalid, error)),
                readOnly: step.disabled ? 'readOnly' : null,
                onChange: field.onChange,
                value: field.value,
                possibleValues: step.options,
                defaultValue: defaultValue,
                httpClient: httpClient
              }, step)));
            }
          });

        default:
          return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
            render: step.render,
            field: {
              setValue: function setValue(key, value) {
                return _setValue(key, value);
              },
              rawValues: getValues(),
              value: getValues(entry),
              onChange: function onChange(v) {
                return _setValue(entry, v);
              }
            },
            error: error
          }, /*#__PURE__*/_react["default"].createElement("input", _extends({}, step.props, {
            type: step.format || 'number',
            id: entry,
            className: (0, _classnames["default"])(classes.input, _defineProperty({}, classes.input__invalid, error)),
            readOnly: step.disabled ? 'readOnly' : null,
            name: entry,
            placeholder: step.placeholder,
            defaultValue: defaultValue
          }, register(entry))));
      }

    case _type.type.bool:
      return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
        name: entry,
        control: control,
        render: function render(_ref9) {
          var field = _ref9.field;
          return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
            render: step.render,
            field: _objectSpread({
              setValue: function setValue(key, value) {
                return _setValue(key, value);
              },
              rawValues: getValues()
            }, field),
            error: error
          }, /*#__PURE__*/_react["default"].createElement(_index.BooleanInput, _extends({}, step.props, {
            className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
            readOnly: step.disabled ? 'readOnly' : null,
            onChange: field.onChange,
            value: field.value
          })));
        }
      });

    case _type.type.object:
      switch (step.format) {
        case _format.format.buttonsSelect:
        case _format.format.select:
          return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
            name: entry,
            control: control,
            defaultValue: step.defaultValue,
            render: function render(_ref10) {
              var field = _ref10.field;
              return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
                render: step.render,
                field: _objectSpread({
                  setValue: function setValue(key, value) {
                    return _setValue(key, value);
                  },
                  rawValues: getValues()
                }, field),
                error: error
              }, /*#__PURE__*/_react["default"].createElement(_index.SelectInput, _extends({}, step.props, {
                className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
                readOnly: step.disabled ? 'readOnly' : null,
                onChange: field.onChange,
                value: field.value,
                possibleValues: step.options,
                httpClient: httpClient
              }, step)));
            }
          });

        case _format.format.form:
          var flow = (0, _Option.option)(step.flow).getOrElse((0, _Option.option)(step.schema).map(function (s) {
            return Object.keys(s);
          }).getOrNull());
          return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
            render: step.render,
            field: {
              setValue: function setValue(key, value) {
                return _setValue(key, value);
              },
              rawValues: getValues(),
              value: getValues(entry),
              onChange: function onChange(v) {
                return _setValue(entry, v, {
                  shouldValidate: true
                });
              }
            },
            error: error
          }, /*#__PURE__*/_react["default"].createElement(NestedForm, {
            schema: step.schema,
            flow: flow,
            step: step,
            parent: entry,
            inputWrapper: inputWrapper,
            maybeCustomHttpClient: httpClient,
            value: getValues(entry) || defaultValue,
            error: error,
            index: index
          }));

        default:
          return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
            name: entry,
            control: control,
            defaultValue: step.defaultValue,
            render: function render(_ref11) {
              var field = _ref11.field;
              return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
                render: step.render,
                field: _objectSpread({
                  setValue: function setValue(key, value) {
                    return _setValue(key, value);
                  },
                  rawValues: getValues()
                }, field),
                error: error
              }, /*#__PURE__*/_react["default"].createElement(_index.ObjectInput, _extends({}, step.props, {
                className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
                readOnly: step.disabled ? 'readOnly' : null,
                onChange: field.onChange,
                value: field.value,
                possibleValues: step.options
              }, step)));
            }
          });
      }

    case _type.type.date:
      return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
        name: entry,
        control: control,
        defaultValue: step.defaultValue,
        render: function render(_ref12) {
          var field = _ref12.field;
          return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
            render: step.render,
            field: _objectSpread({
              setValue: function setValue(key, value) {
                return _setValue(key, value);
              },
              rawValues: getValues()
            }, field),
            error: error
          }, /*#__PURE__*/_react["default"].createElement(_reactRainbowComponents.DatePicker, _extends({}, step.props, {
            id: "datePicker-1",
            className: (0, _classnames["default"])(_defineProperty({}, classes.input__invalid, error)),
            readOnly: step.disabled ? 'readOnly' : null,
            value: field.value,
            onChange: field.onChange,
            formatStyle: "large" // locale={state.locale.name}

          })));
        }
      });

    case _type.type.file:
      if (step.format === _format.format.hidden) {
        return /*#__PURE__*/_react["default"].createElement(_reactHookForm.Controller, {
          name: entry,
          control: control,
          render: function render(_ref13) {
            var field = _ref13.field;

            var FileInput = function FileInput(_ref14) {
              var onChange = _ref14.onChange;

              var _useState = (0, _react.useState)(false),
                  _useState2 = _slicedToArray(_useState, 2),
                  uploading = _useState2[0],
                  setUploading = _useState2[1];

              var _useState3 = (0, _react.useState)(undefined),
                  _useState4 = _slicedToArray(_useState3, 2),
                  input = _useState4[0],
                  setInput = _useState4[1];

              var setFiles = function setFiles(e) {
                var files = e.target.files;
                setUploading(true);
                onChange(files);
                setUploading(false);
              };

              var trigger = function trigger() {
                input.click();
              };

              return /*#__PURE__*/_react["default"].createElement("div", {
                className: (0, _classnames["default"])("d-flex flex-row justify-content-start", _defineProperty({}, classes.input__invalid, error))
              }, /*#__PURE__*/_react["default"].createElement("input", {
                ref: function ref(r) {
                  return setInput(r);
                },
                type: "file",
                multiple: true,
                className: classes.d_none,
                onChange: setFiles
              }), /*#__PURE__*/_react["default"].createElement("button", {
                type: "button",
                className: "".concat(classes.btn, " ").concat(classes.flex, " ").concat(classes.ai_center),
                disabled: uploading,
                onClick: trigger
              }, uploading && /*#__PURE__*/_react["default"].createElement(_reactFeather.Loader, null), !uploading && /*#__PURE__*/_react["default"].createElement(_reactFeather.Upload, null), /*#__PURE__*/_react["default"].createElement("span", {
                className: "".concat(classes.ml_5)
              }, "Select file")));
            };

            return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
              render: step.render,
              field: _objectSpread({
                setValue: function setValue(key, value) {
                  return _setValue(key, value);
                },
                rawValues: getValues()
              }, field),
              error: error
            }, /*#__PURE__*/_react["default"].createElement(FileInput, {
              onChange: field.onChange,
              error: error
            }));
          }
        });
      }

      return /*#__PURE__*/_react["default"].createElement(CustomizableInput, {
        render: step.render,
        field: {
          setValue: function setValue(key, value) {
            return _setValue(key, value);
          },
          rawValues: getValues(),
          value: getValues(entry),
          onChange: function onChange(v) {
            return _setValue(entry, v, {
              shouldValidate: true
            });
          }
        },
        error: error
      }, /*#__PURE__*/_react["default"].createElement("input", _extends({}, step.props, {
        type: "file",
        id: entry,
        className: (0, _classnames["default"])(classes.input, _defineProperty({}, classes.input__invalid, error)),
        readOnly: step.disabled ? 'readOnly' : null,
        name: entry,
        placeholder: step.placeholder
      }, register(entry))));

    default:
      return null;
  }
};

var ArrayStep = function ArrayStep(_ref15) {
  var entry = _ref15.entry,
      step = _ref15.step,
      control = _ref15.control,
      trigger = _ref15.trigger,
      register = _ref15.register,
      error = _ref15.error,
      component = _ref15.component,
      values = _ref15.values,
      defaultValue = _ref15.defaultValue,
      setValue = _ref15.setValue;
  var classes = (0, _styleContext.useCustomStyle)();

  var _useFieldArray = (0, _reactHookForm.useFieldArray)({
    control: control,
    // control props comes from useForm (optional: if you are using FormContext)
    name: entry // unique name for your Field Array
    // keyName: "id", default to "id", you can change the key name

  }),
      fields = _useFieldArray.fields,
      append = _useFieldArray.append,
      remove = _useFieldArray.remove;

  return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, fields.map(function (field, idx) {
    return /*#__PURE__*/_react["default"].createElement("div", {
      key: field.id,
      className: "d-flex flex-row"
    }, /*#__PURE__*/_react["default"].createElement("div", {
      className: "flex-grow-1"
    }, component(_objectSpread(_objectSpread({
      key: field.id
    }, field), {}, {
      defaultValue: values[idx] || defaultValue
    }), idx)), /*#__PURE__*/_react["default"].createElement("div", {
      className: "input-group-append"
    }, /*#__PURE__*/_react["default"].createElement("button", {
      className: "btn btn-danger btn-sm",
      onClick: function onClick() {
        remove(idx);
        trigger(entry);
      }
    }, "remove")));
  }), /*#__PURE__*/_react["default"].createElement("div", null, /*#__PURE__*/_react["default"].createElement("input", {
    type: "button",
    className: (0, _classnames["default"])("btn btn-info mt-2", _defineProperty({}, classes.input__invalid, error)),
    onClick: function onClick() {
      append({
        value: step.addableDefaultValue
      });
      trigger(entry);
    },
    value: "Add"
  }), error && /*#__PURE__*/_react["default"].createElement("div", {
    className: "invalid-feedback"
  }, error.message)));
};

var NestedForm = function NestedForm(_ref16) {
  var schema = _ref16.schema,
      flow = _ref16.flow,
      parent = _ref16.parent,
      inputWrapper = _ref16.inputWrapper,
      maybeCustomHttpClient = _ref16.maybeCustomHttpClient,
      index = _ref16.index,
      error = _ref16.error,
      value = _ref16.value,
      step = _ref16.step;

  var _useFormContext = (0, _reactHookForm.useFormContext)(),
      register = _useFormContext.register,
      control = _useFormContext.control,
      getValues = _useFormContext.getValues,
      setValue = _useFormContext.setValue,
      trigger = _useFormContext.trigger,
      watch = _useFormContext.watch; // retrieve all hook methods


  var _useState5 = (0, _react.useState)(false),
      _useState6 = _slicedToArray(_useState5, 2),
      collapsed = _useState6[0],
      setCollapsed = _useState6[1];

  var classes = (0, _styleContext.useCustomStyle)();
  var schemaAndFlow = (0, _Option.option)(step.conditionalSchema).map(function (condiSchema) {
    var ref = (0, _Option.option)(condiSchema.ref).map(function (ref) {
      return getValues(ref);
    }).getOrNull();
    var rawData = getValues();
    var filterSwitch = condiSchema["switch"].find(function (s) {
      if (typeof s.condition === 'function') {
        return s.condition({
          rawData: rawData,
          ref: ref
        });
      } else {
        return s.condition === ref;
      }
    });
    return (0, _Option.option)(filterSwitch).getOrElse(condiSchema["switch"].find(function (s) {
      return s["default"];
    }));
  }).getOrElse({
    schema: schema,
    flow: flow
  });
  var prevSchema = usePrevious(schemaAndFlow.schema);
  (0, _react.useEffect)(function () {
    if (!!prevSchema && JSON.stringify(prevSchema) !== JSON.stringify(schemaAndFlow.schema)) {
      var def = getDefaultValues(schemaAndFlow.flow, schemaAndFlow.schema);
      setValue(parent, def, {
        shouldValidate: false
      });
    }
  }, [prevSchema, schemaAndFlow.schema]);
  return /*#__PURE__*/_react["default"].createElement("div", {
    style: {
      borderLeft: '2px solid lightGray',
      paddingLeft: '1rem',
      marginBottom: '.5rem',
      position: 'relative'
    }
  }, collapsed && /*#__PURE__*/_react["default"].createElement(_reactFeather.ArrowDown, {
    size: 30,
    className: classes.cursor_pointer,
    style: {
      position: 'absolute',
      top: '5px',
      left: '-16px'
    },
    "stroke-width": "3",
    onClick: function onClick() {
      return setCollapsed(!collapsed);
    }
  }), !collapsed && /*#__PURE__*/_react["default"].createElement(_reactFeather.ArrowUp, {
    size: 30,
    className: classes.cursor_pointer,
    style: {
      position: 'absolute',
      top: '5px',
      left: '-16px'
    },
    "stroke-width": "3",
    onClick: function onClick() {
      return setCollapsed(!collapsed);
    }
  }), schemaAndFlow.flow.map(function (entry, idx) {
    var _schemaAndFlow$schema;

    var step = schemaAndFlow.schema[entry];
    var realError = error && error[entry];
    console.debug({
      schema: schema,
      entry: entry,
      result: (0, _Option.option)((_schemaAndFlow$schema = schemaAndFlow.schema) === null || _schemaAndFlow$schema === void 0 ? void 0 : _schemaAndFlow$schema.collapseField).map(function (f) {
        return f === entry;
      }).getOrElse(idx > 0)
    });
    var isCollapsed = collapsed && (0, _Option.option)(!step.visibleOnCollapse).getOrElse(idx > 0);
    return /*#__PURE__*/_react["default"].createElement(BasicWrapper, {
      key: "".concat(entry, ".").concat(idx),
      className: (0, _classnames["default"])(_defineProperty({}, classes.display__none, isCollapsed)),
      entry: "".concat(parent, ".").concat(entry),
      error: realError,
      label: (step === null || step === void 0 ? void 0 : step.label) === null ? null : (step === null || step === void 0 ? void 0 : step.label) || entry,
      help: step.help,
      render: inputWrapper
    }, /*#__PURE__*/_react["default"].createElement(Step, {
      key: "step.".concat(entry, ".").concat(idx),
      entry: "".concat(parent, ".").concat(entry),
      realEntry: entry,
      step: schemaAndFlow.schema[entry],
      error: realError,
      register: register,
      schema: schemaAndFlow.schema,
      control: control,
      trigger: trigger,
      getValues: getValues,
      setValue: setValue,
      watch: watch,
      inputWrapper: inputWrapper,
      httpClient: maybeCustomHttpClient,
      defaultValue: value && value[entry]
    }));
  }));
};