@movk/nuxt 1.1.2 → 1.2.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 (120) hide show
  1. package/README.md +5 -29
  2. package/dist/module.d.mts +3 -1
  3. package/dist/module.json +3 -3
  4. package/dist/module.mjs +120 -34
  5. package/dist/runtime/auto-form/controls.d.ts +221 -0
  6. package/dist/runtime/auto-form/controls.js +70 -0
  7. package/dist/runtime/{utils → auto-form}/field-utils.d.ts +4 -20
  8. package/dist/runtime/{utils → auto-form}/field-utils.js +1 -2
  9. package/dist/runtime/auto-form/metadata.d.ts +22 -0
  10. package/dist/runtime/auto-form/metadata.js +53 -0
  11. package/dist/runtime/auto-form/provider.d.ts +27 -0
  12. package/dist/runtime/{internal/useAutoFormProvider.js → auto-form/provider.js} +1 -1
  13. package/dist/runtime/{utils → auto-form}/reactive-utils.d.ts +4 -22
  14. package/dist/runtime/{utils → auto-form}/schema-introspector.d.ts +3 -9
  15. package/dist/runtime/{utils → auto-form}/schema-introspector.js +11 -9
  16. package/dist/runtime/components/AutoForm.d.vue.ts +4 -5
  17. package/dist/runtime/components/AutoForm.vue +12 -35
  18. package/dist/runtime/components/AutoForm.vue.d.ts +4 -5
  19. package/dist/runtime/components/ColorChooser.d.vue.ts +10 -6
  20. package/dist/runtime/components/ColorChooser.vue +4 -7
  21. package/dist/runtime/components/ColorChooser.vue.d.ts +10 -6
  22. package/dist/runtime/components/DatePicker.d.vue.ts +16 -10
  23. package/dist/runtime/components/DatePicker.vue.d.ts +16 -10
  24. package/dist/runtime/components/SearchForm.d.vue.ts +171 -0
  25. package/dist/runtime/components/SearchForm.vue +216 -0
  26. package/dist/runtime/components/SearchForm.vue.d.ts +171 -0
  27. package/dist/runtime/components/SlideVerify.d.vue.ts +5 -32
  28. package/dist/runtime/components/SlideVerify.vue +4 -4
  29. package/dist/runtime/components/SlideVerify.vue.d.ts +5 -32
  30. package/dist/runtime/components/StarRating.d.vue.ts +8 -16
  31. package/dist/runtime/components/StarRating.vue +50 -65
  32. package/dist/runtime/components/StarRating.vue.d.ts +8 -16
  33. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.d.vue.ts +10 -2
  34. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue +16 -23
  35. package/dist/runtime/components/auto-form-renderer/AutoFormRendererArray.vue.d.ts +10 -2
  36. package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.d.vue.ts +26 -0
  37. package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.vue +50 -0
  38. package/dist/runtime/components/auto-form-renderer/AutoFormRendererChildren.vue.d.ts +26 -0
  39. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.d.vue.ts +8 -2
  40. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue +2 -2
  41. package/dist/runtime/components/auto-form-renderer/AutoFormRendererField.vue.d.ts +8 -2
  42. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.d.vue.ts +8 -2
  43. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue +29 -64
  44. package/dist/runtime/components/auto-form-renderer/AutoFormRendererLayout.vue.d.ts +8 -2
  45. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.d.vue.ts +8 -2
  46. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue +15 -69
  47. package/dist/runtime/components/auto-form-renderer/AutoFormRendererNested.vue.d.ts +8 -2
  48. package/dist/runtime/components/input/AsPhoneNumberInput.d.vue.ts +36 -0
  49. package/dist/runtime/components/input/AsPhoneNumberInput.vue +35 -0
  50. package/dist/runtime/components/input/AsPhoneNumberInput.vue.d.ts +36 -0
  51. package/dist/runtime/components/input/WithCharacterLimit.d.vue.ts +17 -9
  52. package/dist/runtime/components/input/WithCharacterLimit.vue +5 -5
  53. package/dist/runtime/components/input/WithCharacterLimit.vue.d.ts +17 -9
  54. package/dist/runtime/components/input/WithClear.d.vue.ts +13 -9
  55. package/dist/runtime/components/input/WithClear.vue +2 -2
  56. package/dist/runtime/components/input/WithClear.vue.d.ts +13 -9
  57. package/dist/runtime/components/input/WithCopy.d.vue.ts +16 -10
  58. package/dist/runtime/components/input/WithCopy.vue +3 -3
  59. package/dist/runtime/components/input/WithCopy.vue.d.ts +16 -10
  60. package/dist/runtime/components/input/WithFloatingLabel.d.vue.ts +36 -0
  61. package/dist/runtime/components/input/WithFloatingLabel.vue +67 -0
  62. package/dist/runtime/components/input/WithFloatingLabel.vue.d.ts +36 -0
  63. package/dist/runtime/components/input/WithPasswordToggle.d.vue.ts +11 -9
  64. package/dist/runtime/components/input/WithPasswordToggle.vue +3 -3
  65. package/dist/runtime/components/input/WithPasswordToggle.vue.d.ts +11 -9
  66. package/dist/runtime/components/theme-picker/ThemePicker.d.vue.ts +1 -1
  67. package/dist/runtime/components/theme-picker/ThemePicker.vue +19 -25
  68. package/dist/runtime/components/theme-picker/ThemePicker.vue.d.ts +1 -1
  69. package/dist/runtime/components/theme-picker/ThemePickerButton.d.vue.ts +1 -7
  70. package/dist/runtime/components/theme-picker/ThemePickerButton.vue.d.ts +1 -7
  71. package/dist/runtime/composables/index.d.ts +1 -1
  72. package/dist/runtime/composables/index.js +1 -1
  73. package/dist/runtime/composables/useApiFetch.d.ts +17 -14
  74. package/dist/runtime/composables/useApiFetch.js +3 -28
  75. package/dist/runtime/composables/useAutoForm.d.ts +14 -98
  76. package/dist/runtime/composables/useAutoForm.js +37 -157
  77. package/dist/runtime/composables/useClientApiFetch.d.ts +5 -6
  78. package/dist/runtime/composables/useDownloadWithProgress.js +5 -6
  79. package/dist/runtime/composables/useLazyApiFetch.d.ts +18 -0
  80. package/dist/runtime/composables/useLazyApiFetch.js +4 -0
  81. package/dist/runtime/composables/useTheme.d.ts +17 -14
  82. package/dist/runtime/composables/useTheme.js +68 -72
  83. package/dist/runtime/composables/useUploadWithProgress.d.ts +2 -2
  84. package/dist/runtime/composables/useUploadWithProgress.js +7 -7
  85. package/dist/runtime/constants/api-defaults.d.ts +9 -0
  86. package/dist/runtime/constants/api-defaults.js +32 -0
  87. package/dist/runtime/constants/auto-form.d.ts +0 -2
  88. package/dist/runtime/constants/auto-form.js +0 -25
  89. package/dist/runtime/constants/grid-cols.d.ts +7 -0
  90. package/dist/runtime/constants/grid-cols.js +44 -0
  91. package/dist/runtime/plugins/api.factory.js +78 -121
  92. package/dist/runtime/plugins/theme.js +44 -64
  93. package/dist/runtime/style.css +1 -1
  94. package/dist/runtime/types/api.d.ts +277 -146
  95. package/dist/runtime/types/auto-form.d.ts +122 -411
  96. package/dist/runtime/types/index.d.ts +2 -2
  97. package/dist/runtime/types/index.js +2 -2
  98. package/dist/runtime/types/module.d.ts +70 -13
  99. package/dist/runtime/types/theme.d.ts +2 -0
  100. package/dist/runtime/types/zod.d.ts +11 -10
  101. package/dist/runtime/utils/api-utils.d.ts +27 -48
  102. package/dist/runtime/utils/api-utils.js +18 -47
  103. package/dist/runtime/utils/meta.d.ts +7 -0
  104. package/dist/runtime/utils/meta.js +16 -0
  105. package/package.json +36 -35
  106. package/dist/runtime/composables/useApiAuth.d.ts +0 -47
  107. package/dist/runtime/composables/useApiAuth.js +0 -66
  108. package/dist/runtime/internal/useAutoFormProvider.d.ts +0 -50
  109. package/dist/runtime/schemas/api.d.ts +0 -590
  110. package/dist/runtime/schemas/api.js +0 -228
  111. package/dist/runtime/server/api/_movk/session.post.d.ts +0 -10
  112. package/dist/runtime/server/api/_movk/session.post.js +0 -18
  113. package/dist/runtime/types/auth.d.ts +0 -34
  114. package/dist/runtime/types/auto-form-renderer.d.ts +0 -22
  115. package/dist/runtime/types/components.d.ts +0 -43
  116. package/dist/runtime/types/components.js +0 -0
  117. package/dist/runtime/utils/auto-form.d.ts +0 -3
  118. package/dist/runtime/utils/auto-form.js +0 -18
  119. /package/dist/runtime/{utils → auto-form}/reactive-utils.js +0 -0
  120. /package/dist/runtime/types/{auto-form-renderer.js → theme.js} +0 -0
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  [![Movk Nuxt](https://nuxt.mhaibaraai.cn/og-image.png)](https://nuxt.mhaibaraai.cn/)
2
2
 
3
- > `@movk/nuxt` 是一个为 Nuxt 4 设计的模块化工程套件,提供 Schema 驱动的自动表单生成、API 集成系统、独立 UI 组件和通用工具函数。
3
+ > Nuxt 4 模块化工程套件 — 基于 Zod v4 的 Schema 驱动自动表单、带认证与进度追踪的 API 集成系统、10+ 独立 UI 组件和通用 Composables。
4
4
 
5
5
  [![Install MCP in Cursor](https://nuxt.mhaibaraai.cn/mcp/badge.svg)](https://nuxt.mhaibaraai.cn/mcp/deeplink)
6
6
  [![Install MCP in VS Code](https://nuxt.mhaibaraai.cn/mcp/badge.svg?ide=vscode)](https://nuxt.mhaibaraai.cn/mcp/deeplink?ide=vscode)
@@ -18,7 +18,7 @@
18
18
 
19
19
  - **Schema 驱动** - 基于 Zod v4 的声明式表单定义,一份 Schema 同时定义数据结构、验证规则和 UI 配置。
20
20
  - **自动化系统** - AutoForm 通过 Schema 自动生成完整表单界面,支持 15+ 种控件类型。
21
- - **API 集成** - 内置 useApiFetch、useApiAuth、useUploadWithProgress、useDownloadWithProgress,提供多端点支持、自动认证、业务状态码检查、Toast 提示和进度监控。
21
+ - **API 集成** - 内置 useApiFetch、useUploadWithProgress、useDownloadWithProgress,提供多端点支持、自动认证、业务状态码检查、Toast 提示和进度监控。
22
22
  - **模块化设计** - 采用分层架构,按需使用 UI 组件、工具函数或全套自动化系统。
23
23
  - **独立组件库** - 内置 DatePicker、StarRating、WithCopy 等 10+ 个通用 UI 组件。
24
24
  - **类型安全** - 完整的 TypeScript 类型推断,从 Schema 到表单数据。
@@ -67,7 +67,7 @@ export default defineNuxtConfig({
67
67
  ```vue
68
68
  <script setup lang="ts">
69
69
  import type { FormSubmitEvent } from '@nuxt/ui'
70
- import type { z } from 'zod/v4'
70
+ import type { z } from 'zod'
71
71
 
72
72
  const { afz } = useAutoForm()
73
73
 
@@ -237,29 +237,6 @@ const { data } = await useApiFetch<User>('/users', {
237
237
  const { data } = await useApiFetch('/users', { endpoint: 'v2' })
238
238
  ```
239
239
 
240
- #### useApiAuth
241
-
242
- 与 nuxt-auth-utils 集成的认证管理:
243
-
244
- ```ts
245
- const { login, clear, loggedIn, user } = useApiAuth()
246
-
247
- // 登录
248
- await login({
249
- loginPath: '/auth/login',
250
- credentials: { username: 'admin', password: '123456' },
251
- userInfoPath: '/auth/me' // 可选,登录后获取用户信息
252
- })
253
-
254
- // 登出
255
- await clear()
256
-
257
- // 响应式状态
258
- if (loggedIn.value) {
259
- console.log('当前用户:', user.value)
260
- }
261
- ```
262
-
263
240
  #### useUploadWithProgress
264
241
 
265
242
  带进度监控的文件上传:
@@ -293,7 +270,7 @@ await download('/api/export/report', {
293
270
  Movk Nuxt 采用清晰的分层架构:
294
271
 
295
272
  - **Core Systems** - AutoForm(已发布)
296
- - **API System** - useApiFetch、useApiAuth,提供完整的 API 请求和认证方案
273
+ - **API System** - useApiFetch、useUploadWithProgress、useDownloadWithProgress,提供完整的 API 请求方案
297
274
  - **Standalone Components** - DatePicker、StarRating、WithCopy 等独立 UI 组件
298
275
  - **Composables** - useDateFormatter、useAutoForm 等通用组合式函数
299
276
  - **Foundation** - 基于 [Nuxt UI](https://ui.nuxt.com)、[Zod v4](https://zod.dev)、[VueUse](https://vueuse.org)
@@ -310,9 +287,8 @@ Movk Nuxt 采用清晰的分层架构:
310
287
  ## 🗺️ 开发路线图
311
288
 
312
289
  - ✅ **AutoForm** - Schema 驱动的表单系统(已发布)
313
- - ✅ **API System** - API 请求封装和认证管理(已发布)
290
+ - ✅ **API System** - API 请求封装(已发布)
314
291
  - useApiFetch、useClientApiFetch - API 请求
315
- - useApiAuth - 认证管理
316
292
  - useUploadWithProgress、useDownloadWithProgress - 进度监控
317
293
  - ✅ **独立组件库** - DatePicker、StarRating、WithCopy 等组件(已发布)
318
294
 
package/dist/module.d.mts CHANGED
@@ -1,5 +1,7 @@
1
+ import * as _nuxt_schema from '@nuxt/schema';
2
+ import { ModuleOptions } from '../dist/runtime/types/index.js';
1
3
  export * from '../dist/runtime/types/index.js';
2
4
 
3
- declare const _default: any;
5
+ declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, ModuleOptions, false>;
4
6
 
5
7
  export { _default as default };
package/dist/module.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@movk/nuxt",
3
- "version": "1.1.2",
3
+ "version": "1.2.0",
4
4
  "configKey": "movk",
5
5
  "compatibility": {
6
- "nuxt": ">=4.2.0"
6
+ "nuxt": ">=4.4.2"
7
7
  },
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "1.0.2",
10
- "unbuild": "3.6.1"
10
+ "unbuild": "unknown"
11
11
  }
12
12
  }
package/dist/module.mjs CHANGED
@@ -1,52 +1,119 @@
1
- import { addPlugin, defineNuxtModule, createResolver, addComponentsDir, addImportsDir, addServerHandler } from '@nuxt/kit';
2
- import { apiToastConfigSchema, apiAuthConfigSchema, apiResponseConfigSchema } from '../dist/runtime/schemas/api.js';
3
- import defu from 'defu';
1
+ import { addPlugin, defineNuxtModule, createResolver, addComponentsDir, addImportsDir } from '@nuxt/kit';
2
+ import defu, { defu as defu$1 } from 'defu';
3
+ import { DEFAULT_TOAST_CONFIG, DEFAULT_AUTH_CONFIG, DEFAULT_RESPONSE_CONFIG, DEFAULT_ENDPOINT } from '../dist/runtime/constants/api-defaults.js';
4
+ import { getPackageJsonMetadata } from '../dist/runtime/utils/meta.js';
5
+ import { defineFontProvider } from 'unifont';
4
6
  export * from '../dist/runtime/types/index.js';
5
7
 
6
8
  const name = "@movk/nuxt";
7
- const version = "1.1.2";
9
+ const version = "1.2.0";
8
10
 
9
- function setupTheme(nuxt, resolve) {
11
+ function setupTheme(nuxt, resolve, options) {
12
+ if (options.theme?.enabled === false) return;
10
13
  nuxt.options.appConfig.theme = defu(nuxt.options.appConfig.theme || {}, {
11
14
  radius: 0.25,
12
15
  blackAsPrimary: false,
13
- font: "Public Sans",
16
+ font: "Alibaba PuHuiTi",
14
17
  icons: "lucide"
15
18
  });
19
+ nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, {
20
+ colors: {
21
+ primary: "sky",
22
+ secondary: "blue",
23
+ success: "green",
24
+ info: "blue",
25
+ warning: "yellow",
26
+ error: "red",
27
+ neutral: "slate"
28
+ }
29
+ });
16
30
  nuxt.options.app.head.meta = nuxt.options.app.head.meta || [];
17
31
  nuxt.options.app.head.meta.push(
18
32
  { charset: "utf-8" },
19
33
  { name: "viewport", content: "width=device-width, initial-scale=1" }
20
34
  );
35
+ nuxt.options.app.head.htmlAttrs = defu(nuxt.options.app.head.htmlAttrs || {}, {
36
+ lang: "zh-CN",
37
+ dir: "ltr"
38
+ });
21
39
  addPlugin({
22
40
  src: resolve("runtime/plugins/theme"),
23
41
  mode: "all"
24
42
  });
25
43
  }
26
44
 
27
- const DEFAULT_ENDPOINT = { default: { baseURL: "/api" } };
28
- function splitEndpointConfigs(endpoints) {
29
- const publicEndpoints = {};
30
- const privateEndpoints = {};
31
- if (!endpoints) return { publicEndpoints, privateEndpoints };
32
- for (const [name2, { headers, ...publicConfig }] of Object.entries(endpoints)) {
33
- publicEndpoints[name2] = publicConfig;
34
- if (headers) {
35
- privateEndpoints[name2] = { headers };
45
+ const WEIGHT_MAP = {
46
+ 100: "Thin",
47
+ 300: "Light",
48
+ 400: "Regular",
49
+ 500: "Medium",
50
+ 600: "SemiBold",
51
+ 700: "Bold",
52
+ 800: "ExtraBold",
53
+ 900: "Heavy",
54
+ 950: "Black"
55
+ };
56
+ const FONT_FAMILY = "Alibaba PuHuiTi";
57
+ function createAlibabaPuHuiTiProvider(cdnBase) {
58
+ return defineFontProvider("alibaba-puhuiti", () => ({
59
+ async resolveFont(fontFamily, options) {
60
+ if (fontFamily !== FONT_FAMILY) return void 0;
61
+ const weights = options.weights?.length ? options.weights.filter((w) => WEIGHT_MAP[w]) : Object.keys(WEIGHT_MAP);
62
+ const fonts = weights.map((weight) => ({
63
+ src: [{ url: `${cdnBase}/AlibabaPuHuiTi-${WEIGHT_MAP[weight]}.woff2`, format: "woff2" }],
64
+ weight,
65
+ style: "normal"
66
+ }));
67
+ return { fonts };
36
68
  }
69
+ }));
70
+ }
71
+
72
+ const FONT_PROVIDERS = [
73
+ {
74
+ key: "alibabaPuhuiti",
75
+ providerKey: "alibaba-puhuiti",
76
+ create: createAlibabaPuHuiTiProvider
37
77
  }
38
- return { publicEndpoints, privateEndpoints };
78
+ ];
79
+ const BUNNY_FONT_NAMES = ["Public Sans", "DM Sans", "Geist", "Inter", "Poppins", "Outfit", "Raleway"];
80
+ function setupFonts(options, nuxt) {
81
+ if (options.fonts?.enabled === false) return;
82
+ const nuxtOpts = nuxt.options;
83
+ nuxtOpts.fonts = nuxtOpts.fonts || {};
84
+ nuxtOpts.fonts.families = nuxtOpts.fonts.families || [];
85
+ const existingNames = new Set(nuxtOpts.fonts.families.map((f) => f.name));
86
+ for (const name of BUNNY_FONT_NAMES) {
87
+ if (!existingNames.has(name)) {
88
+ nuxtOpts.fonts.families.push({ name, provider: "bunny" });
89
+ }
90
+ }
91
+ const active = FONT_PROVIDERS.filter((fp) => options.fonts?.[fp.key]?.cdn);
92
+ if (!active.length) return;
93
+ nuxt.hook("fonts:providers", (providers) => {
94
+ for (const fp of active) {
95
+ providers[fp.providerKey] = fp.create(options.fonts[fp.key].cdn);
96
+ }
97
+ });
39
98
  }
99
+
40
100
  function buildApiRuntimeConfig(apiConfig) {
41
- const { publicEndpoints, privateEndpoints } = splitEndpointConfigs(apiConfig.endpoints);
101
+ const publicEndpoints = {};
102
+ const privateEndpoints = {};
103
+ if (apiConfig.endpoints) {
104
+ for (const [key, { headers, ...rest }] of Object.entries(apiConfig.endpoints)) {
105
+ publicEndpoints[key] = rest;
106
+ if (headers) privateEndpoints[key] = { headers };
107
+ }
108
+ }
42
109
  const hasEndpoints = Object.keys(publicEndpoints).length > 0;
43
110
  const publicConfig = {
44
111
  defaultEndpoint: apiConfig.defaultEndpoint ?? "default",
45
112
  debug: apiConfig.debug ?? false,
46
113
  endpoints: hasEndpoints ? publicEndpoints : DEFAULT_ENDPOINT,
47
- response: apiResponseConfigSchema.parse(apiConfig.response ?? {}),
48
- auth: apiAuthConfigSchema.parse(apiConfig.auth ?? {}),
49
- toast: apiToastConfigSchema.parse(apiConfig.toast ?? {})
114
+ response: defu$1(apiConfig.response, DEFAULT_RESPONSE_CONFIG),
115
+ auth: defu$1(apiConfig.auth, DEFAULT_AUTH_CONFIG),
116
+ toast: defu$1(apiConfig.toast, DEFAULT_TOAST_CONFIG)
50
117
  };
51
118
  const privateConfig = {
52
119
  endpoints: Object.keys(privateEndpoints).length > 0 ? privateEndpoints : void 0
@@ -58,26 +125,46 @@ const module$1 = defineNuxtModule({
58
125
  name,
59
126
  version,
60
127
  configKey: "movk",
61
- compatibility: { nuxt: ">=4.2.0" }
128
+ compatibility: { nuxt: ">=4.4.2" }
129
+ },
130
+ defaults: {
131
+ prefix: "M",
132
+ theme: {
133
+ enabled: true
134
+ },
135
+ fonts: {
136
+ enabled: true,
137
+ alibabaPuhuiti: {
138
+ cdn: "https://cdn.mhaibaraai.cn/fonts"
139
+ }
140
+ }
62
141
  },
63
- defaults: { prefix: "M" },
64
142
  moduleDependencies: {
143
+ "@vueuse/nuxt": { version: ">=14.2.1" },
65
144
  "@nuxt/image": { version: ">=2.0.0" },
66
- "@nuxt/ui": { version: ">=4.3.0" },
67
- "@vueuse/nuxt": { version: ">=14.1.0" },
68
- "nuxt-og-image": { version: ">=5.1.13" },
69
- "nuxt-auth-utils": { version: ">=0.5.26" }
145
+ "@nuxt/ui": { version: ">=4.6.0" },
146
+ "nuxt-og-image": {
147
+ version: ">=6.3.1",
148
+ defaults: { zeroRuntime: true }
149
+ },
150
+ "nuxt-auth-utils": { version: ">=0.5.29" }
70
151
  },
71
- setup(options, nuxt) {
152
+ async setup(options, nuxt) {
72
153
  const { resolve } = createResolver(import.meta.url);
73
- setupTheme(nuxt, resolve);
154
+ setupTheme(nuxt, resolve, options);
155
+ setupFonts(options, nuxt);
74
156
  nuxt.options.alias["#movk"] = resolve("./runtime");
157
+ nuxt.options.css = nuxt.options.css || [];
75
158
  nuxt.options.css.push(resolve("runtime/style.css"));
159
+ const componentIgnore = ["auto-form-renderer/**"];
160
+ if (options.theme?.enabled === false) {
161
+ componentIgnore.push("theme-picker/**");
162
+ }
76
163
  addComponentsDir({
77
164
  path: resolve("runtime/components"),
78
165
  prefix: options.prefix,
79
166
  pathPrefix: false,
80
- ignore: ["auto-form-renderer/**", "theme-picker/ThemePickerButton.vue"]
167
+ ignore: componentIgnore
81
168
  });
82
169
  addImportsDir(resolve("runtime/composables"));
83
170
  const apiConfig = options.api ?? {};
@@ -86,12 +173,11 @@ const module$1 = defineNuxtModule({
86
173
  nuxt.options.runtimeConfig.movkApi = privateConfig;
87
174
  nuxt.options.runtimeConfig.public.movkApi = publicConfig;
88
175
  addPlugin({ src: resolve("runtime/plugins/api.factory"), mode: "all" });
89
- addServerHandler({
90
- route: "/api/_movk/session",
91
- method: "post",
92
- handler: resolve("runtime/server/api/_movk/session.post")
93
- });
94
176
  }
177
+ const meta = await getPackageJsonMetadata(nuxt.options.rootDir);
178
+ nuxt.options.site = defu$1(nuxt.options.site, {
179
+ name: meta.name || "movk-nuxt"
180
+ });
95
181
  }
96
182
  });
97
183
 
@@ -0,0 +1,221 @@
1
+ import type { IsComponent } from '@movk/core';
2
+ import type { AutoFormControl, _Unset } from '../types/auto-form.js';
3
+ import type { InputProps, InputSlots, TextareaProps, TextareaSlots } from '@nuxt/ui';
4
+ import { UInput, UTextarea } from '#components';
5
+ /** 声明单个控件配置,恒等函数,仅用于保留精确的组件 props/slots 类型推断 */
6
+ export declare function defineControl<C extends IsComponent, P = _Unset, S = _Unset>(e: AutoFormControl<C, P, S>): AutoFormControl<C, P, S>;
7
+ declare const DEFAULT_CONTROL_COMPONENTS: {
8
+ readonly string: any;
9
+ readonly number: any;
10
+ readonly boolean: any;
11
+ readonly enum: any;
12
+ readonly file: any;
13
+ readonly calendarDate: <R extends boolean, M extends boolean, P extends "click" | "hover" = "click">(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
14
+ slots: {
15
+ default?: (props: any) => any;
16
+ } & {
17
+ leading?: (props: any) => any;
18
+ } & {
19
+ trailing?: (props: any) => any;
20
+ } & {
21
+ anchor?: (props: any) => any;
22
+ } & {
23
+ day?: (props: any) => any;
24
+ } & {
25
+ heading?: (props: any) => any;
26
+ } & {
27
+ 'week-day'?: (props: any) => any;
28
+ };
29
+ attrs: any;
30
+ emit: any;
31
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
32
+ props: any;
33
+ expose: (exposed: {}) => void;
34
+ attrs: any;
35
+ slots: {
36
+ default?: (props: any) => any;
37
+ } & {
38
+ leading?: (props: any) => any;
39
+ } & {
40
+ trailing?: (props: any) => any;
41
+ } & {
42
+ anchor?: (props: any) => any;
43
+ } & {
44
+ day?: (props: any) => any;
45
+ } & {
46
+ heading?: (props: any) => any;
47
+ } & {
48
+ 'week-day'?: (props: any) => any;
49
+ };
50
+ emit: any;
51
+ }>) => import("vue").VNode & {
52
+ __ctx?: Awaited<typeof __VLS_setup>;
53
+ };
54
+ readonly datePicker: <R extends boolean, M extends boolean, P extends "click" | "hover" = "click">(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
55
+ slots: {
56
+ default?: (props: any) => any;
57
+ } & {
58
+ leading?: (props: any) => any;
59
+ } & {
60
+ trailing?: (props: any) => any;
61
+ } & {
62
+ anchor?: (props: any) => any;
63
+ } & {
64
+ day?: (props: any) => any;
65
+ } & {
66
+ heading?: (props: any) => any;
67
+ } & {
68
+ 'week-day'?: (props: any) => any;
69
+ };
70
+ attrs: any;
71
+ emit: any;
72
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
73
+ props: any;
74
+ expose: (exposed: {}) => void;
75
+ attrs: any;
76
+ slots: {
77
+ default?: (props: any) => any;
78
+ } & {
79
+ leading?: (props: any) => any;
80
+ } & {
81
+ trailing?: (props: any) => any;
82
+ } & {
83
+ anchor?: (props: any) => any;
84
+ } & {
85
+ day?: (props: any) => any;
86
+ } & {
87
+ heading?: (props: any) => any;
88
+ } & {
89
+ 'week-day'?: (props: any) => any;
90
+ };
91
+ emit: any;
92
+ }>) => import("vue").VNode & {
93
+ __ctx?: Awaited<typeof __VLS_setup>;
94
+ };
95
+ readonly switch: any;
96
+ readonly textarea: any;
97
+ readonly slider: any;
98
+ readonly pinInput: any;
99
+ readonly inputTags: any;
100
+ readonly selectMenu: any;
101
+ readonly inputMenu: any;
102
+ readonly checkboxGroup: any;
103
+ readonly radioGroup: any;
104
+ readonly inputDate: any;
105
+ readonly inputTime: any;
106
+ readonly withClear: <T extends import("@nuxt/ui").InputValue>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
107
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
108
+ attrs: any;
109
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
110
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
111
+ props: any;
112
+ expose: (exposed: {}) => void;
113
+ attrs: any;
114
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
115
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
116
+ }>) => import("vue").VNode & {
117
+ __ctx?: Awaited<typeof __VLS_setup>;
118
+ };
119
+ readonly withPasswordToggle: <T extends import("@nuxt/ui").InputValue>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
120
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
121
+ attrs: any;
122
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
123
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
124
+ props: any;
125
+ expose: (exposed: {}) => void;
126
+ attrs: any;
127
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
128
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
129
+ }>) => import("vue").VNode & {
130
+ __ctx?: Awaited<typeof __VLS_setup>;
131
+ };
132
+ readonly withCopy: <T extends import("@nuxt/ui").InputValue>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
133
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
134
+ attrs: any;
135
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
136
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
137
+ props: any;
138
+ expose: (exposed: {}) => void;
139
+ attrs: any;
140
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
141
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
142
+ }>) => import("vue").VNode & {
143
+ __ctx?: Awaited<typeof __VLS_setup>;
144
+ };
145
+ readonly withCharacterLimit: <T extends import("@nuxt/ui").InputValue>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
146
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
147
+ attrs: any;
148
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
149
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
150
+ props: any;
151
+ expose: (exposed: {}) => void;
152
+ attrs: any;
153
+ slots: import("@movk/core").OmitByKey<InputSlots, "trailing">;
154
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
155
+ }>) => import("vue").VNode & {
156
+ __ctx?: Awaited<typeof __VLS_setup>;
157
+ };
158
+ readonly asPhoneNumberInput: <T extends import("@nuxt/ui").InputValue>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
159
+ slots: import("@movk/core").OmitByKey<InputSlots, "leading">;
160
+ attrs: any;
161
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
162
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
163
+ props: any;
164
+ expose: (exposed: {}) => void;
165
+ attrs: any;
166
+ slots: import("@movk/core").OmitByKey<InputSlots, "leading">;
167
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
168
+ }>) => import("vue").VNode & {
169
+ __ctx?: Awaited<typeof __VLS_setup>;
170
+ };
171
+ readonly withFloatingLabel: <T extends import("@nuxt/ui").InputValue>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
172
+ slots: import("@movk/core").OmitByKey<InputSlots, "default" | "trailing">;
173
+ attrs: any;
174
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
175
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
176
+ props: any;
177
+ expose: (exposed: {}) => void;
178
+ attrs: any;
179
+ slots: import("@movk/core").OmitByKey<InputSlots, "default" | "trailing">;
180
+ emit: any & ((event: "update:modelValue", value: T | undefined) => void);
181
+ }>) => import("vue").VNode & {
182
+ __ctx?: Awaited<typeof __VLS_setup>;
183
+ };
184
+ readonly colorChooser: <P extends "click" | "hover" = "click">(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: {
185
+ slots: {
186
+ default?: (props: any) => any;
187
+ } & {
188
+ leading?: (props: any) => any;
189
+ } & {
190
+ trailing?: (props: any) => any;
191
+ } & {
192
+ anchor?: (props: any) => any;
193
+ };
194
+ attrs: any;
195
+ emit: any & ((event: "update:modelValue", value: string | undefined) => void);
196
+ }, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
197
+ props: any;
198
+ expose: (exposed: {}) => void;
199
+ attrs: any;
200
+ slots: {
201
+ default?: (props: any) => any;
202
+ } & {
203
+ leading?: (props: any) => any;
204
+ } & {
205
+ trailing?: (props: any) => any;
206
+ } & {
207
+ anchor?: (props: any) => any;
208
+ };
209
+ emit: any & ((event: "update:modelValue", value: string | undefined) => void);
210
+ }>) => import("vue").VNode & {
211
+ __ctx?: Awaited<typeof __VLS_setup>;
212
+ };
213
+ readonly starRating: any;
214
+ readonly slideVerify: any;
215
+ };
216
+ type DefaultControlComponents = typeof DEFAULT_CONTROL_COMPONENTS;
217
+ type DefaultControlMap = {
218
+ readonly [K in keyof DefaultControlComponents]: K extends 'string' ? AutoFormControl<typeof UInput, InputProps, InputSlots> : K extends 'textarea' ? AutoFormControl<typeof UTextarea, TextareaProps, TextareaSlots> : AutoFormControl<DefaultControlComponents[K]>;
219
+ };
220
+ export declare const DEFAULT_CONTROLS: DefaultControlMap;
221
+ export {};
@@ -0,0 +1,70 @@
1
+ import WithClear from "../components/input/WithClear.vue";
2
+ import WithPasswordToggle from "../components/input/WithPasswordToggle.vue";
3
+ import WithCopy from "../components/input/WithCopy.vue";
4
+ import WithCharacterLimit from "../components/input/WithCharacterLimit.vue";
5
+ import AsPhoneNumberInput from "../components/input/AsPhoneNumberInput.vue";
6
+ import WithFloatingLabel from "../components/input/WithFloatingLabel.vue";
7
+ import DatePicker from "../components/DatePicker.vue";
8
+ import ColorChooser from "../components/ColorChooser.vue";
9
+ import StarRating from "../components/StarRating.vue";
10
+ import SlideVerify from "../components/SlideVerify.vue";
11
+ import {
12
+ UInput,
13
+ UInputNumber,
14
+ UCheckbox,
15
+ USwitch,
16
+ UTextarea,
17
+ USlider,
18
+ UPinInput,
19
+ UInputTags,
20
+ UFileUpload,
21
+ USelect,
22
+ USelectMenu,
23
+ UInputMenu,
24
+ UCheckboxGroup,
25
+ URadioGroup,
26
+ UInputDate,
27
+ UInputTime
28
+ } from "#components";
29
+ const DEFAULT_CONTROL_PROPS = { class: "w-full" };
30
+ export function defineControl(e) {
31
+ return e;
32
+ }
33
+ function createControlMap(components, defaultProps = DEFAULT_CONTROL_PROPS) {
34
+ return Object.fromEntries(
35
+ Object.entries(components).map(([key, component]) => [
36
+ key,
37
+ { component, controlProps: defaultProps }
38
+ ])
39
+ );
40
+ }
41
+ const DEFAULT_CONTROL_COMPONENTS = {
42
+ string: UInput,
43
+ number: UInputNumber,
44
+ boolean: UCheckbox,
45
+ enum: USelect,
46
+ file: UFileUpload,
47
+ calendarDate: DatePicker,
48
+ datePicker: DatePicker,
49
+ switch: USwitch,
50
+ textarea: UTextarea,
51
+ slider: USlider,
52
+ pinInput: UPinInput,
53
+ inputTags: UInputTags,
54
+ selectMenu: USelectMenu,
55
+ inputMenu: UInputMenu,
56
+ checkboxGroup: UCheckboxGroup,
57
+ radioGroup: URadioGroup,
58
+ inputDate: UInputDate,
59
+ inputTime: UInputTime,
60
+ withClear: WithClear,
61
+ withPasswordToggle: WithPasswordToggle,
62
+ withCopy: WithCopy,
63
+ withCharacterLimit: WithCharacterLimit,
64
+ asPhoneNumberInput: AsPhoneNumberInput,
65
+ withFloatingLabel: WithFloatingLabel,
66
+ colorChooser: ColorChooser,
67
+ starRating: StarRating,
68
+ slideVerify: SlideVerify
69
+ };
70
+ export const DEFAULT_CONTROLS = createControlMap(DEFAULT_CONTROL_COMPONENTS);
@@ -1,8 +1,6 @@
1
1
  import type { VNode } from 'vue';
2
2
  import type { AutoFormField } from '../types/auto-form.js';
3
- /**
4
- * 字段分类
5
- */
3
+ /** 将字段列表分类为叶子/嵌套/数组/布局四组 */
6
4
  export declare function classifyFields(fields: AutoFormField[]): {
7
5
  leafFields: AutoFormField[];
8
6
  nestedFields: AutoFormField[];
@@ -10,25 +8,11 @@ export declare function classifyFields(fields: AutoFormField[]): {
10
8
  layoutFields: AutoFormField[];
11
9
  hasComplexFields: boolean;
12
10
  };
13
- /**
14
- * 优化的字段类型检测 - 基于 meta.type 判断
15
- * @param field - 自动表单字段
16
- * @returns 是否为叶子字段(非 object 和 array)
17
- */
18
11
  export declare function isLeafField(field: AutoFormField): boolean;
19
- /**
20
- * 获取字段类型
21
- * @param field - 自动表单字段
22
- * @returns 字段类型
23
- */
24
12
  export declare function getFieldType(field: AutoFormField): 'leaf' | 'nested';
25
- /**
26
- * 收集字段默认值
27
- */
13
+ /** 递归收集字段的默认值,object 类型返回嵌套结构,叶子类型直接返回值 */
28
14
  export declare function collectFieldDefaults(field: AutoFormField): {} | null | undefined;
29
- /**
30
- * 从 SelectMenuItem 数组中提取枚举值
31
- */
15
+ /** 从 items 选项中提取枚举值,支持对象格式(取 valueKey/value/label)和原始值 */
32
16
  export declare function extractEnumValuesFromItems(items: any, valueKey?: string): string[];
33
- /** 创建提示插槽工厂 */
17
+ /** 创建数组项的 hint 插槽渲染函数,根据层级和字段类型组合删除按钮与折叠图标 */
34
18
  export declare function createHintSlotFactory(removeCallback: (count?: number) => void): (field: AutoFormField, path: string, open?: boolean, count?: number) => VNode | undefined;
@@ -95,7 +95,6 @@ export function createHintSlotFactory(removeCallback) {
95
95
  color: "error",
96
96
  variant: "ghost",
97
97
  size: "xs",
98
- square: true,
99
98
  onClick: (event) => {
100
99
  event?.stopPropagation();
101
100
  removeCallback(count);
@@ -104,7 +103,7 @@ export function createHintSlotFactory(removeCallback) {
104
103
  if (!isObject) {
105
104
  return deleteButton;
106
105
  }
107
- return h("div", { class: "flex items-center gap-2" }, [
106
+ return h("div", { class: "flex items-center gap-1.5" }, [
108
107
  deleteButton,
109
108
  chevronIcon
110
109
  ]);