"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _react = require("react");
var _utils = require("./utils");
var _classnames = _interopRequireDefault(require("classnames"));
var _reactMeasure = _interopRequireDefault(require("react-measure"));
var _constants = require("../../constants");
var _Button = _interopRequireDefault(require("../Button"));
var _ButtonContext = require("../Button/ButtonContext");
var _FormField = _interopRequireDefault(require("../FormField"));
var _Section = _interopRequireDefault(require("../Section"));
var _Translate = _interopRequireDefault(require("../Translate"));
var _FormContext = _interopRequireDefault(require("./FormContext"));
var _VerticalContext = _interopRequireWildcard(require("../VerticalContext"));
var _DisabledContext = _interopRequireDefault(require("./DisabledContext"));
var _utils2 = require("../utils");
var _jsxRuntime = require("react/jsx-runtime");
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (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; }
// Copyright 1999-2023. Plesk International GmbH. All rights reserved.

const actionButtonsConfig = (0, _ButtonContext.getButtonContextValue)({
  defaultProps: {
    size: 'lg'
  }
});
class Form extends _react.Component {
  constructor() {
    var _this;
    super(...arguments);
    _this = this;
    (0, _defineProperty2.default)(this, "state", {
      values: this.props.values,
      vertical: this.props.vertical || false,
      requiredFields: [],
      formContext: {
        getValues: () => this.state.values,
        getValue: (name, def) => {
          if (this.state.values) {
            return (0, _utils.getIn)(this.state.values, name, def);
          }
          return def;
        },
        setValue: (name, value) => {
          this.setState(_ref => {
            let {
              values
            } = _ref;
            if (values) {
              return {
                values: (0, _utils.setIn)(values, name, value)
              };
            }
            return null;
          });
          (0, _utils2.safeInvoke)(this.props.onFieldChange, name, value);
        },
        getErrors: name => {
          if (this.props.errors) {
            return (0, _utils.getIn)(this.props.errors, name, {});
          }
          return {};
        },
        registerField: (name, field) => {
          if (name) {
            this.fields[name] = field;
          }
        },
        unregisterField: name => {
          if (name) {
            delete this.fields[name];
          }
        },
        setRequiredField: (name, required) => {
          this.setState(prevState => {
            if (required) {
              return {
                requiredFields: [...prevState.requiredFields, name]
              };
            }
            return {
              requiredFields: prevState.requiredFields.filter(v => v !== name)
            };
          });
        },
        getRequiredMark: () => this.props.requiredMark
      }
    });
    (0, _defineProperty2.default)(this, "fields", {});
    (0, _defineProperty2.default)(this, "handleSubmit", e => {
      e.preventDefault();
      if (this.props.onSubmit && this.state.values) {
        this.props.onSubmit(this.state.values, false);
      }
    });
    (0, _defineProperty2.default)(this, "handleSubmitClick", e => {
      if (e.currentTarget.type === 'submit') {
        return;
      }
      if (this.props.onSubmit && this.state.values) {
        this.props.onSubmit(this.state.values, false);
      }
    });
    (0, _defineProperty2.default)(this, "handleApplyClick", e => {
      if (e.currentTarget.type === 'submit') {
        return;
      }
      if (this.props.onSubmit && this.state.values) {
        this.props.onSubmit(this.state.values, true);
      }
    });
    (0, _defineProperty2.default)(this, "handleResize", _ref2 => {
      let {
        bounds
      } = _ref2;
      const {
        vertical
      } = this.props;
      if (vertical !== undefined) {
        this.setState({
          vertical
        });
        return;
      }
      this.setState({
        vertical: bounds.width < _VerticalContext.VERTICAL_BREAKPOINT
      });
    });
    (0, _defineProperty2.default)(this, "renderForm", function () {
      let {
        actionButtons
      } = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
      const {
        innerRef,
        baseClassName,
        className,
        children,
        requiredMark,
        hideRequiredLegend,
        values,
        errors,
        submitButton,
        applyButton,
        cancelButton,
        onFieldChange,
        onSubmit,
        additionalButtons,
        footerClassName,
        state,
        render,
        vertical,
        ...props
      } = _this.props;
      return /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormContext.default.Provider, {
        value: _this.state.formContext,
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_VerticalContext.default.Provider, {
          value: _this.state.vertical,
          children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_DisabledContext.default.Provider, {
            value: !!state,
            children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactMeasure.default, {
              onResize: _this.handleResize,
              innerRef: innerRef,
              bounds: true,
              children: _ref3 => {
                let {
                  measureRef
                } = _ref3;
                return /*#__PURE__*/(0, _jsxRuntime.jsxs)("form", {
                  ref: measureRef,
                  className: (0, _classnames.default)(baseClassName, {
                    [`${baseClassName}--has-required`]: _this.hasRequiredField()
                  }, className),
                  onSubmit: _this.handleSubmit,
                  ...props,
                  children: [children, actionButtons, /*#__PURE__*/(0, _jsxRuntime.jsx)("input", {
                    type: "image",
                    src: "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=",
                    style: {
                      border: 0,
                      height: 0,
                      width: 0,
                      position: 'absolute'
                    }
                  })]
                });
              }
            })
          })
        })
      });
    });
    (0, _defineProperty2.default)(this, "renderActionButtons", () => {
      const {
        submitButton,
        applyButton,
        cancelButton,
        state,
        additionalButtons,
        baseClassName,
        footerClassName
      } = this.props;
      return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Section.default, {
        className: (0, _classnames.default)(`${baseClassName}__footer`, footerClassName),
        children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_FormField.default, {
          children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_ButtonContext.ButtonContext.Provider, {
            value: actionButtonsConfig,
            children: [this.renderSubmitButton({
              submitButton,
              state
            }), this.renderApplyButton({
              applyButton,
              state
            }), this.renderAdditionalButtons({
              additionalButtons
            }), this.renderCancelButton({
              cancelButton,
              state
            })]
          })
        })
      });
    });
  }
  static getDerivedStateFromProps(props, state) {
    const {
      values,
      errors,
      requiredMark
    } = props;
    const {
      prevValues,
      prevErrors,
      prevRequiredMark
    } = state;
    const nextState = {};
    if (values !== prevValues) {
      nextState.values = values;
    }
    if (values !== prevValues || errors !== prevErrors || requiredMark !== prevRequiredMark) {
      nextState.formContext = {
        ...state.formContext
      };
    }
    nextState.prevValues = values;
    nextState.prevErrors = errors;
    nextState.prevRequiredMark = requiredMark;
    return nextState;
  }
  componentDidUpdate(prevProps) {
    const {
      errors
    } = this.props;
    if (errors !== prevProps.errors) {
      let field;
      let fieldErrors;
      Object.keys(this.fields).every(name => {
        const foundError = (0, _utils.getIn)(errors, name);
        if (foundError && typeof foundError === 'object' && Object.keys(foundError).length > 0) {
          field = this.fields[name];
          fieldErrors = foundError;
          return false;
        }
        return true;
      });
      if (field) {
        field.focus(fieldErrors);
      }
    }
  }
  hasRequiredField() {
    return this.props.requiredMark && this.state.requiredFields.length > 0;
  }
  renderSubmitButton(_ref4) {
    let {
      submitButton,
      state
    } = _ref4;
    if (!submitButton) {
      return null;
    }
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
      intent: "primary",
      state: state === 'submit' ? 'loading' : undefined,
      disabled: !!state,
      onClick: this.handleSubmitClick
      // eslint-disable-next-line react/no-children-prop
      ,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Translate.default, {
        content: "Form.submitButton",
        fallback: "Save"
      }),
      ...(typeof submitButton === 'object' ? submitButton : {})
    });
  }
  renderApplyButton(_ref5) {
    let {
      applyButton,
      state
    } = _ref5;
    if (!applyButton) {
      return null;
    }
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
      intent: "primary",
      state: state === 'apply' ? 'loading' : undefined,
      disabled: !!state,
      onClick: this.handleApplyClick
      // eslint-disable-next-line react/no-children-prop
      ,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Translate.default, {
        content: "Form.applyButton",
        fallback: "Apply"
      }),
      ...(typeof applyButton === 'object' ? applyButton : {})
    });
  }
  renderCancelButton(_ref6) {
    let {
      cancelButton,
      state
    } = _ref6;
    if (!cancelButton) {
      return null;
    }
    return /*#__PURE__*/(0, _jsxRuntime.jsx)(_Button.default, {
      state: state === 'cancel' ? 'loading' : undefined,
      disabled: !!state
      // eslint-disable-next-line react/no-children-prop
      ,
      children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_Translate.default, {
        content: "Form.cancelButton",
        fallback: "Cancel"
      }),
      ...(typeof cancelButton === 'object' ? cancelButton : {})
    });
  }
  renderAdditionalButtons(_ref7) {
    let {
      additionalButtons
    } = _ref7;
    const {
      baseClassName
    } = this.props;
    if (Array.isArray(additionalButtons)) {
      return additionalButtons.map(element => {
        if ( /*#__PURE__*/(0, _react.isValidElement)(element)) {
          const props = {
            className: (0, _classnames.default)(element.props.className, `${baseClassName}__additional-button`)
          };
          return /*#__PURE__*/(0, _react.cloneElement)(element, props);
        }
        return element;
      });
    }
    return null;
  }
  render() {
    const {
      render
    } = this.props;
    if (typeof render === 'function') {
      return render({
        renderForm: this.renderForm,
        renderActionButtons: this.renderActionButtons
      });
    }
    return this.renderForm({
      actionButtons: this.renderActionButtons()
    });
  }
}
(0, _defineProperty2.default)(Form, "defaultProps", {
  children: undefined,
  requiredMark: /*#__PURE__*/(0, _jsxRuntime.jsx)("span", {
    className: `${_constants.CLS_PREFIX}form__required`
  }),
  hideRequiredLegend: false,
  values: {},
  errors: {},
  state: undefined,
  submitButton: true,
  applyButton: true,
  cancelButton: true,
  additionalButtons: [],
  onFieldChange: undefined,
  onSubmit: undefined,
  className: undefined,
  footerClassName: undefined,
  vertical: undefined,
  baseClassName: `${_constants.CLS_PREFIX}form`,
  render: undefined,
  innerRef: undefined
});
const RefForwardingForm = /*#__PURE__*/(0, _react.forwardRef)((props, ref) => {
  const innerRef = (0, _react.useRef)(null);
  (0, _react.useImperativeHandle)(ref, () => ({
    submit() {
      innerRef.current?.dispatchEvent(new Event('submit', {
        cancelable: true,
        bubbles: true
      }));
    }
  }));
  return /*#__PURE__*/(0, _jsxRuntime.jsx)(Form, {
    innerRef: innerRef,
    ...props
  });
});
RefForwardingForm.displayName = 'Form';
/**
 * `Form` component is used for entering and submitting of user data.
 * [More details about designing of forms.](#!/Good%20Forms)
 * @since 0.0.54
 */
var _default = exports.default = RefForwardingForm;