@schemx/vue 0.1.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.
Files changed (63) hide show
  1. package/README.md +136 -0
  2. package/dist/components/FormGroup/index.d.ts +17 -0
  3. package/dist/components/FormGroup/index.d.ts.map +1 -0
  4. package/dist/components/FormItem/index.d.ts +17 -0
  5. package/dist/components/FormItem/index.d.ts.map +1 -0
  6. package/dist/form.d.ts +34 -0
  7. package/dist/form.d.ts.map +1 -0
  8. package/dist/hocs/index.d.ts +10 -0
  9. package/dist/hocs/index.d.ts.map +1 -0
  10. package/dist/hocs/withRemoteOptions.d.ts +74 -0
  11. package/dist/hocs/withRemoteOptions.d.ts.map +1 -0
  12. package/dist/hooks/index.d.ts +24 -0
  13. package/dist/hooks/index.d.ts.map +1 -0
  14. package/dist/hooks/useContext.d.ts +40 -0
  15. package/dist/hooks/useContext.d.ts.map +1 -0
  16. package/dist/hooks/useDictionary.d.ts +63 -0
  17. package/dist/hooks/useDictionary.d.ts.map +1 -0
  18. package/dist/hooks/useEffect.d.ts +34 -0
  19. package/dist/hooks/useEffect.d.ts.map +1 -0
  20. package/dist/hooks/useField.d.ts +38 -0
  21. package/dist/hooks/useField.d.ts.map +1 -0
  22. package/dist/hooks/useFieldContext.d.ts +23 -0
  23. package/dist/hooks/useFieldContext.d.ts.map +1 -0
  24. package/dist/hooks/useForm.d.ts +59 -0
  25. package/dist/hooks/useForm.d.ts.map +1 -0
  26. package/dist/hooks/useStableRef.d.ts +28 -0
  27. package/dist/hooks/useStableRef.d.ts.map +1 -0
  28. package/dist/hooks/useViewSchemas.d.ts +6 -0
  29. package/dist/hooks/useViewSchemas.d.ts.map +1 -0
  30. package/dist/hooks/useWatch.d.ts +65 -0
  31. package/dist/hooks/useWatch.d.ts.map +1 -0
  32. package/dist/index.cjs +2 -0
  33. package/dist/index.cjs.map +1 -0
  34. package/dist/index.d.ts +19 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.mjs +686 -0
  37. package/dist/index.mjs.map +1 -0
  38. package/dist/index.umd.js +2 -0
  39. package/dist/index.umd.js.map +1 -0
  40. package/dist/style.css +1 -0
  41. package/dist/types/field.d.ts +23 -0
  42. package/dist/types/field.d.ts.map +1 -0
  43. package/dist/types/form.d.ts +18 -0
  44. package/dist/types/form.d.ts.map +1 -0
  45. package/dist/types/index.d.ts +2 -0
  46. package/dist/types/index.d.ts.map +1 -0
  47. package/dist/utils/diff.d.ts +33 -0
  48. package/dist/utils/diff.d.ts.map +1 -0
  49. package/dist/utils/dynamic.d.ts +99 -0
  50. package/dist/utils/dynamic.d.ts.map +1 -0
  51. package/dist/utils/equal.d.ts +22 -0
  52. package/dist/utils/equal.d.ts.map +1 -0
  53. package/dist/utils/index.d.ts +13 -0
  54. package/dist/utils/index.d.ts.map +1 -0
  55. package/dist/utils/rendererProvider.d.ts +17 -0
  56. package/dist/utils/rendererProvider.d.ts.map +1 -0
  57. package/dist/utils/rulesProvider.d.ts +17 -0
  58. package/dist/utils/rulesProvider.d.ts.map +1 -0
  59. package/dist/utils/slot.d.ts +49 -0
  60. package/dist/utils/slot.d.ts.map +1 -0
  61. package/dist/utils/validation.d.ts +43 -0
  62. package/dist/utils/validation.d.ts.map +1 -0
  63. package/package.json +64 -0
package/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # @schemx/vue
2
+
3
+ Vue 3 adapter for schemx.
4
+
5
+ `@schemx/vue` 将 `@schemx/core` 的表单实例和 ViewSchemas 渲染为 Vue 组件树。它不绑定具体 UI 组件库,适合接入业务组件、设计系统或新的 UI adapter。
6
+
7
+ 如果项目使用 Vant,推荐直接安装 [`@schemx/vant`](../vant)。该包已经注册好常用移动端表单 renderer。
8
+
9
+ ## 特性
10
+
11
+ - 提供 Vue 3 表单组件和 Composition API。
12
+ - 通过 `rendererRegistry` 注册自定义 renderer。
13
+ - 支持 `v-model`、`initialValues`、表单级事件和实例方法。
14
+ - 复用 `@schemx/core` 的字段依赖、校验、运行时 schema node 和 ViewSchemas。
15
+ - 直接导出 `@schemx/core` 的公开类型与工具。
16
+
17
+ ## 安装
18
+
19
+ ```bash
20
+ pnpm add @schemx/vue vue
21
+ ```
22
+
23
+ ## 快速开始
24
+
25
+ `@schemx/vue` 默认不提供具体输入控件。使用前需要注册 renderer:
26
+
27
+ ```ts
28
+ import { markRaw } from "vue"
29
+
30
+ import { rendererRegistry } from "@schemx/vue"
31
+
32
+ import InputRenderer from "./components/InputRenderer.vue"
33
+
34
+ rendererRegistry.register("input", markRaw(InputRenderer))
35
+ ```
36
+
37
+ 然后通过默认导出的 `Schemx` 组件渲染表单:
38
+
39
+ ```vue
40
+ <script setup lang="ts">
41
+ import { ref } from "vue"
42
+
43
+ import Schemx from "@schemx/vue"
44
+
45
+ import type { SchemxField } from "@schemx/vue"
46
+
47
+ type ProfileValues = {
48
+ nickname: string
49
+ }
50
+
51
+ const formData = ref<ProfileValues>({
52
+ nickname: "",
53
+ })
54
+
55
+ const schemas: SchemxField<ProfileValues>[] = [
56
+ {
57
+ name: "nickname",
58
+ label: "昵称",
59
+ componentType: "input",
60
+ rules: "required",
61
+ placeholder: "请输入昵称",
62
+ },
63
+ ]
64
+ </script>
65
+
66
+ <template>
67
+ <Schemx v-model="formData" :schemas="schemas" />
68
+ </template>
69
+ ```
70
+
71
+ ## 自定义 Renderer
72
+
73
+ renderer 会接收到 `value`、`onUpdate:value`、`onChange`、`onBlur`、`readonly`、`disabled` 和 `placeholder` 等公共属性。可以使用标准 Vue 事件更新字段值:
74
+
75
+ ```vue
76
+ <script setup lang="ts">
77
+ defineProps<{
78
+ value?: string
79
+ readonly?: boolean
80
+ disabled?: boolean
81
+ placeholder?: string
82
+ }>()
83
+
84
+ const emit = defineEmits<{
85
+ "update:value": [value: string]
86
+ change: [value: string]
87
+ blur: [value: string]
88
+ }>()
89
+ </script>
90
+
91
+ <template>
92
+ <input
93
+ :value="value"
94
+ :readonly="readonly"
95
+ :disabled="disabled"
96
+ :placeholder="placeholder"
97
+ @input="emit('update:value', ($event.target as HTMLInputElement).value)"
98
+ @change="emit('change', ($event.target as HTMLInputElement).value)"
99
+ @blur="emit('blur', ($event.target as HTMLInputElement).value)"
100
+ />
101
+ </template>
102
+ ```
103
+
104
+ 也可以为单个表单实例传入独立的 registry:
105
+
106
+ ```ts
107
+ import { createRendererRegistry } from "@schemx/vue"
108
+
109
+ const rendererRegistry = createRendererRegistry("input")
110
+
111
+ rendererRegistry.register("input", InputRenderer)
112
+ ```
113
+
114
+ ```vue
115
+ <Schemx :schemas="schemas" :renderer-registry="rendererRegistry" />
116
+ ```
117
+
118
+ ## Composition API
119
+
120
+ | API | 说明 |
121
+ | ------------------- | --------------------------------------------- |
122
+ | `useForm()` | 创建表单实例,并通过 Vue context 提供给子组件 |
123
+ | `useField()` | 获取字段级读写、校验和状态能力 |
124
+ | `useWatch()` | 监听字段变化 |
125
+ | `useWatchField()` | 监听单个字段 |
126
+ | `useWatchFields()` | 监听多个字段 |
127
+ | `useWatchAll()` | 监听整张表单 |
128
+ | `useDictionary()` | 管理依赖字段的远程或本地选项 |
129
+ | `useEffect()` | 创建字段依赖追踪 effect |
130
+ | `useFieldContext()` | 获取当前字段上下文 |
131
+
132
+ ## Adapter 边界
133
+
134
+ Vue 适配层只负责将 core 输出的 ViewSchemas 映射为 Vue 组件树。descriptor 编译、dependency 执行、validation、scheduler 和 node 生命周期由 `@schemx/core` 管理。
135
+
136
+ 自定义 adapter 应优先使用 `form.getViewSchemas()`、`form.subscribeViewSchemas()` 和 `form.registerRenderer()` 等公开 API,避免依赖 core 内部目录。
@@ -0,0 +1,17 @@
1
+ import { SchemxViewGroupSchema, Values } from '@schemx/core';
2
+
3
+ /**
4
+ * FormGroup Props
5
+ *
6
+ * @typeParam T - 表单值类型
7
+ */
8
+ export interface SchemxGroupProps<T extends Values = Values> {
9
+ schema: SchemxViewGroupSchema<T>;
10
+ }
11
+ declare const FormGroup: import('vue').DefineSetupFnComponent<{
12
+ schema: SchemxViewGroupSchema;
13
+ }, {}, {}, {
14
+ schema: SchemxViewGroupSchema;
15
+ } & {}, import('vue').PublicProps>;
16
+ export default FormGroup;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FormGroup/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,OAAO,KAAK,EAAE,qBAAqB,EAAoB,MAAM,EAAE,MAAM,cAAc,CAAA;AAEnF;;;;GAIG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACzD,MAAM,EAAE,qBAAqB,CAAC,CAAC,CAAC,CAAA;CACjC;AAED,QAAA,MAAM,SAAS;;;;kCAyEd,CAAA;AAED,eAAe,SAAS,CAAA"}
@@ -0,0 +1,17 @@
1
+ import { SchemxViewSchema, Values } from '@schemx/core';
2
+
3
+ /**
4
+ * FormItem 属性。
5
+ *
6
+ * @typeParam T - 表单值类型
7
+ */
8
+ export interface SchemxItemProps<T extends Values = Values> {
9
+ schema: SchemxViewSchema<T>;
10
+ }
11
+ declare const FormItem: import('vue').DefineSetupFnComponent<{
12
+ schema: SchemxViewSchema;
13
+ }, {}, {}, {
14
+ schema: SchemxViewSchema;
15
+ } & {}, import('vue').PublicProps>;
16
+ export default FormItem;
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/FormItem/index.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAkBH,OAAO,KAAK,EAOV,gBAAgB,EAChB,MAAM,EACP,MAAM,cAAc,CAAA;AAErB;;;;GAIG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM;IACxD,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAA;CAC5B;AAED,QAAA,MAAM,QAAQ;;;;kCAyPb,CAAA;AAED,eAAe,QAAQ,CAAA"}
package/dist/form.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ import { App, DefineComponent } from 'vue';
2
+ import { default as FormItem } from './components/FormItem';
3
+ import { SchemxFormProps } from './types';
4
+
5
+ /**
6
+ * SchemxForm 插件安装选项
7
+ *
8
+ * 在 `app.use(SchemxForm, options)` 时传入,用于配置全局默认行为。
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * import SchemxForm from '@schemx/vue'
13
+ *
14
+ * app.use(SchemxForm, {
15
+ * request: (url) => fetch(url).then(r => r.json()),
16
+ * })
17
+ * ```
18
+ */
19
+ export interface SchemxInstallOptions {
20
+ }
21
+ /**
22
+ * 为组件挂载静态属性并保留原始类型
23
+ *
24
+ * @param comp - 原始组件
25
+ * @param extra - 要挂载的静态属性
26
+ */
27
+ export declare function withInstall<T extends object, E extends Record<string, unknown>>(comp: T, extra: E): T & E;
28
+ export type SchemxFormPlugin = DefineComponent<SchemxFormProps> & {
29
+ install: (app: App, options?: SchemxInstallOptions) => void;
30
+ FormItem: typeof FormItem;
31
+ };
32
+ declare const SchemxFormExport: SchemxFormPlugin;
33
+ export default SchemxFormExport;
34
+ //# sourceMappingURL=form.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form.d.ts","sourceRoot":"","sources":["../src/form.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,eAAe,EAAE,MAAM,KAAK,CAAA;AAE/C,OAAO,QAAQ,MAAM,uBAAuB,CAAA;AAG5C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,oBAAoB;CAAG;AAExC;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7E,IAAI,EAAE,CAAC,EACP,KAAK,EAAE,CAAC,GAE6B,CAAC,GAAG,CAAC,CAC3C;AAED,MAAM,MAAM,gBAAgB,GAAG,eAAe,CAAC,eAAe,CAAC,GAAG;IAChE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,CAAC,EAAE,oBAAoB,KAAK,IAAI,CAAA;IAC3D,QAAQ,EAAE,OAAO,QAAQ,CAAA;CAC1B,CAAA;AAED,QAAA,MAAM,gBAAgB,EAOL,gBAAgB,CAAA;AAEjC,eAAe,gBAAgB,CAAA"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * 高阶组件(HOC)模块
3
+ *
4
+ * 提供用于增强渲染器组件能力的高阶组件函数。
5
+ *
6
+ * @module hocs
7
+ */
8
+ export { WithRemoteOptions } from './withRemoteOptions';
9
+ export type { SchemxDictionary, SchemxWithDictionary } from './withRemoteOptions';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hocs/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAEvD,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA"}
@@ -0,0 +1,74 @@
1
+ import { Component, PropType } from 'vue';
2
+ import { NamePath, SchemxDictionary } from '@schemx/core';
3
+
4
+ export type { SchemxDictionary, SchemxWithDictionary } from '@schemx/core';
5
+ /**
6
+ * WithRemoteOptions 注入给被包装组件的额外 Props
7
+ */
8
+ export interface RemoteOptionsInjectedProps {
9
+ /** 加载的选项列表 */
10
+ options: any[];
11
+ /** 加载状态 */
12
+ loading: boolean;
13
+ }
14
+ /**
15
+ * 选项高阶组件
16
+ *
17
+ * 包装一个渲染器组件,当 dict prop 存在时,
18
+ * 调用 useDictionary 加载选项,并将结果作为 options prop 注入。
19
+ *
20
+ * 当组件自身已传入非空 options 且无 dict 时,优先使用静态 options。
21
+ *
22
+ * @param WrappedComponent - 被包装的渲染器组件
23
+ * @returns 增强后的组件,自动具备选项加载能力
24
+ *
25
+ * @example
26
+ * ```ts
27
+ * import { WithRemoteOptions } from '@schemx/vue'
28
+ * import MySelect from './MySelect.vue'
29
+ *
30
+ * const RemoteSelect = WithRemoteOptions(MySelect)
31
+ *
32
+ * // 在 schema 中使用
33
+ * const schema = {
34
+ * name: 'city',
35
+ * label: '城市',
36
+ * componentType: 'select',
37
+ * componentProps: {
38
+ * dict: {
39
+ * api: async (values) => fetchCities(values.province),
40
+ * dependsOn: ['province'],
41
+ * shouldFetch: (values) => !!values.province,
42
+ * resetOnDepsChange: true,
43
+ * immediate: false,
44
+ * },
45
+ * },
46
+ * }
47
+ * ```
48
+ */
49
+ export declare function WithRemoteOptions(WrappedComponent: Component): import('vue').DefineComponent<import('vue').ExtractPropTypes<{
50
+ dict: {
51
+ type: PropType<SchemxDictionary>;
52
+ default: undefined;
53
+ };
54
+ fieldName: {
55
+ type: PropType<NamePath>;
56
+ default: undefined;
57
+ };
58
+ }>, () => import('vue').VNode<import('vue').RendererNode, import('vue').RendererElement, {
59
+ [key: string]: any;
60
+ }>, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<{
61
+ dict: {
62
+ type: PropType<SchemxDictionary>;
63
+ default: undefined;
64
+ };
65
+ fieldName: {
66
+ type: PropType<NamePath>;
67
+ default: undefined;
68
+ };
69
+ }>> & Readonly<{}>, {
70
+ dict: SchemxDictionary<import('@schemx/core').Values, any>;
71
+ fieldName: string;
72
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
73
+ export default WithRemoteOptions;
74
+ //# sourceMappingURL=withRemoteOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"withRemoteOptions.d.ts","sourceRoot":"","sources":["../../src/hocs/withRemoteOptions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,SAAS,EAAgC,QAAQ,EAAgB,MAAM,KAAK,CAAA;AAIrF,OAAO,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAE9D,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAE1E;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,cAAc;IACd,OAAO,EAAE,GAAG,EAAE,CAAA;IACd,WAAW;IACX,OAAO,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,wBAAgB,iBAAiB,CAAC,gBAAgB,EAAE,SAAS;;cAMrC,QAAQ,CAAC,gBAAgB,CAAC;;;;cAIjB,QAAQ,CAAC,QAAQ,CAAC;;;;;;;cAJ3B,QAAQ,CAAC,gBAAgB,CAAC;;;;cAIjB,QAAQ,CAAC,QAAQ,CAAC;;;;;;6EAoBlD;AAED,eAAe,iBAAiB,CAAA"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Hooks 统一导出
3
+ *
4
+ * @module hooks
5
+ */
6
+ /** useForm - 表单状态管理 */
7
+ export { useForm } from './useForm';
8
+ /** useField - 单字段控制 */
9
+ export { useField } from './useField';
10
+ /** useWatch - 字段变化监听 */
11
+ export { useWatch, useWatchField, useWatchFields, useWatchAll } from './useWatch';
12
+ /** useEffect - 通用 Signal effect */
13
+ export { useEffect } from './useEffect';
14
+ /** useDictionary - 字典选项加载 */
15
+ export { useDictionary, type SchemxDictionary, type SchemxWithDictionary, type UseDictOptionsReturn, } from './useDictionary';
16
+ /** useContext - 表单上下文注入与消费 */
17
+ export { type FormContextProps, useContext } from './useContext';
18
+ /** useStableRef - 引用稳定化的 shallowRef */
19
+ export { useStableRef } from './useStableRef';
20
+ /** useViewSchemas - ViewSchemas Vue 桥接 */
21
+ export { useViewSchemas } from './useViewSchemas';
22
+ /** useFieldContext - 字段上下文注入与消费 */
23
+ export { useFieldContext } from './useFieldContext';
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,uBAAuB;AACvB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,uBAAuB;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAErC,wBAAwB;AACxB,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAEjF,mCAAmC;AACnC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEvC,6BAA6B;AAC7B,OAAO,EACL,aAAa,EACb,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,iBAAiB,CAAA;AAExB,8BAA8B;AAC9B,OAAO,EAAE,KAAK,gBAAgB,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAEhE,uCAAuC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAE7C,0CAA0C;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEjD,mCAAmC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA"}
@@ -0,0 +1,40 @@
1
+ import { SchemxFormProps } from '../types';
2
+ import { Values } from '@schemx/core';
3
+
4
+ /** FormContext 注入 key */
5
+ export declare const FORM_CONTEXT_KEY: unique symbol;
6
+ /**
7
+ * 表单上下文属性
8
+ *
9
+ * 由 schemx 组件注入,包含表单级别的全局配置。
10
+ *
11
+ * @typeParam T - 表单值类型
12
+ */
13
+ export interface FormContextProps<T extends Values = Values> extends Omit<SchemxFormProps<T>, "form" | "modelValue" | "rendererRegistry" | "defaultRendererType" | "rulesRegistery" | "onFinish" | "onFinishFailed" | "onValuesChange" | "onFieldsChange"> {
14
+ }
15
+ /**
16
+ * 创建并注入表单上下文
17
+ *
18
+ * 在 schemx 的 setup 中调用,将表单级别配置注入到子组件树中。
19
+ *
20
+ * @typeParam T - 表单值类型
21
+ * @param props - 表单上下文属性
22
+ */
23
+ export declare const createContext: <T extends Values = Values>(props: FormContextProps<T>) => void;
24
+ /**
25
+ * 获取表单上下文配置
26
+ *
27
+ * 在子组件中获取 schemx 注入的全局配置(readonly、disabled、labelAlign 等)。
28
+ *
29
+ * @returns 表单上下文属性
30
+ *
31
+ * @throws Error 如果不在 schemx 提供的上下文中调用
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const context = useContext()
36
+ * console.log(context.readonly, context.disabled)
37
+ * ```
38
+ */
39
+ export declare function useContext(): FormContextProps;
40
+ //# sourceMappingURL=useContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAA;AAE9C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAE1C,yBAAyB;AACzB,eAAO,MAAM,gBAAgB,eAAwB,CAAA;AAErD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,IAAI,CACvE,eAAe,CAAC,CAAC,CAAC,EAChB,MAAM,GACN,YAAY,GACZ,kBAAkB,GAClB,qBAAqB,GACrB,gBAAgB,GAChB,UAAU,GACV,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,CACnB;CAAG;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,OAAO,gBAAgB,CAAC,CAAC,CAAC,SAElF,CAAA;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,IAAI,gBAAgB,CAQ7C"}
@@ -0,0 +1,63 @@
1
+ import { Ref } from 'vue';
2
+ import { FieldValue, NamePath, SchemxDictionary, Values } from '@schemx/core';
3
+
4
+ export type { SchemxDictionary, SchemxWithDictionary } from '@schemx/core';
5
+ /**
6
+ * useDictionary 返回值
7
+ */
8
+ export interface UseDictOptionsReturn {
9
+ /** 远程加载的字典选项列表(响应式) */
10
+ list: Ref<any[]>;
11
+ /** 请求加载状态(响应式) */
12
+ loading: Ref<boolean>;
13
+ /** 请求错误信息(响应式) */
14
+ error: Ref<Error | undefined>;
15
+ /** 触发字典选项加载 */
16
+ loadDict: () => Promise<void>;
17
+ /** 使用当前配置重新执行 api */
18
+ refresh: () => Promise<void>;
19
+ /** 直接修改 list 的值,不触发 api 调用 */
20
+ mutate: (data: any[]) => void;
21
+ }
22
+ /**
23
+ * 将未知抛出值规范化为 `Error` 实例
24
+ *
25
+ * @param err - 捕获的值(可能是任意类型)
26
+ * @returns 包装原始值的 `Error` 对象
27
+ */
28
+ export declare function normalizeError(err: unknown): Error;
29
+ /**
30
+ * 加载字典选项
31
+ *
32
+ * 通过 api 函数获取数据,支持完整的表单值泛型推导。
33
+ * 自动在组件挂载时加载,支持依赖字段联动、竞态控制、
34
+ * 重试、错误处理等能力。
35
+ *
36
+ * @typeParam TValues - 表单值类型
37
+ * @param options - 字典配置选项
38
+ * @param fieldName - 当前字段名,用于 resetOnDepsChange 时清空字段值
39
+ * @returns 响应式选项列表、loading/error 状态及控制方法
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * // 基础用法
44
+ * const { list } = useDictionary({
45
+ * api: async () => {
46
+ * const res = await fetch('/api/options')
47
+ * return res.json()
48
+ * },
49
+ * })
50
+ *
51
+ * // 依赖联动(带泛型)
52
+ * const { list } = useDictionary<MyFormValues>({
53
+ * api: async (values) => fetchCities(values.province),
54
+ * dependsOn: ['province'],
55
+ * shouldFetch: (values) => !!values.province,
56
+ * resetOnDepsChange: true,
57
+ * immediate: false,
58
+ * }, 'city')
59
+ * ```
60
+ */
61
+ export declare const useDictionary: <TValues extends Values = Values, TName extends NamePath<TValues> = NamePath<TValues>, TValue = FieldValue<TValues, TName>>(options: SchemxDictionary<TValues>, fieldName?: TName) => UseDictOptionsReturn;
62
+ export default useDictionary;
63
+ //# sourceMappingURL=useDictionary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDictionary.d.ts","sourceRoot":"","sources":["../../src/hooks/useDictionary.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAa,GAAG,EAAO,MAAM,KAAK,CAAA;AAKzC,OAAO,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAElF,YAAY,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAA;AAE1E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uBAAuB;IACvB,IAAI,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,CAAA;IAChB,kBAAkB;IAClB,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAA;IACrB,kBAAkB;IAClB,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,SAAS,CAAC,CAAA;IAC7B,eAAe;IACf,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7B,qBAAqB;IACrB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC5B,8BAA8B;IAC9B,MAAM,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,CAAA;CAC9B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK,CAIlD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,aAAa,GACxB,OAAO,SAAS,MAAM,GAAG,MAAM,EAC/B,KAAK,SAAS,QAAQ,CAAC,OAAO,CAAC,GAAG,QAAQ,CAAC,OAAO,CAAC,EACnD,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,EAEnC,SAAS,gBAAgB,CAAC,OAAO,CAAC,EAClC,YAAY,KAAK,KAChB,oBAmIF,CAAA;AAED,eAAe,aAAa,CAAA"}
@@ -0,0 +1,34 @@
1
+ import { CreateEffectReturn, EffectCallback } from '@schemx/core';
2
+
3
+ /**
4
+ * 创建 Signal effect 并在组件卸载时自动取消。
5
+ *
6
+ * 在 effect 回调中访问任何 Signal 值时自动追踪依赖,
7
+ * 依赖变化时自动重新执行回调。
8
+ * 回调可返回一个清理函数,在 effect 重新执行前或被 dispose 时调用。
9
+ *
10
+ * @param callback - effect 回调函数,可选返回清理函数
11
+ *
12
+ * @returns 取消 effect 的 dispose 函数(通常无需手动调用,组件卸载时自动取消)
13
+ *
14
+ * @example
15
+ * ```ts
16
+ * // 监听字段值变化
17
+ * useEffect(() => {
18
+ * const name = form.getFieldValue('name')
19
+ * console.log('name changed:', name)
20
+ * })
21
+ *
22
+ * // 带清理函数
23
+ * useEffect(() => {
24
+ * const timer = setInterval(() => {
25
+ * console.log('value:', form.getFieldValue('count'))
26
+ * }, 1000)
27
+ *
28
+ * return () => clearInterval(timer)
29
+ * })
30
+ * ```
31
+ */
32
+ export declare function useEffect(callback: EffectCallback): CreateEffectReturn;
33
+ export default useEffect;
34
+ //# sourceMappingURL=useEffect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useEffect.d.ts","sourceRoot":"","sources":["../../src/hooks/useEffect.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAEtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,cAAc,GAAG,kBAAkB,CAMtE;AAED,eAAe,SAAS,CAAA"}
@@ -0,0 +1,38 @@
1
+ import { FieldInstance } from '../types/field';
2
+ import { NamePath, Values } from '@schemx/core';
3
+
4
+ /**
5
+ * 获取单个字段的控制能力
6
+ *
7
+ * 通过 core 层 createField 提供字段操作方法,
8
+ * 通过 subscribe 回调桥接 Signal 变化到 Vue shallowRef。
9
+ *
10
+ * @param name - 字段名(支持嵌套路径,如 'user.address.city')
11
+ * @returns 字段状态和操作方法
12
+ *
13
+ * @example
14
+ * ```typescript
15
+ * const field = useField('username')
16
+ *
17
+ * // 响应式值(在 computed/watchEffect/template 中自动追踪)
18
+ * field.getValue()
19
+ *
20
+ * // 响应式错误
21
+ * field.error.value // string[] | undefined
22
+ *
23
+ * // 响应式脏状态
24
+ * field.dirty.value // boolean
25
+ *
26
+ * // 响应式操作中状态
27
+ * field.pending.value // boolean
28
+ *
29
+ * // 写入值
30
+ * field.setValue('new value')
31
+ *
32
+ * // 校验
33
+ * const result = await field.validate()
34
+ * ```
35
+ */
36
+ export declare const useField: <TValues extends Values = Values>(name: NamePath<TValues>) => FieldInstance<TValues>;
37
+ export default useField;
38
+ //# sourceMappingURL=useField.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useField.d.ts","sourceRoot":"","sources":["../../src/hooks/useField.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAMH,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAI7C,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,EAAE,MAAM,cAAc,CAAA;AAoEpE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,QAAQ,GAAI,OAAO,SAAS,MAAM,GAAG,MAAM,EACtD,MAAM,QAAQ,CAAC,OAAO,CAAC,KACtB,aAAa,CAAC,OAAO,CAuCvB,CAAA;AAED,eAAe,QAAQ,CAAA"}
@@ -0,0 +1,23 @@
1
+ import { Values } from '@schemx/core';
2
+ import { FieldInstance } from '../types/field';
3
+ import { useField } from './useField';
4
+
5
+ /**
6
+ * 向子组件树注入当前字段上下文。
7
+ *
8
+ * 应在 FormItem(或任何创建了 useField 的组件)的 setup 中调用。
9
+ *
10
+ * @param field - useField 返回的字段实例
11
+ */
12
+ export declare function provideFieldContext<TValues extends Values = Values>(field: FieldInstance<TValues>): void;
13
+ /**
14
+ * 从最近的 FormItem 获取当前字段上下文。
15
+ *
16
+ * 必须在 FormItem 的组件子树内调用,否则抛出错误。
17
+ *
18
+ * @returns useField 返回的字段实例
19
+ *
20
+ * @throws 当不在 FormItem 子树内时抛出
21
+ */
22
+ export declare function useFieldContext(): ReturnType<typeof useField>;
23
+ //# sourceMappingURL=useFieldContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFieldContext.d.ts","sourceRoot":"","sources":["../../src/hooks/useFieldContext.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAIH,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAErC,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAK1C;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EACjE,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,GAC5B,IAAI,CAEN;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,IAAI,UAAU,CAAC,OAAO,QAAQ,CAAC,CAQ7D"}
@@ -0,0 +1,59 @@
1
+ import { CreateFormOptions, NamePath, SchemxInstance, Values } from '@schemx/core';
2
+
3
+ /** SchemxInstance 在 Vue provide/inject 中的注入 key */
4
+ export declare const SCHEMX_INSTANCE_KEY: unique symbol;
5
+ /** @deprecated 请使用 SCHEMX_INSTANCE_KEY。保留给旧测试和旧适配代码兼容。 */
6
+ export declare const FORM_INSTANCE_KEY: symbol;
7
+ /**
8
+ * useForm 配置选项
9
+ *
10
+ * 扩展 core 层的 CreateFormOptions,增加 Vue 层特有的 request 配置。
11
+ *
12
+ * @typeParam TValues - 表单值类型
13
+ */
14
+ export interface UseFormOptions<TValues extends Values> extends CreateFormOptions<TValues, NamePath<TValues>> {
15
+ }
16
+ /**
17
+ * 表单组合式函数
18
+ *
19
+ * 创建 SchemxInstance 并通过 Vue provide 注入到子组件树中,
20
+ * 组件卸载时自动销毁实例。
21
+ *
22
+ * @typeParam TValues - 表单值类型
23
+ *
24
+ * @param options - 表单配置选项
25
+ * @returns 表单实例(SchemxInstance 接口)
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * // 在 setup 中使用
30
+ * const form = useForm({
31
+ * initialValues: { name: '', email: '' },
32
+ * onFinish: async (values) => {
33
+ * await api.submit(values)
34
+ * },
35
+ * })
36
+ *
37
+ * form.setFieldValue('name', 'John')
38
+ * ```
39
+ */
40
+ export declare function useForm<TValues extends Values = Values>(options: UseFormOptions<TValues>): SchemxInstance<TValues>;
41
+ /**
42
+ * 获取表单实例
43
+ *
44
+ * 在子组件中获取 useForm 创建的 SchemxInstance,
45
+ * 可用于读写字段值、校验、订阅等操作。
46
+ *
47
+ * @typeParam TValues - 表单值类型
48
+ * @returns 表单实例
49
+ *
50
+ * @throws Error 如果不在 schemx 提供的上下文中调用
51
+ *
52
+ * @example
53
+ * ```ts
54
+ * const form = useFormInstance()
55
+ * form.setFieldValue('name', 'hello')
56
+ * ```
57
+ */
58
+ export declare function useFormInstance<TValues extends Values = Values>(): SchemxInstance<TValues>;
59
+ //# sourceMappingURL=useForm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useForm.d.ts","sourceRoot":"","sources":["../../src/hooks/useForm.ts"],"names":[],"mappings":"AA8BA,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,cAAc,CAAA;AAEvF,mDAAmD;AACnD,eAAO,MAAM,mBAAmB,eAA4B,CAAA;AAC5D,0DAA0D;AAC1D,eAAO,MAAM,iBAAiB,QAAsB,CAAA;AAEpD;;;;;;GAMG;AACH,MAAM,WAAW,cAAc,CAAC,OAAO,SAAS,MAAM,CAAE,SAAQ,iBAAiB,CAC/E,OAAO,EACP,QAAQ,CAAC,OAAO,CAAC,CAClB;CAAG;AAEJ;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,OAAO,CAAC,OAAO,SAAS,MAAM,GAAG,MAAM,EACrD,OAAO,EAAE,cAAc,CAAC,OAAO,CAAC,GAC/B,cAAc,CAAC,OAAO,CAAC,CAkBzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,OAAO,SAAS,MAAM,GAAG,MAAM,KAC5B,cAAc,CAAC,OAAO,CAAC,CAQ3B"}
@@ -0,0 +1,28 @@
1
+ import { ShallowRef } from 'vue';
2
+
3
+ /**
4
+ * 创建一个引用稳定的 shallowRef。
5
+ *
6
+ * 在 watchEffect 中执行工厂函数,自动追踪响应式依赖。
7
+ * 仅当新旧值浅比较不相等时才替换 `.value`,保持引用稳定。
8
+ *
9
+ * @typeParam T - 对象类型
10
+ *
11
+ * @param factory - 返回目标对象的工厂函数,在 watchEffect 内执行
12
+ *
13
+ * @returns 只读的 ShallowRef,引用仅在属性值真正变化时更新
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const props = useStableRef(() => ({
18
+ * value: field.getValue(),
19
+ * onChange: handleChange,
20
+ * }))
21
+ *
22
+ * // props.value 的引用在属性值未变时保持不变
23
+ * h(Component, props.value)
24
+ * ```
25
+ */
26
+ export declare function useStableRef<T extends Record<string, any>>(factory: () => T): Readonly<ShallowRef<T>>;
27
+ export default useStableRef;
28
+ //# sourceMappingURL=useStableRef.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useStableRef.d.ts","sourceRoot":"","sources":["../../src/hooks/useStableRef.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,KAAK,UAAU,EAA2B,MAAM,KAAK,CAAA;AAI9D;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACxD,OAAO,EAAE,MAAM,CAAC,GACf,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAYzB;AAED,eAAe,YAAY,CAAA"}