@veltra/desktop 1.2.19 → 1.2.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,9 +9,9 @@ declare const __VLS_base: import("vue").DefineComponent<ActionGroupProps, _Actio
9
9
  type: import("@veltra/utils").ColorType;
10
10
  text: boolean;
11
11
  size: "small" | "default" | "large";
12
+ circle: boolean;
12
13
  max: number;
13
14
  loading: boolean;
14
- circle: boolean;
15
15
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
16
16
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
17
17
  declare const _default: typeof __VLS_export;
@@ -15,8 +15,8 @@ declare const __VLS_base: import("vue").DefineComponent<ActionProps, {}, {}, {},
15
15
  type: ButtonType;
16
16
  text: boolean;
17
17
  size: import("@veltra/utils").ComponentSize;
18
- loading: boolean;
19
18
  circle: boolean;
19
+ loading: boolean;
20
20
  inDropdown: boolean;
21
21
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
22
22
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -13,6 +13,7 @@ var form_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ defineCompo
13
13
  cols: {},
14
14
  model: {},
15
15
  labelWidth: {},
16
+ labelPosition: {},
16
17
  noTips: { type: Boolean },
17
18
  readonly: { type: Boolean },
18
19
  disabled: { type: Boolean },
@@ -1 +1 @@
1
- {"version":3,"file":"form.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"grid\"\n @submit.prevent\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { nextTick, toRef, useTemplateRef } from 'vue'\n\nimport type { BreakCols, FormProps, _FormExposed, FormEmits } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { useFormFields } from './use-form-fields'\nimport { useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'UForm' })\n\nconst props = defineProps<FormProps>()\n\nconst emit = defineEmits<FormEmits>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\nconst formItemCls = bem('form-item')\nconst gridRef = useTemplateRef('grid')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst {\n validate: runValidate,\n clearValidate,\n reset,\n registerField,\n unregisterField,\n shouldValidate\n} = useFormFields({ props })\n\nasync function validate(keys?: string[]) {\n const valid = await runValidate(keys)\n if (!valid) {\n await nextTick()\n\n gridRef.value?.el\n ?.querySelector(`.${formItemCls.e('error-text')}`)\n ?.scrollIntoView({ block: 'center' })\n }\n return valid\n}\n\nfunction handleFieldChange(field: string, value: any) {\n emit('field:change', field, value)\n}\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate,\n handleFieldChange\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;EAuCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAIb,MAAM,MAAM,IAAI,MAAM;EACtB,MAAM,cAAc,IAAI,WAAW;EACnC,MAAM,UAAU,eAAe,MAAM;EAErC,MAAM,iBAA4B;GAAE,IAAI;GAAG,IAAI;GAAG,IAAI;GAAG,IAAI;GAAG,SAAS;EAAE;EAE3E,MAAM,EACJ,UAAU,aACV,eACA,OACA,eACA,iBACA,mBACE,cAAc,EAAE,MAAM,CAAC;EAE3B,eAAe,SAAS,MAAiB;GACvC,MAAM,QAAQ,MAAM,YAAY,IAAI;GACpC,IAAI,CAAC,OAAO;IACV,MAAM,SAAS;IAEf,QAAQ,OAAO,IACX,cAAc,IAAI,YAAY,EAAE,YAAY,GAAG,CAAA,EAC/C,eAAe,EAAE,OAAO,SAAS,CAAC;GACxC;GACA,OAAO;EACT;EAEA,SAAS,kBAAkB,OAAe,OAAY;GACpD,KAAK,gBAAgB,OAAO,KAAK;EACnC;EAEA,mBAAmB;GACjB,WAAW;GACX;GACA;GACA,gBAAgB;GAChB;GACA;EACF,CAAC;EAED,MAAM,EAAE,kBAAkB,mBAAmB;EAE7C,SAAS,kBAAkB,OAAe,OAAY;GACpD,IAAI,CAAC,MAAM,OAAO;GAClB,EAAE,MAAM,KAAK,CAAC,CAAC,IAAI,OAAO,KAAK;EACjC;EAEA,SAA2B;GAAE,IAAI,YAAY,QAAQ,OAAO,EAAE;GAAG;GAAU;GAAe;EAAM,CAAC;;uBA3F/F,YAqBS,MAAA,SAAA,GAAA;IApBP,KAAI;IACJ,KAAI;IACH,UAAM,OAAA,OAAA,OAAA,KAAA,oBAAP,CAAA,GAAe,CAAA,SAAA,CAAA;IACd,MAAM,QAAA,QAAQ;IACd,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,GAAG,MAAA,GAAA,CAAG,CAAC,GAAE,YAAa,QAAA,QAAQ,CAAA,CAAA;;2BAGwC,EAAA,UAAA,IAAA,GADnF,mBAaW,UAAA,MAAA,WAZwD,MAAA,aAAA,CAAa,CAAA,IAAA,EAArE,MAAM,YAAY,eAAe,OAAO,iBAAU;6DACrD,KAAK,IAAA,GAAA,CAAA,CAES,cAAc,SAAA,UAAA,GAAlC,YAMc,MAAA,iBAAA,GANd,WAMc;;;QANmC,aAAa,GAAA;6BAK1D,EAAA,UAAA,GAJF,YAIE,wBAHK,IAAI,GAAA;OACR,eAAa,cAAc,MAAA,CAAA,CAAC,CAAC,QAAA,SAAK,CAAA,CAAA,CAAA,CAAQ,IAAI,KAAK;OACnD,wBAAkB,WAAE,kBAAkB,OAAO,MAAM;;;+BAIxD,YAA+B,wBAAR,IAAI,GAAA,EAAA,KAAA,EAAA,CAAA,EAAA,GAAA,EAAA"}
1
+ {"version":3,"file":"form.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/form/form.vue"],"sourcesContent":["<template>\n <u-grid\n tag=\"form\"\n ref=\"grid\"\n @submit.prevent\n :cols=\"cols || breakpointCols\"\n :class=\"[cls.b, bem.is('readonly', readonly)]\"\n >\n <template\n v-for=\"{ node, isFormItem, formItemProps, field, modelValue } of getSlotsNodes()\"\n :key=\"node.key\"\n >\n <u-form-item v-if=\"!isFormItem && field\" v-bind=\"formItemProps\">\n <component\n :is=\"node\"\n :model-value=\"modelValue ?? o(model ?? {}).get(field)\"\n @update:model-value=\"handleUpdateValue(field, $event)\"\n />\n </u-form-item>\n\n <component v-else :is=\"node\" />\n </template>\n </u-grid>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { bem } from '@veltra/utils'\nimport { provideFormContext } from '@veltra/utils'\nimport { nextTick, toRef, useTemplateRef } from 'vue'\n\nimport type { BreakCols, FormProps, _FormExposed, FormEmits } from '../../types'\nimport { UFormItem } from '../form-item'\nimport { UGrid } from '../grid'\nimport { useFormFields } from './use-form-fields'\nimport { useNodeInterceptor } from './use-node-interceptor'\n\ndefineOptions({ name: 'UForm' })\n\nconst props = defineProps<FormProps>()\n\nconst emit = defineEmits<FormEmits>()\n\ndefineSlots<{ default(props?: { data: Record<string, any> | undefined }): any }>()\n\nconst cls = bem('form')\nconst formItemCls = bem('form-item')\nconst gridRef = useTemplateRef('grid')\n\nconst breakpointCols: BreakCols = { xs: 1, md: 2, lg: 3, xl: 4, default: 4 }\n\nconst {\n validate: runValidate,\n clearValidate,\n reset,\n registerField,\n unregisterField,\n shouldValidate\n} = useFormFields({ props })\n\nasync function validate(keys?: string[]) {\n const valid = await runValidate(keys)\n if (!valid) {\n await nextTick()\n\n gridRef.value?.el\n ?.querySelector(`.${formItemCls.e('error-text')}`)\n ?.scrollIntoView({ block: 'center' })\n }\n return valid\n}\n\nfunction handleFieldChange(field: string, value: any) {\n emit('field:change', field, value)\n}\n\nprovideFormContext({\n formProps: props,\n registerField,\n unregisterField,\n validateFields: validate,\n shouldValidate,\n handleFieldChange\n})\n\nconst { getSlotsNodes } = useNodeInterceptor()\n\nfunction handleUpdateValue(field: string, value: any) {\n if (!props.model) return\n o(props.model).set(field, value)\n}\n\ndefineExpose<_FormExposed>({ el: toRef(() => gridRef.value?.el), validate, clearValidate, reset })\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;EAuCA,MAAM,QAAQ;EAEd,MAAM,OAAO;EAIb,MAAM,MAAM,IAAI,MAAM;EACtB,MAAM,cAAc,IAAI,WAAW;EACnC,MAAM,UAAU,eAAe,MAAM;EAErC,MAAM,iBAA4B;GAAE,IAAI;GAAG,IAAI;GAAG,IAAI;GAAG,IAAI;GAAG,SAAS;EAAE;EAE3E,MAAM,EACJ,UAAU,aACV,eACA,OACA,eACA,iBACA,mBACE,cAAc,EAAE,MAAM,CAAC;EAE3B,eAAe,SAAS,MAAiB;GACvC,MAAM,QAAQ,MAAM,YAAY,IAAI;GACpC,IAAI,CAAC,OAAO;IACV,MAAM,SAAS;IAEf,QAAQ,OAAO,IACX,cAAc,IAAI,YAAY,EAAE,YAAY,GAAG,CAAA,EAC/C,eAAe,EAAE,OAAO,SAAS,CAAC;GACxC;GACA,OAAO;EACT;EAEA,SAAS,kBAAkB,OAAe,OAAY;GACpD,KAAK,gBAAgB,OAAO,KAAK;EACnC;EAEA,mBAAmB;GACjB,WAAW;GACX;GACA;GACA,gBAAgB;GAChB;GACA;EACF,CAAC;EAED,MAAM,EAAE,kBAAkB,mBAAmB;EAE7C,SAAS,kBAAkB,OAAe,OAAY;GACpD,IAAI,CAAC,MAAM,OAAO;GAClB,EAAE,MAAM,KAAK,CAAC,CAAC,IAAI,OAAO,KAAK;EACjC;EAEA,SAA2B;GAAE,IAAI,YAAY,QAAQ,OAAO,EAAE;GAAG;GAAU;GAAe;EAAM,CAAC;;uBA3F/F,YAqBS,MAAA,SAAA,GAAA;IApBP,KAAI;IACJ,KAAI;IACH,UAAM,OAAA,OAAA,OAAA,KAAA,oBAAP,CAAA,GAAe,CAAA,SAAA,CAAA;IACd,MAAM,QAAA,QAAQ;IACd,OAAK,eAAA,CAAG,MAAA,GAAA,CAAG,CAAC,GAAG,MAAA,GAAA,CAAG,CAAC,GAAE,YAAa,QAAA,QAAQ,CAAA,CAAA;;2BAGwC,EAAA,UAAA,IAAA,GADnF,mBAaW,UAAA,MAAA,WAZwD,MAAA,aAAA,CAAa,CAAA,IAAA,EAArE,MAAM,YAAY,eAAe,OAAO,iBAAU;6DACrD,KAAK,IAAA,GAAA,CAAA,CAES,cAAc,SAAA,UAAA,GAAlC,YAMc,MAAA,iBAAA,GANd,WAMc;;;QANmC,aAAa,GAAA;6BAK1D,EAAA,UAAA,GAJF,YAIE,wBAHK,IAAI,GAAA;OACR,eAAa,cAAc,MAAA,CAAA,CAAC,CAAC,QAAA,SAAK,CAAA,CAAA,CAAA,CAAQ,IAAI,KAAK;OACnD,wBAAkB,WAAE,kBAAkB,OAAO,MAAM;;;+BAIxD,YAA+B,wBAAR,IAAI,GAAA,EAAA,KAAA,EAAA,CAAA,EAAA,GAAA,EAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"form-item.js","names":[],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}:</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}:</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <slot></slot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { type CSSProperties, computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport type { FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate, handleFieldChange } =\n injectFormContext()\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst className = computed(() => {\n return [cls.b, cls.m(size.value), bem.is('error', !!errorTip.value)].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldChange?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":""}
1
+ {"version":3,"file":"form-item.js","names":[],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}:</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}:</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <slot></slot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { type CSSProperties, computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport type { FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate, handleFieldChange } =\n injectFormContext()\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('error', !!errorTip.value),\n bem.is('label-top', labelPosition.value === 'top')\n ].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n if (labelPosition.value === 'top') return {}\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldChange?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":""}
@@ -12,6 +12,7 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
12
12
  __name: "form-item",
13
13
  props: {
14
14
  labelWidth: {},
15
+ labelPosition: {},
15
16
  tips: {},
16
17
  span: {},
17
18
  label: {},
@@ -38,15 +39,18 @@ var form_item_vue_vue_type_script_setup_true_lang_default = /*@__PURE__*/ define
38
39
  let validateSeq = 0;
39
40
  /** 最近一次 validate 的 Promise,供过期调用等待最新结果 */
40
41
  let latestValidatePromise = Promise.resolve(true);
42
+ const labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? "left");
41
43
  const className = computed(() => {
42
44
  return [
43
45
  formItemCls.b,
44
46
  formItemCls.m(size.value),
45
- bem.is("error", !!errorTip.value)
47
+ bem.is("error", !!errorTip.value),
48
+ bem.is("label-top", labelPosition.value === "top")
46
49
  ].join(" ");
47
50
  });
48
51
  /** label样式 */
49
52
  const labelStyles = computed(() => {
53
+ if (labelPosition.value === "top") return {};
50
54
  return { width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, "px") };
51
55
  });
52
56
  const fieldItem = defineField({
@@ -1 +1 @@
1
- {"version":3,"file":"form-item.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}:</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}:</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <slot></slot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { type CSSProperties, computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport type { FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate, handleFieldChange } =\n injectFormContext()\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst className = computed(() => {\n return [cls.b, cls.m(size.value), bem.is('error', !!errorTip.value)].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldChange?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;EAiDA,MAAM,QAAQ;;EASd,MAAM,EAAE,WAAW,eAAe,iBAAiB,gBAAgB,sBACjE,kBAAkB;EAEpB,MAAM,EAAE,WAAW,UAAU;EAE7B,MAAM,EAAE,MAAM,aAAa,iBAAiB,CAAC,aAAa,CAAC,GAAG,KAAK,GAAG;GACpE,MAAM;GACN,UAAU;EACZ,CAAC;EAED,MAAM,WAAW,WAAmB;;EAEpC,IAAI,cAAc;;EAElB,IAAI,wBAA0C,QAAQ,QAAQ,IAAI;EAElE,MAAM,YAAY,eAAe;GAC/B,OAAO;IAAC,YAAI;IAAG,YAAI,EAAE,KAAK,KAAK;IAAG,IAAI,GAAG,SAAS,CAAC,CAAC,SAAS,KAAK;GAAC,CAAC,CAAC,KAAK,GAAG;EAC/E,CAAC;;EAGD,MAAM,cAAc,eAA8B;GAChD,OAAO,EACL,OAAO,SAAS,MAAM,cAAc,WAAW,cAAc,OAAO,KAAK,YAAY,IAAI,EAC3F;EACF,CAAC;EAED,MAAM,YAAY,YAAY;GAC5B,gBAAgB;IACd,SAAS,QAAQ;GACnB;GACA,MAAM,WAAW;IACf,IAAI,CAAC,MAAM,SAAS,CAAC,WAAW,SAAS,CAAC,MAAM,SAAS,CAAC,iBAAiB,GAAG,OAAO;IAErF,MAAM,MAAM,EAAE;IAEd,wBAAwB,cAAc,UAAU,OAAQ,MAAM,OAAQ,MAAM,KAAM,CAAC,CAAC,MACjF,QAAQ;KACP,IAAI,QAAQ,aAAa,OAAO;KAEhC,SAAS,QAAQ;KACjB,OAAO,CAAC,SAAS;IACnB,CACF;IACA,OAAO;GACT;EACF,CAAC;EAED,YACQ,MAAM,QACX,OAAO,aAAa;GACnB,IAAI,UACF,kBAAkB,QAAQ;GAE5B,IAAI,OACF,gBAAgB,OAAO,SAAS;EAEpC,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,IAAI;EAEJ,MACE,OAAO,WAAW,aAAa,MAAM,KAAK,IACzC,CAAC,OAAO,WAAW;GAClB,sBAAsB;GAEtB,IAAI,CAAC,SAAS,CAAC,OAAO;GAEtB,sBAAsB,YACd,EAAE,KAAK,CAAC,CAAC,IAAI,KAAK,IACvB,UAAU;IACT,oBAAoB,OAAO,KAAK;IAChC,UAAU,SAAS;GACrB,CACF;EACF,GACA,EAAE,WAAW,KAAK,CACpB;EAEA,sBAAsB;GACpB,MAAM,SAAS,kBAAkB,MAAM,KAAK;EAC9C,CAAC;;uBA5IC,YA8Bc,MAAA,WAAA,GAAA;IA9BA,MAAM,QAAA;IAAO,OAAK,eAAE,UAAA,KAAS;;2BAcjC,CAZA,MAAM,SAASA,KAAAA,OAAO,SAAA,UAAA,GAD9B,mBAaQ,SAAA;;KAXL,OAAK,eAAA,CAAG,MAAA,WAAA,CAAG,CAAC,EAAC,OAAA,GAAW,MAAA,GAAA,CAAG,CAAC,GAAE,YAAA,CAAA,CAAe,QAAA,OAAO,QAAQ,CAAA,CAAA;KAC5D,OAAK,eAAE,YAAA,KAAW;QAEN,QAAA,QAAA,UAAA,GAAb,YAIQ,MAAA,SAAA,GAAA;;KAJY,SAAS,QAAA;KAAO,OAAK,eAAE,MAAA,WAAA,CAAG,CAAC,EAAC,MAAA,CAAA;;4BAGvC,CAFP,mBAEO,QAAA,EAFA,OAAK,eAAE,MAAA,WAAA,CAAG,CAAC,EAAC,WAAA,CAAA,EAAA,GAAA,CACjB,WAAsC,KAAA,QAAA,SAAA,CAAA,SAAA,CAAA,gBAAA,gBAAhB,QAAA,KAAK,IAAG,KAAC,CAAA,CAAA,CAAA,CAAA,GAAA,CAAA,CAAA,CAAA;;mCAIjC,WAAsC,KAAA,QAAA,SAAA,EAAA,KAAA,EAAA,SAAA,CAAA,gBAAA,gBAAhB,QAAA,KAAK,IAAG,KAAC,CAAA,CAAA,CAAA,CAAA,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,GAInC,mBAaU,WAAA,EAbA,OAAK,eAAE,MAAA,WAAA,CAAG,CAAC,EAAC,SAAA,CAAA,EAAA,GAAA;KACpB,mBAEM,OAAA,EAFA,OAAK,eAAE,MAAA,WAAA,CAAG,CAAC,EAAC,SAAA,CAAA,EAAA,GAAA,CAChB,WAAa,KAAA,QAAA,SAAA,CAAA,GAAA,CAAA;KAGf,mBAAA,0BAAA;MACwC,MAAA,QAAA,KAAQ,CAAK,MAAA,SAAA,CAAS,EAAE,UAAA,UAAA,GAAhE,mBAMU,WAAA;;MANA,OAAK,eAAE,MAAA,WAAA,CAAG,CAAC,EAAC,OAAA,CAAA;SACpB,YAIa,YAAA;MAJD,MAAK;MAAiB,MAAK;;6BAG9B,CAAA,CAAA,CAFoC,SAAA,SAAA,UAAA,GAA3C,mBAEO,QAAA;;OAFA,OAAK,eAAE,MAAA,WAAA,CAAG,CAAC,EAAC,YAAA,CAAA;yBACd,SAAA,KAAQ,GAAA,CAAA,KAAA,mBAAA,QAAA,IAAA,CAAA,CAAA"}
1
+ {"version":3,"file":"form-item.vue_vue_type_script_setup_true_lang.js","names":["$slots"],"sources":["../../../src/components/form-item/form-item.vue"],"sourcesContent":["<template>\n <u-grid-item :span=\"span\" :class=\"className\">\n <label\n v-if=\"props.label || $slots.label\"\n :class=\"[cls.e('label'), bem.is('required', !!rules?.required)]\"\n :style=\"labelStyles\"\n >\n <u-tip v-if=\"tips\" :content=\"tips\" :class=\"cls.e('tips')\">\n <span :class=\"cls.e('tip-label')\">\n <slot name=\"label\">{{ label }}:</slot>\n </span>\n </u-tip>\n <template v-else>\n <slot name=\"label\">{{ label }}:</slot>\n </template>\n </label>\n\n <section :class=\"cls.e('wrapper')\">\n <div :class=\"cls.e('content')\">\n <slot></slot>\n </div>\n\n <!-- 只有表单控件处于非只读状态时,才显示错误提示 -->\n <section :class=\"cls.e('error')\" v-if=\"!readonly && !formProps?.noTips\">\n <transition name=\"form-item-tips\" mode=\"out-in\">\n <span :class=\"cls.e('error-text')\" v-if=\"!!errorTip\">\n {{ errorTip }}\n </span>\n </transition>\n </section>\n </section>\n </u-grid-item>\n</template>\n\n<script lang=\"tsx\" setup>\nimport { o } from '@cat-kit/core'\nimport { useConfig, useFallbackProps } from '@veltra/compositions'\nimport { bem, withUnit } from '@veltra/utils'\nimport { injectFormContext } from '@veltra/utils'\nimport { type CSSProperties, computed, onBeforeUnmount, shallowRef, watch } from 'vue'\n\nimport type { FormItemProps, ComponentSize } from '../../types'\nimport { UGridItem } from '../grid'\nimport { UTip } from '../tip'\nimport { formItemCls as cls, defineField } from './helper'\nimport { validateField } from './validate'\n\ndefineOptions({ name: 'UFormItem' })\n\nconst props = withDefaults(defineProps<FormItemProps>(), { readonly: undefined })\n\ndefineSlots<{\n /** 标签插槽 */\n label?: () => any\n default?: () => any\n}>()\n\n/** 表单组件上下文 */\nconst { formProps, registerField, unregisterField, shouldValidate, handleFieldChange } =\n injectFormContext()\n\nconst { config } = useConfig()\n\nconst { size, readonly } = useFallbackProps([formProps ?? {}, props], {\n size: 'default' as ComponentSize,\n readonly: false\n})\n\nconst errorTip = shallowRef<string>()\n/** 递增序号,丢弃过期的异步校验结果 */\nlet validateSeq = 0\n/** 最近一次 validate 的 Promise,供过期调用等待最新结果 */\nlet latestValidatePromise: Promise<boolean> = Promise.resolve(true)\n\nconst labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')\n\nconst className = computed(() => {\n return [\n cls.b,\n cls.m(size.value),\n bem.is('error', !!errorTip.value),\n bem.is('label-top', labelPosition.value === 'top')\n ].join(' ')\n})\n\n/** label样式 */\nconst labelStyles = computed<CSSProperties>(() => {\n if (labelPosition.value === 'top') return {}\n return {\n width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')\n }\n})\n\nconst fieldItem = defineField({\n clearValidate() {\n errorTip.value = ''\n },\n async validate() {\n if (!props.field || !formProps?.model || !props.rules || !shouldValidate?.()) return true\n\n const seq = ++validateSeq\n\n latestValidatePromise = validateField(formProps.model!, props.field!, props.rules!).then(\n (tip) => {\n if (seq !== validateSeq) return latestValidatePromise\n\n errorTip.value = tip\n return !errorTip.value\n }\n )\n return latestValidatePromise\n }\n})\n\nwatch(\n () => props.field,\n (field, oldField) => {\n if (oldField) {\n unregisterField?.(oldField)\n }\n if (field) {\n registerField?.(field, fieldItem)\n }\n },\n { immediate: true }\n)\n\nlet stopWatchFieldValue: (() => void) | undefined\n\nwatch(\n [() => formProps?.model, () => props.field],\n ([model, field]) => {\n stopWatchFieldValue?.()\n\n if (!field || !model) return\n\n stopWatchFieldValue = watch(\n () => o(model).get(field),\n (value) => {\n handleFieldChange?.(field, value)\n fieldItem.validate()\n }\n )\n },\n { immediate: true }\n)\n\nonBeforeUnmount(() => {\n props.field && unregisterField?.(props.field)\n})\n</script>\n"],"mappings":"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"}
@@ -121,6 +121,19 @@
121
121
  border-bottom: 1px dashed var(--u-color-info);
122
122
  color: var(--u-color-info);
123
123
  }
124
+ .u-form-item.is-label-top {
125
+ display: flex;
126
+ flex-direction: column;
127
+ align-items: stretch;
128
+ width: 100%;
129
+ }
130
+ .u-form-item.is-label-top .u-form-item__label {
131
+ min-height: auto;
132
+ padding-right: 0;
133
+ padding-bottom: 4px;
134
+ text-align: left;
135
+ justify-content: flex-start;
136
+ }
124
137
 
125
138
  .form-item-tips-enter-from,
126
139
  .form-item-tips-leave-to {
@@ -6,11 +6,11 @@ type __VLS_Slots = {
6
6
  tip?: (scope: StepsSlotScope) => any;
7
7
  };
8
8
  declare const __VLS_base: import("vue").DefineComponent<StepsProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
9
- "item-click": (item: Record<string, any>, index: number) => any;
10
9
  "update:current": (value?: string | number | undefined) => any;
10
+ "item-click": (item: Record<string, any>, index: number) => any;
11
11
  }, string, import("vue").PublicProps, Readonly<StepsProps> & Readonly<{
12
- "onItem-click"?: ((item: Record<string, any>, index: number) => any) | undefined;
13
12
  "onUpdate:current"?: ((value?: string | number | undefined) => any) | undefined;
13
+ "onItem-click"?: ((item: Record<string, any>, index: number) => any) | undefined;
14
14
  }>, {
15
15
  labelKey: string;
16
16
  direction: "horizontal" | "vertical";
@@ -5,6 +5,8 @@ import { FormComponentProps } from "@veltra/utils";
5
5
  interface FormItemProps extends FormComponentProps {
6
6
  /** 标签宽度 */
7
7
  labelWidth?: string | number;
8
+ /** 标签位置 */
9
+ labelPosition?: 'top' | 'left';
8
10
  }
9
11
  /** 组件项组件定义的事件 */
10
12
  interface FormItemEmits {}
@@ -13,6 +13,8 @@ interface FormProps extends ComponentProps {
13
13
  model?: Record<string, any>;
14
14
  /** 表单项label宽度 */
15
15
  labelWidth?: string | number;
16
+ /** 表单项 label 位置 */
17
+ labelPosition?: 'top' | 'left';
16
18
  /** 是否不显示tips */
17
19
  noTips?: boolean;
18
20
  /** 是否只读 */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@veltra/desktop",
3
- "version": "1.2.19",
3
+ "version": "1.2.20",
4
4
  "files": [
5
5
  "dist",
6
6
  "src"
@@ -57,11 +57,11 @@
57
57
  "@cat-kit/core": ">=1.1.8",
58
58
  "@cat-kit/excel": ">=1.0.0",
59
59
  "@cat-kit/fe": "^1.1.8",
60
- "@veltra/compositions": "1.2.19",
61
- "@veltra/directives": "1.2.19",
62
- "@veltra/icons": "1.2.19",
63
- "@veltra/styles": "1.2.19",
64
- "@veltra/utils": "1.2.19",
60
+ "@veltra/compositions": "1.2.20",
61
+ "@veltra/directives": "1.2.20",
62
+ "@veltra/icons": "1.2.20",
63
+ "@veltra/styles": "1.2.20",
64
+ "@veltra/utils": "1.2.20",
65
65
  "vue": ">=3.5.39"
66
66
  },
67
67
  "devDependencies": {
@@ -72,12 +72,20 @@ let validateSeq = 0
72
72
  /** 最近一次 validate 的 Promise,供过期调用等待最新结果 */
73
73
  let latestValidatePromise: Promise<boolean> = Promise.resolve(true)
74
74
 
75
+ const labelPosition = computed(() => props.labelPosition ?? formProps?.labelPosition ?? 'left')
76
+
75
77
  const className = computed(() => {
76
- return [cls.b, cls.m(size.value), bem.is('error', !!errorTip.value)].join(' ')
78
+ return [
79
+ cls.b,
80
+ cls.m(size.value),
81
+ bem.is('error', !!errorTip.value),
82
+ bem.is('label-top', labelPosition.value === 'top')
83
+ ].join(' ')
77
84
  })
78
85
 
79
86
  /** label样式 */
80
87
  const labelStyles = computed<CSSProperties>(() => {
88
+ if (labelPosition.value === 'top') return {}
81
89
  return {
82
90
  width: withUnit(props.labelWidth ?? formProps?.labelWidth ?? config.form.labelWidth, 'px')
83
91
  }
@@ -97,6 +97,21 @@ $root-name: form-item;
97
97
  border-bottom: 1px dashed fn.use-var(color, info);
98
98
  color: fn.use-var(color, info);
99
99
  }
100
+
101
+ @include m.is(label-top) {
102
+ display: flex;
103
+ flex-direction: column;
104
+ align-items: stretch;
105
+ width: 100%;
106
+
107
+ @include m.bem($root-name, label) {
108
+ min-height: auto;
109
+ padding-right: 0;
110
+ padding-bottom: 4px;
111
+ text-align: left;
112
+ justify-content: flex-start;
113
+ }
114
+ }
100
115
  }
101
116
 
102
117
  .#{$root-name}-tips-enter-from,
@@ -4,6 +4,8 @@ import type { FormComponentProps } from '@veltra/utils'
4
4
  export interface FormItemProps extends FormComponentProps {
5
5
  /** 标签宽度 */
6
6
  labelWidth?: string | number
7
+ /** 标签位置 */
8
+ labelPosition?: 'top' | 'left'
7
9
  }
8
10
 
9
11
  /** 组件项组件定义的事件 */
package/src/types/form.ts CHANGED
@@ -13,6 +13,8 @@ export interface FormProps extends ComponentProps {
13
13
  // showModified?: boolean
14
14
  /** 表单项label宽度 */
15
15
  labelWidth?: string | number
16
+ /** 表单项 label 位置 */
17
+ labelPosition?: 'top' | 'left'
16
18
  /** 是否不显示tips */
17
19
  noTips?: boolean
18
20
  /** 是否只读 */