@xiaohaih/json-form-vant 0.0.1

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 (213) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/README.md +807 -0
  3. package/TODO.md +36 -0
  4. package/components/area/index.ts +6 -0
  5. package/components/area/index.vue +120 -0
  6. package/components/area/types.ts +84 -0
  7. package/components/cascader/index.ts +6 -0
  8. package/components/cascader/index.vue +146 -0
  9. package/components/cascader/types.ts +75 -0
  10. package/components/checkbox/index.ts +6 -0
  11. package/components/checkbox/index.vue +59 -0
  12. package/components/checkbox/types.ts +54 -0
  13. package/components/checkbox-group/index.ts +6 -0
  14. package/components/checkbox-group/index.vue +67 -0
  15. package/components/checkbox-group/types.ts +63 -0
  16. package/components/component-definition/components.ts +29 -0
  17. package/components/component-definition/definition.ts +25 -0
  18. package/components/component-definition/index.ts +4 -0
  19. package/components/custom-render/index.ts +6 -0
  20. package/components/custom-render/index.vue +66 -0
  21. package/components/custom-render/types.ts +43 -0
  22. package/components/date-picker/index.ts +6 -0
  23. package/components/date-picker/index.vue +130 -0
  24. package/components/date-picker/types.ts +91 -0
  25. package/components/date-time-picker-group/index.ts +6 -0
  26. package/components/date-time-picker-group/index.vue +158 -0
  27. package/components/date-time-picker-group/types.ts +115 -0
  28. package/components/datetime-picker/index.ts +6 -0
  29. package/components/datetime-picker/index.vue +128 -0
  30. package/components/datetime-picker/types.ts +78 -0
  31. package/components/dynamic-group/index.ts +10 -0
  32. package/components/dynamic-group/index.vue +140 -0
  33. package/components/dynamic-group/types.ts +68 -0
  34. package/components/group/assist.ts +99 -0
  35. package/components/group/index.ts +7 -0
  36. package/components/group/index.vue +117 -0
  37. package/components/group/types.ts +57 -0
  38. package/components/group/virtual-group.vue +38 -0
  39. package/components/index.ts +10 -0
  40. package/components/input/index.ts +6 -0
  41. package/components/input/index.vue +83 -0
  42. package/components/input/types.ts +43 -0
  43. package/components/input-slot/index.ts +6 -0
  44. package/components/input-slot/index.vue +148 -0
  45. package/components/input-slot/types.ts +34 -0
  46. package/components/number-keyboard/index.ts +6 -0
  47. package/components/number-keyboard/index.vue +81 -0
  48. package/components/number-keyboard/types.ts +57 -0
  49. package/components/password-input/index.ts +6 -0
  50. package/components/password-input/index.vue +103 -0
  51. package/components/password-input/types.ts +64 -0
  52. package/components/picker/index.ts +6 -0
  53. package/components/picker/index.vue +136 -0
  54. package/components/picker/types.ts +94 -0
  55. package/components/radio/index.ts +6 -0
  56. package/components/radio/index.vue +68 -0
  57. package/components/radio/types.ts +58 -0
  58. package/components/radio-group/index.ts +6 -0
  59. package/components/radio-group/index.vue +74 -0
  60. package/components/radio-group/types.ts +65 -0
  61. package/components/rate/index.ts +6 -0
  62. package/components/rate/index.vue +63 -0
  63. package/components/rate/types.ts +47 -0
  64. package/components/share.ts +78 -0
  65. package/components/signature/index.ts +6 -0
  66. package/components/signature/index.vue +65 -0
  67. package/components/signature/instance.vue +161 -0
  68. package/components/signature/types.ts +79 -0
  69. package/components/slider/index.ts +6 -0
  70. package/components/slider/index.vue +63 -0
  71. package/components/slider/types.ts +53 -0
  72. package/components/stepper/index.ts +6 -0
  73. package/components/stepper/index.vue +62 -0
  74. package/components/stepper/types.ts +47 -0
  75. package/components/switch/index.ts +6 -0
  76. package/components/switch/index.vue +61 -0
  77. package/components/switch/types.ts +51 -0
  78. package/components/time-picker/index.ts +6 -0
  79. package/components/time-picker/index.vue +130 -0
  80. package/components/time-picker/types.ts +91 -0
  81. package/components/tree-select/index.ts +6 -0
  82. package/components/tree-select/index.vue +160 -0
  83. package/components/tree-select/types.ts +77 -0
  84. package/components/upload/index.ts +6 -0
  85. package/components/upload/index.vue +109 -0
  86. package/components/upload/types.ts +85 -0
  87. package/components/use.ts +45 -0
  88. package/components/utils.ts +52 -0
  89. package/components/wrapper/index.ts +6 -0
  90. package/components/wrapper/index.vue +117 -0
  91. package/components/wrapper/types.ts +94 -0
  92. package/dist/components/area/index.d.ts +5 -0
  93. package/dist/components/area/index.vue.d.ts +1843 -0
  94. package/dist/components/area/types.d.ts +1434 -0
  95. package/dist/components/cascader/index.d.ts +5 -0
  96. package/dist/components/cascader/index.vue.d.ts +2467 -0
  97. package/dist/components/cascader/types.d.ts +1419 -0
  98. package/dist/components/checkbox/index.d.ts +5 -0
  99. package/dist/components/checkbox/index.vue.d.ts +1550 -0
  100. package/dist/components/checkbox/types.d.ts +1313 -0
  101. package/dist/components/checkbox-group/index.d.ts +5 -0
  102. package/dist/components/checkbox-group/index.vue.d.ts +1643 -0
  103. package/dist/components/checkbox-group/types.d.ts +1372 -0
  104. package/dist/components/component-definition/components.d.ts +30 -0
  105. package/dist/components/component-definition/index.d.ts +4 -0
  106. package/dist/components/custom-render/index.d.ts +5 -0
  107. package/dist/components/custom-render/index.vue.d.ts +1473 -0
  108. package/dist/components/custom-render/types.d.ts +1175 -0
  109. package/dist/components/date-picker/index.d.ts +5 -0
  110. package/dist/components/date-picker/index.vue.d.ts +1888 -0
  111. package/dist/components/date-picker/types.d.ts +1458 -0
  112. package/dist/components/date-time-picker-group/index.d.ts +5 -0
  113. package/dist/components/date-time-picker-group/index.vue.d.ts +2181 -0
  114. package/dist/components/date-time-picker-group/types.d.ts +1549 -0
  115. package/dist/components/dynamic-group/index.d.ts +5 -0
  116. package/dist/components/dynamic-group/index.vue.d.ts +457 -0
  117. package/dist/components/dynamic-group/types.d.ts +403 -0
  118. package/dist/components/group/assist.d.ts +58 -0
  119. package/dist/components/group/index.d.ts +6 -0
  120. package/dist/components/group/index.vue.d.ts +139 -0
  121. package/dist/components/group/types.d.ts +189 -0
  122. package/dist/components/group/virtual-group.vue.d.ts +42 -0
  123. package/dist/components/index.d.ts +3 -0
  124. package/dist/components/input/index.d.ts +5 -0
  125. package/dist/components/input/index.vue.d.ts +2229 -0
  126. package/dist/components/input/types.d.ts +1258 -0
  127. package/dist/components/input-slot/index.d.ts +5 -0
  128. package/dist/components/input-slot/index.vue.d.ts +626 -0
  129. package/dist/components/input-slot/types.d.ts +311 -0
  130. package/dist/components/number-keyboard/index.d.ts +5 -0
  131. package/dist/components/number-keyboard/index.vue.d.ts +1643 -0
  132. package/dist/components/number-keyboard/types.d.ts +1324 -0
  133. package/dist/components/password-input/index.d.ts +5 -0
  134. package/dist/components/password-input/index.vue.d.ts +1715 -0
  135. package/dist/components/password-input/types.d.ts +1357 -0
  136. package/dist/components/picker/index.d.ts +5 -0
  137. package/dist/components/picker/index.vue.d.ts +1868 -0
  138. package/dist/components/picker/types.d.ts +1466 -0
  139. package/dist/components/radio/index.d.ts +5 -0
  140. package/dist/components/radio/index.vue.d.ts +1563 -0
  141. package/dist/components/radio/types.d.ts +1327 -0
  142. package/dist/components/radio-group/index.d.ts +5 -0
  143. package/dist/components/radio-group/index.vue.d.ts +1617 -0
  144. package/dist/components/radio-group/types.d.ts +1383 -0
  145. package/dist/components/rate/index.d.ts +5 -0
  146. package/dist/components/rate/index.vue.d.ts +1557 -0
  147. package/dist/components/rate/types.d.ts +1281 -0
  148. package/dist/components/share.d.ts +679 -0
  149. package/dist/components/signature/index.d.ts +5 -0
  150. package/dist/components/signature/index.vue.d.ts +3017 -0
  151. package/dist/components/signature/instance.vue.d.ts +1614 -0
  152. package/dist/components/signature/types.d.ts +1369 -0
  153. package/dist/components/slider/index.d.ts +5 -0
  154. package/dist/components/slider/index.vue.d.ts +1563 -0
  155. package/dist/components/slider/types.d.ts +1302 -0
  156. package/dist/components/stepper/index.d.ts +5 -0
  157. package/dist/components/stepper/index.vue.d.ts +1620 -0
  158. package/dist/components/stepper/types.d.ts +1281 -0
  159. package/dist/components/switch/index.d.ts +5 -0
  160. package/dist/components/switch/index.vue.d.ts +1529 -0
  161. package/dist/components/switch/types.d.ts +1296 -0
  162. package/dist/components/time-picker/index.d.ts +5 -0
  163. package/dist/components/time-picker/index.vue.d.ts +1936 -0
  164. package/dist/components/time-picker/types.d.ts +1458 -0
  165. package/dist/components/tree-select/index.d.ts +5 -0
  166. package/dist/components/tree-select/index.vue.d.ts +1802 -0
  167. package/dist/components/tree-select/types.d.ts +1411 -0
  168. package/dist/components/upload/index.d.ts +5 -0
  169. package/dist/components/upload/index.vue.d.ts +1697 -0
  170. package/dist/components/upload/types.d.ts +1376 -0
  171. package/dist/components/use.d.ts +53 -0
  172. package/dist/components/utils.d.ts +15 -0
  173. package/dist/components/wrapper/index.d.ts +5 -0
  174. package/dist/components/wrapper/index.vue.d.ts +1085 -0
  175. package/dist/components/wrapper/types.d.ts +541 -0
  176. package/dist/docs/.vitepress/config.d.ts +3 -0
  177. package/dist/docs/.vitepress/theme/index.d.ts +2 -0
  178. package/dist/index.cjs.js +5459 -0
  179. package/dist/index.cjs.js.map +1 -0
  180. package/dist/index.cjs.min.js +3568 -0
  181. package/dist/index.cjs.min.js.map +1 -0
  182. package/dist/index.esm.js +5264 -0
  183. package/dist/index.esm.js.map +1 -0
  184. package/dist/index.esm.min.js +3559 -0
  185. package/dist/index.esm.min.js.map +1 -0
  186. package/dist/index.umd.js +5465 -0
  187. package/dist/index.umd.js.map +1 -0
  188. package/dist/index.umd.min.js +3573 -0
  189. package/dist/index.umd.min.js.map +1 -0
  190. package/dist/src/assist.d.ts +32 -0
  191. package/dist/src/index.d.ts +5 -0
  192. package/dist/src/interface.d.ts +129 -0
  193. package/dist/src/utils.d.ts +9 -0
  194. package/dist/src/version.d.ts +2 -0
  195. package/docs/.vitepress/config.ts +99 -0
  196. package/docs/.vitepress/theme/index.ts +5 -0
  197. package/docs/README.md +20 -0
  198. package/docs/index.md +25 -0
  199. package/env.d.ts +8 -0
  200. package/package.json +71 -0
  201. package/scripts/generate-version.mjs +26 -0
  202. package/scripts/postinstall.cjs +13 -0
  203. package/scripts/utils.cjs +67 -0
  204. package/src/assist.ts +40 -0
  205. package/src/index.ts +5 -0
  206. package/src/interface.ts +293 -0
  207. package/src/utils.ts +22 -0
  208. package/src/version.ts +2 -0
  209. package/tsconfig.app.json +41 -0
  210. package/tsconfig.json +7 -0
  211. package/tsconfig.node.json +24 -0
  212. package/tsdown.config.ts +12 -0
  213. package/vite.config.ts +93 -0
@@ -0,0 +1,68 @@
1
+ import type { CamelCase, Obj2Props, PlainProps, usePlain } from '@xiaohaih/json-form-core';
2
+ import { plainProps } from '@xiaohaih/json-form-core';
3
+ import type { Component, ExtractPublicPropTypes, PropType } from 'vue';
4
+ import type { ComponentExposed, ComponentProps } from 'vue-component-type-helpers';
5
+ import type { groupPropsGeneric, GroupSlots } from '../group/index';
6
+ import { groupProps } from '../group/index';
7
+ import type { ComponentType } from '../share';
8
+
9
+ /** 组件传参 - 私有 */
10
+ export function dynamicGroupPropsGeneric<Query extends Record<string, any>, OptionQuery extends Record<string, any>>() {
11
+ return {
12
+ ...plainProps as PlainProps<Query, OptionQuery>,
13
+ /** 当前组件类型(防止被继承, 主动声明) */
14
+ t: { type: String },
15
+ /** 渲染的标签 */
16
+ tag: { type: [Object, String, Array, Function] as PropType<any>, default: 'div' },
17
+ /** 渲染的子条件 */
18
+ config: { type: [Object, Array, Function] as PropType<any> },
19
+ /**
20
+ * 如果是组件是存在于数组中的, 需要传递一个唯一键, 读取当前对象中的某个值
21
+ * 防止依赖本数组其它下标中的值时, 如果前一项被删除, 导致依赖误触发
22
+ * 也是作为循环时唯一 key
23
+ *
24
+ * @example
25
+ * ``` ts
26
+ * // 当表单项根据 query.users 动态生成时, 想保证某些情况下依赖不会产生错误
27
+ * // 可传递 uniqueKey: 'id', 此时依赖判断会以条件项的 user[].id 的值做唯一值判断
28
+ * const query = { users: [{ id: '1', name: '', value: '' }, { id: '2', name: '', value: '' }, ...] }
29
+ * ```
30
+ */
31
+ uniqueKey: { type: String },
32
+ /** 传递给每行表单项 DOM 节点的属性 */
33
+ contentProps: { type: Object as PropType<Partial<Record<'class' | 'style', string | Record<string, any> | any[]>>> },
34
+ /** 传递给组件的插槽 - 重写声明 */
35
+ slots: { type: Object as PropType<DynamicGroupSlots<Query, OptionQuery>> },
36
+ /** 传递给动态渲染组件的插槽 */
37
+ itemSlots: { type: Object as PropType<{
38
+ /** 在动态表单项前渲染 */
39
+ prepend?: ComponentType<{ query: Query; checked: any[]; index: number; plain: ReturnType<typeof usePlain> }>;
40
+ /** 在动态表单项后渲染 */
41
+ append?: ComponentType<{ query: Query; checked: any[]; index: number; plain: ReturnType<typeof usePlain> }>;
42
+ }>, default: () => ({}) },
43
+ } as const;
44
+ }
45
+ /** 组件传参 - 私有 */
46
+ export const dynamicGroupPropsPrivate = dynamicGroupPropsGeneric();
47
+ /** 组件传参 - 外部调用 */
48
+
49
+ export const dynamicGroupProps = dynamicGroupPropsPrivate;
50
+ export type DynamicGroupProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof dynamicGroupPropsGeneric<Query, OptionQuery>>>;
51
+
52
+ /** 组件事件 - 私有 */
53
+ export function dynamicGroupEmitsGeneric<T>() {
54
+ return {
55
+ };
56
+ }
57
+ /** 组件事件 - 私有 */
58
+ export const dynamicGroupEmitsPrivate = dynamicGroupEmitsGeneric();
59
+ /** 组件事件 - 外部调用 */
60
+ export const dynamicGroupEmits = dynamicGroupEmitsPrivate;
61
+ export type DynamicGroupEmits<T> = ReturnType<typeof dynamicGroupEmitsGeneric<T>>;
62
+
63
+ export interface DynamicGroupSlots<Query extends Record<string, any> = any, OptionQuery extends Record<string, any> = any> {
64
+ /** 在表单项前渲染 */
65
+ prepend?: ComponentType<{ query: Query; checked: any[]; plain: ReturnType<typeof usePlain> }>;
66
+ /** 在表单项后渲染 */
67
+ append?: ComponentType<{ query: Query; checked: any[]; plain: ReturnType<typeof usePlain> }>;
68
+ }
@@ -0,0 +1,99 @@
1
+ import { markRaw } from 'vue';
2
+ import {
3
+ HArea,
4
+ HCascader,
5
+ HCheckbox,
6
+ HCheckboxGroup,
7
+ HCustomRender,
8
+ HDatePicker,
9
+ HDatetimePicker,
10
+ HDateTimePickerGroup,
11
+ HInput,
12
+ HNumberKeyboard,
13
+ HPasswordInput,
14
+ HPicker,
15
+ HRadio,
16
+ HRadioGroup,
17
+ HRate,
18
+ HSignature,
19
+ HSlider,
20
+ HStepper,
21
+ HSwitch,
22
+ HTimePicker,
23
+ HTreeSelect,
24
+ HUpload,
25
+ } from '../component-definition/components';
26
+
27
+ /* eslint-disable ts/no-unnecessary-type-assertion */
28
+ const compMap = {
29
+ 'area': markRaw(HArea) as typeof HArea,
30
+ 'cascader': markRaw(HCascader) as typeof HCascader,
31
+ 'checkbox': markRaw(HCheckbox) as typeof HCheckbox,
32
+ 'checkbox-group': markRaw(HCheckboxGroup) as typeof HCheckboxGroup,
33
+ 'custom-render': markRaw(HCustomRender) as typeof HCustomRender,
34
+ 'datepicker': markRaw(HDatePicker) as typeof HDatePicker,
35
+ 'date-picker': markRaw(HDatePicker) as typeof HDatePicker,
36
+ 'date-time-picker-group': markRaw(HDateTimePickerGroup) as typeof HDateTimePickerGroup,
37
+ 'datetime-picker': markRaw(HDatetimePicker) as typeof HDatetimePicker,
38
+ 'input': markRaw(HInput) as typeof HInput,
39
+ 'number-keyboard': markRaw(HNumberKeyboard) as typeof HNumberKeyboard,
40
+ 'password-input': markRaw(HPasswordInput) as typeof HPasswordInput,
41
+ 'picker': markRaw(HPicker) as typeof HPicker,
42
+ 'select': markRaw(HPicker) as typeof HPicker,
43
+ 'radio': markRaw(HRadio) as typeof HRadio,
44
+ 'radio-group': markRaw(HRadioGroup) as typeof HRadioGroup,
45
+ 'rate': markRaw(HRate) as typeof HRate,
46
+ 'signature': markRaw(HSignature) as typeof HSignature,
47
+ 'slider': markRaw(HSlider) as typeof HSlider,
48
+ 'stepper': markRaw(HStepper) as typeof HStepper,
49
+ 'switch': markRaw(HSwitch) as typeof HSwitch,
50
+ 'time-picker': markRaw(HTimePicker) as typeof HTimePicker,
51
+ 'timepicker': markRaw(HTimePicker) as typeof HTimePicker,
52
+ 'tree-select': markRaw(HTreeSelect) as typeof HTreeSelect,
53
+ 'upload': markRaw(HUpload) as typeof HUpload,
54
+ };
55
+ /* eslint-enable ts/no-unnecessary-type-assertion */
56
+ const userCompMap: Record<string, any> = {};
57
+
58
+ /** 默认定义组件的类型 */
59
+ export type ComponentTypeDef = (typeof compMap)[keyof typeof compMap];
60
+
61
+ /**
62
+ * 注册自定义组件
63
+ * @param {string} name 类型
64
+ * @param {} comp 可渲染的组件
65
+ */
66
+ export function registerComponent(name: string, comp: any) {
67
+ userCompMap[name] = markRaw(comp);
68
+ }
69
+
70
+ /**
71
+ * 删除自定义组件
72
+ * @param {string} name 定义的类型
73
+ */
74
+ export function unregisterComponent(name: string) {
75
+ delete userCompMap[name];
76
+ }
77
+
78
+ /**
79
+ * 获取指定组件
80
+ * 根据组件类型名称获取对应的组件实例,优先从用户自定义组件中查找
81
+ *
82
+ * @param {string} name - 组件类型名称
83
+ * @returns {ComponentTypeDef | null} - 返回指定的组件
84
+ */
85
+ export function getComponent(name: string): ComponentTypeDef | null {
86
+ return userCompMap[name] || compMap[name as keyof typeof compMap] || (console.warn('未找到该组件类型: ', name), null);
87
+ }
88
+
89
+ /**
90
+ * 获取指定类型/所有组件
91
+ *
92
+ * @param {string} [type] 内置组件(builtIn)
93
+ *
94
+ * @returns {Record<string, ComponentTypeDef>} - 返回指定的组件或所有组件的映射表
95
+ */
96
+ export function getAllComponent(type?: 'builtIn' | 'user'): Record<string, ComponentTypeDef> {
97
+ if (!type) return { ...compMap, ...userCompMap };
98
+ else return type === 'user' ? { ...userCompMap } : { ...compMap };
99
+ }
@@ -0,0 +1,7 @@
1
+ import type { ComponentExposed } from 'vue-component-type-helpers';
2
+ import HGroup from './index.vue';
3
+
4
+ export { HGroup };
5
+ export type HGroupInstance = ComponentExposed<typeof HGroup>;
6
+ export * from './assist';
7
+ export * from './types';
@@ -0,0 +1,117 @@
1
+ <template>
2
+ <!-- eslint-disable-next-line vue/no-unused-refs -->
3
+ <VirtualGroup ref="virtualGroupRef" v-bind="$attrs" :tag="virtualTag" :slots="virtualSlots || tagSlots" :query="query" :wrapper="wrapper">
4
+ <template v-if="slots?.prepend || ($slots as GroupSlots).prepend">
5
+ <component :is="getNode(slots?.prepend || ($slots as GroupSlots).prepend)" :query="query" :wrapper="wrapper" />
6
+ </template>
7
+ <template v-if="slots?.default">
8
+ <component :is="slots.default" :config="finalConfig" :query="query" :wrapper="wrapper" />
9
+ </template>
10
+ <slot v-else-if="$slots.default" :config="finalConfig" :query="query" />
11
+ <template v-else>
12
+ <template v-for="(item, key) of finalConfig" :key="item.as || item.field || item[REWRITE_FIELD_KEY] || key">
13
+ <component :is="getComponent2(item.t)!" v-if="item" v-bind="item" :field="item.as || item.field || item[REWRITE_FIELD_KEY] || key" :query="query" />
14
+ </template>
15
+ </template>
16
+ <template v-if="slots?.append || ($slots as GroupSlots).append">
17
+ <component :is="getNode(slots?.append || ($slots as GroupSlots).append)" :query="query" :wrapper="wrapper" />
18
+ </template>
19
+ </VirtualGroup>
20
+ </template>
21
+
22
+ <script lang="tsx">
23
+ import { get, getNode, getProvideValue, hasOwn, hyphenate, isPlainObject, useEmitter, usePlain } from '@xiaohaih/json-form-core';
24
+ import { CellGroup as VanCellGroup } from 'vant';
25
+ import type { FunctionalComponent, SlotsType } from 'vue';
26
+ import { computed, defineComponent, markRaw, ref, watch } from 'vue';
27
+ import { pick } from '../../src/utils';
28
+ import { getComponent } from './assist';
29
+ import type { GroupSlots } from './types';
30
+ import { groupEmitsPrivate as emits, groupPropsPrivate as props } from './types';
31
+ import VirtualGroup from './virtual-group.vue';
32
+
33
+ /** 当 field 不存在, 但 fields 存在时, 合并 fields 到对象上的 key */
34
+ const REWRITE_FIELD_KEY = '__field__' as const;
35
+ /** 特殊类型可以直接复用组件的 */
36
+ const specialComponents: Record<string, {
37
+ /** 重渲染的组件 */
38
+ tag: any;
39
+ /** 该组件所拥有的插槽(默认插槽不用定义) */
40
+ slots?: (slots: Record<string, any> | undefined) => Record<string, any> | undefined;
41
+ }> = {
42
+ 'cell-group': {
43
+ tag: markRaw(VanCellGroup),
44
+ slots: (slots) => slots?.title ? { title: slots.title } : undefined,
45
+ },
46
+ };
47
+
48
+ /**
49
+ * @file 自定义组件 - 支持多列渲染
50
+ */
51
+ export default defineComponent({
52
+ name: 'HGroup',
53
+ components: {
54
+ VirtualGroup,
55
+ },
56
+ inheritAttrs: false,
57
+ props,
58
+ emits,
59
+ slots: Object as SlotsType<GroupSlots>,
60
+ setup(props, ctx) {
61
+ const virtualGroupRef = ref<Record<string, any> | undefined>();
62
+ const virtualTag = computed(() => {
63
+ const { tag, t } = props;
64
+ return specialComponents[t!]?.tag || tag;
65
+ });
66
+ const virtualSlots = computed(() => {
67
+ const { t, slots } = props;
68
+ return specialComponents[t!]?.slots?.(slots);
69
+ });
70
+ const tagRef = computed(() => virtualGroupRef.value?.tagRef);
71
+ /** 容器注入值 */
72
+ const wrapper = getProvideValue();
73
+ const finalConfig = computed(() => {
74
+ const { config } = props;
75
+ // 如果函数且提供了 formRef 时, formRef 获取失败时不渲染
76
+ // 防止重复渲染一次导致 getOptions 重复请求
77
+ if (typeof config === 'function' && props.getFormRef && !props.getFormRef?.()) return [];
78
+ return typeof config === 'function' ? coverObjOption2Arr<any[]>(config({ query: props.query, wrapper, formRef: props.getFormRef?.() })) : coverObjOption2Arr<any[]>(config);
79
+ });
80
+ /** 将对象形式的配置项转为数组 */
81
+ function coverObjOption2Arr<T>(opt: any): T {
82
+ if (isPlainObject(opt)) {
83
+ const r: any[] = [];
84
+ Object.entries(opt).forEach(([key, value]) => {
85
+ value.field = key;
86
+ r.push(value);
87
+ });
88
+ return r as unknown as T;
89
+ }
90
+ opt.forEach((o: any) => !o.field && o.fields && (o[REWRITE_FIELD_KEY] = o.fields.join(',')));
91
+ return opt as unknown as T;
92
+ }
93
+ /** 对 group 组件特殊处理 */
94
+ function getComponent2(name: string) {
95
+ return name === 'group' || specialComponents[name] ? 'HGroup' : getComponent(name);
96
+ }
97
+
98
+ const emitter = useEmitter(wrapper);
99
+ props.hooks?.created?.({ props, wrapper, ...emitter });
100
+
101
+ return {
102
+ hyphenate,
103
+ getNode,
104
+ REWRITE_FIELD_KEY,
105
+ virtualGroupRef,
106
+ virtualTag,
107
+ virtualSlots,
108
+ tagRef,
109
+ wrapper,
110
+ finalConfig,
111
+ getComponent2,
112
+ };
113
+ },
114
+ });
115
+ </script>
116
+
117
+ <style lang="css" scoped></style>
@@ -0,0 +1,57 @@
1
+ import type { EventsWithoutInstance, getProvideValue } from '@xiaohaih/json-form-core';
2
+ import type { ExtractPublicPropTypes, PropType } from 'vue';
3
+ import type { ComponentType } from '../share';
4
+
5
+ export interface GroupHookOption {
6
+ /** 组件创建前触发的钩子, 可在内部监听生命周期, 获取实例, 以及操作该组件内的各种属性 */
7
+ created?: (options: { props: ExtractPublicPropTypes<ReturnType<typeof groupPropsGeneric>>; wrapper: ReturnType<typeof getProvideValue> } & EventsWithoutInstance) => void;
8
+ }
9
+
10
+ /** 组件传参 */
11
+ export function groupPropsGeneric<Query extends Record<string, any>, OptionQuery extends Record<string, any>>() {
12
+ return {
13
+ ...{} as unknown as Record<'class' | 'style', { type: PropType<string | Record<string, any> | any[]> }>,
14
+ /** 当前组件类型(防止被继承, 主动声明) */
15
+ t: { type: String },
16
+ /** 提交字段 */
17
+ field: { type: String },
18
+ /** 当前条件对象 */
19
+ query: { type: Object as PropType<Query>, required: true },
20
+ /** 渲染的标签 */
21
+ tag: { type: [Object, String, Array, Function] as PropType<any>, default: 'div' },
22
+ /** 传递给渲染标签的插槽(默认插槽是渲染的子条件) */
23
+ tagSlots: { type: Object as PropType<Record<string, ComponentType<{ query: Query; wrapper: ReturnType<typeof getProvideValue> }>>> },
24
+ /** 渲染的子条件 */
25
+ config: { type: [Object, Array, Function] as PropType<any> },
26
+ /** 传递给组件的插槽 */
27
+ slots: { type: Object as PropType<GroupSlots<Query, OptionQuery>> },
28
+ /** 组件额外的钩子() */
29
+ hooks: { type: [Object] as PropType<GroupHookOption>, default: undefined },
30
+ /** 获取表单组件实例 */
31
+ getFormRef: { type: Function as PropType<() => any> },
32
+ } as const;
33
+ }
34
+ /** 组件传参 */
35
+ export const groupPropsPrivate = groupPropsGeneric();
36
+ /** 组件传参 - 外部调用 */
37
+ export const groupProps = groupPropsPrivate;
38
+ export type GroupProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof groupPropsGeneric<Query, OptionQuery>>>;
39
+
40
+ /** 组件事件 */
41
+ export function groupEmitsGeneric<T>() {
42
+ return {};
43
+ }
44
+ /** 组件事件 */
45
+ export const groupEmitsPrivate = groupEmitsGeneric();
46
+ /** 组件事件 - 外部调用 */
47
+ export const groupEmits = groupEmitsPrivate;
48
+ export type GroupEmits<T> = ReturnType<typeof groupEmitsGeneric<T>>;
49
+
50
+ export interface GroupSlots<Query extends Record<string, any> = any, OptionQuery extends Record<string, any> = any> {
51
+ /** 在表单项前渲染 */
52
+ prepend?: ComponentType<{ query: Query; wrapper: ReturnType<typeof getProvideValue> }>;
53
+ /** 自定义表单渲染逻辑 */
54
+ default?: ComponentType<{ config: Record<string, any> | Record<string, any>[]; query: Query; wrapper: ReturnType<typeof getProvideValue> }>;
55
+ /** 在表单项后渲染 */
56
+ append?: ComponentType<{ query: Query; wrapper: ReturnType<typeof getProvideValue> }>;
57
+ }
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <template v-if="tag">
3
+ <component :is="tag" v-bind="$attrs" ref="tagRef" v-on="events">
4
+ <slot />
5
+ <template v-for="(item, slotName) in slots" :key="slotName" #[slotName]="row">
6
+ <component :is="getNode(item)" v-bind="row" :wrapper="wrapper" :query="query" />
7
+ </template>
8
+ </component>
9
+ </template>
10
+ <slot v-else />
11
+ </template>
12
+
13
+ <script lang="tsx">
14
+ import { getNode } from '@xiaohaih/json-form-core';
15
+ import type { PropType } from 'vue';
16
+ import { computed, defineComponent, ref } from 'vue';
17
+
18
+ /**
19
+ * @file 对 Group 组件进行包装, 以支持无根节点渲染
20
+ */
21
+ export default defineComponent({
22
+ name: 'VirtualGroup',
23
+ inheritAttrs: false,
24
+ props: {
25
+ tag: { type: [Object, String, Array, Function] as PropType<any>, default: 'div' },
26
+ slots: { type: [Object] as PropType<Record<string, any>> },
27
+ wrapper: { type: [Object] as PropType<Record<string, any>> },
28
+ query: { type: [Object] as PropType<Record<string, any>> },
29
+ },
30
+ setup(props, ctx) {
31
+ // @ts-expect-error 兼容 vue2.x
32
+ const events = computed(() => ctx.listeners || {});
33
+ return { getNode, tagRef: ref<Record<string, any> | undefined>(), events };
34
+ },
35
+ });
36
+ </script>
37
+
38
+ <style lang="css" scoped></style>
@@ -0,0 +1,10 @@
1
+ // 在 pnpm 中, 由于打包时引用的 @vue/shared 路径实际被解析为'.pnpm/@vue+shared@3.5.26/node_modules/@vue/shared'
2
+ // 导致无法生成声明文件, 因此需要单独引入 @vue/shared, 避免报错(不确定是否是 vant 导致的)
3
+ // 报错原因可参考下方链接
4
+ // https://blog.gitcode.com/8425e0ada8aa47b422a780f6e0b1ae0f.html
5
+ // https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-5.html#consulting-packagejson-dependencies-for-declaration-file-generation
6
+ import type {} from '@vue/shared';
7
+
8
+ export * from './component-definition/index';
9
+ export * from './share';
10
+ export * from './wrapper/index';
@@ -0,0 +1,6 @@
1
+ import type { ComponentExposed } from 'vue-component-type-helpers';
2
+ import HInput from './index.vue';
3
+
4
+ export { HInput };
5
+ export type HInputInstance = ComponentExposed<typeof HInput>;
6
+ export * from './types';
@@ -0,0 +1,83 @@
1
+ <template>
2
+ <VanField
3
+ v-if="!hide"
4
+ v-bind="$attrs"
5
+ ref="fieldRef"
6
+ :name="field"
7
+ :disabled="globalDisabled || disabled"
8
+ :readonly="globalDisabled || readonly"
9
+ :clearable="clearable"
10
+ :model-value="(tempChecked as string)"
11
+ @update:model-value="change"
12
+ @keydown.enter="enterHandle"
13
+ >
14
+ <template v-for="(item, slotName) of slots" :key="slotName" #[hyphenate(slotName)]="row">
15
+ <component :is="getNode(item)" v-bind="slotProps" v-bind.prop="row" />
16
+ </template>
17
+ </VanField>
18
+ </template>
19
+
20
+ <script lang="ts">
21
+ import { getNode, hyphenate, usePlain } from '@xiaohaih/json-form-core';
22
+ import { Field as VanField } from 'vant';
23
+ import type { SlotsType } from 'vue';
24
+ import { computed, defineComponent, ref } from 'vue';
25
+ import type { ComponentExposed } from 'vue-component-type-helpers';
26
+ import { useCommonSetup, useTempChecked } from '../use';
27
+ import type { InputSlots } from './types';
28
+ import { inputEmitsPrivate as emits, inputPropsPrivate as props } from './types';
29
+
30
+ /**
31
+ * @file 输入框
32
+ */
33
+ export default defineComponent({
34
+ name: 'HInput',
35
+ components: { VanField },
36
+ inheritAttrs: false,
37
+ props,
38
+ emits,
39
+ slots: Object as SlotsType<InputSlots>,
40
+ setup(props, ctx) {
41
+ const plain = usePlain(props);
42
+ const { slotProps } = useCommonSetup(props, ctx, plain);
43
+ const { tempChecked, changeSync } = useTempChecked(plain.checked);
44
+ const fieldRef = ref<ComponentExposed<typeof VanField>>();
45
+
46
+ /**
47
+ * 节流
48
+ * @param {string} value: 输入值
49
+ */
50
+ let timer = 0;
51
+ function change(value: string) {
52
+ if (value === tempChecked.value) return;
53
+ const { debounceTime } = props;
54
+ timer && clearTimeout(timer);
55
+ tempChecked.value = value;
56
+
57
+ debounceTime
58
+ ? timer = setTimeout(() => changeSync(tempChecked.value), debounceTime) as unknown as number
59
+ : changeSync(value);
60
+ }
61
+ /** 回车事件 */
62
+ function enterHandle(ev: Event | KeyboardEvent) {
63
+ timer && clearTimeout(timer);
64
+ plain.checked.value !== tempChecked.value && (plain.checked.value = tempChecked.value);
65
+ plain.wrapper?.search();
66
+ }
67
+
68
+ return {
69
+ hyphenate,
70
+ getNode,
71
+ fieldRef,
72
+ ...plain,
73
+ slotProps,
74
+ tempChecked,
75
+ change,
76
+ enterHandle,
77
+ };
78
+ },
79
+ });
80
+ </script>
81
+
82
+ <style lang="scss" scoped>
83
+ </style>
@@ -0,0 +1,43 @@
1
+ import type { emits2obj, PlainProps } from '@xiaohaih/json-form-core';
2
+ import { emits2props, plainProps } from '@xiaohaih/json-form-core';
3
+ import { Field as VanField } from 'vant';
4
+ import type { ExtractPublicPropTypes, PropType } from 'vue';
5
+ import type { CommonProps, CommonSlots, ComponentType } from '../share';
6
+ import { commonProps } from '../share';
7
+
8
+ /** 组件传参 - 私有 */
9
+ export function inputPropsGeneric<Query extends Record<string, any>, OptionQuery extends Record<string, any>>() {
10
+ return {
11
+ ...commonProps as CommonProps<Query, OptionQuery>,
12
+ ...plainProps as PlainProps<Query, OptionQuery>,
13
+ /** 是否显示清除按钮 @default true */
14
+ clearable: { type: Boolean as PropType<boolean>, default: true },
15
+ /** 实时触发时防抖动的时间 */
16
+ debounceTime: { type: Number as PropType<number>, default: 300 },
17
+ } as const;
18
+ }
19
+ /** 组件传参 - 私有 */
20
+ export const inputPropsPrivate = inputPropsGeneric();
21
+ /** 组件传参 - 外部调用 */
22
+ export const inputProps = {
23
+ ...VanField.props as unknown as {},
24
+ ...inputPropsPrivate,
25
+ };
26
+ export type InputProps<Query extends Record<string, any>, OptionQuery extends Record<string, any>> = ExtractPublicPropTypes<ReturnType<typeof inputPropsGeneric<Query, OptionQuery>>>;
27
+
28
+ /** 组件事件 - 私有 */
29
+ export function inputEmitsGeneric<T>() {
30
+ return {};
31
+ }
32
+ /** 组件事件 - 私有 */
33
+ export const inputEmitsPrivate = inputEmitsGeneric();
34
+ /** 组件事件 - 外部调用 */
35
+ export const inputEmits = {
36
+ ...VanField.emits,
37
+ ...inputEmitsPrivate,
38
+ };
39
+
40
+ export type InputEmits<T> = ReturnType<typeof inputEmitsGeneric<T>>;
41
+
42
+ export interface InputSlots extends CommonSlots<any> {
43
+ }
@@ -0,0 +1,6 @@
1
+ import type { ComponentExposed } from 'vue-component-type-helpers';
2
+ import HInputSlot from './index.vue';
3
+
4
+ export { HInputSlot };
5
+ export type HInputSlotInstance = ComponentExposed<typeof HInputSlot>;
6
+ export * from './types';