@qin-ui/vant-pro 1.0.4 → 1.1.0

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.
Files changed (88) hide show
  1. package/AI-CONTEXT.md +165 -23
  2. package/LICENSE +9 -0
  3. package/README.md +1 -1
  4. package/api.json +27 -22
  5. package/bin/init-ai.mjs +242 -52
  6. package/es/component-provider/{index-DC_k4_R3.js → index-cldbPMDQ.js} +5 -4
  7. package/es/component-provider/index-cldbPMDQ.js.map +1 -0
  8. package/es/component-provider/index.js +2 -1
  9. package/es/component-provider/index.js.map +1 -0
  10. package/es/components/component-provider/components/index.vue.d.ts +27 -0
  11. package/es/components/component-provider/components/index.vue.d.ts.map +1 -0
  12. package/es/components/component-provider/constants/index.d.ts +16 -0
  13. package/es/components/component-provider/constants/index.d.ts.map +1 -0
  14. package/es/components/component-provider/index.d.ts +4 -0
  15. package/es/components/component-provider/index.d.ts.map +1 -0
  16. package/es/components/component-provider/types/index.d.ts +16 -0
  17. package/es/components/component-provider/types/index.d.ts.map +1 -0
  18. package/es/components/form/components/BaseField/index.vue.d.ts +1323 -0
  19. package/es/components/form/components/BaseField/index.vue.d.ts.map +1 -0
  20. package/es/components/form/components/BaseField/utils/index.d.ts +3 -0
  21. package/es/components/form/components/BaseField/utils/index.d.ts.map +1 -0
  22. package/es/components/form/components/BaseFormItem/index.vue.d.ts +7 -0
  23. package/es/components/form/components/BaseFormItem/index.vue.d.ts.map +1 -0
  24. package/es/components/form/components/ContainerFragment/index.vue.d.ts +23 -0
  25. package/es/components/form/components/ContainerFragment/index.vue.d.ts.map +1 -0
  26. package/es/components/form/components/GroupedFieldAttrs/index.vue.d.ts +24 -0
  27. package/es/components/form/components/GroupedFieldAttrs/index.vue.d.ts.map +1 -0
  28. package/es/components/form/components/PathProvider/index.vue.d.ts +23 -0
  29. package/es/components/form/components/PathProvider/index.vue.d.ts.map +1 -0
  30. package/es/components/form/components/ProForm/index.vue.d.ts +34 -0
  31. package/es/components/form/components/ProForm/index.vue.d.ts.map +1 -0
  32. package/es/components/form/components/SlotComponent/index.vue.d.ts +7 -0
  33. package/es/components/form/components/SlotComponent/index.vue.d.ts.map +1 -0
  34. package/es/components/form/components/index.d.ts +12 -0
  35. package/es/components/form/components/index.d.ts.map +1 -0
  36. package/es/components/form/constants/index.d.ts +62 -0
  37. package/es/components/form/constants/index.d.ts.map +1 -0
  38. package/es/components/form/hooks/index.d.ts +6 -0
  39. package/es/components/form/hooks/index.d.ts.map +1 -0
  40. package/es/components/form/hooks/useFields.d.ts +57 -0
  41. package/es/components/form/hooks/useFields.d.ts.map +1 -0
  42. package/es/components/form/hooks/useForm.d.ts +101 -0
  43. package/es/components/form/hooks/useForm.d.ts.map +1 -0
  44. package/es/components/form/hooks/useFormPopup.d.ts +57 -0
  45. package/es/components/form/hooks/useFormPopup.d.ts.map +1 -0
  46. package/es/components/form/hooks/useFormRef.d.ts +30 -0
  47. package/es/components/form/hooks/useFormRef.d.ts.map +1 -0
  48. package/es/components/form/index.d.ts +7 -0
  49. package/es/components/form/index.d.ts.map +1 -0
  50. package/es/components/form/types/index.d.ts +152 -0
  51. package/es/components/form/types/index.d.ts.map +1 -0
  52. package/es/form/index.js +11 -7
  53. package/es/form/index.js.map +1 -0
  54. package/es/index.d.ts +58 -954
  55. package/es/index.d.ts.map +1 -0
  56. package/es/index.js +10 -21
  57. package/es/index.js.map +1 -0
  58. package/es/shared/core/index.d.ts +6 -0
  59. package/es/shared/core/index.d.ts.map +1 -0
  60. package/es/shared/ui/index.d.ts +2 -0
  61. package/es/shared/ui/index.d.ts.map +1 -0
  62. package/package.json +11 -12
  63. package/src/components/component-provider/components/index.vue +67 -0
  64. package/src/components/component-provider/constants/index.ts +110 -0
  65. package/src/components/component-provider/index.ts +6 -0
  66. package/src/components/component-provider/types/index.ts +31 -0
  67. package/src/components/form/components/BaseField/index.vue +340 -0
  68. package/src/components/form/components/BaseField/utils/index.ts +14 -0
  69. package/src/components/form/components/BaseFormItem/index.vue +77 -0
  70. package/src/components/form/components/ContainerFragment/index.vue +24 -0
  71. package/src/components/form/components/GroupedFieldAttrs/index.vue +51 -0
  72. package/src/components/form/components/PathProvider/index.vue +18 -0
  73. package/src/components/form/components/ProForm/index.vue +114 -0
  74. package/src/components/form/components/SlotComponent/index.vue +26 -0
  75. package/src/components/form/components/index.ts +15 -0
  76. package/src/components/form/constants/index.ts +109 -0
  77. package/src/components/form/hooks/index.ts +6 -0
  78. package/src/components/form/hooks/useFields.ts +67 -0
  79. package/src/components/form/hooks/useForm.ts +126 -0
  80. package/src/components/form/hooks/useFormPopup.ts +111 -0
  81. package/src/components/form/hooks/useFormRef.ts +35 -0
  82. package/src/components/form/index.ts +27 -0
  83. package/src/components/form/types/index.ts +220 -0
  84. package/src/index.ts +62 -0
  85. package/src/shared/core/index.ts +37 -0
  86. package/src/shared/ui/index.ts +26 -0
  87. package/es/core/index-B5vvm4Fj.js +0 -236
  88. package/es/vendor/utils/lodash-es-DN4QDiDm.js +0 -1079
@@ -0,0 +1,109 @@
1
+ import {
2
+ Field,
3
+ Button,
4
+ Picker,
5
+ DatePicker,
6
+ TimePicker,
7
+ Cascader,
8
+ Area,
9
+ Signature,
10
+ Switch,
11
+ Stepper,
12
+ Rate,
13
+ Slider,
14
+ Uploader,
15
+ CheckboxGroup,
16
+ RadioGroup,
17
+ } from '../../../shared/ui';
18
+
19
+ /**
20
+ * 内置组件映射表
21
+ * @description Vant 内置支持的组件类型映射
22
+ */
23
+ export type BaseComponentMap = {
24
+ field: typeof Field;
25
+ switch: typeof Switch;
26
+ stepper: typeof Stepper;
27
+ rate: typeof Rate;
28
+ slider: typeof Slider;
29
+ uploader: typeof Uploader;
30
+ 'checkbox-group': typeof CheckboxGroup;
31
+ 'radio-group': typeof RadioGroup;
32
+ picker: typeof Picker;
33
+ 'date-picker': typeof DatePicker;
34
+ 'time-picker': typeof TimePicker;
35
+ cascader: typeof Cascader;
36
+ area: typeof Area;
37
+ signature: typeof Signature;
38
+ button: typeof Button;
39
+ };
40
+
41
+ /**
42
+ * 组件映射扩展接口
43
+ * @description 通过 TypeScript 声明合并添加自定义组件
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * declare module '@qin-ui/vant-pro' {
48
+ * interface ComponentMap {
49
+ * 'my-custom': typeof MyComponent;
50
+ * }
51
+ * }
52
+ * ```
53
+
54
+ * @public
55
+ */
56
+ // eslint-disable-next-line @typescript-eslint/no-empty-object-type
57
+ export interface ComponentMap {}
58
+
59
+ /**
60
+ * 组件名称联合类型
61
+ * @description 所有支持的组件名称
62
+
63
+ * @public
64
+ */
65
+ export type ComponentName =
66
+ | keyof BaseComponentMap
67
+ | keyof ComponentMap
68
+ | 'custom';
69
+
70
+ /**
71
+ * 根据组件名获取组件类型
72
+ * @template K - 组件名称
73
+ */
74
+ export type GetComponentType<K extends ComponentName> =
75
+ K extends keyof ComponentMap
76
+ ? ComponentMap[K]
77
+ : K extends keyof BaseComponentMap
78
+ ? BaseComponentMap[K]
79
+ : never;
80
+
81
+ /**
82
+ * 组件名称到 Vant 组件的映射
83
+ */
84
+ export const componentMap: BaseComponentMap = {
85
+ field: Field,
86
+ switch: Switch,
87
+ stepper: Stepper,
88
+ rate: Rate,
89
+ slider: Slider,
90
+ uploader: Uploader,
91
+ 'checkbox-group': CheckboxGroup,
92
+ 'radio-group': RadioGroup,
93
+ picker: Picker,
94
+ 'date-picker': DatePicker,
95
+ 'time-picker': TimePicker,
96
+ cascader: Cascader,
97
+ area: Area,
98
+ signature: Signature,
99
+ button: Button,
100
+ };
101
+
102
+ /**
103
+ * Teleport 组件名称前缀
104
+ * @description 用于通过插槽动态替换指定 path 的组件
105
+ */
106
+ export const TeleportComponentNamePrefix = 'TeleportComponent_';
107
+
108
+ // inject keys
109
+ export { InjectionFormKey, InjectionPathKey } from '../../../shared/core';
@@ -0,0 +1,6 @@
1
+ export * from './useForm';
2
+ export * from './useFields';
3
+ export * from './useFormRef';
4
+ export * from './useFormPopup';
5
+
6
+ export { useFormData } from '../../../shared/core';
@@ -0,0 +1,67 @@
1
+ import { FieldInstance } from '../../../shared/ui';
2
+ import {
3
+ useFields as coreUseFields,
4
+ type UseFieldsReturn,
5
+ } from '../../../shared/core';
6
+ import type { Data } from '../../../shared/core';
7
+ import type { Field, Fields } from '../types';
8
+ import type { ComponentName } from '../constants';
9
+
10
+ /**
11
+ * 字段配置管理 Hook
12
+ *
13
+ * @description 基于 `@qin-ui/pro-components-core` 的 `useFields`,将泛型参数绑定为 Vant 的本地类型:
14
+ * - 字段类型 F -> `Field<ComponentName, D>`(支持 Vant 组件类型推导)
15
+ * - Field 实例 -> Vant 的 `FieldInstance`
16
+ *
17
+ * 提供对字段配置数组的增删改查操作,支持:
18
+ * - 通过路径字符串或查找函数定位字段
19
+ * - 深层嵌套字段的遍历和匹配
20
+ * - 字段配置的合并/覆盖更新
21
+ * - 字段的添加、插入、删除
22
+ * - 父级字段查找
23
+ *
24
+ * @template D - 表单数据类型
25
+ * @param {Fields<D>} [initFields] - 初始字段配置数组
26
+ *
27
+ * @returns 字段操作对象,包含以下属性:
28
+ * - `fields` - 字段配置数组(响应式 Ref\<F[]\>)
29
+ * - `getField(path)` - 获取字段配置,支持路径字符串或查找函数
30
+ * - `setField(path, field, options?)` - 更新字段配置,默认合并模式
31
+ * - `deleteField(path, options?)` - 删除字段配置
32
+ * - `appendField(path, field, options?)` - 在指定字段后追加
33
+ * - `prependField(path, field, options?)` - 在指定字段前插入
34
+ * - `getParentField(path, options?)` - 获取父级字段配置
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * interface User { name: string; age: number }
39
+ *
40
+ * const { fields, getField, setField } = useFields<User>([
41
+ * { path: 'name', label: '姓名', component: 'field' },
42
+ * { path: 'age', label: '年龄', component: 'stepper' },
43
+ * ])
44
+ *
45
+ * // 通过路径获取
46
+ * getField('name')
47
+ * // 通过查找函数获取
48
+ * getField(f => f.label === '姓名')
49
+ * // 更新字段(合并模式)
50
+ * setField('name', { label: '用户名', disabled: true })
51
+ * ```
52
+ *
53
+ * @see {@link coreUseFields} 底层核心实现(来自 @qin-ui/pro-components-core)
54
+ *
55
+ * @public
56
+ */
57
+ export function useFields<D extends Data = Data>(
58
+ initFields?: Fields<D>
59
+ ): UseFieldsReturn<D, Field<ComponentName, D>, FieldInstance>;
60
+ export function useFields(initFields?: any) {
61
+ return coreUseFields(initFields);
62
+ }
63
+
64
+ /** useFields 返回值类型
65
+ * @public
66
+ */
67
+ export type UseFields<D extends Data = Data> = ReturnType<typeof useFields<D>>;
@@ -0,0 +1,126 @@
1
+ import {
2
+ useForm as coreUseForm,
3
+ type Form as _Form,
4
+ } from '../../../shared/core';
5
+ import type { Data, ExtendWithAny, DeepPartial } from '../../../shared/core';
6
+ import type { Field } from '../types';
7
+ import type { ComponentName } from '../constants';
8
+ import type { FormInstance } from '../../../shared/ui';
9
+ import { useFormPopup, type FormPopup } from './useFormPopup';
10
+
11
+ /**
12
+ * 表单实例类型
13
+ *
14
+ * @description 在 core Form 类型的基础上,将字段类型 F 绑定为本地 Field<ComponentName, D>,
15
+ * 将底层表单实例 I 绑定为 Vant 的 FormInstance,使 formRef 获得完整的类型提示。
16
+ * 额外包含 formPopup 对象,用于管理弹出层表单。
17
+ *
18
+ * @template D - 表单数据类型
19
+ * @template F - 字段配置类型,默认使用本地 Field 类型
20
+ *
21
+ * @property formData - 响应式表单数据对象,可直接读写,支持深层路径如 `formData.address.city`
22
+ * @property getFormData - 获取指定路径的表单数据,支持点号分隔的深层路径,如 `getFormData('address.city')`
23
+ * @property setFormData - 设置表单数据,支持三种调用方式:<br>
24
+ * 1. `setFormData(path, value)` - 设置指定路径的值<br>
25
+ * 2. `setFormData(path, prev => newVal)` - 函数式更新<br>
26
+ * 3. `setFormData({ ... })` - 批量覆盖整个表单
27
+ * @property fields - 字段配置数组(响应式 Ref),ProForm 根据此数组渲染表单字段
28
+ * @property getField - 获取字段配置,支持路径字符串(如 `'name'`)或查找函数(如 `f => f.label === '姓名'`)
29
+ * @property setField - 更新字段配置,默认合并模式(Object.assign),可通过 `{ updateType: 'rewrite' }` 覆盖
30
+ * @property deleteField - 删除字段配置,支持 `{ all: true }` 批量删除所有匹配项
31
+ * @property appendField - 在指定字段后追加新字段,传 `undefined` 则在末尾追加
32
+ * @property prependField - 在指定字段前插入新字段,传 `undefined` 则在开头插入
33
+ * @property getParentField - 获取指定字段的父级字段配置,用于嵌套字段场景
34
+ * @property formRef - 底层 Vant Form 组件实例的响应式引用(Ref),可调用 `validate()`、`resetValidation()` 等方法
35
+ * @property setFormRef - 设置底层 Form 组件实例,由 ProForm 内部自动调用,一般无需手动使用
36
+ * @property formPopup - 弹出层表单管理对象,提供 `open(path)`、`close()` 等方法,用于移动端弹窗表单
37
+ *
38
+ * @example
39
+ * ```ts
40
+ * interface User { name: string; age: number }
41
+ * const form: Form<User> = useForm({ name: '张三', age: 25 })
42
+ *
43
+ * form.formData.name // 直接读写响应式数据
44
+ * form.getFormData('name') // 通过路径读取
45
+ * form.setFormData('name', '李四') // 更新数据
46
+ * form.formRef.value?.validate() // 访问底层 Form 实例
47
+ * form.formPopup.open('address') // 打开弹出层表单
48
+ * ```
49
+ *
50
+ * @public
51
+ */
52
+ export type Form<
53
+ D extends Data = Data,
54
+ F extends Field<ComponentName, D> = Field<ComponentName, D>,
55
+ > = _Form<D, F, FormInstance> & { formPopup: FormPopup };
56
+
57
+ /**
58
+ * 创建表单实例的 Hook
59
+ *
60
+ * @description 基于 `@qin-ui/pro-components-core` 的 `useForm`,将泛型参数绑定为 Vant 的本地类型:
61
+ * - 字段类型 F -> `Field<ComponentName, D>`(支持 Vant 组件类型推导)
62
+ * - 表单实例 -> Vant 的 `FormInstance`(使 formRef 获得完整的类型提示)
63
+ *
64
+ * 在 core useForm 基础上额外提供 formPopup,用于移动端弹窗表单场景。
65
+ *
66
+ * 表单实例组合了四个子模块的能力:
67
+ * - **useFormData**:表单数据管理(响应式数据、读写、批量更新)
68
+ * - **useFields**:字段配置管理(增删改查字段配置,支持嵌套)
69
+ * - **useFormRef**:底层 Form 组件实例引用
70
+ * - **useFormPopup**:弹出层表单管理(Vant 专属)
71
+ *
72
+ * @template D - 表单数据类型
73
+ *
74
+ * @param {ExtendWithAny<DeepPartial<D>>} [initFormData] - 初始表单数据
75
+ * @param {Field<ComponentName, D>[]} [initFields] - 初始字段配置数组
76
+ * @param {boolean} [root=true] - 是否为根表单。设为 `false` 时尝试从父组件注入获取表单实例
77
+ *
78
+ * @returns {Form<D>} 表单实例,包含数据操作、字段操作、ref 操作和弹出层管理
79
+ *
80
+ * @example
81
+ * ```ts
82
+ * interface User { name: string; age: number }
83
+ *
84
+ * // 方式一:同时传入初始数据和字段
85
+ * const form = useForm<User>(
86
+ * { name: '张三', age: 25 },
87
+ * [
88
+ * { path: 'name', label: '姓名', component: 'field' },
89
+ * ],
90
+ * true
91
+ * )
92
+ *
93
+ * // 方式二:仅设置 root 标识
94
+ * const form = useForm<User>(true)
95
+ *
96
+ * // 使用
97
+ * const { formData, formRef, fields, setFormData, formPopup } = form
98
+ * setFormData('name', '李四')
99
+ * formPopup.open('address') // 打开弹出层表单
100
+ * ```
101
+ *
102
+ * @see {@link coreUseForm} 底层核心实现(来自 @qin-ui/pro-components-core)
103
+ *
104
+ * @public
105
+ */
106
+ export function useForm<D extends Data = Data>(
107
+ initFormData?: ExtendWithAny<DeepPartial<D>>,
108
+ initFields?: Field<ComponentName, D>[],
109
+ root?: boolean
110
+ ): Form<D, Field<ComponentName, D>>;
111
+ export function useForm<D extends Data = Data>(
112
+ root?: boolean
113
+ ): Form<D, Field<ComponentName, D>>;
114
+ export function useForm(...args: any[]) {
115
+ let root = true;
116
+ if (args.length === 1) {
117
+ root = args[0] as boolean;
118
+ } else if (args.length >= 2) {
119
+ root = (args[2] as boolean) ?? root;
120
+ }
121
+
122
+ const form = coreUseForm(...args);
123
+ const formPopup = useFormPopup(root);
124
+
125
+ return { ...form, formPopup };
126
+ }
@@ -0,0 +1,111 @@
1
+ import {
2
+ computed,
3
+ ComputedRef,
4
+ inject,
5
+ provide,
6
+ reactive,
7
+ Ref,
8
+ ref,
9
+ } from 'vue';
10
+ import { Popup } from '../../../shared/ui';
11
+ import { ComponentProps } from 'vue-component-type-helpers';
12
+ import { ContainerComponent } from '../types';
13
+
14
+ /**
15
+ * Vant Popup 组件属性类型
16
+ * @description 用于配置表单弹出层的属性
17
+
18
+ * @public
19
+ */
20
+ export type PopupProps = ComponentProps<typeof Popup> & {
21
+ container: ContainerComponent;
22
+ };
23
+
24
+ /**
25
+ * 表单弹出层管理对象
26
+ * @description Vant 移动端特有的表单弹出层功能
27
+
28
+ * @public
29
+ */
30
+ export type FormPopup = {
31
+ /** Popup 组件属性 */
32
+ props: PopupProps;
33
+ /** 打开指定路径字段的弹出层 */
34
+ open: (path: string) => void;
35
+ /** 关闭弹出层 */
36
+ close: () => void;
37
+ /** 更新 Popup 组件属性 */
38
+ updateProps: (props: Partial<PopupProps>) => void;
39
+ /** 弹出层是否可见 */
40
+ visible: ComputedRef<boolean>;
41
+ /** 当前弹出层对应的字段路径 */
42
+ popupFieldPath: Ref<string | undefined>;
43
+ /** 当前弹出层字段的值 */
44
+ popupFieldValue: Ref<any | undefined>;
45
+ };
46
+
47
+ /** 弹出层注入 key */
48
+ export const InjectionPopupKey = Symbol('form-popup');
49
+
50
+ /**
51
+ * @qin-ui/vant-pro 表单弹出层管理 Hook
52
+ *
53
+ * @description 用于管理 Vant 移动端的表单弹出层(Popup)。
54
+ * 在移动端表单中,某些字段(如地址选择、日期选择)需要以弹出层形式展示。
55
+ *
56
+ * @returns {FormPopup} 弹出层管理对象
57
+ *
58
+ * @example
59
+ * ```ts
60
+ * const formPopup = useFormPopup(true)
61
+ * formPopup.open('address') // 打开地址选择弹出层
62
+ * formPopup.close() // 关闭
63
+ * formPopup.updateProps({ position: 'top' })
64
+ * ```
65
+
66
+ * @public
67
+ */
68
+ export function useFormPopup(root?: boolean): FormPopup;
69
+
70
+ export function useFormPopup(initRoot?: boolean) {
71
+ if (!initRoot) {
72
+ const injectStore = inject(InjectionPopupKey, undefined);
73
+ if (injectStore) return injectStore as never;
74
+ }
75
+
76
+ const props = reactive<Partial<PopupProps>>({
77
+ safeAreaInsetBottom: true,
78
+ position: 'bottom',
79
+ round: true,
80
+ });
81
+
82
+ const popupFieldPath = ref<string>();
83
+ const popupFieldValue = ref();
84
+
85
+ function open(path: string) {
86
+ popupFieldPath.value = path;
87
+ }
88
+
89
+ function close() {
90
+ popupFieldPath.value = undefined;
91
+ popupFieldValue.value = undefined;
92
+ }
93
+
94
+ const visible = computed(() => !!popupFieldPath.value);
95
+
96
+ function updateProps(_props: Partial<PopupProps>) {
97
+ Object.assign(props, _props);
98
+ }
99
+
100
+ const store = {
101
+ props,
102
+ open,
103
+ close,
104
+ updateProps,
105
+ visible,
106
+ popupFieldPath,
107
+ popupFieldValue,
108
+ };
109
+ provide(InjectionPopupKey, store);
110
+ return store;
111
+ }
@@ -0,0 +1,35 @@
1
+ import {
2
+ useFormRef as coreUseFormRef,
3
+ type UseFormRefReturn,
4
+ } from '../../../shared/core';
5
+ import type { FormInstance } from '../../../shared/ui';
6
+
7
+ /**
8
+ * 表单组件实例引用 Hook
9
+ *
10
+ * @description 基于 `@qin-ui/pro-components-core` 的 `useFormRef`,将泛型参数绑定为 Vant 的 `FormInstance`,
11
+ * 使 formRef 获取到完整的 Vant Form 组件 API 类型提示(如 `validate()`、`resetValidation()` 等)。
12
+ *
13
+ * `formRef` 由 ProForm 组件内部自动通过 `setFormRef` 绑定,无需手动调用。
14
+ *
15
+ * @returns 表单组件实例引用管理对象:
16
+ * - `formRef` — Vant Form 组件实例的响应式引用(`Ref<FormInstance | undefined>`)
17
+ * - `setFormRef(inst)` — 设置 Form 组件实例,由 ProForm 内部自动调用
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * const { formRef, setFormRef } = useFormRef()
22
+ *
23
+ * // formRef 由 ProForm 自动绑定,可直接使用
24
+ * await formRef.value?.validate()
25
+ * formRef.value?.resetValidation()
26
+ * formRef.value?.scrollToField('username')
27
+ * ```
28
+ *
29
+ * @see {@link coreUseFormRef} 底层核心实现(来自 @qin-ui/pro-components-core)
30
+ *
31
+ * @public
32
+ */
33
+ export function useFormRef(): UseFormRefReturn<FormInstance> {
34
+ return coreUseFormRef();
35
+ }
@@ -0,0 +1,27 @@
1
+ import ProForm from './components/ProForm/index.vue';
2
+
3
+ // 1. 仅导出核心 Vue 组件包装及外部可重用组件与类型
4
+ export {
5
+ ContainerFragment,
6
+ SlotComponent,
7
+ type ProFormProps,
8
+ type ProFormInstance,
9
+ } from './components';
10
+
11
+ // 2. 仅导出允许模块合并扩展的 ComponentMap 以及组件名类型
12
+ export { type ComponentMap, type ComponentName } from './constants';
13
+
14
+ // 3. 仅导出核心表单配置 Schema 类型
15
+ export { type Field, type Fields } from './types';
16
+
17
+ // 4. 仅导出核心业务 Hooks
18
+ export {
19
+ useForm,
20
+ useFields,
21
+ useFormRef,
22
+ useFormData,
23
+ type Form,
24
+ type UseFields,
25
+ } from './hooks';
26
+
27
+ export default ProForm;
@@ -0,0 +1,220 @@
1
+ import { type FormInstance, type FieldProps } from '../../../shared/ui';
2
+ import type {
3
+ ComponentProps,
4
+ ComponentSlots,
5
+ } from 'vue-component-type-helpers';
6
+ import {
7
+ type CSSProperties,
8
+ type Component,
9
+ type Raw,
10
+ type MaybeRef,
11
+ type ComputedRef,
12
+ VNodeProps,
13
+ DefineComponent,
14
+ VNodeTypes,
15
+ VNode,
16
+ } from 'vue';
17
+ import { ComponentName, GetComponentType } from '../constants';
18
+ import type { Data, Path } from '../../../shared/core';
19
+ import { PopupProps } from '../hooks/useFormPopup';
20
+
21
+ export type { FormInstance };
22
+
23
+ export type PathProps = { path?: string } & Data;
24
+
25
+ export type VModelProps<T = any> = {
26
+ modelValue?: T;
27
+ 'onUpdate:modelValue'?: (val: T) => void;
28
+ };
29
+
30
+ export type ValueFormatter =
31
+ | { (val: any, oldVal: any): any }
32
+ | { get?: (val: any) => any; set?: (val: any, oldVal: any) => any };
33
+
34
+ export type DisplayFormatter = (val: any) => string;
35
+
36
+ /**
37
+ * @description 自定义组件
38
+ */
39
+ export type RenderComponentType = Component<VModelProps & PathProps>;
40
+
41
+ /**
42
+ * @description 插槽组件类型
43
+ */
44
+ export type SlotComponentType =
45
+ | Component<PathProps>
46
+ | VNode
47
+ | string
48
+ | number
49
+ | boolean
50
+ | null
51
+ | undefined
52
+ | ((...args: any[]) => SlotComponentType);
53
+
54
+ /**
55
+ * @description 容器组件类型
56
+ */
57
+ export type ContainerComponent =
58
+ | Component<PathProps>
59
+ | DefineComponent<PathProps>
60
+ | VNodeTypes
61
+ | symbol;
62
+
63
+ /**
64
+ * @description 插槽对象类型
65
+ */
66
+ export type Slots = {
67
+ [name: string]: SlotComponentType;
68
+ };
69
+
70
+ type BaseCommon<D extends Data = Data> = {
71
+ /**
72
+ * @description 字段标识namePath, 同name
73
+ */
74
+ path?: Path<D>;
75
+ /**
76
+ * @description 字段是否隐藏
77
+ */
78
+ hidden?: boolean;
79
+ /**
80
+ * @description 字段是否禁用
81
+ */
82
+ disabled?: boolean;
83
+ /**
84
+ * @description 字段中文名称,支持字符串或组件
85
+ */
86
+ label?: SlotComponentType;
87
+ /**
88
+ * @description 字段插槽配置
89
+ */
90
+ slots?: Slots;
91
+ /**
92
+ * @description 嵌套 fields 容器包裹组件
93
+ */
94
+ fieldContainer?: ContainerComponent;
95
+ /**
96
+ * @description 额外的自定义属性,不会被当作组件参数
97
+ */
98
+ extraProps?: Record<string, any>;
99
+ };
100
+
101
+ type BaseWithFields<D extends Data = Data> = BaseCommon<D> & {
102
+ /**
103
+ * @description 嵌套子字段配置 (Vant 中主要用于分组,或者通过 CellGroup 包裹)
104
+ */
105
+ fields: Fields<D>;
106
+ component?: never;
107
+ componentStyle?: never;
108
+ componentClass?: never;
109
+ componentContainer?: never;
110
+ fieldStyle?: never;
111
+ fieldClass?: never;
112
+ valueFormatter?: never;
113
+ displayFormatter?: never;
114
+ modelProp?: never;
115
+ popup?: never;
116
+ };
117
+
118
+ type BaseWithoutFields<D extends Data = Data> = BaseCommon<D> & {
119
+ fields?: undefined;
120
+ /**
121
+ * @description 表单字段component样式属性
122
+ */
123
+ componentStyle?: CSSProperties;
124
+ /**
125
+ * @description 表单字段component样式类名
126
+ */
127
+ componentClass?: any;
128
+ /**
129
+ * @description 表单字段外层 van-field 样式属性
130
+ */
131
+ fieldStyle?: CSSProperties;
132
+ /**
133
+ * @description 表单字段外层 van-field 样式类名
134
+ */
135
+ fieldClass?: any;
136
+ /**
137
+ * @description 字段component容器包裹组件
138
+ */
139
+ componentContainer?: ContainerComponent;
140
+ /**
141
+ * @description 字段值处理函数,在onUpdateValue前执行
142
+ */
143
+ valueFormatter?: ValueFormatter;
144
+ /**
145
+ * @description 针对 Popup 展现形式的组件,将选中值转化为输入框展示文字
146
+ */
147
+ displayFormatter?: DisplayFormatter;
148
+ /**
149
+ * @description 组件v-model双向绑定更新属性名
150
+ */
151
+ modelProp?: string;
152
+ /**
153
+ * @description 是否通过 Popup 弹窗展示该组件(为 true 或传递 PopupProps 配置对象时开启)
154
+ */
155
+ popup?: boolean | Partial<PopupProps>;
156
+ };
157
+
158
+ export type Base<D extends Data = Data> =
159
+ | BaseWithFields<D>
160
+ | BaseWithoutFields<D>;
161
+
162
+ /**
163
+ * @type {FieldTypeMap} 字段类型集合
164
+ */
165
+ export type FieldTypeMap<D extends Data = Data> = {
166
+ [K in ComponentName]: K extends 'custom'
167
+ ? WithCommon<{ slots?: Slots; [x: string]: any }, D> & {
168
+ component?: RenderComponentType | Raw<RenderComponentType>;
169
+ }
170
+ : WithComponent<GetComponentType<K>, D> & { component?: K };
171
+ };
172
+
173
+ type NotSupportedRefOrGetterProps =
174
+ | 'component'
175
+ | 'fieldContainer'
176
+ | 'componentContainer'
177
+ | 'valueFormatter'
178
+ | 'displayFormatter'
179
+ | 'fields'
180
+ | 'slots'
181
+ | 'modelProp'
182
+ | 'popup';
183
+
184
+ type MaybeRefOrComputedRef<T = any> = MaybeRef<T> | ComputedRef<T>;
185
+
186
+ export type WithRef<T> = {
187
+ [P in keyof T]: P extends NotSupportedRefOrGetterProps
188
+ ? T[P]
189
+ : T[P] extends (...args: any[]) => any
190
+ ? T[P]
191
+ : MaybeRefOrComputedRef<T[P]>;
192
+ };
193
+
194
+ type WithCommonBase<T = unknown> = T &
195
+ Partial<Omit<FieldProps, 'label' | 'name' | 'type'>>;
196
+
197
+ type WithCommon<T, D extends Data = Data> = WithRef<
198
+ WithCommonBase<T> & BaseWithoutFields<D>
199
+ >;
200
+
201
+ type WithFields<D extends Data = Data> = WithRef<
202
+ WithCommonBase & BaseWithFields<D>
203
+ >;
204
+
205
+ type WithComponent<
206
+ T extends abstract new (...args: any) => any,
207
+ D extends Data = Data,
208
+ > = WithCommon<
209
+ { slots?: Partial<ComponentSlots<T>> } & Partial<
210
+ Omit<ComponentProps<T>, keyof VNodeProps>
211
+ >,
212
+ D
213
+ >;
214
+
215
+ export type Field<
216
+ C extends ComponentName = ComponentName,
217
+ D extends Data = Data,
218
+ > = FieldTypeMap<D>[C] | WithFields<D>;
219
+
220
+ export type Fields<D extends Data = Data> = Array<Field<ComponentName, D>>;