{"version":3,"file":"form2.mjs","names":[],"sources":["../../../../../../packages/components/form/src/form.vue"],"sourcesContent":["<template>\n  <form ref=\"formRef\" :class=\"formClasses\">\n    <slot />\n  </form>\n</template>\n\n<script lang=\"ts\" setup>\nimport { computed, provide, reactive, ref, toRefs, watch } from 'vue'\nimport { cloneDeep } from 'lodash-unified'\nimport {\n  debugWarn,\n  ensureArray,\n  getProp,\n  isArray,\n  isFunction,\n} from '@element-plus/utils'\nimport { useNamespace } from '@element-plus/hooks'\nimport { useFormSize } from './hooks'\nimport { formContextKey } from './constants'\nimport { formEmits } from './form'\nimport { filterFields, useFormLabelWidth } from './utils'\n\nimport type { ValidateFieldsError } from 'async-validator'\nimport type { Arrayable } from '@element-plus/utils'\nimport type { FormProps } from './form'\nimport type {\n  FormContext,\n  FormItemContext,\n  FormValidateCallback,\n  FormValidationResult,\n} from './types'\nimport type { FormItemProp } from './form-item'\n\nconst COMPONENT_NAME = 'ElForm'\ndefineOptions({\n  name: COMPONENT_NAME,\n})\nconst props = withDefaults(defineProps<FormProps>(), {\n  labelPosition: 'right',\n  requireAsteriskPosition: 'left',\n  labelWidth: '',\n  labelSuffix: '',\n  showMessage: true,\n  validateOnRuleChange: true,\n  scrollIntoViewOptions: true,\n})\nconst emit = defineEmits(formEmits)\n\nconst formRef = ref<HTMLElement>()\nconst fields = reactive<FormItemContext[]>([])\nconst initialValues = new Map<string, any>()\n\nconst formSize = useFormSize()\nconst ns = useNamespace('form')\nconst formClasses = computed(() => {\n  const { labelPosition, inline } = props\n  return [\n    ns.b(),\n    ns.m(formSize.value || 'default'),\n    {\n      [ns.m(`label-${labelPosition}`)]: labelPosition,\n      [ns.m('inline')]: inline,\n    },\n  ]\n})\n\nconst getField: FormContext['getField'] = (prop) => {\n  return filterFields(fields, [prop])[0]\n}\n\nconst addField: FormContext['addField'] = (field) => {\n  fields.push(field)\n  if (field.propString) {\n    if (initialValues.has(field.propString)) {\n      field.setInitialValue(initialValues.get(field.propString))\n    } else {\n      initialValues.set(field.propString, cloneDeep(field.fieldValue))\n    }\n  }\n}\n\nconst removeField: FormContext['removeField'] = (field) => {\n  if (field.prop) {\n    fields.splice(fields.indexOf(field), 1)\n  }\n}\n\nconst setInitialValues: FormContext['setInitialValues'] = (initModel) => {\n  if (!props.model) {\n    debugWarn(COMPONENT_NAME, 'model is required for setInitialValues to work.')\n    return\n  }\n  if (!initModel) {\n    debugWarn(\n      COMPONENT_NAME,\n      'initModel is required for setInitialValues to work.'\n    )\n    return\n  }\n\n  for (const key of initialValues.keys()) {\n    initialValues.set(key, cloneDeep(getProp(initModel, key).value))\n  }\n  fields.forEach((field) => {\n    if (field.prop) {\n      field.setInitialValue(getProp(initModel, field.prop).value)\n    }\n  })\n}\n\nconst resetFields: FormContext['resetFields'] = (properties = []) => {\n  if (!props.model) {\n    debugWarn(COMPONENT_NAME, 'model is required for resetFields to work.')\n    return\n  }\n\n  filterFields(fields, properties).forEach((field) => field.resetField())\n\n  const activePropStrings = new Set(\n    fields.map((f) => f.propString).filter(Boolean)\n  )\n  const propsToCheck =\n    properties.length > 0\n      ? ensureArray(properties).map((p) => (isArray(p) ? p.join('.') : p))\n      : [...initialValues.keys()]\n\n  for (const propString of propsToCheck) {\n    if (!activePropStrings.has(propString) && initialValues.has(propString)) {\n      getProp(props.model, propString).value = cloneDeep(\n        initialValues.get(propString)\n      )\n    }\n  }\n}\n\nconst clearValidate: FormContext['clearValidate'] = (props = []) => {\n  filterFields(fields, props).forEach((field) => field.clearValidate())\n}\n\nconst isValidatable = computed(() => {\n  const hasModel = !!props.model\n  if (!hasModel) {\n    debugWarn(COMPONENT_NAME, 'model is required for validate to work.')\n  }\n  return hasModel\n})\n\nconst obtainValidateFields = (props: Arrayable<FormItemProp>) => {\n  if (fields.length === 0) return []\n\n  const filteredFields = filterFields(fields, props)\n  if (!filteredFields.length) {\n    debugWarn(COMPONENT_NAME, 'please pass correct props!')\n    return []\n  }\n  return filteredFields\n}\n\nconst validate = async (\n  callback?: FormValidateCallback\n): FormValidationResult => validateField(undefined, callback)\n\nconst doValidateField = async (\n  props: Arrayable<FormItemProp> = []\n): Promise<boolean> => {\n  if (!isValidatable.value) return false\n\n  const fields = obtainValidateFields(props)\n  if (fields.length === 0) return true\n\n  let validationErrors: ValidateFieldsError = {}\n  for (const field of fields) {\n    try {\n      await field.validate('')\n      if (field.validateState === 'error' && !field.error) field.resetField()\n    } catch (fields) {\n      validationErrors = {\n        ...validationErrors,\n        ...(fields as ValidateFieldsError),\n      }\n    }\n  }\n\n  if (Object.keys(validationErrors).length === 0) return true\n  return Promise.reject(validationErrors)\n}\n\nconst validateField: FormContext['validateField'] = async (\n  modelProps = [],\n  callback\n) => {\n  let result = false\n  const shouldThrow = !isFunction(callback)\n  try {\n    result = await doValidateField(modelProps)\n    // When result is false meaning that the fields are not validatable\n    if (result === true) {\n      await callback?.(result)\n    }\n    return result\n  } catch (e) {\n    if (e instanceof Error) throw e\n\n    const invalidFields = e as ValidateFieldsError\n\n    if (props.scrollToError) {\n      // form-item may be dynamically rendered based on the judgment conditions, and the order in invalidFields is uncertain.\n      // Therefore, the first form field with an error is determined by directly looking for the rendered element.\n      if (formRef.value) {\n        const formItem = formRef.value.querySelector(`.${ns.b()}-item.is-error`)\n        formItem?.scrollIntoView(props.scrollIntoViewOptions)\n      }\n    }\n    !result && (await callback?.(false, invalidFields))\n    return shouldThrow && Promise.reject(invalidFields)\n  }\n}\n\nconst scrollToField = (prop: FormItemProp) => {\n  const field = getField(prop)\n  if (field) {\n    field.$el?.scrollIntoView(props.scrollIntoViewOptions)\n  }\n}\n\nwatch(\n  () => props.rules,\n  () => {\n    if (props.validateOnRuleChange) {\n      validate().catch((err) => debugWarn(err))\n    }\n  },\n  { deep: true, flush: 'post' }\n)\n\nprovide(\n  formContextKey,\n  reactive({\n    ...toRefs(props),\n    emit,\n\n    resetFields,\n    clearValidate,\n    validateField,\n    getField,\n    addField,\n    removeField,\n    setInitialValues,\n\n    ...useFormLabelWidth(),\n  })\n)\n\ndefineExpose({\n  /**\n   * @description Validate the whole form. Receives a callback or returns `Promise`.\n   */\n  validate,\n  /**\n   * @description Validate specified fields.\n   */\n  validateField,\n  /**\n   * @description Reset specified fields and remove validation result.\n   */\n  resetFields,\n  /**\n   * @description Clear validation message for specified fields.\n   */\n  clearValidate,\n  /**\n   * @description Scroll to the specified fields.\n   */\n  scrollToField,\n  /**\n   * @description Get a field context.\n   */\n  getField,\n  /**\n   * @description All fields context.\n   */\n  fields,\n  /**\n   * @description Set initial values for form fields. When `resetFields` is called, fields will reset to these values.\n   */\n  setInitialValues,\n})\n</script>\n"],"mappings":""}