前端初始化
This commit is contained in:
+8
@@ -0,0 +1,8 @@
|
||||
import { FormContext, FormItemContext } from "./types.js";
|
||||
import { InjectionKey } from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/constants.d.ts
|
||||
declare const formContextKey: InjectionKey<FormContext>;
|
||||
declare const formItemContextKey: InjectionKey<FormItemContext | undefined>;
|
||||
//#endregion
|
||||
export { formContextKey, formItemContextKey };
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
//#region ../../packages/components/form/src/constants.ts
|
||||
const formContextKey = Symbol("formContextKey");
|
||||
const formItemContextKey = Symbol("formItemContextKey");
|
||||
//#endregion
|
||||
export { formContextKey, formItemContextKey };
|
||||
|
||||
//# sourceMappingURL=constants.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"constants.mjs","names":[],"sources":["../../../../../../packages/components/form/src/constants.ts"],"sourcesContent":["import type { InjectionKey } from 'vue'\nimport type { FormContext, FormItemContext } from './types'\n\nexport const formContextKey: InjectionKey<FormContext> =\n Symbol('formContextKey')\nexport const formItemContextKey: InjectionKey<FormItemContext | undefined> =\n Symbol('formItemContextKey')\n"],"mappings":";AAGA,MAAa,iBACX,OAAO,iBAAiB;AAC1B,MAAa,qBACX,OAAO,qBAAqB"}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
import { EpPropFinalized, EpPropMergeType } from "../../../utils/vue/props/types.js";
|
||||
import { ComponentSize } from "../../../constants/size.js";
|
||||
import { Arrayable } from "../../../utils/typescript.js";
|
||||
import { FormItemRule } from "./types.js";
|
||||
import * as _$vue from "vue";
|
||||
import { ExtractPublicPropTypes } from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/form-item.d.ts
|
||||
declare const formItemValidateStates: readonly ["", "error", "validating", "success"];
|
||||
type FormItemValidateState = (typeof formItemValidateStates)[number];
|
||||
type FormItemProp = Arrayable<string>;
|
||||
interface FormItemProps {
|
||||
/**
|
||||
* @description Label text.
|
||||
*/
|
||||
label?: string;
|
||||
/**
|
||||
* @description Width of label, e.g. `'50px'`. `'auto'` is supported.
|
||||
*/
|
||||
labelWidth?: string | number;
|
||||
/**
|
||||
* @description Position of label. If set to `'left'` or `'right'`, `label-width` prop is also required. The default is extend from `form label-position`.
|
||||
*/
|
||||
labelPosition?: 'left' | 'right' | 'top' | '';
|
||||
/**
|
||||
* @description A key of `model`. It could be an array of property paths (e.g `['a', 'b', '0']`). In the use of `validate` and `resetFields` method, the attribute is required.
|
||||
*/
|
||||
prop?: FormItemProp;
|
||||
/**
|
||||
* @description Whether the field is required or not, will be determined by validation rules if omitted.
|
||||
*/
|
||||
required?: boolean;
|
||||
/**
|
||||
* @description Validation rules of form, see the [following table](#formitemrule), more advanced usage at [async-validator](https://github.com/yiminghe/async-validator).
|
||||
*/
|
||||
rules?: Arrayable<FormItemRule>;
|
||||
/**
|
||||
* @description Field error message, set its value and the field will validate error and show this message immediately.
|
||||
*/
|
||||
error?: string;
|
||||
/**
|
||||
* @description Validation state of formItem.
|
||||
*/
|
||||
validateStatus?: FormItemValidateState;
|
||||
/**
|
||||
* @description Same as for in native label.
|
||||
*/
|
||||
for?: string;
|
||||
/**
|
||||
* @description Inline style validate message.
|
||||
*/
|
||||
inlineMessage?: boolean;
|
||||
/**
|
||||
* @description Whether to show the error message.
|
||||
*/
|
||||
showMessage?: boolean;
|
||||
/**
|
||||
* @description Control the size of components in this form-item.
|
||||
*/
|
||||
size?: ComponentSize;
|
||||
}
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormItemProps` instead.
|
||||
*/
|
||||
declare const formItemProps: {
|
||||
readonly label: StringConstructor;
|
||||
readonly labelWidth: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<readonly [StringConstructor, NumberConstructor], unknown, unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly labelPosition: EpPropFinalized<StringConstructor, "" | "top" | "right" | "left", unknown, "", boolean>;
|
||||
readonly prop: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<(new (...args: any[]) => string | string[]) | (() => FormItemProp) | (((new (...args: any[]) => string | string[]) | (() => FormItemProp)) | null)[], unknown, unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly required: EpPropFinalized<BooleanConstructor, unknown, unknown, undefined, boolean>;
|
||||
readonly rules: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<(new (...args: any[]) => FormItemRule | FormItemRule[]) | (() => Arrayable<FormItemRule>) | (((new (...args: any[]) => FormItemRule | FormItemRule[]) | (() => Arrayable<FormItemRule>)) | null)[], unknown, unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly error: StringConstructor;
|
||||
readonly validateStatus: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<StringConstructor, "" | "success" | "error" | "validating", unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly for: StringConstructor;
|
||||
readonly inlineMessage: EpPropFinalized<BooleanConstructor, unknown, unknown, undefined, boolean>;
|
||||
readonly showMessage: EpPropFinalized<BooleanConstructor, unknown, unknown, true, boolean>;
|
||||
readonly size: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<StringConstructor, "" | "default" | "small" | "large", unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormItemProps` instead.
|
||||
*/
|
||||
type FormItemPropsPublic = ExtractPublicPropTypes<typeof formItemProps>;
|
||||
//#endregion
|
||||
export { FormItemProp, FormItemProps, FormItemPropsPublic, FormItemValidateState, formItemProps, formItemValidateStates };
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import { componentSizes } from "../../../constants/size.mjs";
|
||||
import { buildProps, definePropType } from "../../../utils/vue/props/runtime.mjs";
|
||||
//#region ../../packages/components/form/src/form-item.ts
|
||||
const formItemValidateStates = [
|
||||
"",
|
||||
"error",
|
||||
"validating",
|
||||
"success"
|
||||
];
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormItemProps` instead.
|
||||
*/
|
||||
const formItemProps = buildProps({
|
||||
/**
|
||||
* @description Label text.
|
||||
*/
|
||||
label: String,
|
||||
/**
|
||||
* @description Width of label, e.g. `'50px'`. `'auto'` is supported.
|
||||
*/
|
||||
labelWidth: { type: [String, Number] },
|
||||
/**
|
||||
* @description Position of label. If set to `'left'` or `'right'`, `label-width` prop is also required. The default is extend from `form label-position`.
|
||||
*/
|
||||
labelPosition: {
|
||||
type: String,
|
||||
values: [
|
||||
"left",
|
||||
"right",
|
||||
"top",
|
||||
""
|
||||
],
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* @description A key of `model`. It could be an array of property paths (e.g `['a', 'b', '0']`). In the use of `validate` and `resetFields` method, the attribute is required.
|
||||
*/
|
||||
prop: { type: definePropType([String, Array]) },
|
||||
/**
|
||||
* @description Whether the field is required or not, will be determined by validation rules if omitted.
|
||||
*/
|
||||
required: {
|
||||
type: Boolean,
|
||||
default: void 0
|
||||
},
|
||||
/**
|
||||
* @description Validation rules of form, see the [following table](#formitemrule), more advanced usage at [async-validator](https://github.com/yiminghe/async-validator).
|
||||
*/
|
||||
rules: { type: definePropType([Object, Array]) },
|
||||
/**
|
||||
* @description Field error message, set its value and the field will validate error and show this message immediately.
|
||||
*/
|
||||
error: String,
|
||||
/**
|
||||
* @description Validation state of formItem.
|
||||
*/
|
||||
validateStatus: {
|
||||
type: String,
|
||||
values: formItemValidateStates
|
||||
},
|
||||
/**
|
||||
* @description Same as for in native label.
|
||||
*/
|
||||
for: String,
|
||||
/**
|
||||
* @description Inline style validate message.
|
||||
*/
|
||||
inlineMessage: {
|
||||
type: Boolean,
|
||||
default: void 0
|
||||
},
|
||||
/**
|
||||
* @description Whether to show the error message.
|
||||
*/
|
||||
showMessage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* @description Control the size of components in this form-item.
|
||||
*/
|
||||
size: {
|
||||
type: String,
|
||||
values: componentSizes
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
export { formItemProps, formItemValidateStates };
|
||||
|
||||
//# sourceMappingURL=form-item.mjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+61
@@ -0,0 +1,61 @@
|
||||
import { FormValidateCallback, FormValidationResult } from "./types.js";
|
||||
import { FormItemProps } from "./form-item.js";
|
||||
import * as _$vue from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/form-item.vue.d.ts
|
||||
declare var __VLS_13: {
|
||||
label: string;
|
||||
}, __VLS_15: {}, __VLS_23: {
|
||||
error: string;
|
||||
};
|
||||
type __VLS_Slots = {} & {
|
||||
label?: (props: typeof __VLS_13) => any;
|
||||
} & {
|
||||
default?: (props: typeof __VLS_15) => any;
|
||||
} & {
|
||||
error?: (props: typeof __VLS_23) => any;
|
||||
};
|
||||
declare const __VLS_base: _$vue.DefineComponent<FormItemProps, {
|
||||
/**
|
||||
* @description Form item size.
|
||||
*/
|
||||
size: _$vue.ComputedRef<"" | "default" | "small" | "large">;
|
||||
/**
|
||||
* @description Validation message.
|
||||
*/
|
||||
validateMessage: _$vue.Ref<string, string>;
|
||||
/**
|
||||
* @description Validation state.
|
||||
*/
|
||||
validateState: _$vue.Ref<"" | "success" | "error" | "validating", "" | "success" | "error" | "validating">;
|
||||
/**
|
||||
* @description Validate form item.
|
||||
*/
|
||||
validate: (trigger: string, callback?: FormValidateCallback) => FormValidationResult;
|
||||
/**
|
||||
* @description Remove validation status of the field.
|
||||
*/
|
||||
clearValidate: () => void;
|
||||
/**
|
||||
* @description Reset current field and remove validation result.
|
||||
*/
|
||||
resetField: () => void;
|
||||
/**
|
||||
* @description Set initial value for this field. When `resetField` is called, the field will reset to this value.
|
||||
*/
|
||||
setInitialValue: (value: any) => void;
|
||||
}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<FormItemProps> & Readonly<{}>, {
|
||||
required: boolean;
|
||||
labelPosition: "left" | "right" | "top" | "";
|
||||
inlineMessage: boolean;
|
||||
showMessage: boolean;
|
||||
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
||||
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
||||
declare const _default: typeof __VLS_export;
|
||||
type __VLS_WithSlots<T, S> = T & {
|
||||
new (): {
|
||||
$slots: S;
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
Generated
Vendored
+303
@@ -0,0 +1,303 @@
|
||||
import { isArray, isBoolean, isFunction } from "../../../utils/types.mjs";
|
||||
import { getProp } from "../../../utils/objects.mjs";
|
||||
import { addUnit } from "../../../utils/dom/style.mjs";
|
||||
import { ensureArray } from "../../../utils/arrays.mjs";
|
||||
import { useNamespace } from "../../../hooks/use-namespace/index.mjs";
|
||||
import { useId } from "../../../hooks/use-id/index.mjs";
|
||||
import { formContextKey, formItemContextKey } from "./constants.mjs";
|
||||
import { useFormSize } from "./hooks/use-form-common-props.mjs";
|
||||
import { formItemProps } from "./form-item.mjs";
|
||||
import form_label_wrap_default from "./form-label-wrap.mjs";
|
||||
import { refDebounced } from "@vueuse/core";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { TransitionGroup, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, nextTick, normalizeClass, normalizeStyle, onBeforeUnmount, onMounted, openBlock, provide, reactive, ref, renderSlot, resolveDynamicComponent, toDisplayString, toRefs, unref, useSlots, watch, withCtx } from "vue";
|
||||
import AsyncValidator from "async-validator";
|
||||
//#region ../../packages/components/form/src/form-item.vue?vue&type=script&setup=true&lang.ts
|
||||
const _hoisted_1 = ["role", "aria-labelledby"];
|
||||
var form_item_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
||||
name: "ElFormItem",
|
||||
__name: "form-item",
|
||||
props: formItemProps,
|
||||
setup(__props, { expose: __expose }) {
|
||||
const props = __props;
|
||||
const slots = useSlots();
|
||||
const formContext = inject(formContextKey, void 0);
|
||||
const parentFormItemContext = inject(formItemContextKey, void 0);
|
||||
const _size = useFormSize(void 0, { formItem: false });
|
||||
const ns = useNamespace("form-item");
|
||||
const labelId = useId().value;
|
||||
const inputIds = ref([]);
|
||||
const validateState = ref("");
|
||||
const validateStateDebounced = refDebounced(validateState, 100);
|
||||
const validateMessage = ref("");
|
||||
const formItemRef = ref();
|
||||
let initialValue = void 0;
|
||||
let isResettingField = false;
|
||||
const labelPosition = computed(() => props.labelPosition || formContext?.labelPosition);
|
||||
const labelStyle = computed(() => {
|
||||
if (labelPosition.value === "top") return {};
|
||||
return { width: addUnit(props.labelWidth ?? formContext?.labelWidth) };
|
||||
});
|
||||
const contentStyle = computed(() => {
|
||||
if (labelPosition.value === "top" || formContext?.inline) return {};
|
||||
if (!props.label && !props.labelWidth && isNested) return {};
|
||||
const labelWidth = addUnit(props.labelWidth ?? formContext?.labelWidth);
|
||||
if (!props.label && !slots.label) return { marginLeft: labelWidth };
|
||||
return {};
|
||||
});
|
||||
const formItemClasses = computed(() => [
|
||||
ns.b(),
|
||||
ns.m(_size.value),
|
||||
ns.is("error", validateState.value === "error"),
|
||||
ns.is("validating", validateState.value === "validating"),
|
||||
ns.is("success", validateState.value === "success"),
|
||||
ns.is("required", isRequired.value || props.required),
|
||||
ns.is("no-asterisk", formContext?.hideRequiredAsterisk),
|
||||
formContext?.requireAsteriskPosition === "right" ? "asterisk-right" : "asterisk-left",
|
||||
{
|
||||
[ns.m("feedback")]: formContext?.statusIcon,
|
||||
[ns.m(`label-${labelPosition.value}`)]: labelPosition.value
|
||||
}
|
||||
]);
|
||||
const _inlineMessage = computed(() => isBoolean(props.inlineMessage) ? props.inlineMessage : formContext?.inlineMessage || false);
|
||||
const validateClasses = computed(() => [ns.e("error"), { [ns.em("error", "inline")]: _inlineMessage.value }]);
|
||||
const propString = computed(() => {
|
||||
if (!props.prop) return "";
|
||||
return isArray(props.prop) ? props.prop.join(".") : props.prop;
|
||||
});
|
||||
const hasLabel = computed(() => {
|
||||
return !!(props.label || slots.label);
|
||||
});
|
||||
const labelFor = computed(() => {
|
||||
return props.for ?? (inputIds.value.length === 1 ? inputIds.value[0] : void 0);
|
||||
});
|
||||
const isGroup = computed(() => {
|
||||
return !labelFor.value && hasLabel.value;
|
||||
});
|
||||
const isNested = !!parentFormItemContext;
|
||||
const fieldValue = computed(() => {
|
||||
const model = formContext?.model;
|
||||
if (!model || !props.prop) return;
|
||||
return getProp(model, props.prop).value;
|
||||
});
|
||||
const normalizedRules = computed(() => {
|
||||
const { required } = props;
|
||||
const rules = [];
|
||||
if (props.rules) rules.push(...ensureArray(props.rules));
|
||||
const formRules = formContext?.rules;
|
||||
if (formRules && props.prop) {
|
||||
const _rules = getProp(formRules, props.prop).value;
|
||||
if (_rules) rules.push(...ensureArray(_rules));
|
||||
}
|
||||
if (required !== void 0) {
|
||||
const requiredRules = rules.map((rule, i) => [rule, i]).filter(([rule]) => "required" in rule);
|
||||
if (requiredRules.length > 0) for (const [rule, i] of requiredRules) {
|
||||
if (rule.required === required) continue;
|
||||
rules[i] = {
|
||||
...rule,
|
||||
required
|
||||
};
|
||||
}
|
||||
else rules.push({ required });
|
||||
}
|
||||
return rules;
|
||||
});
|
||||
const validateEnabled = computed(() => normalizedRules.value.length > 0);
|
||||
const getFilteredRule = (trigger) => {
|
||||
return normalizedRules.value.filter((rule) => {
|
||||
if (!rule.trigger || !trigger) return true;
|
||||
if (isArray(rule.trigger)) return rule.trigger.includes(trigger);
|
||||
else return rule.trigger === trigger;
|
||||
}).map(({ trigger, ...rule }) => rule);
|
||||
};
|
||||
const isRequired = computed(() => normalizedRules.value.some((rule) => rule.required));
|
||||
const shouldShowError = computed(() => validateStateDebounced.value === "error" && props.showMessage && (formContext?.showMessage ?? true));
|
||||
const currentLabel = computed(() => `${props.label || ""}${formContext?.labelSuffix || ""}`);
|
||||
const setValidationState = (state) => {
|
||||
validateState.value = state;
|
||||
};
|
||||
const onValidationFailed = (error) => {
|
||||
const { errors, fields } = error;
|
||||
if (!errors || !fields) console.error(error);
|
||||
setValidationState("error");
|
||||
validateMessage.value = errors ? errors?.[0]?.message ?? `${props.prop} is required` : "";
|
||||
formContext?.emit("validate", props.prop, false, validateMessage.value);
|
||||
};
|
||||
const onValidationSucceeded = () => {
|
||||
setValidationState("success");
|
||||
formContext?.emit("validate", props.prop, true, "");
|
||||
};
|
||||
const doValidate = async (rules) => {
|
||||
const modelName = propString.value;
|
||||
return new AsyncValidator({ [modelName]: rules }).validate({ [modelName]: fieldValue.value }, { firstFields: true }).then(() => {
|
||||
onValidationSucceeded();
|
||||
return true;
|
||||
}).catch((err) => {
|
||||
onValidationFailed(err);
|
||||
return Promise.reject(err);
|
||||
});
|
||||
};
|
||||
const validate = async (trigger, callback) => {
|
||||
if (isResettingField || !props.prop) return false;
|
||||
const hasCallback = isFunction(callback);
|
||||
if (!validateEnabled.value) {
|
||||
callback?.(false);
|
||||
return false;
|
||||
}
|
||||
const rules = getFilteredRule(trigger);
|
||||
if (rules.length === 0) {
|
||||
callback?.(true);
|
||||
return true;
|
||||
}
|
||||
setValidationState("validating");
|
||||
return doValidate(rules).then(() => {
|
||||
callback?.(true);
|
||||
return true;
|
||||
}).catch((err) => {
|
||||
const { fields } = err;
|
||||
callback?.(false, fields);
|
||||
return hasCallback ? false : Promise.reject(fields);
|
||||
});
|
||||
};
|
||||
const clearValidate = () => {
|
||||
setValidationState("");
|
||||
validateMessage.value = "";
|
||||
isResettingField = false;
|
||||
};
|
||||
const resetField = async () => {
|
||||
const model = formContext?.model;
|
||||
if (!model || !props.prop) return;
|
||||
const computedValue = getProp(model, props.prop);
|
||||
isResettingField = true;
|
||||
computedValue.value = cloneDeep(initialValue);
|
||||
await nextTick();
|
||||
clearValidate();
|
||||
isResettingField = false;
|
||||
};
|
||||
const addInputId = (id) => {
|
||||
if (!inputIds.value.includes(id)) inputIds.value.push(id);
|
||||
};
|
||||
const removeInputId = (id) => {
|
||||
inputIds.value = inputIds.value.filter((listId) => listId !== id);
|
||||
};
|
||||
const setInitialValue = (value) => {
|
||||
initialValue = cloneDeep(value);
|
||||
};
|
||||
const getInitialValue = () => initialValue;
|
||||
watch(() => props.error, (val) => {
|
||||
validateMessage.value = val || "";
|
||||
setValidationState(val ? "error" : "");
|
||||
}, { immediate: true });
|
||||
watch(() => props.validateStatus, (val) => setValidationState(val || ""));
|
||||
const context = reactive({
|
||||
...toRefs(props),
|
||||
$el: formItemRef,
|
||||
size: _size,
|
||||
validateMessage,
|
||||
validateState,
|
||||
labelId,
|
||||
inputIds,
|
||||
isGroup,
|
||||
hasLabel,
|
||||
fieldValue,
|
||||
addInputId,
|
||||
removeInputId,
|
||||
resetField,
|
||||
clearValidate,
|
||||
validate,
|
||||
propString,
|
||||
setInitialValue,
|
||||
getInitialValue
|
||||
});
|
||||
provide(formItemContextKey, context);
|
||||
watch(propString, (newPropString, oldPropString) => {
|
||||
if (!formContext || !oldPropString) return;
|
||||
formContext.removeField(context, oldPropString);
|
||||
if (newPropString) {
|
||||
setInitialValue(fieldValue.value);
|
||||
formContext.addField(context);
|
||||
}
|
||||
});
|
||||
onMounted(() => {
|
||||
if (props.prop) {
|
||||
setInitialValue(fieldValue.value);
|
||||
formContext?.addField(context);
|
||||
}
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
formContext?.removeField(context);
|
||||
});
|
||||
__expose({
|
||||
/**
|
||||
* @description Form item size.
|
||||
*/
|
||||
size: _size,
|
||||
/**
|
||||
* @description Validation message.
|
||||
*/
|
||||
validateMessage,
|
||||
/**
|
||||
* @description Validation state.
|
||||
*/
|
||||
validateState,
|
||||
/**
|
||||
* @description Validate form item.
|
||||
*/
|
||||
validate,
|
||||
/**
|
||||
* @description Remove validation status of the field.
|
||||
*/
|
||||
clearValidate,
|
||||
/**
|
||||
* @description Reset current field and remove validation result.
|
||||
*/
|
||||
resetField,
|
||||
/**
|
||||
* @description Set initial value for this field. When `resetField` is called, the field will reset to this value.
|
||||
*/
|
||||
setInitialValue
|
||||
});
|
||||
return (_ctx, _cache) => {
|
||||
return openBlock(), createElementBlock("div", {
|
||||
ref_key: "formItemRef",
|
||||
ref: formItemRef,
|
||||
class: normalizeClass(formItemClasses.value),
|
||||
role: isGroup.value ? "group" : void 0,
|
||||
"aria-labelledby": isGroup.value ? unref(labelId) : void 0
|
||||
}, [createVNode(unref(form_label_wrap_default), {
|
||||
"is-auto-width": labelStyle.value.width === "auto",
|
||||
"update-all": unref(formContext)?.labelWidth === "auto"
|
||||
}, {
|
||||
default: withCtx(() => [!!(__props.label || _ctx.$slots.label) ? (openBlock(), createBlock(resolveDynamicComponent(labelFor.value ? "label" : "div"), {
|
||||
key: 0,
|
||||
id: unref(labelId),
|
||||
for: labelFor.value,
|
||||
class: normalizeClass(unref(ns).e("label")),
|
||||
style: normalizeStyle(labelStyle.value)
|
||||
}, {
|
||||
default: withCtx(() => [renderSlot(_ctx.$slots, "label", { label: currentLabel.value }, () => [createTextVNode(toDisplayString(currentLabel.value), 1)])]),
|
||||
_: 3
|
||||
}, 8, [
|
||||
"id",
|
||||
"for",
|
||||
"class",
|
||||
"style"
|
||||
])) : createCommentVNode("v-if", true)]),
|
||||
_: 3
|
||||
}, 8, ["is-auto-width", "update-all"]), createElementVNode("div", {
|
||||
class: normalizeClass(unref(ns).e("content")),
|
||||
style: normalizeStyle(contentStyle.value)
|
||||
}, [renderSlot(_ctx.$slots, "default"), createVNode(TransitionGroup, { name: `${unref(ns).namespace.value}-zoom-in-top` }, {
|
||||
default: withCtx(() => [shouldShowError.value ? renderSlot(_ctx.$slots, "error", {
|
||||
key: 0,
|
||||
error: validateMessage.value
|
||||
}, () => [createElementVNode("div", { class: normalizeClass(validateClasses.value) }, toDisplayString(validateMessage.value), 3)]) : createCommentVNode("v-if", true)]),
|
||||
_: 3
|
||||
}, 8, ["name"])], 6)], 10, _hoisted_1);
|
||||
};
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
export { form_item_vue_vue_type_script_setup_true_lang_default as default };
|
||||
|
||||
//# sourceMappingURL=form-item.vue_vue_type_script_setup_true_lang.mjs.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+7
@@ -0,0 +1,7 @@
|
||||
import form_item_vue_vue_type_script_setup_true_lang_default from "./form-item.vue_vue_type_script_setup_true_lang.mjs";
|
||||
//#region ../../packages/components/form/src/form-item.vue
|
||||
var form_item_default = form_item_vue_vue_type_script_setup_true_lang_default;
|
||||
//#endregion
|
||||
export { form_item_default as default };
|
||||
|
||||
//# sourceMappingURL=form-item2.mjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+16
@@ -0,0 +1,16 @@
|
||||
import * as _$vue from "vue";
|
||||
import * as _$vue_jsx_runtime0 from "vue/jsx-runtime";
|
||||
|
||||
//#region ../../packages/components/form/src/form-label-wrap.d.ts
|
||||
declare const _default: _$vue.DefineComponent<_$vue.ExtractPropTypes<{
|
||||
isAutoWidth: BooleanConstructor;
|
||||
updateAll: BooleanConstructor;
|
||||
}>, () => _$vue_jsx_runtime0.JSX.Element | null, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {}, string, _$vue.PublicProps, Readonly<_$vue.ExtractPropTypes<{
|
||||
isAutoWidth: BooleanConstructor;
|
||||
updateAll: BooleanConstructor;
|
||||
}>> & Readonly<{}>, {
|
||||
isAutoWidth: boolean;
|
||||
updateAll: boolean;
|
||||
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, true, {}, any>;
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
import { throwError } from "../../../utils/error.mjs";
|
||||
import { useNamespace } from "../../../hooks/use-namespace/index.mjs";
|
||||
import { formContextKey, formItemContextKey } from "./constants.mjs";
|
||||
import { useResizeObserver } from "@vueuse/core";
|
||||
import { Fragment, computed, createVNode, defineComponent, inject, nextTick, onBeforeUnmount, onMounted, onUpdated, ref, watch } from "vue";
|
||||
//#region ../../packages/components/form/src/form-label-wrap.tsx
|
||||
const COMPONENT_NAME = "ElLabelWrap";
|
||||
var form_label_wrap_default = /* @__PURE__ */ defineComponent({
|
||||
name: COMPONENT_NAME,
|
||||
props: {
|
||||
isAutoWidth: Boolean,
|
||||
updateAll: Boolean
|
||||
},
|
||||
setup(props, { slots }) {
|
||||
const formContext = inject(formContextKey, void 0);
|
||||
const formItemContext = inject(formItemContextKey);
|
||||
if (!formItemContext) throwError(COMPONENT_NAME, "usage: <el-form-item><label-wrap /></el-form-item>");
|
||||
const ns = useNamespace("form");
|
||||
const el = ref();
|
||||
const computedWidth = ref(0);
|
||||
const getLabelWidth = () => {
|
||||
if (el.value?.firstElementChild) {
|
||||
const width = window.getComputedStyle(el.value.firstElementChild).width;
|
||||
return Math.ceil(Number.parseFloat(width));
|
||||
} else return 0;
|
||||
};
|
||||
const updateLabelWidth = (action = "update") => {
|
||||
nextTick(() => {
|
||||
if (slots.default && props.isAutoWidth) {
|
||||
if (action === "update") computedWidth.value = getLabelWidth();
|
||||
else if (action === "remove") formContext?.deregisterLabelWidth(computedWidth.value);
|
||||
}
|
||||
});
|
||||
};
|
||||
const updateLabelWidthFn = () => updateLabelWidth("update");
|
||||
onMounted(() => {
|
||||
updateLabelWidthFn();
|
||||
});
|
||||
onBeforeUnmount(() => {
|
||||
updateLabelWidth("remove");
|
||||
});
|
||||
onUpdated(() => updateLabelWidthFn());
|
||||
watch(computedWidth, (val, oldVal) => {
|
||||
if (props.updateAll) formContext?.registerLabelWidth(val, oldVal);
|
||||
});
|
||||
useResizeObserver(computed(() => el.value?.firstElementChild ?? null), updateLabelWidthFn);
|
||||
return () => {
|
||||
if (!slots) return null;
|
||||
const { isAutoWidth } = props;
|
||||
if (isAutoWidth) {
|
||||
const autoLabelWidth = formContext?.autoLabelWidth;
|
||||
const hasLabel = formItemContext?.hasLabel;
|
||||
const style = {};
|
||||
if (hasLabel && autoLabelWidth && autoLabelWidth !== "auto") {
|
||||
const marginWidth = Math.max(0, Number.parseInt(autoLabelWidth, 10) - computedWidth.value);
|
||||
const marginPosition = (formItemContext.labelPosition || formContext.labelPosition) === "left" ? "marginRight" : "marginLeft";
|
||||
if (marginWidth) style[marginPosition] = `${marginWidth}px`;
|
||||
}
|
||||
return createVNode("div", {
|
||||
"ref": el,
|
||||
"class": [ns.be("item", "label-wrap")],
|
||||
"style": style
|
||||
}, [slots.default?.()]);
|
||||
} else return createVNode(Fragment, { "ref": el }, [slots.default?.()]);
|
||||
};
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
export { form_label_wrap_default as default };
|
||||
|
||||
//# sourceMappingURL=form-label-wrap.mjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+134
@@ -0,0 +1,134 @@
|
||||
import { EpPropFinalized, EpPropMergeType } from "../../../utils/vue/props/types.js";
|
||||
import { ComponentSize } from "../../../constants/size.js";
|
||||
import { Arrayable } from "../../../utils/typescript.js";
|
||||
import { FormItemRule, FormRules } from "./types.js";
|
||||
import { FormItemProp } from "./form-item.js";
|
||||
import * as _$vue from "vue";
|
||||
import { ExtractPublicPropTypes } from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/form.d.ts
|
||||
interface FormMetaProps {
|
||||
/**
|
||||
* @description Control the size of components in this form.
|
||||
*/
|
||||
size?: ComponentSize;
|
||||
/**
|
||||
* @description Whether to disable all components in this form. If set to `true`, it will override the `disabled` prop of the inner component.
|
||||
*/
|
||||
disabled?: boolean;
|
||||
}
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormMetaProps` instead.
|
||||
*/
|
||||
declare const formMetaProps: {
|
||||
readonly size: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<StringConstructor, "" | "default" | "small" | "large", unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly disabled: BooleanConstructor;
|
||||
};
|
||||
interface FormProps extends FormMetaProps {
|
||||
/**
|
||||
* @description Data of form component.
|
||||
*/
|
||||
model?: Record<string, any>;
|
||||
/**
|
||||
* @description Validation rules of form.
|
||||
*/
|
||||
rules?: FormRules;
|
||||
/**
|
||||
* @description Position of label. If set to `'left'` or `'right'`, `label-width` prop is also required.
|
||||
*/
|
||||
labelPosition?: 'left' | 'right' | 'top';
|
||||
/**
|
||||
* @description Position of asterisk.
|
||||
*/
|
||||
requireAsteriskPosition?: 'left' | 'right';
|
||||
/**
|
||||
* @description Width of label, e.g. `'50px'`. All its direct child form items will inherit this value. `auto` is supported.
|
||||
*/
|
||||
labelWidth?: string | number;
|
||||
/**
|
||||
* @description Suffix of the label.
|
||||
*/
|
||||
labelSuffix?: string;
|
||||
/**
|
||||
* @description Whether the form is inline.
|
||||
*/
|
||||
inline?: boolean;
|
||||
/**
|
||||
* @description Whether to display the error message inline with the form item.
|
||||
*/
|
||||
inlineMessage?: boolean;
|
||||
/**
|
||||
* @description Whether to display an icon indicating the validation result.
|
||||
*/
|
||||
statusIcon?: boolean;
|
||||
/**
|
||||
* @description Whether to show the error message.
|
||||
*/
|
||||
showMessage?: boolean;
|
||||
/**
|
||||
* @description Whether to trigger validation when the `rules` prop is changed.
|
||||
*/
|
||||
validateOnRuleChange?: boolean;
|
||||
/**
|
||||
* @description Whether to hide required fields should have a red asterisk (star) beside their labels.
|
||||
*/
|
||||
hideRequiredAsterisk?: boolean;
|
||||
/**
|
||||
* @description When validation fails, scroll to the first error form entry.
|
||||
*/
|
||||
scrollToError?: boolean;
|
||||
/**
|
||||
* @description When validation fails, it scrolls to the first error item based on the scrollIntoView option.
|
||||
*/
|
||||
scrollIntoViewOptions?: ScrollIntoViewOptions | boolean;
|
||||
}
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormProps` instead.
|
||||
*/
|
||||
declare const formProps: {
|
||||
readonly model: ObjectConstructor;
|
||||
readonly rules: {
|
||||
readonly type: _$vue.PropType<Partial<Record<string, Record<string, any> | Arrayable<FormItemRule>>>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly labelPosition: EpPropFinalized<StringConstructor, "top" | "right" | "left", unknown, "right", boolean>;
|
||||
readonly requireAsteriskPosition: EpPropFinalized<StringConstructor, "right" | "left", unknown, "left", boolean>;
|
||||
readonly labelWidth: EpPropFinalized<readonly [StringConstructor, NumberConstructor], unknown, unknown, "", boolean>;
|
||||
readonly labelSuffix: EpPropFinalized<StringConstructor, unknown, unknown, "", boolean>;
|
||||
readonly inline: BooleanConstructor;
|
||||
readonly inlineMessage: BooleanConstructor;
|
||||
readonly statusIcon: BooleanConstructor;
|
||||
readonly showMessage: EpPropFinalized<BooleanConstructor, unknown, unknown, true, boolean>;
|
||||
readonly validateOnRuleChange: EpPropFinalized<BooleanConstructor, unknown, unknown, true, boolean>;
|
||||
readonly hideRequiredAsterisk: BooleanConstructor;
|
||||
readonly scrollToError: BooleanConstructor;
|
||||
readonly scrollIntoViewOptions: EpPropFinalized<(new (...args: any[]) => boolean | ScrollIntoViewOptions) | (() => boolean | ScrollIntoViewOptions) | (((new (...args: any[]) => boolean | ScrollIntoViewOptions) | (() => boolean | ScrollIntoViewOptions)) | null)[], unknown, unknown, true, boolean>;
|
||||
readonly size: {
|
||||
readonly type: _$vue.PropType<EpPropMergeType<StringConstructor, "" | "default" | "small" | "large", unknown>>;
|
||||
readonly required: false;
|
||||
readonly validator: ((val: unknown) => boolean) | undefined;
|
||||
__epPropKey: true;
|
||||
};
|
||||
readonly disabled: BooleanConstructor;
|
||||
};
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormProps` instead.
|
||||
*/
|
||||
type FormPropsPublic = ExtractPublicPropTypes<typeof formProps>;
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormMetaProps` instead.
|
||||
*/
|
||||
type FormMetaPropsPublic = ExtractPublicPropTypes<typeof formMetaProps>;
|
||||
declare const formEmits: {
|
||||
validate: (prop: FormItemProp, isValid: boolean, message: string) => boolean;
|
||||
};
|
||||
type FormEmits = typeof formEmits;
|
||||
//#endregion
|
||||
export { FormEmits, FormMetaProps, FormMetaPropsPublic, FormProps, FormPropsPublic, formEmits, formMetaProps, formProps };
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
import { componentSizes } from "../../../constants/size.mjs";
|
||||
import { isArray, isBoolean, isString } from "../../../utils/types.mjs";
|
||||
import { buildProps, definePropType } from "../../../utils/vue/props/runtime.mjs";
|
||||
//#region ../../packages/components/form/src/form.ts
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormMetaProps` instead.
|
||||
*/
|
||||
const formMetaProps = buildProps({
|
||||
/**
|
||||
* @description Control the size of components in this form.
|
||||
*/
|
||||
size: {
|
||||
type: String,
|
||||
values: componentSizes
|
||||
},
|
||||
/**
|
||||
* @description Whether to disable all components in this form. If set to `true`, it will override the `disabled` prop of the inner component.
|
||||
*/
|
||||
disabled: Boolean
|
||||
});
|
||||
/**
|
||||
* @deprecated Removed after 3.0.0, Use `FormProps` instead.
|
||||
*/
|
||||
const formProps = buildProps({
|
||||
...formMetaProps,
|
||||
/**
|
||||
* @description Data of form component.
|
||||
*/
|
||||
model: Object,
|
||||
/**
|
||||
* @description Validation rules of form.
|
||||
*/
|
||||
rules: { type: definePropType(Object) },
|
||||
/**
|
||||
* @description Position of label. If set to `'left'` or `'right'`, `label-width` prop is also required.
|
||||
*/
|
||||
labelPosition: {
|
||||
type: String,
|
||||
values: [
|
||||
"left",
|
||||
"right",
|
||||
"top"
|
||||
],
|
||||
default: "right"
|
||||
},
|
||||
/**
|
||||
* @description Position of asterisk.
|
||||
*/
|
||||
requireAsteriskPosition: {
|
||||
type: String,
|
||||
values: ["left", "right"],
|
||||
default: "left"
|
||||
},
|
||||
/**
|
||||
* @description Width of label, e.g. `'50px'`. All its direct child form items will inherit this value. `auto` is supported.
|
||||
*/
|
||||
labelWidth: {
|
||||
type: [String, Number],
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* @description Suffix of the label.
|
||||
*/
|
||||
labelSuffix: {
|
||||
type: String,
|
||||
default: ""
|
||||
},
|
||||
/**
|
||||
* @description Whether the form is inline.
|
||||
*/
|
||||
inline: Boolean,
|
||||
/**
|
||||
* @description Whether to display the error message inline with the form item.
|
||||
*/
|
||||
inlineMessage: Boolean,
|
||||
/**
|
||||
* @description Whether to display an icon indicating the validation result.
|
||||
*/
|
||||
statusIcon: Boolean,
|
||||
/**
|
||||
* @description Whether to show the error message.
|
||||
*/
|
||||
showMessage: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* @description Whether to trigger validation when the `rules` prop is changed.
|
||||
*/
|
||||
validateOnRuleChange: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
/**
|
||||
* @description Whether to hide required fields should have a red asterisk (star) beside their labels.
|
||||
*/
|
||||
hideRequiredAsterisk: Boolean,
|
||||
/**
|
||||
* @description When validation fails, scroll to the first error form entry.
|
||||
*/
|
||||
scrollToError: Boolean,
|
||||
/**
|
||||
* @description When validation fails, it scrolls to the first error item based on the scrollIntoView option.
|
||||
*/
|
||||
scrollIntoViewOptions: {
|
||||
type: definePropType([Object, Boolean]),
|
||||
default: true
|
||||
}
|
||||
});
|
||||
const formEmits = { validate: (prop, isValid, message) => (isArray(prop) || isString(prop)) && isBoolean(isValid) && isString(message) };
|
||||
//#endregion
|
||||
export { formEmits, formMetaProps, formProps };
|
||||
|
||||
//# sourceMappingURL=form.mjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+66
@@ -0,0 +1,66 @@
|
||||
import { Arrayable } from "../../../utils/typescript.js";
|
||||
import { FormItemContext, FormValidateCallback, FormValidationResult } from "./types.js";
|
||||
import { FormItemProp } from "./form-item.js";
|
||||
import { FormProps } from "./form.js";
|
||||
import * as _$vue from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/form.vue.d.ts
|
||||
declare var __VLS_1: {};
|
||||
type __VLS_Slots = {} & {
|
||||
default?: (props: typeof __VLS_1) => any;
|
||||
};
|
||||
declare const __VLS_base: _$vue.DefineComponent<FormProps, {
|
||||
/**
|
||||
* @description Validate the whole form. Receives a callback or returns `Promise`.
|
||||
*/
|
||||
validate: (callback?: FormValidateCallback) => FormValidationResult;
|
||||
/**
|
||||
* @description Validate specified fields.
|
||||
*/
|
||||
validateField: (props?: Arrayable<FormItemProp>, callback?: FormValidateCallback) => FormValidationResult;
|
||||
/**
|
||||
* @description Reset specified fields and remove validation result.
|
||||
*/
|
||||
resetFields: (props?: Arrayable<FormItemProp>) => void;
|
||||
/**
|
||||
* @description Clear validation message for specified fields.
|
||||
*/
|
||||
clearValidate: (props?: Arrayable<FormItemProp>) => void;
|
||||
/**
|
||||
* @description Scroll to the specified fields.
|
||||
*/
|
||||
scrollToField: (prop: FormItemProp) => void;
|
||||
/**
|
||||
* @description Get a field context.
|
||||
*/
|
||||
getField: (prop: FormItemProp) => FormItemContext | undefined;
|
||||
/**
|
||||
* @description All fields context.
|
||||
*/
|
||||
fields: _$vue.Reactive<FormItemContext[]>;
|
||||
/**
|
||||
* @description Set initial values for form fields. When `resetFields` is called, fields will reset to these values.
|
||||
*/
|
||||
setInitialValues: (initModel: Record<string, any>) => void;
|
||||
}, {}, {}, {}, _$vue.ComponentOptionsMixin, _$vue.ComponentOptionsMixin, {
|
||||
validate: (prop: FormItemProp, isValid: boolean, message: string) => void;
|
||||
}, string, _$vue.PublicProps, Readonly<FormProps> & Readonly<{
|
||||
onValidate?: ((prop: FormItemProp, isValid: boolean, message: string) => any) | undefined;
|
||||
}>, {
|
||||
scrollIntoViewOptions: ScrollIntoViewOptions | boolean;
|
||||
labelWidth: string | number;
|
||||
labelPosition: "left" | "right" | "top";
|
||||
requireAsteriskPosition: "left" | "right";
|
||||
labelSuffix: string;
|
||||
showMessage: boolean;
|
||||
validateOnRuleChange: boolean;
|
||||
}, {}, {}, {}, string, _$vue.ComponentProvideOptions, false, {}, any>;
|
||||
declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
|
||||
declare const _default: typeof __VLS_export;
|
||||
type __VLS_WithSlots<T, S> = T & {
|
||||
new (): {
|
||||
$slots: S;
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
export { _default as default };
|
||||
Generated
Vendored
+202
@@ -0,0 +1,202 @@
|
||||
import { isArray, isFunction } from "../../../utils/types.mjs";
|
||||
import { getProp } from "../../../utils/objects.mjs";
|
||||
import { debugWarn } from "../../../utils/error.mjs";
|
||||
import { NOOP } from "../../../utils/functions.mjs";
|
||||
import { ensureArray } from "../../../utils/arrays.mjs";
|
||||
import { useNamespace } from "../../../hooks/use-namespace/index.mjs";
|
||||
import { formEmits, formProps } from "./form.mjs";
|
||||
import { formContextKey } from "./constants.mjs";
|
||||
import { useFormSize } from "./hooks/use-form-common-props.mjs";
|
||||
import { filterFields, useFormLabelWidth } from "./utils.mjs";
|
||||
import { cloneDeep } from "lodash-unified";
|
||||
import { computed, createElementBlock, defineComponent, normalizeClass, openBlock, provide, reactive, ref, renderSlot, toRefs, watch } from "vue";
|
||||
//#region ../../packages/components/form/src/form.vue?vue&type=script&setup=true&lang.ts
|
||||
const COMPONENT_NAME = "ElForm";
|
||||
var form_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
|
||||
name: COMPONENT_NAME,
|
||||
__name: "form",
|
||||
props: formProps,
|
||||
emits: formEmits,
|
||||
setup(__props, { expose: __expose, emit: __emit }) {
|
||||
const props = __props;
|
||||
const emit = __emit;
|
||||
const formRef = ref();
|
||||
const fields = reactive([]);
|
||||
const initialValues = /* @__PURE__ */ new Map();
|
||||
const formSize = useFormSize();
|
||||
const ns = useNamespace("form");
|
||||
const formClasses = 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 filterFields(fields, [prop])[0];
|
||||
};
|
||||
const addField = (field) => {
|
||||
if (!fields.includes(field)) fields.push(field);
|
||||
if (field.propString) if (initialValues.has(field.propString)) field.setInitialValue(initialValues.get(field.propString));
|
||||
else initialValues.set(field.propString, cloneDeep(field.fieldValue));
|
||||
};
|
||||
const removeField = (field, oldPropString) => {
|
||||
if (oldPropString) {
|
||||
initialValues.delete(oldPropString);
|
||||
return;
|
||||
}
|
||||
const idx = fields.indexOf(field);
|
||||
if (idx > -1) {
|
||||
fields.splice(idx, 1);
|
||||
if (field.propString) initialValues.set(field.propString, cloneDeep(field.getInitialValue()));
|
||||
}
|
||||
};
|
||||
const setInitialValues = (initModel) => {
|
||||
if (!props.model) {
|
||||
debugWarn(COMPONENT_NAME, "model is required for setInitialValues to work.");
|
||||
return;
|
||||
}
|
||||
if (!initModel) {
|
||||
debugWarn(COMPONENT_NAME, "initModel is required for setInitialValues to work.");
|
||||
return;
|
||||
}
|
||||
for (const key of initialValues.keys()) initialValues.set(key, cloneDeep(getProp(initModel, key).value));
|
||||
fields.forEach((field) => {
|
||||
if (field.prop) field.setInitialValue(getProp(initModel, field.prop).value);
|
||||
});
|
||||
};
|
||||
const resetFields = (properties = []) => {
|
||||
if (!props.model) {
|
||||
debugWarn(COMPONENT_NAME, "model is required for resetFields to work.");
|
||||
return;
|
||||
}
|
||||
filterFields(fields, properties).forEach((field) => field.resetField());
|
||||
const activePropStrings = new Set(fields.map((f) => f.propString).filter(Boolean));
|
||||
const propsToCheck = properties.length > 0 ? ensureArray(properties).map((p) => isArray(p) ? p.join(".") : p) : [...initialValues.keys()];
|
||||
for (const propString of propsToCheck) if (!activePropStrings.has(propString) && initialValues.has(propString)) getProp(props.model, propString).value = cloneDeep(initialValues.get(propString));
|
||||
};
|
||||
const clearValidate = (props = []) => {
|
||||
filterFields(fields, props).forEach((field) => field.clearValidate());
|
||||
};
|
||||
const isValidatable = computed(() => {
|
||||
const hasModel = !!props.model;
|
||||
if (!hasModel) debugWarn(COMPONENT_NAME, "model is required for validate to work.");
|
||||
return hasModel;
|
||||
});
|
||||
const obtainValidateFields = (props) => {
|
||||
if (fields.length === 0) return [];
|
||||
const filteredFields = filterFields(fields, props);
|
||||
if (!filteredFields.length) {
|
||||
debugWarn(COMPONENT_NAME, "please pass correct props!");
|
||||
return [];
|
||||
}
|
||||
return filteredFields;
|
||||
};
|
||||
const validate = async (callback) => validateField(void 0, callback);
|
||||
const doValidateField = async (props = []) => {
|
||||
if (!isValidatable.value) return false;
|
||||
const fields = obtainValidateFields(props);
|
||||
if (fields.length === 0) return true;
|
||||
let validationErrors = {};
|
||||
for (const field of fields) try {
|
||||
await field.validate("");
|
||||
if (field.validateState === "error" && !field.error) field.resetField();
|
||||
} catch (fields) {
|
||||
validationErrors = {
|
||||
...validationErrors,
|
||||
...fields
|
||||
};
|
||||
}
|
||||
if (Object.keys(validationErrors).length === 0) return true;
|
||||
return Promise.reject(validationErrors);
|
||||
};
|
||||
const validateField = async (modelProps = [], callback) => {
|
||||
let result = false;
|
||||
const shouldThrow = !isFunction(callback);
|
||||
try {
|
||||
result = await doValidateField(modelProps);
|
||||
if (result === true) await callback?.(result);
|
||||
return result;
|
||||
} catch (e) {
|
||||
if (e instanceof Error) throw e;
|
||||
const invalidFields = e;
|
||||
if (props.scrollToError) {
|
||||
if (formRef.value) formRef.value.querySelector(`.${ns.b()}-item.is-error`)?.scrollIntoView(props.scrollIntoViewOptions);
|
||||
}
|
||||
!result && await callback?.(false, invalidFields);
|
||||
return shouldThrow && Promise.reject(invalidFields);
|
||||
}
|
||||
};
|
||||
const scrollToField = (prop) => {
|
||||
const field = getField(prop);
|
||||
if (field) field.$el?.scrollIntoView(props.scrollIntoViewOptions);
|
||||
};
|
||||
watch(() => props.rules, () => {
|
||||
if (props.validateOnRuleChange) validate().catch(NOOP);
|
||||
}, {
|
||||
deep: true,
|
||||
flush: "post"
|
||||
});
|
||||
provide(formContextKey, reactive({
|
||||
...toRefs(props),
|
||||
emit,
|
||||
resetFields,
|
||||
clearValidate,
|
||||
validateField,
|
||||
getField,
|
||||
addField,
|
||||
removeField,
|
||||
setInitialValues,
|
||||
...useFormLabelWidth()
|
||||
}));
|
||||
__expose({
|
||||
/**
|
||||
* @description Validate the whole form. Receives a callback or returns `Promise`.
|
||||
*/
|
||||
validate,
|
||||
/**
|
||||
* @description Validate specified fields.
|
||||
*/
|
||||
validateField,
|
||||
/**
|
||||
* @description Reset specified fields and remove validation result.
|
||||
*/
|
||||
resetFields,
|
||||
/**
|
||||
* @description Clear validation message for specified fields.
|
||||
*/
|
||||
clearValidate,
|
||||
/**
|
||||
* @description Scroll to the specified fields.
|
||||
*/
|
||||
scrollToField,
|
||||
/**
|
||||
* @description Get a field context.
|
||||
*/
|
||||
getField,
|
||||
/**
|
||||
* @description All fields context.
|
||||
*/
|
||||
fields,
|
||||
/**
|
||||
* @description Set initial values for form fields. When `resetFields` is called, fields will reset to these values.
|
||||
*/
|
||||
setInitialValues
|
||||
});
|
||||
return (_ctx, _cache) => {
|
||||
return openBlock(), createElementBlock("form", {
|
||||
ref_key: "formRef",
|
||||
ref: formRef,
|
||||
class: normalizeClass(formClasses.value)
|
||||
}, [renderSlot(_ctx.$slots, "default")], 2);
|
||||
};
|
||||
}
|
||||
});
|
||||
//#endregion
|
||||
export { form_vue_vue_type_script_setup_true_lang_default as default };
|
||||
|
||||
//# sourceMappingURL=form.vue_vue_type_script_setup_true_lang.mjs.map
|
||||
Generated
Vendored
+1
File diff suppressed because one or more lines are too long
+7
@@ -0,0 +1,7 @@
|
||||
import form_vue_vue_type_script_setup_true_lang_default from "./form.vue_vue_type_script_setup_true_lang.mjs";
|
||||
//#region ../../packages/components/form/src/form.vue
|
||||
var form_default = form_vue_vue_type_script_setup_true_lang_default;
|
||||
//#endregion
|
||||
export { form_default as default };
|
||||
|
||||
//# sourceMappingURL=form2.mjs.map
|
||||
+1
File diff suppressed because one or more lines are too long
+3
@@ -0,0 +1,3 @@
|
||||
import { useDisabled, useFormDisabled, useFormSize, useSize } from "./use-form-common-props.js";
|
||||
import { IUseFormItemInputCommonProps, useFormItem, useFormItemInputId } from "./use-form-item.js";
|
||||
export { IUseFormItemInputCommonProps, useDisabled, useFormDisabled, useFormItem, useFormItemInputId, useFormSize, useSize };
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
import { useDisabled, useFormDisabled, useFormSize, useSize } from "./use-form-common-props.mjs";
|
||||
import { useFormItem, useFormItemInputId } from "./use-form-item.mjs";
|
||||
export { useDisabled, useFormDisabled, useFormItem, useFormItemInputId, useFormSize, useSize };
|
||||
Generated
Vendored
+11
@@ -0,0 +1,11 @@
|
||||
import { ComponentSize } from "../../../../constants/size.js";
|
||||
import * as _$vue from "vue";
|
||||
import { MaybeRef } from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/hooks/use-form-common-props.d.ts
|
||||
declare const useFormSize: (fallback?: MaybeRef<ComponentSize | undefined>, ignore?: Partial<Record<"prop" | "form" | "formItem" | "global", boolean>>) => _$vue.ComputedRef<"" | "default" | "small" | "large">;
|
||||
declare const useFormDisabled: (fallback?: MaybeRef<boolean | undefined>) => _$vue.ComputedRef<boolean>;
|
||||
declare const useSize: (fallback?: MaybeRef<ComponentSize | undefined>, ignore?: Partial<Record<"prop" | "form" | "formItem" | "global", boolean>>) => _$vue.ComputedRef<"" | "default" | "small" | "large">;
|
||||
declare const useDisabled: (fallback?: MaybeRef<boolean | undefined>) => _$vue.ComputedRef<boolean>;
|
||||
//#endregion
|
||||
export { useDisabled, useFormDisabled, useFormSize, useSize };
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
import { useProp } from "../../../../hooks/use-prop/index.mjs";
|
||||
import { useGlobalSize } from "../../../../hooks/use-size/index.mjs";
|
||||
import { formContextKey, formItemContextKey } from "../constants.mjs";
|
||||
import { computed, inject, ref, unref } from "vue";
|
||||
//#region ../../packages/components/form/src/hooks/use-form-common-props.ts
|
||||
const useFormSize = (fallback, ignore = {}) => {
|
||||
const emptyRef = ref(void 0);
|
||||
const size = ignore.prop ? emptyRef : useProp("size");
|
||||
const globalConfig = ignore.global ? emptyRef : useGlobalSize();
|
||||
const form = ignore.form ? { size: void 0 } : inject(formContextKey, void 0);
|
||||
const formItem = ignore.formItem ? { size: void 0 } : inject(formItemContextKey, void 0);
|
||||
return computed(() => size.value || unref(fallback) || formItem?.size || form?.size || globalConfig.value || "");
|
||||
};
|
||||
const useFormDisabled = (fallback) => {
|
||||
const disabled = useProp("disabled");
|
||||
const form = inject(formContextKey, void 0);
|
||||
return computed(() => {
|
||||
return disabled.value ?? unref(fallback) ?? form?.disabled ?? false;
|
||||
});
|
||||
};
|
||||
const useSize = useFormSize;
|
||||
const useDisabled = useFormDisabled;
|
||||
//#endregion
|
||||
export { useDisabled, useFormDisabled, useFormSize, useSize };
|
||||
|
||||
//# sourceMappingURL=use-form-common-props.mjs.map
|
||||
Generated
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"use-form-common-props.mjs","names":[],"sources":["../../../../../../../packages/components/form/src/hooks/use-form-common-props.ts"],"sourcesContent":["import { computed, inject, ref, unref } from 'vue'\nimport { useGlobalSize } from '@element-plus/hooks/use-size'\nimport { useProp } from '@element-plus/hooks/use-prop'\nimport { formContextKey, formItemContextKey } from '../constants'\n\nimport type { ComponentSize } from '@element-plus/constants'\nimport type { MaybeRef } from 'vue'\n\nexport const useFormSize = (\n fallback?: MaybeRef<ComponentSize | undefined>,\n ignore: Partial<Record<'prop' | 'form' | 'formItem' | 'global', boolean>> = {}\n) => {\n const emptyRef = ref(undefined)\n\n const size = ignore.prop ? emptyRef : useProp<ComponentSize>('size')\n const globalConfig = ignore.global ? emptyRef : useGlobalSize()\n const form = ignore.form\n ? { size: undefined }\n : inject(formContextKey, undefined)\n const formItem = ignore.formItem\n ? { size: undefined }\n : inject(formItemContextKey, undefined)\n\n return computed(\n (): ComponentSize =>\n size.value ||\n unref(fallback) ||\n formItem?.size ||\n form?.size ||\n globalConfig.value ||\n ''\n )\n}\n\nexport const useFormDisabled = (fallback?: MaybeRef<boolean | undefined>) => {\n const disabled = useProp<boolean>('disabled')\n const form = inject(formContextKey, undefined)\n\n return computed(() => {\n return disabled.value ?? unref(fallback) ?? form?.disabled ?? false\n })\n}\n\n// These exports are used for preventing breaking changes\nexport const useSize = useFormSize\nexport const useDisabled = useFormDisabled\n"],"mappings":";;;;;AAQA,MAAa,eACX,UACA,SAA4E,EAAE,KAC3E;CACH,MAAM,WAAW,IAAI,KAAA,EAAU;CAE/B,MAAM,OAAO,OAAO,OAAO,WAAW,QAAuB,OAAO;CACpE,MAAM,eAAe,OAAO,SAAS,WAAW,eAAe;CAC/D,MAAM,OAAO,OAAO,OAChB,EAAE,MAAM,KAAA,GAAW,GACnB,OAAO,gBAAgB,KAAA,EAAU;CACrC,MAAM,WAAW,OAAO,WACpB,EAAE,MAAM,KAAA,GAAW,GACnB,OAAO,oBAAoB,KAAA,EAAU;CAEzC,OAAO,eAEH,KAAK,SACL,MAAM,SAAS,IACf,UAAU,QACV,MAAM,QACN,aAAa,SACb,GACH;;AAGH,MAAa,mBAAmB,aAA6C;CAC3E,MAAM,WAAW,QAAiB,WAAW;CAC7C,MAAM,OAAO,OAAO,gBAAgB,KAAA,EAAU;CAE9C,OAAO,eAAe;EACpB,OAAO,SAAS,SAAS,MAAM,SAAS,IAAI,MAAM,YAAY;GAC9D;;AAIJ,MAAa,UAAU;AACvB,MAAa,cAAc"}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
import { FormContext, FormItemContext } from "../types.js";
|
||||
import { ComputedRef, Ref } from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/hooks/use-form-item.d.ts
|
||||
declare const useFormItem: () => {
|
||||
form: FormContext | undefined;
|
||||
formItem: FormItemContext | undefined;
|
||||
};
|
||||
type IUseFormItemInputCommonProps = {
|
||||
id?: string;
|
||||
label?: string | number | boolean | Record<string, any>;
|
||||
ariaLabel?: string | number | boolean | Record<string, any>;
|
||||
};
|
||||
declare const useFormItemInputId: (props: Partial<IUseFormItemInputCommonProps>, {
|
||||
formItemContext,
|
||||
disableIdGeneration,
|
||||
disableIdManagement
|
||||
}: {
|
||||
formItemContext?: FormItemContext;
|
||||
disableIdGeneration?: ComputedRef<boolean> | Ref<boolean>;
|
||||
disableIdManagement?: ComputedRef<boolean> | Ref<boolean>;
|
||||
}) => {
|
||||
isLabeledByFormItem: ComputedRef<boolean>;
|
||||
inputId: Ref<string | undefined, string | undefined>;
|
||||
};
|
||||
//#endregion
|
||||
export { IUseFormItemInputCommonProps, useFormItem, useFormItemInputId };
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
import { useId } from "../../../../hooks/use-id/index.mjs";
|
||||
import { formContextKey, formItemContextKey } from "../constants.mjs";
|
||||
import { computed, getCurrentInstance, inject, onMounted, onUnmounted, ref, toRef, watch } from "vue";
|
||||
//#region ../../packages/components/form/src/hooks/use-form-item.ts
|
||||
const useFormItem = () => {
|
||||
return {
|
||||
form: inject(formContextKey, void 0),
|
||||
formItem: inject(formItemContextKey, void 0)
|
||||
};
|
||||
};
|
||||
const useFormItemInputId = (props, { formItemContext, disableIdGeneration, disableIdManagement }) => {
|
||||
if (!disableIdGeneration) disableIdGeneration = ref(false);
|
||||
if (!disableIdManagement) disableIdManagement = ref(false);
|
||||
const instance = getCurrentInstance();
|
||||
const inLabel = () => {
|
||||
let parent = instance?.parent;
|
||||
while (parent) {
|
||||
if (parent.type.name === "ElFormItem") return false;
|
||||
if (parent.type.name === "ElLabelWrap") return true;
|
||||
parent = parent.parent;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const inputId = ref();
|
||||
let idUnwatch = void 0;
|
||||
const isLabeledByFormItem = computed(() => {
|
||||
return !!(!(props.label || props.ariaLabel) && formItemContext && formItemContext.inputIds && formItemContext.inputIds?.length <= 1);
|
||||
});
|
||||
onMounted(() => {
|
||||
idUnwatch = watch([toRef(props, "id"), disableIdGeneration], ([id, disableIdGeneration]) => {
|
||||
const newId = id ?? (!disableIdGeneration ? useId().value : void 0);
|
||||
if (newId !== inputId.value) {
|
||||
if (formItemContext?.removeInputId && !inLabel()) {
|
||||
inputId.value && formItemContext.removeInputId(inputId.value);
|
||||
if (!disableIdManagement?.value && !disableIdGeneration && newId) formItemContext.addInputId(newId);
|
||||
}
|
||||
inputId.value = newId;
|
||||
}
|
||||
}, { immediate: true });
|
||||
});
|
||||
onUnmounted(() => {
|
||||
idUnwatch && idUnwatch();
|
||||
if (formItemContext?.removeInputId) inputId.value && formItemContext.removeInputId(inputId.value);
|
||||
});
|
||||
return {
|
||||
isLabeledByFormItem,
|
||||
inputId
|
||||
};
|
||||
};
|
||||
//#endregion
|
||||
export { useFormItem, useFormItemInputId };
|
||||
|
||||
//# sourceMappingURL=use-form-item.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"use-form-item.mjs","names":[],"sources":["../../../../../../../packages/components/form/src/hooks/use-form-item.ts"],"sourcesContent":["import {\n computed,\n getCurrentInstance,\n inject,\n onMounted,\n onUnmounted,\n ref,\n toRef,\n watch,\n} from 'vue'\nimport { useId } from '@element-plus/hooks/use-id'\nimport { formContextKey, formItemContextKey } from '../constants'\n\nimport type { ComputedRef, Ref, WatchStopHandle } from 'vue'\nimport type { FormItemContext } from '../types'\n\nexport const useFormItem = () => {\n const form = inject(formContextKey, undefined)\n const formItem = inject(formItemContextKey, undefined)\n return {\n form,\n formItem,\n }\n}\n\nexport type IUseFormItemInputCommonProps = {\n id?: string\n label?: string | number | boolean | Record<string, any>\n ariaLabel?: string | number | boolean | Record<string, any>\n}\n\nexport const useFormItemInputId = (\n props: Partial<IUseFormItemInputCommonProps>,\n {\n formItemContext,\n disableIdGeneration,\n disableIdManagement,\n }: {\n formItemContext?: FormItemContext\n disableIdGeneration?: ComputedRef<boolean> | Ref<boolean>\n disableIdManagement?: ComputedRef<boolean> | Ref<boolean>\n }\n) => {\n if (!disableIdGeneration) {\n disableIdGeneration = ref<boolean>(false)\n }\n if (!disableIdManagement) {\n disableIdManagement = ref<boolean>(false)\n }\n\n const instance = getCurrentInstance()\n\n const inLabel = () => {\n let parent = instance?.parent\n while (parent) {\n if (parent.type.name === 'ElFormItem') {\n return false\n }\n if (parent.type.name === 'ElLabelWrap') {\n return true\n }\n parent = parent.parent\n }\n return false\n }\n\n const inputId = ref<string>()\n let idUnwatch: WatchStopHandle | undefined = undefined\n\n const isLabeledByFormItem = computed<boolean>(() => {\n return !!(\n !(props.label || props.ariaLabel) &&\n formItemContext &&\n formItemContext.inputIds &&\n formItemContext.inputIds?.length <= 1\n )\n })\n\n // Generate id for ElFormItem label if not provided as prop\n onMounted(() => {\n idUnwatch = watch(\n [toRef(props, 'id'), disableIdGeneration] as any,\n ([id, disableIdGeneration]: [string, boolean]) => {\n const newId = id ?? (!disableIdGeneration ? useId().value : undefined)\n if (newId !== inputId.value) {\n if (formItemContext?.removeInputId && !inLabel()) {\n inputId.value && formItemContext.removeInputId(inputId.value)\n if (!disableIdManagement?.value && !disableIdGeneration && newId) {\n formItemContext.addInputId(newId)\n }\n }\n inputId.value = newId\n }\n },\n { immediate: true }\n )\n })\n\n onUnmounted(() => {\n idUnwatch && idUnwatch()\n if (formItemContext?.removeInputId) {\n inputId.value && formItemContext.removeInputId(inputId.value)\n }\n })\n\n return {\n isLabeledByFormItem,\n inputId,\n }\n}\n"],"mappings":";;;;AAgBA,MAAa,oBAAoB;CAG/B,OAAO;EACL,MAHW,OAAO,gBAAgB,KAAA,EAG9B;EACJ,UAHe,OAAO,oBAAoB,KAAA,EAGlC;EACT;;AASH,MAAa,sBACX,OACA,EACE,iBACA,qBACA,0BAMC;CACH,IAAI,CAAC,qBACH,sBAAsB,IAAa,MAAM;CAE3C,IAAI,CAAC,qBACH,sBAAsB,IAAa,MAAM;CAG3C,MAAM,WAAW,oBAAoB;CAErC,MAAM,gBAAgB;EACpB,IAAI,SAAS,UAAU;EACvB,OAAO,QAAQ;GACb,IAAI,OAAO,KAAK,SAAS,cACvB,OAAO;GAET,IAAI,OAAO,KAAK,SAAS,eACvB,OAAO;GAET,SAAS,OAAO;;EAElB,OAAO;;CAGT,MAAM,UAAU,KAAa;CAC7B,IAAI,YAAyC,KAAA;CAE7C,MAAM,sBAAsB,eAAwB;EAClD,OAAO,CAAC,EACN,EAAE,MAAM,SAAS,MAAM,cACvB,mBACA,gBAAgB,YAChB,gBAAgB,UAAU,UAAU;GAEtC;CAGF,gBAAgB;EACd,YAAY,MACV,CAAC,MAAM,OAAO,KAAK,EAAE,oBAAoB,GACxC,CAAC,IAAI,yBAA4C;GAChD,MAAM,QAAQ,OAAO,CAAC,sBAAsB,OAAO,CAAC,QAAQ,KAAA;GAC5D,IAAI,UAAU,QAAQ,OAAO;IAC3B,IAAI,iBAAiB,iBAAiB,CAAC,SAAS,EAAE;KAChD,QAAQ,SAAS,gBAAgB,cAAc,QAAQ,MAAM;KAC7D,IAAI,CAAC,qBAAqB,SAAS,CAAC,uBAAuB,OACzD,gBAAgB,WAAW,MAAM;;IAGrC,QAAQ,QAAQ;;KAGpB,EAAE,WAAW,MAAM,CACpB;GACD;CAEF,kBAAkB;EAChB,aAAa,WAAW;EACxB,IAAI,iBAAiB,eACnB,QAAQ,SAAS,gBAAgB,cAAc,QAAQ,MAAM;GAE/D;CAEF,OAAO;EACL;EACA;EACD"}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import { ComponentSize } from "../../../constants/size.js";
|
||||
import { Arrayable, FieldPath } from "../../../utils/typescript.js";
|
||||
import { useFormLabelWidth } from "./utils.js";
|
||||
import { FormItemProp, FormItemProps, FormItemValidateState } from "./form-item.js";
|
||||
import { FormEmits, FormProps } from "./form.js";
|
||||
import { MaybeRef, SetupContext, UnwrapRef } from "vue";
|
||||
import { RuleItem, ValidateError, ValidateFieldsError } from "async-validator";
|
||||
|
||||
//#region ../../packages/components/form/src/types.d.ts
|
||||
type FormLabelWidthContext = ReturnType<typeof useFormLabelWidth>;
|
||||
interface FormItemRule extends RuleItem {
|
||||
trigger?: Arrayable<string>;
|
||||
}
|
||||
type FormRuleValue<V> = V extends any[] ? Arrayable<FormItemRule> : V extends Record<string, any> ? Arrayable<FormItemRule> | { [K in keyof V]?: FormRuleValue<V[K]> } : Arrayable<FormItemRule>;
|
||||
type FormRules<T extends MaybeRef<Record<string, any> | string> = string> = UnwrapRef<T> extends Record<string, any> ? { [P in FieldPath<UnwrapRef<T>>]?: P extends keyof UnwrapRef<T> ? FormRuleValue<UnwrapRef<T>[P]> : Arrayable<FormItemRule> } : Partial<Record<string, Arrayable<FormItemRule> | Record<string, any>>>;
|
||||
type FormValidationResult = Promise<boolean>;
|
||||
type FormValidateCallback = (isValid: boolean, invalidFields?: ValidateFieldsError) => Promise<void> | void;
|
||||
interface FormValidateFailure {
|
||||
errors: ValidateError[] | null;
|
||||
fields: ValidateFieldsError;
|
||||
}
|
||||
type FormContext = FormProps & UnwrapRef<FormLabelWidthContext> & {
|
||||
emit: SetupContext<FormEmits>['emit'];
|
||||
getField: (prop: FormItemProp) => FormItemContext | undefined;
|
||||
addField: (field: FormItemContext) => void;
|
||||
removeField: (field: FormItemContext, oldPropString?: string) => void;
|
||||
resetFields: (props?: Arrayable<FormItemProp>) => void;
|
||||
setInitialValues: (initModel: Record<string, any>) => void;
|
||||
clearValidate: (props?: Arrayable<FormItemProp>) => void;
|
||||
validateField: (props?: Arrayable<FormItemProp>, callback?: FormValidateCallback) => FormValidationResult;
|
||||
};
|
||||
interface FormItemContext extends FormItemProps {
|
||||
$el: HTMLDivElement | undefined;
|
||||
size: ComponentSize;
|
||||
validateMessage: string;
|
||||
validateState: FormItemValidateState;
|
||||
isGroup: boolean;
|
||||
labelId: string;
|
||||
inputIds: string[];
|
||||
hasLabel: boolean;
|
||||
fieldValue: any;
|
||||
propString: string;
|
||||
addInputId: (id: string) => void;
|
||||
removeInputId: (id: string) => void;
|
||||
validate: (trigger: string, callback?: FormValidateCallback) => FormValidationResult;
|
||||
resetField(): void;
|
||||
clearValidate(): void;
|
||||
setInitialValue: (value: any) => void;
|
||||
getInitialValue: () => any;
|
||||
}
|
||||
//#endregion
|
||||
export { FormContext, FormItemContext, FormItemRule, FormLabelWidthContext, FormRules, FormValidateCallback, FormValidateFailure, FormValidationResult };
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
import { Arrayable } from "../../../utils/typescript.js";
|
||||
import { FormItemContext } from "./types.js";
|
||||
import { FormItemProp } from "./form-item.js";
|
||||
import * as _$vue from "vue";
|
||||
|
||||
//#region ../../packages/components/form/src/utils.d.ts
|
||||
declare function useFormLabelWidth(): {
|
||||
autoLabelWidth: _$vue.ComputedRef<string>;
|
||||
registerLabelWidth: (val: number, oldVal: number) => void;
|
||||
deregisterLabelWidth: (val: number) => void;
|
||||
};
|
||||
declare const filterFields: (fields: FormItemContext[], props: Arrayable<FormItemProp>) => FormItemContext[];
|
||||
//#endregion
|
||||
export { filterFields, useFormLabelWidth };
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
import { isArray } from "../../../utils/types.mjs";
|
||||
import { debugWarn } from "../../../utils/error.mjs";
|
||||
import { ensureArray } from "../../../utils/arrays.mjs";
|
||||
import { computed, ref } from "vue";
|
||||
//#region ../../packages/components/form/src/utils.ts
|
||||
const SCOPE = "ElForm";
|
||||
function useFormLabelWidth() {
|
||||
const potentialLabelWidthArr = ref([]);
|
||||
const autoLabelWidth = computed(() => {
|
||||
if (!potentialLabelWidthArr.value.length) return "0";
|
||||
const max = Math.max(...potentialLabelWidthArr.value);
|
||||
return max ? `${max}px` : "";
|
||||
});
|
||||
function getLabelWidthIndex(width) {
|
||||
const index = potentialLabelWidthArr.value.indexOf(width);
|
||||
if (index === -1 && autoLabelWidth.value === "0") debugWarn(SCOPE, `unexpected width ${width}`);
|
||||
return index;
|
||||
}
|
||||
function registerLabelWidth(val, oldVal) {
|
||||
if (val && oldVal) {
|
||||
const index = getLabelWidthIndex(oldVal);
|
||||
potentialLabelWidthArr.value.splice(index, 1, val);
|
||||
} else if (val) potentialLabelWidthArr.value.push(val);
|
||||
}
|
||||
function deregisterLabelWidth(val) {
|
||||
const index = getLabelWidthIndex(val);
|
||||
if (index > -1) potentialLabelWidthArr.value.splice(index, 1);
|
||||
}
|
||||
return {
|
||||
autoLabelWidth,
|
||||
registerLabelWidth,
|
||||
deregisterLabelWidth
|
||||
};
|
||||
}
|
||||
const filterFields = (fields, props) => {
|
||||
const normalized = ensureArray(props).map((prop) => isArray(prop) ? prop.join(".") : prop);
|
||||
return normalized.length > 0 ? fields.filter((field) => field.propString && normalized.includes(field.propString)) : fields;
|
||||
};
|
||||
//#endregion
|
||||
export { filterFields, useFormLabelWidth };
|
||||
|
||||
//# sourceMappingURL=utils.mjs.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.mjs","names":[],"sources":["../../../../../../packages/components/form/src/utils.ts"],"sourcesContent":["import { computed, ref } from 'vue'\nimport { debugWarn, ensureArray, isArray } from '@element-plus/utils'\n\nimport type { Arrayable } from '@element-plus/utils'\nimport type { FormItemContext } from './types'\nimport type { FormItemProp } from './form-item'\n\nconst SCOPE = 'ElForm'\n\nexport function useFormLabelWidth() {\n const potentialLabelWidthArr = ref<number[]>([])\n\n const autoLabelWidth = computed(() => {\n if (!potentialLabelWidthArr.value.length) return '0'\n const max = Math.max(...potentialLabelWidthArr.value)\n return max ? `${max}px` : ''\n })\n\n function getLabelWidthIndex(width: number) {\n const index = potentialLabelWidthArr.value.indexOf(width)\n if (index === -1 && autoLabelWidth.value === '0') {\n debugWarn(SCOPE, `unexpected width ${width}`)\n }\n return index\n }\n\n function registerLabelWidth(val: number, oldVal: number) {\n if (val && oldVal) {\n const index = getLabelWidthIndex(oldVal)\n potentialLabelWidthArr.value.splice(index, 1, val)\n } else if (val) {\n potentialLabelWidthArr.value.push(val)\n }\n }\n\n function deregisterLabelWidth(val: number) {\n const index = getLabelWidthIndex(val)\n if (index > -1) {\n potentialLabelWidthArr.value.splice(index, 1)\n }\n }\n\n return {\n autoLabelWidth,\n registerLabelWidth,\n deregisterLabelWidth,\n }\n}\n\nexport const filterFields = (\n fields: FormItemContext[],\n props: Arrayable<FormItemProp>\n) => {\n const normalized = ensureArray(props).map((prop) =>\n isArray(prop) ? prop.join('.') : prop\n )\n return normalized.length > 0\n ? fields.filter(\n (field) => field.propString && normalized.includes(field.propString)\n )\n : fields\n}\n"],"mappings":";;;;;AAOA,MAAM,QAAQ;AAEd,SAAgB,oBAAoB;CAClC,MAAM,yBAAyB,IAAc,EAAE,CAAC;CAEhD,MAAM,iBAAiB,eAAe;EACpC,IAAI,CAAC,uBAAuB,MAAM,QAAQ,OAAO;EACjD,MAAM,MAAM,KAAK,IAAI,GAAG,uBAAuB,MAAM;EACrD,OAAO,MAAM,GAAG,IAAI,MAAM;GAC1B;CAEF,SAAS,mBAAmB,OAAe;EACzC,MAAM,QAAQ,uBAAuB,MAAM,QAAQ,MAAM;EACzD,IAAI,UAAU,MAAM,eAAe,UAAU,KAC3C,UAAU,OAAO,oBAAoB,QAAQ;EAE/C,OAAO;;CAGT,SAAS,mBAAmB,KAAa,QAAgB;EACvD,IAAI,OAAO,QAAQ;GACjB,MAAM,QAAQ,mBAAmB,OAAO;GACxC,uBAAuB,MAAM,OAAO,OAAO,GAAG,IAAI;SAC7C,IAAI,KACT,uBAAuB,MAAM,KAAK,IAAI;;CAI1C,SAAS,qBAAqB,KAAa;EACzC,MAAM,QAAQ,mBAAmB,IAAI;EACrC,IAAI,QAAQ,IACV,uBAAuB,MAAM,OAAO,OAAO,EAAE;;CAIjD,OAAO;EACL;EACA;EACA;EACD;;AAGH,MAAa,gBACX,QACA,UACG;CACH,MAAM,aAAa,YAAY,MAAM,CAAC,KAAK,SACzC,QAAQ,KAAK,GAAG,KAAK,KAAK,IAAI,GAAG,KAClC;CACD,OAAO,WAAW,SAAS,IACvB,OAAO,QACJ,UAAU,MAAM,cAAc,WAAW,SAAS,MAAM,WAAW,CACrE,GACD"}
|
||||
Reference in New Issue
Block a user