完全跑通1.0版本

This commit is contained in:
2026-05-26 12:56:03 +08:00
parent 2ece5174a7
commit 93c714a93b
11557 changed files with 1648225 additions and 36 deletions

View File

@@ -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 };

View File

@@ -0,0 +1,9 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region ../../packages/components/form/src/constants.ts
const formContextKey = Symbol("formContextKey");
const formItemContextKey = Symbol("formItemContextKey");
//#endregion
exports.formContextKey = formContextKey;
exports.formItemContextKey = formItemContextKey;
//# sourceMappingURL=constants.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"constants.js","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"}

View File

@@ -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" | "left" | "right", 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, "" | "error" | "success" | "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 };

View File

@@ -0,0 +1,92 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_size = require("../../../constants/size.js");
const require_runtime = require("../../../utils/vue/props/runtime.js");
//#region ../../packages/components/form/src/form-item.ts
const formItemValidateStates = [
"",
"error",
"validating",
"success"
];
/**
* @deprecated Removed after 3.0.0, Use `FormItemProps` instead.
*/
const formItemProps = require_runtime.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: require_runtime.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: require_runtime.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: require_size.componentSizes
}
});
//#endregion
exports.formItemProps = formItemProps;
exports.formItemValidateStates = formItemValidateStates;
//# sourceMappingURL=form-item.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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<"" | "error" | "success" | "validating", "" | "error" | "success" | "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 };

View File

@@ -0,0 +1,305 @@
const require_runtime = require("../../../_virtual/_rolldown/runtime.js");
const require_types = require("../../../utils/types.js");
const require_objects = require("../../../utils/objects.js");
const require_style = require("../../../utils/dom/style.js");
const require_index = require("../../../hooks/use-namespace/index.js");
const require_index$1 = require("../../../hooks/use-id/index.js");
const require_constants = require("./constants.js");
const require_use_form_common_props = require("./hooks/use-form-common-props.js");
const require_form_item = require("./form-item.js");
const require_form_label_wrap = require("./form-label-wrap.js");
let _vueuse_core = require("@vueuse/core");
let lodash_unified = require("lodash-unified");
let vue = require("vue");
let async_validator = require("async-validator");
async_validator = require_runtime.__toESM(async_validator);
let _vue_shared = require("@vue/shared");
//#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__ */ (0, vue.defineComponent)({
name: "ElFormItem",
__name: "form-item",
props: require_form_item.formItemProps,
setup(__props, { expose: __expose }) {
const props = __props;
const slots = (0, vue.useSlots)();
const formContext = (0, vue.inject)(require_constants.formContextKey, void 0);
const parentFormItemContext = (0, vue.inject)(require_constants.formItemContextKey, void 0);
const _size = require_use_form_common_props.useFormSize(void 0, { formItem: false });
const ns = require_index.useNamespace("form-item");
const labelId = require_index$1.useId().value;
const inputIds = (0, vue.ref)([]);
const validateState = (0, vue.ref)("");
const validateStateDebounced = (0, _vueuse_core.refDebounced)(validateState, 100);
const validateMessage = (0, vue.ref)("");
const formItemRef = (0, vue.ref)();
let initialValue = void 0;
let isResettingField = false;
const labelPosition = (0, vue.computed)(() => props.labelPosition || formContext?.labelPosition);
const labelStyle = (0, vue.computed)(() => {
if (labelPosition.value === "top") return {};
return { width: require_style.addUnit(props.labelWidth ?? formContext?.labelWidth) };
});
const contentStyle = (0, vue.computed)(() => {
if (labelPosition.value === "top" || formContext?.inline) return {};
if (!props.label && !props.labelWidth && isNested) return {};
const labelWidth = require_style.addUnit(props.labelWidth ?? formContext?.labelWidth);
if (!props.label && !slots.label) return { marginLeft: labelWidth };
return {};
});
const formItemClasses = (0, vue.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 = (0, vue.computed)(() => require_types.isBoolean(props.inlineMessage) ? props.inlineMessage : formContext?.inlineMessage || false);
const validateClasses = (0, vue.computed)(() => [ns.e("error"), { [ns.em("error", "inline")]: _inlineMessage.value }]);
const propString = (0, vue.computed)(() => {
if (!props.prop) return "";
return (0, _vue_shared.isArray)(props.prop) ? props.prop.join(".") : props.prop;
});
const hasLabel = (0, vue.computed)(() => {
return !!(props.label || slots.label);
});
const labelFor = (0, vue.computed)(() => {
return props.for ?? (inputIds.value.length === 1 ? inputIds.value[0] : void 0);
});
const isGroup = (0, vue.computed)(() => {
return !labelFor.value && hasLabel.value;
});
const isNested = !!parentFormItemContext;
const fieldValue = (0, vue.computed)(() => {
const model = formContext?.model;
if (!model || !props.prop) return;
return require_objects.getProp(model, props.prop).value;
});
const normalizedRules = (0, vue.computed)(() => {
const { required } = props;
const rules = [];
if (props.rules) rules.push(...(0, lodash_unified.castArray)(props.rules));
const formRules = formContext?.rules;
if (formRules && props.prop) {
const _rules = require_objects.getProp(formRules, props.prop).value;
if (_rules) rules.push(...(0, lodash_unified.castArray)(_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 = (0, vue.computed)(() => normalizedRules.value.length > 0);
const getFilteredRule = (trigger) => {
return normalizedRules.value.filter((rule) => {
if (!rule.trigger || !trigger) return true;
if ((0, _vue_shared.isArray)(rule.trigger)) return rule.trigger.includes(trigger);
else return rule.trigger === trigger;
}).map(({ trigger, ...rule }) => rule);
};
const isRequired = (0, vue.computed)(() => normalizedRules.value.some((rule) => rule.required));
const shouldShowError = (0, vue.computed)(() => validateStateDebounced.value === "error" && props.showMessage && (formContext?.showMessage ?? true));
const currentLabel = (0, vue.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 async_validator.default({ [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 = (0, _vue_shared.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 = require_objects.getProp(model, props.prop);
isResettingField = true;
computedValue.value = (0, lodash_unified.cloneDeep)(initialValue);
await (0, vue.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 = (0, lodash_unified.cloneDeep)(value);
};
const getInitialValue = () => initialValue;
(0, vue.watch)(() => props.error, (val) => {
validateMessage.value = val || "";
setValidationState(val ? "error" : "");
}, { immediate: true });
(0, vue.watch)(() => props.validateStatus, (val) => setValidationState(val || ""));
const context = (0, vue.reactive)({
...(0, vue.toRefs)(props),
$el: formItemRef,
size: _size,
validateMessage,
validateState,
labelId,
inputIds,
isGroup,
hasLabel,
fieldValue,
addInputId,
removeInputId,
resetField,
clearValidate,
validate,
propString,
setInitialValue,
getInitialValue
});
(0, vue.provide)(require_constants.formItemContextKey, context);
(0, vue.watch)(propString, (newPropString, oldPropString) => {
if (!formContext || !oldPropString) return;
formContext.removeField(context, oldPropString);
if (newPropString) {
setInitialValue(fieldValue.value);
formContext.addField(context);
}
});
(0, vue.onMounted)(() => {
if (props.prop) {
setInitialValue(fieldValue.value);
formContext?.addField(context);
}
});
(0, vue.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 (0, vue.openBlock)(), (0, vue.createElementBlock)("div", {
ref_key: "formItemRef",
ref: formItemRef,
class: (0, vue.normalizeClass)(formItemClasses.value),
role: isGroup.value ? "group" : void 0,
"aria-labelledby": isGroup.value ? (0, vue.unref)(labelId) : void 0
}, [(0, vue.createVNode)((0, vue.unref)(require_form_label_wrap.default), {
"is-auto-width": labelStyle.value.width === "auto",
"update-all": (0, vue.unref)(formContext)?.labelWidth === "auto"
}, {
default: (0, vue.withCtx)(() => [!!(__props.label || _ctx.$slots.label) ? ((0, vue.openBlock)(), (0, vue.createBlock)((0, vue.resolveDynamicComponent)(labelFor.value ? "label" : "div"), {
key: 0,
id: (0, vue.unref)(labelId),
for: labelFor.value,
class: (0, vue.normalizeClass)((0, vue.unref)(ns).e("label")),
style: (0, vue.normalizeStyle)(labelStyle.value)
}, {
default: (0, vue.withCtx)(() => [(0, vue.renderSlot)(_ctx.$slots, "label", { label: currentLabel.value }, () => [(0, vue.createTextVNode)((0, vue.toDisplayString)(currentLabel.value), 1)])]),
_: 3
}, 8, [
"id",
"for",
"class",
"style"
])) : (0, vue.createCommentVNode)("v-if", true)]),
_: 3
}, 8, ["is-auto-width", "update-all"]), (0, vue.createElementVNode)("div", {
class: (0, vue.normalizeClass)((0, vue.unref)(ns).e("content")),
style: (0, vue.normalizeStyle)(contentStyle.value)
}, [(0, vue.renderSlot)(_ctx.$slots, "default"), (0, vue.createVNode)(vue.TransitionGroup, { name: `${(0, vue.unref)(ns).namespace.value}-zoom-in-top` }, {
default: (0, vue.withCtx)(() => [shouldShowError.value ? (0, vue.renderSlot)(_ctx.$slots, "error", {
key: 0,
error: validateMessage.value
}, () => [(0, vue.createElementVNode)("div", { class: (0, vue.normalizeClass)(validateClasses.value) }, (0, vue.toDisplayString)(validateMessage.value), 3)]) : (0, vue.createCommentVNode)("v-if", true)]),
_: 3
}, 8, ["name"])], 6)], 10, _hoisted_1);
};
}
});
//#endregion
exports.default = form_item_vue_vue_type_script_setup_true_lang_default;
//# sourceMappingURL=form-item.vue_vue_type_script_setup_true_lang.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
Object.defineProperties(exports, {
__esModule: { value: true },
[Symbol.toStringTag]: { value: "Module" }
});
//#region ../../packages/components/form/src/form-item.vue
var form_item_default = require("./form-item.vue_vue_type_script_setup_true_lang.js").default;
//#endregion
exports.default = form_item_default;
//# sourceMappingURL=form-item2.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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 };

View File

@@ -0,0 +1,72 @@
require("../../../_virtual/_rolldown/runtime.js");
const require_error = require("../../../utils/error.js");
const require_index = require("../../../hooks/use-namespace/index.js");
const require_constants = require("./constants.js");
let _vueuse_core = require("@vueuse/core");
let vue = require("vue");
//#region ../../packages/components/form/src/form-label-wrap.tsx
const COMPONENT_NAME = "ElLabelWrap";
var form_label_wrap_default = /* @__PURE__ */ (0, vue.defineComponent)({
name: COMPONENT_NAME,
props: {
isAutoWidth: Boolean,
updateAll: Boolean
},
setup(props, { slots }) {
const formContext = (0, vue.inject)(require_constants.formContextKey, void 0);
const formItemContext = (0, vue.inject)(require_constants.formItemContextKey);
if (!formItemContext) require_error.throwError(COMPONENT_NAME, "usage: <el-form-item><label-wrap /></el-form-item>");
const ns = require_index.useNamespace("form");
const el = (0, vue.ref)();
const computedWidth = (0, vue.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") => {
(0, vue.nextTick)(() => {
if (slots.default && props.isAutoWidth) {
if (action === "update") computedWidth.value = getLabelWidth();
else if (action === "remove") formContext?.deregisterLabelWidth(computedWidth.value);
}
});
};
const updateLabelWidthFn = () => updateLabelWidth("update");
(0, vue.onMounted)(() => {
updateLabelWidthFn();
});
(0, vue.onBeforeUnmount)(() => {
updateLabelWidth("remove");
});
(0, vue.onUpdated)(() => updateLabelWidthFn());
(0, vue.watch)(computedWidth, (val, oldVal) => {
if (props.updateAll) formContext?.registerLabelWidth(val, oldVal);
});
(0, _vueuse_core.useResizeObserver)((0, vue.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 (0, vue.createVNode)("div", {
"ref": el,
"class": [ns.be("item", "label-wrap")],
"style": style
}, [slots.default?.()]);
} else return (0, vue.createVNode)(vue.Fragment, { "ref": el }, [slots.default?.()]);
};
}
});
//#endregion
exports.default = form_label_wrap_default;
//# sourceMappingURL=form-label-wrap.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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" | "left" | "right", unknown, "right", boolean>;
readonly requireAsteriskPosition: EpPropFinalized<StringConstructor, "left" | "right", 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 };

View File

@@ -0,0 +1,119 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
require("../../../_virtual/_rolldown/runtime.js");
const require_size = require("../../../constants/size.js");
const require_types = require("../../../utils/types.js");
const require_runtime$1 = require("../../../utils/vue/props/runtime.js");
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/form/src/form.ts
/**
* @deprecated Removed after 3.0.0, Use `FormMetaProps` instead.
*/
const formMetaProps = require_runtime$1.buildProps({
/**
* @description Control the size of components in this form.
*/
size: {
type: String,
values: require_size.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 = require_runtime$1.buildProps({
...formMetaProps,
/**
* @description Data of form component.
*/
model: Object,
/**
* @description Validation rules of form.
*/
rules: { type: require_runtime$1.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: require_runtime$1.definePropType([Object, Boolean]),
default: true
}
});
const formEmits = { validate: (prop, isValid, message) => ((0, _vue_shared.isArray)(prop) || (0, _vue_shared.isString)(prop)) && require_types.isBoolean(isValid) && (0, _vue_shared.isString)(message) };
//#endregion
exports.formEmits = formEmits;
exports.formMetaProps = formMetaProps;
exports.formProps = formProps;
//# sourceMappingURL=form.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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;
}>, {
labelWidth: string | number;
labelPosition: "left" | "right" | "top";
requireAsteriskPosition: "left" | "right";
labelSuffix: string;
showMessage: boolean;
validateOnRuleChange: boolean;
scrollIntoViewOptions: ScrollIntoViewOptions | 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 };

View File

@@ -0,0 +1,201 @@
require("../../../_virtual/_rolldown/runtime.js");
const require_objects = require("../../../utils/objects.js");
const require_error = require("../../../utils/error.js");
const require_index = require("../../../hooks/use-namespace/index.js");
const require_form = require("./form.js");
const require_constants = require("./constants.js");
const require_use_form_common_props = require("./hooks/use-form-common-props.js");
const require_utils = require("./utils.js");
let lodash_unified = require("lodash-unified");
let vue = require("vue");
let _vue_shared = require("@vue/shared");
//#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__ */ (0, vue.defineComponent)({
name: COMPONENT_NAME,
__name: "form",
props: require_form.formProps,
emits: require_form.formEmits,
setup(__props, { expose: __expose, emit: __emit }) {
const props = __props;
const emit = __emit;
const formRef = (0, vue.ref)();
const fields = (0, vue.reactive)([]);
const initialValues = /* @__PURE__ */ new Map();
const formSize = require_use_form_common_props.useFormSize();
const ns = require_index.useNamespace("form");
const formClasses = (0, 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 require_utils.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, (0, lodash_unified.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, (0, lodash_unified.cloneDeep)(field.getInitialValue()));
}
};
const setInitialValues = (initModel) => {
if (!props.model) {
require_error.debugWarn(COMPONENT_NAME, "model is required for setInitialValues to work.");
return;
}
if (!initModel) {
require_error.debugWarn(COMPONENT_NAME, "initModel is required for setInitialValues to work.");
return;
}
for (const key of initialValues.keys()) initialValues.set(key, (0, lodash_unified.cloneDeep)(require_objects.getProp(initModel, key).value));
fields.forEach((field) => {
if (field.prop) field.setInitialValue(require_objects.getProp(initModel, field.prop).value);
});
};
const resetFields = (properties = []) => {
if (!props.model) {
require_error.debugWarn(COMPONENT_NAME, "model is required for resetFields to work.");
return;
}
require_utils.filterFields(fields, properties).forEach((field) => field.resetField());
const activePropStrings = new Set(fields.map((f) => f.propString).filter(Boolean));
const propsToCheck = properties.length > 0 ? (0, lodash_unified.castArray)(properties).map((p) => (0, _vue_shared.isArray)(p) ? p.join(".") : p) : [...initialValues.keys()];
for (const propString of propsToCheck) if (!activePropStrings.has(propString) && initialValues.has(propString)) require_objects.getProp(props.model, propString).value = (0, lodash_unified.cloneDeep)(initialValues.get(propString));
};
const clearValidate = (props = []) => {
require_utils.filterFields(fields, props).forEach((field) => field.clearValidate());
};
const isValidatable = (0, vue.computed)(() => {
const hasModel = !!props.model;
if (!hasModel) require_error.debugWarn(COMPONENT_NAME, "model is required for validate to work.");
return hasModel;
});
const obtainValidateFields = (props) => {
if (fields.length === 0) return [];
const filteredFields = require_utils.filterFields(fields, props);
if (!filteredFields.length) {
require_error.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 = !(0, _vue_shared.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);
};
(0, vue.watch)(() => props.rules, () => {
if (props.validateOnRuleChange) validate().catch(_vue_shared.NOOP);
}, {
deep: true,
flush: "post"
});
(0, vue.provide)(require_constants.formContextKey, (0, vue.reactive)({
...(0, vue.toRefs)(props),
emit,
resetFields,
clearValidate,
validateField,
getField,
addField,
removeField,
setInitialValues,
...require_utils.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 (0, vue.openBlock)(), (0, vue.createElementBlock)("form", {
ref_key: "formRef",
ref: formRef,
class: (0, vue.normalizeClass)(formClasses.value)
}, [(0, vue.renderSlot)(_ctx.$slots, "default")], 2);
};
}
});
//#endregion
exports.default = form_vue_vue_type_script_setup_true_lang_default;
//# sourceMappingURL=form.vue_vue_type_script_setup_true_lang.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,10 @@
Object.defineProperties(exports, {
__esModule: { value: true },
[Symbol.toStringTag]: { value: "Module" }
});
//#region ../../packages/components/form/src/form.vue
var form_default = require("./form.vue_vue_type_script_setup_true_lang.js").default;
//#endregion
exports.default = form_default;
//# sourceMappingURL=form2.js.map

File diff suppressed because one or more lines are too long

View File

@@ -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 };

View File

@@ -0,0 +1,9 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_use_form_common_props = require("./use-form-common-props.js");
const require_use_form_item = require("./use-form-item.js");
exports.useDisabled = require_use_form_common_props.useDisabled;
exports.useFormDisabled = require_use_form_common_props.useFormDisabled;
exports.useFormItem = require_use_form_item.useFormItem;
exports.useFormItemInputId = require_use_form_item.useFormItemInputId;
exports.useFormSize = require_use_form_common_props.useFormSize;
exports.useSize = require_use_form_common_props.useSize;

View File

@@ -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 };

View File

@@ -0,0 +1,31 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
require("../../../../_virtual/_rolldown/runtime.js");
const require_index = require("../../../../hooks/use-prop/index.js");
const require_index$1 = require("../../../../hooks/use-size/index.js");
const require_constants = require("../constants.js");
let vue = require("vue");
//#region ../../packages/components/form/src/hooks/use-form-common-props.ts
const useFormSize = (fallback, ignore = {}) => {
const emptyRef = (0, vue.ref)(void 0);
const size = ignore.prop ? emptyRef : require_index.useProp("size");
const globalConfig = ignore.global ? emptyRef : require_index$1.useGlobalSize();
const form = ignore.form ? { size: void 0 } : (0, vue.inject)(require_constants.formContextKey, void 0);
const formItem = ignore.formItem ? { size: void 0 } : (0, vue.inject)(require_constants.formItemContextKey, void 0);
return (0, vue.computed)(() => size.value || (0, vue.unref)(fallback) || formItem?.size || form?.size || globalConfig.value || "");
};
const useFormDisabled = (fallback) => {
const disabled = require_index.useProp("disabled");
const form = (0, vue.inject)(require_constants.formContextKey, void 0);
return (0, vue.computed)(() => {
return disabled.value ?? (0, vue.unref)(fallback) ?? form?.disabled ?? false;
});
};
const useSize = useFormSize;
const useDisabled = useFormDisabled;
//#endregion
exports.useDisabled = useDisabled;
exports.useFormDisabled = useFormDisabled;
exports.useFormSize = useFormSize;
exports.useSize = useSize;
//# sourceMappingURL=use-form-common-props.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"use-form-common-props.js","names":["useProp","useGlobalSize","formContextKey","formItemContextKey"],"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,YAAA,GAAA,IAAA,KAAe,KAAA,EAAU;CAE/B,MAAM,OAAO,OAAO,OAAO,WAAWA,cAAAA,QAAuB,OAAO;CACpE,MAAM,eAAe,OAAO,SAAS,WAAWC,gBAAAA,eAAe;CAC/D,MAAM,OAAO,OAAO,OAChB,EAAE,MAAM,KAAA,GAAW,IAAA,GAAA,IAAA,QACZC,kBAAAA,gBAAgB,KAAA,EAAU;CACrC,MAAM,WAAW,OAAO,WACpB,EAAE,MAAM,KAAA,GAAW,IAAA,GAAA,IAAA,QACZC,kBAAAA,oBAAoB,KAAA,EAAU;CAEzC,QAAA,GAAA,IAAA,gBAEI,KAAK,UAAA,GAAA,IAAA,OACC,SAAS,IACf,UAAU,QACV,MAAM,QACN,aAAa,SACb,GACH;;AAGH,MAAa,mBAAmB,aAA6C;CAC3E,MAAM,WAAWH,cAAAA,QAAiB,WAAW;CAC7C,MAAM,QAAA,GAAA,IAAA,QAAcE,kBAAAA,gBAAgB,KAAA,EAAU;CAE9C,QAAA,GAAA,IAAA,gBAAsB;EACpB,OAAO,SAAS,UAAA,GAAA,IAAA,OAAe,SAAS,IAAI,MAAM,YAAY;GAC9D;;AAIJ,MAAa,UAAU;AACvB,MAAa,cAAc"}

View File

@@ -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 };

View File

@@ -0,0 +1,56 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
require("../../../../_virtual/_rolldown/runtime.js");
const require_index = require("../../../../hooks/use-id/index.js");
const require_constants = require("../constants.js");
let vue = require("vue");
//#region ../../packages/components/form/src/hooks/use-form-item.ts
const useFormItem = () => {
return {
form: (0, vue.inject)(require_constants.formContextKey, void 0),
formItem: (0, vue.inject)(require_constants.formItemContextKey, void 0)
};
};
const useFormItemInputId = (props, { formItemContext, disableIdGeneration, disableIdManagement }) => {
if (!disableIdGeneration) disableIdGeneration = (0, vue.ref)(false);
if (!disableIdManagement) disableIdManagement = (0, vue.ref)(false);
const instance = (0, vue.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 = (0, vue.ref)();
let idUnwatch = void 0;
const isLabeledByFormItem = (0, vue.computed)(() => {
return !!(!(props.label || props.ariaLabel) && formItemContext && formItemContext.inputIds && formItemContext.inputIds?.length <= 1);
});
(0, vue.onMounted)(() => {
idUnwatch = (0, vue.watch)([(0, vue.toRef)(props, "id"), disableIdGeneration], ([id, disableIdGeneration]) => {
const newId = id ?? (!disableIdGeneration ? require_index.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 });
});
(0, vue.onUnmounted)(() => {
idUnwatch && idUnwatch();
if (formItemContext?.removeInputId) inputId.value && formItemContext.removeInputId(inputId.value);
});
return {
isLabeledByFormItem,
inputId
};
};
//#endregion
exports.useFormItem = useFormItem;
exports.useFormItemInputId = useFormItemInputId;
//# sourceMappingURL=use-form-item.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"use-form-item.js","names":["formContextKey","formItemContextKey","useId"],"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,OAAA,GAAA,IAAA,QAHkBA,kBAAAA,gBAAgB,KAAA,EAG9B;EACJ,WAAA,GAAA,IAAA,QAHsBC,kBAAAA,oBAAoB,KAAA,EAGlC;EACT;;AASH,MAAa,sBACX,OACA,EACE,iBACA,qBACA,0BAMC;CACH,IAAI,CAAC,qBACH,uBAAA,GAAA,IAAA,KAAmC,MAAM;CAE3C,IAAI,CAAC,qBACH,uBAAA,GAAA,IAAA,KAAmC,MAAM;CAG3C,MAAM,YAAA,GAAA,IAAA,qBAA+B;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,WAAA,GAAA,IAAA,MAAuB;CAC7B,IAAI,YAAyC,KAAA;CAE7C,MAAM,uBAAA,GAAA,IAAA,gBAA8C;EAClD,OAAO,CAAC,EACN,EAAE,MAAM,SAAS,MAAM,cACvB,mBACA,gBAAgB,YAChB,gBAAgB,UAAU,UAAU;GAEtC;CAGF,CAAA,GAAA,IAAA,iBAAgB;EACd,aAAA,GAAA,IAAA,OACE,EAAA,GAAA,IAAA,OAAO,OAAO,KAAK,EAAE,oBAAoB,GACxC,CAAC,IAAI,yBAA4C;GAChD,MAAM,QAAQ,OAAO,CAAC,sBAAsBC,cAAAA,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,CAAA,GAAA,IAAA,mBAAkB;EAChB,aAAa,WAAW;EACxB,IAAI,iBAAiB,eACnB,QAAQ,SAAS,gBAAgB,cAAc,QAAQ,MAAM;GAE/D;CAEF,OAAO;EACL;EACA;EACD"}

View File

@@ -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 };

View File

@@ -0,0 +1 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });

View File

@@ -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 };

View File

@@ -0,0 +1,45 @@
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
require("../../../_virtual/_rolldown/runtime.js");
const require_error = require("../../../utils/error.js");
let vue = require("vue");
let lodash_unified = require("lodash-unified");
let _vue_shared = require("@vue/shared");
//#region ../../packages/components/form/src/utils.ts
const SCOPE = "ElForm";
function useFormLabelWidth() {
const potentialLabelWidthArr = (0, vue.ref)([]);
const autoLabelWidth = (0, vue.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") require_error.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 = (0, lodash_unified.castArray)(props).map((prop) => (0, _vue_shared.isArray)(prop) ? prop.join(".") : prop);
return normalized.length > 0 ? fields.filter((field) => field.propString && normalized.includes(field.propString)) : fields;
};
//#endregion
exports.filterFields = filterFields;
exports.useFormLabelWidth = useFormLabelWidth;
//# sourceMappingURL=utils.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"utils.js","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,0BAAA,GAAA,IAAA,KAAuC,EAAE,CAAC;CAEhD,MAAM,kBAAA,GAAA,IAAA,gBAAgC;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,cAAA,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,cAAA,GAAA,eAAA,WAAyB,MAAM,CAAC,KAAK,UAAA,GAAA,YAAA,SACjC,KAAK,GAAG,KAAK,KAAK,IAAI,GAAG,KAClC;CACD,OAAO,WAAW,SAAS,IACvB,OAAO,QACJ,UAAU,MAAM,cAAc,WAAW,SAAS,MAAM,WAAW,CACrE,GACD"}