'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var vue = require('vue');
var isEqual = require('lodash-es/isEqual');
var scrollIntoView = require('scroll-into-view-if-needed');
var util = require('../_util/util.js');
var index = require('../_util/vue-types/index.js');
var classNames = require('../_util/classNames.js');
var warning = require('../_util/warning.js');
var initDefaultProps = require('../_util/props-util/initDefaultProps.js');
var type = require('../_util/type.js');
require('../hooks/index.js');
var context = require('../config-provider/context.js');
var SizeContext = require('../config-provider/SizeContext.js');
var DisabledContext = require('../config-provider/DisabledContext.js');
var index$1 = require('./style/index.js');
var useForm = require('./useForm.js');
var context$1 = require('./context.js');
var asyncUtil = require('./utils/asyncUtil.js');
var messages = require('./utils/messages.js');
var valueUtil = require('./utils/valueUtil.js');
var FormItem = require('./FormItem.js');
var useConfigInject = require('../config-provider/hooks/useConfigInject.js');

const formProps = () => ({
  layout: index.default.oneOf(type.tuple("horizontal", "inline", "vertical")),
  labelCol: type.objectType(),
  wrapperCol: type.objectType(),
  colon: type.booleanType(),
  labelAlign: type.stringType(),
  labelWrap: type.booleanType(),
  prefixCls: String,
  requiredMark: type.someType([String, Boolean]),
  /** @deprecated Will warning in future branch. Pls use `requiredMark` instead. */
  hideRequiredMark: type.booleanType(),
  model: index.default.object,
  rules: type.objectType(),
  validateMessages: type.objectType(),
  validateOnRuleChange: type.booleanType(),
  // 提交失败自动滚动到第一个错误字段
  scrollToFirstError: type.anyType(),
  onSubmit: type.functionType(),
  name: String,
  validateTrigger: type.someType([String, Array]),
  size: type.stringType(),
  disabled: type.booleanType(),
  onValuesChange: type.functionType(),
  onFieldsChange: type.functionType(),
  onFinish: type.functionType(),
  onFinishFailed: type.functionType(),
  onValidate: type.functionType()
});
function isEqualName(name1, name2) {
  return isEqual(util.toArray(name1), util.toArray(name2));
}
const Form = /* @__PURE__ */ vue.defineComponent({
  compatConfig: {
    MODE: 3
  },
  name: "AForm",
  inheritAttrs: false,
  props: initDefaultProps.default(formProps(), {
    layout: "horizontal",
    hideRequiredMark: false,
    colon: true
  }),
  Item: FormItem.default,
  useForm: useForm.default,
  // emits: ['finishFailed', 'submit', 'finish', 'validate'],
  setup(props, {
    emit,
    slots,
    expose,
    attrs
  }) {
    const {
      prefixCls,
      direction,
      form: contextForm,
      size,
      disabled
    } = useConfigInject.default("form", props);
    const requiredMark = vue.computed(() => props.requiredMark === "" || props.requiredMark);
    const mergedRequiredMark = vue.computed(() => {
      var _a;
      if (requiredMark.value !== void 0)
        return requiredMark.value;
      if (contextForm && ((_a = contextForm.value) == null ? void 0 : _a.requiredMark) !== void 0)
        return contextForm.value.requiredMark;
      if (props.hideRequiredMark)
        return false;
      return true;
    });
    SizeContext.useProviderSize(size);
    DisabledContext.useProviderDisabled(disabled);
    const mergedColon = vue.computed(() => {
      var _a, _b;
      return (_b = props.colon) != null ? _b : (_a = contextForm.value) == null ? void 0 : _a.colon;
    });
    const {
      validateMessages: globalValidateMessages
    } = context.useInjectGlobalForm();
    const validateMessages = vue.computed(() => {
      return {
        ...messages.defaultValidateMessages,
        ...globalValidateMessages.value,
        ...props.validateMessages
      };
    });
    const [wrapSSR, hashId] = index$1.default(prefixCls);
    const formClassName = vue.computed(() => classNames.default(prefixCls.value, {
      [`${prefixCls.value}-${props.layout}`]: true,
      [`${prefixCls.value}-hide-required-mark`]: mergedRequiredMark.value === false,
      [`${prefixCls.value}-rtl`]: direction.value === "rtl",
      [`${prefixCls.value}-${size.value}`]: size.value
    }, hashId.value));
    const lastValidatePromise = vue.ref();
    const fields = {};
    const addField = (eventKey, field) => {
      fields[eventKey] = field;
    };
    const removeField = (eventKey) => {
      delete fields[eventKey];
    };
    const getFieldsByNameList = (nameList) => {
      const provideNameList = !!nameList;
      const namePathList = provideNameList ? util.toArray(nameList).map(valueUtil.getNamePath) : [];
      if (!provideNameList) {
        return Object.values(fields);
      } else {
        return Object.values(fields).filter((field) => namePathList.findIndex((namePath) => isEqualName(namePath, field.fieldName.value)) > -1);
      }
    };
    const resetFields = (name) => {
      if (!props.model) {
        warning.default(false, "Form", "model is required for resetFields to work.");
        return;
      }
      getFieldsByNameList(name).forEach((field) => {
        field.resetField();
      });
    };
    const clearValidate = (name) => {
      getFieldsByNameList(name).forEach((field) => {
        field.clearValidate();
      });
    };
    const scrollToField = (name, options = {}) => {
      const fields2 = getFieldsByNameList(name ? [name] : void 0);
      if (fields2.length) {
        const fieldId = fields2[0].fieldId.value;
        const node = fieldId ? document.getElementById(fieldId) : null;
        if (node) {
          scrollIntoView(node, {
            scrollMode: "if-needed",
            block: "nearest",
            ...options
          });
        }
      }
    };
    const handleFinishFailed = (errorInfo) => {
      const {
        scrollToFirstError
      } = props;
      emit("finishFailed", errorInfo);
      if (scrollToFirstError && errorInfo.errorFields.length) {
        let scrollToFieldOptions = {};
        if (typeof scrollToFirstError === "object")
          scrollToFieldOptions = scrollToFirstError;
        scrollToField(errorInfo.errorFields[0].name, scrollToFieldOptions);
      }
    };
    const getFieldsValue = (nameList = true) => {
      if (nameList === true) {
        const allNameList = [];
        Object.values(fields).forEach(({
          namePath
        }) => {
          allNameList.push(namePath.value);
        });
        return valueUtil.cloneByNamePathList(props.model, allNameList);
      } else {
        return valueUtil.cloneByNamePathList(props.model, nameList);
      }
    };
    const validateFields = (nameList, options) => {
      warning.default(!(nameList instanceof Function), "Form", "validateFields/validateField/validate not support callback, please use promise instead");
      if (!props.model) {
        warning.default(false, "Form", "model is required for validateFields to work.");
        return Promise.reject("Form `model` is required for validateFields to work.");
      }
      const provideNameList = !!nameList;
      const namePathList = provideNameList ? util.toArray(nameList).map(valueUtil.getNamePath) : [];
      const promiseList = [];
      Object.values(fields).forEach((field) => {
        var _a;
        if (!provideNameList)
          namePathList.push(field.namePath.value);
        if (!((_a = field.rules) == null ? void 0 : _a.value.length))
          return;
        const fieldNamePath = field.namePath.value;
        if (!provideNameList || valueUtil.containsNamePath(namePathList, fieldNamePath)) {
          const promise = field.validateRules({
            validateMessages: validateMessages.value,
            ...options
          });
          promiseList.push(promise.then(() => ({
            name: fieldNamePath,
            errors: [],
            warnings: []
          })).catch((ruleErrors) => {
            const mergedErrors = [];
            const mergedWarnings = [];
            ruleErrors.forEach(({
              rule: {
                warningOnly
              },
              errors
            }) => {
              if (warningOnly)
                mergedWarnings.push(...errors);
              else
                mergedErrors.push(...errors);
            });
            if (mergedErrors.length) {
              return Promise.reject({
                name: fieldNamePath,
                errors: mergedErrors,
                warnings: mergedWarnings
              });
            }
            return {
              name: fieldNamePath,
              errors: mergedErrors,
              warnings: mergedWarnings
            };
          }));
        }
      });
      const summaryPromise = asyncUtil.allPromiseFinish(promiseList);
      lastValidatePromise.value = summaryPromise;
      const returnPromise = summaryPromise.then(() => {
        if (lastValidatePromise.value === summaryPromise)
          return Promise.resolve(getFieldsValue(namePathList));
        return Promise.reject([]);
      }).catch((results) => {
        const errorList = results.filter((result) => result && result.errors.length);
        return Promise.reject({
          values: getFieldsValue(namePathList),
          errorFields: errorList,
          outOfDate: lastValidatePromise.value !== summaryPromise
        });
      });
      returnPromise.catch((e) => e);
      return returnPromise;
    };
    const validateField = (...args) => {
      return validateFields(...args);
    };
    const validate = (...args) => {
      return validateField(...args);
    };
    const handleSubmit = (e) => {
      e.preventDefault();
      e.stopPropagation();
      emit("submit", e);
      if (props.model) {
        const res = validateFields();
        res.then((values) => {
          emit("finish", values);
        }).catch((errors) => {
          handleFinishFailed(errors);
        });
      }
    };
    expose({
      resetFields,
      clearValidate,
      validateFields,
      getFieldsValue,
      validate,
      scrollToField
    });
    context$1.useProvideForm({
      model: vue.computed(() => props.model),
      name: vue.computed(() => props.name),
      labelAlign: vue.computed(() => props.labelAlign),
      labelCol: vue.computed(() => props.labelCol),
      labelWrap: vue.computed(() => props.labelWrap),
      wrapperCol: vue.computed(() => props.wrapperCol),
      vertical: vue.computed(() => props.layout === "vertical"),
      colon: mergedColon,
      requiredMark: mergedRequiredMark,
      validateTrigger: vue.computed(() => props.validateTrigger),
      rules: vue.computed(() => props.rules),
      addField,
      removeField,
      onValidate: (name, status, errors) => {
        emit("validate", name, status, errors);
      },
      validateMessages
    });
    vue.watch(() => props.rules, () => {
      if (props.validateOnRuleChange)
        validateFields();
    });
    return () => {
      var _a;
      return wrapSSR(vue.createVNode("form", vue.mergeProps(attrs, {
        "onSubmit": handleSubmit,
        "class": [formClassName.value, attrs.class]
      }), [(_a = slots.default) == null ? void 0 : _a.call(slots)]));
    };
  }
});

exports.default = Form;
exports.formProps = formProps;
//# sourceMappingURL=Form.js.map
