"use strict";
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const shared_esmBundler = require("../../../../../@vue/shared/dist/shared.esm-bundler.js");
const objects = require("../../../utils/objects.js");
const error = require("../../../utils/error.js");
const index = require("../../../hooks/use-namespace/index.js");
const form = require("./form.js");
const constants = require("./constants.js");
const useFormCommonProps = require("./hooks/use-form-common-props.js");
const utils = require("./utils.js");
const Vue = require("vue");
const cloneDeep = require("../../../../../lodash-es/cloneDeep.js");
const castArray = require("../../../../../lodash-es/castArray.js");
const COMPONENT_NAME = "ElForm";
var form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ Vue.defineComponent({
  name: COMPONENT_NAME,
  __name: "form",
  props: form.formProps,
  emits: form.formEmits,
  setup(__props, { expose: __expose, emit: __emit }) {
    const props = __props;
    const emit = __emit;
    const formRef = Vue.ref();
    const fields = Vue.reactive([]);
    const initialValues = /* @__PURE__ */ new Map();
    const formSize = useFormCommonProps.useFormSize();
    const ns = index.useNamespace("form");
    const formClasses = Vue.computed(() => {
      const { labelPosition, inline } = props;
      return [
        ns.b(),
        ns.m(formSize.value || "default"),
        {
          [ns.m(`label-${labelPosition}`)]: labelPosition,
          [ns.m("inline")]: inline
        }
      ];
    });
    const getField = (prop) => {
      return utils.filterFields(fields, [prop])[0];
    };
    const addField = (field) => {
      fields.push(field);
      if (field.propString) if (initialValues.has(field.propString)) field.setInitialValue(initialValues.get(field.propString));
      else initialValues.set(field.propString, cloneDeep.default(field.fieldValue));
    };
    const removeField = (field) => {
      if (field.prop) fields.splice(fields.indexOf(field), 1);
    };
    const setInitialValues = (initModel) => {
      if (!props.model) {
        error.debugWarn(COMPONENT_NAME, "model is required for setInitialValues to work.");
        return;
      }
      if (!initModel) {
        error.debugWarn(COMPONENT_NAME, "initModel is required for setInitialValues to work.");
        return;
      }
      for (const key of initialValues.keys()) initialValues.set(key, cloneDeep.default(objects.getProp(initModel, key).value));
      fields.forEach((field) => {
        if (field.prop) field.setInitialValue(objects.getProp(initModel, field.prop).value);
      });
    };
    const resetFields = (properties = []) => {
      if (!props.model) {
        error.debugWarn(COMPONENT_NAME, "model is required for resetFields to work.");
        return;
      }
      utils.filterFields(fields, properties).forEach((field) => field.resetField());
      const activePropStrings = new Set(fields.map((f) => f.propString).filter(Boolean));
      const propsToCheck = properties.length > 0 ? castArray.default(properties).map((p) => shared_esmBundler.isArray(p) ? p.join(".") : p) : [...initialValues.keys()];
      for (const propString of propsToCheck) if (!activePropStrings.has(propString) && initialValues.has(propString)) objects.getProp(props.model, propString).value = cloneDeep.default(initialValues.get(propString));
    };
    const clearValidate = (props2 = []) => {
      utils.filterFields(fields, props2).forEach((field) => field.clearValidate());
    };
    const isValidatable = Vue.computed(() => {
      const hasModel = !!props.model;
      if (!hasModel) error.debugWarn(COMPONENT_NAME, "model is required for validate to work.");
      return hasModel;
    });
    const obtainValidateFields = (props2) => {
      if (fields.length === 0) return [];
      const filteredFields = utils.filterFields(fields, props2);
      if (!filteredFields.length) {
        error.debugWarn(COMPONENT_NAME, "please pass correct props!");
        return [];
      }
      return filteredFields;
    };
    const validate = async (callback) => validateField(void 0, callback);
    const doValidateField = async (props2 = []) => {
      if (!isValidatable.value) return false;
      const fields2 = obtainValidateFields(props2);
      if (fields2.length === 0) return true;
      let validationErrors = {};
      for (const field of fields2) try {
        await field.validate("");
        if (field.validateState === "error" && !field.error) field.resetField();
      } catch (fields3) {
        validationErrors = {
          ...validationErrors,
          ...fields3
        };
      }
      if (Object.keys(validationErrors).length === 0) return true;
      return Promise.reject(validationErrors);
    };
    const validateField = async (modelProps = [], callback) => {
      var _a;
      let result = false;
      const shouldThrow = !shared_esmBundler.isFunction(callback);
      try {
        result = await doValidateField(modelProps);
        if (result === true) await (callback == null ? void 0 : callback(result));
        return result;
      } catch (e) {
        if (e instanceof Error) throw e;
        const invalidFields = e;
        if (props.scrollToError) {
          if (formRef.value) (_a = formRef.value.querySelector(`.${ns.b()}-item.is-error`)) == null ? void 0 : _a.scrollIntoView(props.scrollIntoViewOptions);
        }
        !result && await (callback == null ? void 0 : callback(false, invalidFields));
        return shouldThrow && Promise.reject(invalidFields);
      }
    };
    const scrollToField = (prop) => {
      var _a;
      const field = getField(prop);
      if (field) (_a = field.$el) == null ? void 0 : _a.scrollIntoView(props.scrollIntoViewOptions);
    };
    Vue.watch(() => props.rules, () => {
      if (props.validateOnRuleChange) validate().catch((err) => error.debugWarn(err));
    }, {
      deep: true,
      flush: "post"
    });
    Vue.provide(constants.formContextKey, Vue.reactive({
      ...Vue.toRefs(props),
      emit,
      resetFields,
      clearValidate,
      validateField,
      getField,
      addField,
      removeField,
      setInitialValues,
      ...utils.useFormLabelWidth()
    }));
    __expose({
      validate,
      validateField,
      resetFields,
      clearValidate,
      scrollToField,
      getField,
      fields,
      setInitialValues
    });
    return (_ctx, _cache) => {
      return Vue.openBlock(), Vue.createElementBlock("form", {
        ref_key: "formRef",
        ref: formRef,
        class: Vue.normalizeClass(formClasses.value)
      }, [Vue.renderSlot(_ctx.$slots, "default")], 2);
    };
  }
});
exports.default = form_vue_vue_type_script_setup_true_lang_default;
