@nuxt/ui 4.5.1 → 4.6.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 (183) hide show
  1. package/README.md +1 -1
  2. package/dist/module.d.mts +7 -0
  3. package/dist/module.json +2 -2
  4. package/dist/module.mjs +79 -67
  5. package/dist/runtime/components/Avatar.vue +10 -12
  6. package/dist/runtime/components/Banner.vue +1 -1
  7. package/dist/runtime/components/BlogPost.vue +3 -2
  8. package/dist/runtime/components/Calendar.d.vue.ts +4 -4
  9. package/dist/runtime/components/Calendar.vue.d.ts +4 -4
  10. package/dist/runtime/components/ChangelogVersion.vue +3 -2
  11. package/dist/runtime/components/ChangelogVersions.vue +1 -1
  12. package/dist/runtime/components/ChatMessage.d.vue.ts +4 -1
  13. package/dist/runtime/components/ChatMessage.vue +5 -0
  14. package/dist/runtime/components/ChatMessage.vue.d.ts +4 -1
  15. package/dist/runtime/components/ChatMessages.vue +14 -1
  16. package/dist/runtime/components/ChatPrompt.vue +6 -1
  17. package/dist/runtime/components/ChatReasoning.d.vue.ts +78 -0
  18. package/dist/runtime/components/ChatReasoning.vue +162 -0
  19. package/dist/runtime/components/ChatReasoning.vue.d.ts +78 -0
  20. package/dist/runtime/components/ChatShimmer.d.vue.ts +34 -0
  21. package/dist/runtime/components/ChatShimmer.vue +37 -0
  22. package/dist/runtime/components/ChatShimmer.vue.d.ts +34 -0
  23. package/dist/runtime/components/ChatTool.d.vue.ts +88 -0
  24. package/dist/runtime/components/ChatTool.vue +105 -0
  25. package/dist/runtime/components/ChatTool.vue.d.ts +88 -0
  26. package/dist/runtime/components/Checkbox.d.vue.ts +22 -19
  27. package/dist/runtime/components/Checkbox.vue +9 -8
  28. package/dist/runtime/components/Checkbox.vue.d.ts +22 -19
  29. package/dist/runtime/components/DashboardGroup.d.vue.ts +1 -1
  30. package/dist/runtime/components/DashboardGroup.vue.d.ts +1 -1
  31. package/dist/runtime/components/DashboardSearchButton.vue +2 -2
  32. package/dist/runtime/components/DashboardSidebar.vue +6 -3
  33. package/dist/runtime/components/Drawer.vue +6 -4
  34. package/dist/runtime/components/DropdownMenu.d.vue.ts +29 -3
  35. package/dist/runtime/components/DropdownMenu.vue +9 -0
  36. package/dist/runtime/components/DropdownMenu.vue.d.ts +29 -3
  37. package/dist/runtime/components/DropdownMenuContent.d.vue.ts +9 -3
  38. package/dist/runtime/components/DropdownMenuContent.vue +62 -9
  39. package/dist/runtime/components/DropdownMenuContent.vue.d.ts +9 -3
  40. package/dist/runtime/components/EditorDragHandle.d.vue.ts +4 -4
  41. package/dist/runtime/components/EditorDragHandle.vue.d.ts +4 -4
  42. package/dist/runtime/components/Error.vue +5 -5
  43. package/dist/runtime/components/FileUpload.d.vue.ts +6 -0
  44. package/dist/runtime/components/FileUpload.vue +11 -7
  45. package/dist/runtime/components/FileUpload.vue.d.ts +6 -0
  46. package/dist/runtime/components/Icon.d.vue.ts +2 -1
  47. package/dist/runtime/components/Icon.vue +3 -3
  48. package/dist/runtime/components/Icon.vue.d.ts +2 -1
  49. package/dist/runtime/components/InputDate.d.vue.ts +4 -4
  50. package/dist/runtime/components/InputDate.vue.d.ts +4 -4
  51. package/dist/runtime/components/InputMenu.d.vue.ts +7 -1
  52. package/dist/runtime/components/InputMenu.vue +67 -48
  53. package/dist/runtime/components/InputMenu.vue.d.ts +7 -1
  54. package/dist/runtime/components/InputTime.d.vue.ts +53 -27
  55. package/dist/runtime/components/InputTime.vue +52 -27
  56. package/dist/runtime/components/InputTime.vue.d.ts +53 -27
  57. package/dist/runtime/components/Kbd.vue +1 -1
  58. package/dist/runtime/components/Modal.vue +6 -4
  59. package/dist/runtime/components/NavigationMenu.vue +1 -0
  60. package/dist/runtime/components/Popover.vue +1 -1
  61. package/dist/runtime/components/Progress.d.vue.ts +1 -1
  62. package/dist/runtime/components/Progress.vue.d.ts +1 -1
  63. package/dist/runtime/components/SelectMenu.d.vue.ts +1 -1
  64. package/dist/runtime/components/SelectMenu.vue +1 -1
  65. package/dist/runtime/components/SelectMenu.vue.d.ts +1 -1
  66. package/dist/runtime/components/Sidebar.d.vue.ts +131 -0
  67. package/dist/runtime/components/Sidebar.vue +222 -0
  68. package/dist/runtime/components/Sidebar.vue.d.ts +131 -0
  69. package/dist/runtime/components/Slideover.vue +6 -4
  70. package/dist/runtime/components/Switch.d.vue.ts +22 -19
  71. package/dist/runtime/components/Switch.vue +7 -6
  72. package/dist/runtime/components/Switch.vue.d.ts +22 -19
  73. package/dist/runtime/components/Table.d.vue.ts +1 -1
  74. package/dist/runtime/components/Table.vue +12 -4
  75. package/dist/runtime/components/Table.vue.d.ts +1 -1
  76. package/dist/runtime/components/Tooltip.d.vue.ts +2 -0
  77. package/dist/runtime/components/Tooltip.vue +3 -2
  78. package/dist/runtime/components/Tooltip.vue.d.ts +2 -0
  79. package/dist/runtime/components/color-mode/ColorModeSelect.d.vue.ts +1 -1
  80. package/dist/runtime/components/color-mode/ColorModeSelect.vue.d.ts +1 -1
  81. package/dist/runtime/components/color-mode/ColorModeSwitch.vue +3 -1
  82. package/dist/runtime/components/content/ContentNavigation.vue +9 -2
  83. package/dist/runtime/components/content/ContentSurround.vue +6 -2
  84. package/dist/runtime/components/content/ContentToc.d.vue.ts +5 -0
  85. package/dist/runtime/components/content/ContentToc.vue +57 -11
  86. package/dist/runtime/components/content/ContentToc.vue.d.ts +5 -0
  87. package/dist/runtime/components/locale/LocaleSelect.d.vue.ts +1 -1
  88. package/dist/runtime/components/locale/LocaleSelect.vue.d.ts +1 -1
  89. package/dist/runtime/components/prose/Pre.vue +0 -4
  90. package/dist/runtime/composables/index.d.ts +12 -0
  91. package/dist/runtime/composables/index.js +12 -0
  92. package/dist/runtime/composables/useEditorMenu.js +1 -1
  93. package/dist/runtime/composables/useFileUpload.d.ts +2 -2
  94. package/dist/runtime/composables/useFileUpload.js +3 -3
  95. package/dist/runtime/composables/{internal/useFilter.js → useFilter.js} +1 -1
  96. package/dist/runtime/composables/useIMEGuard.d.ts +10 -0
  97. package/dist/runtime/composables/useIMEGuard.js +22 -0
  98. package/dist/runtime/composables/useScrollShadow.d.ts +23 -0
  99. package/dist/runtime/composables/useScrollShadow.js +36 -0
  100. package/dist/runtime/index.css +1 -1
  101. package/dist/runtime/keyframes.css +1 -1
  102. package/dist/runtime/locale/ar.js +13 -0
  103. package/dist/runtime/locale/az.js +13 -0
  104. package/dist/runtime/locale/be.js +13 -0
  105. package/dist/runtime/locale/bg.js +13 -0
  106. package/dist/runtime/locale/bn.js +13 -0
  107. package/dist/runtime/locale/ca.js +13 -0
  108. package/dist/runtime/locale/ckb.js +13 -0
  109. package/dist/runtime/locale/cs.js +13 -0
  110. package/dist/runtime/locale/da.js +13 -0
  111. package/dist/runtime/locale/de.js +13 -0
  112. package/dist/runtime/locale/de_ch.js +13 -0
  113. package/dist/runtime/locale/el.js +13 -0
  114. package/dist/runtime/locale/en.js +13 -0
  115. package/dist/runtime/locale/es.js +13 -0
  116. package/dist/runtime/locale/et.js +13 -0
  117. package/dist/runtime/locale/eu.js +13 -0
  118. package/dist/runtime/locale/fa_ir.js +13 -0
  119. package/dist/runtime/locale/fi.js +13 -0
  120. package/dist/runtime/locale/fr.js +13 -0
  121. package/dist/runtime/locale/gl.js +13 -0
  122. package/dist/runtime/locale/he.js +13 -0
  123. package/dist/runtime/locale/hi.js +13 -0
  124. package/dist/runtime/locale/hr.js +13 -0
  125. package/dist/runtime/locale/hu.js +13 -0
  126. package/dist/runtime/locale/hy.js +13 -0
  127. package/dist/runtime/locale/id.js +13 -0
  128. package/dist/runtime/locale/index.d.ts +1 -0
  129. package/dist/runtime/locale/index.js +1 -0
  130. package/dist/runtime/locale/is.d.ts +3 -0
  131. package/dist/runtime/locale/is.js +142 -0
  132. package/dist/runtime/locale/it.js +13 -0
  133. package/dist/runtime/locale/ja.js +13 -0
  134. package/dist/runtime/locale/ka.js +13 -0
  135. package/dist/runtime/locale/kk.js +13 -0
  136. package/dist/runtime/locale/km.js +13 -0
  137. package/dist/runtime/locale/ko.js +13 -0
  138. package/dist/runtime/locale/ky.js +13 -0
  139. package/dist/runtime/locale/lb.js +13 -0
  140. package/dist/runtime/locale/lo.js +13 -0
  141. package/dist/runtime/locale/lt.js +13 -0
  142. package/dist/runtime/locale/mn.js +13 -0
  143. package/dist/runtime/locale/ms.js +13 -0
  144. package/dist/runtime/locale/nb_no.js +13 -0
  145. package/dist/runtime/locale/nl.js +13 -0
  146. package/dist/runtime/locale/pl.js +13 -0
  147. package/dist/runtime/locale/pt.js +13 -0
  148. package/dist/runtime/locale/pt_br.js +13 -0
  149. package/dist/runtime/locale/ro.js +13 -0
  150. package/dist/runtime/locale/ru.js +13 -0
  151. package/dist/runtime/locale/sk.js +13 -0
  152. package/dist/runtime/locale/sl.js +13 -0
  153. package/dist/runtime/locale/sq.js +13 -0
  154. package/dist/runtime/locale/sv.js +13 -0
  155. package/dist/runtime/locale/th.js +13 -0
  156. package/dist/runtime/locale/tj.js +13 -0
  157. package/dist/runtime/locale/tr.js +13 -0
  158. package/dist/runtime/locale/ug_cn.js +13 -0
  159. package/dist/runtime/locale/uk.js +13 -0
  160. package/dist/runtime/locale/ur.js +13 -0
  161. package/dist/runtime/locale/uz.js +13 -0
  162. package/dist/runtime/locale/vi.js +13 -0
  163. package/dist/runtime/locale/zh_cn.js +13 -0
  164. package/dist/runtime/locale/zh_tw.js +13 -0
  165. package/dist/runtime/types/index.d.ts +4 -0
  166. package/dist/runtime/types/index.js +4 -0
  167. package/dist/runtime/types/locale.d.ts +13 -0
  168. package/dist/runtime/utils/ai.d.ts +23 -0
  169. package/dist/runtime/utils/ai.js +16 -0
  170. package/dist/runtime/utils/editor.js +17 -5
  171. package/dist/runtime/vue/components/Icon.d.vue.ts +1 -4
  172. package/dist/runtime/vue/components/Icon.vue +28 -3
  173. package/dist/runtime/vue/components/Icon.vue.d.ts +1 -4
  174. package/dist/runtime/vue/components/color-mode/ColorModeSelect.d.vue.ts +1 -1
  175. package/dist/runtime/vue/components/color-mode/ColorModeSelect.vue.d.ts +1 -1
  176. package/dist/runtime/vue/components/color-mode/ColorModeSwitch.vue +3 -1
  177. package/dist/shared/{ui.DI_ypO2T.mjs → ui.DJUbBpE2.mjs} +298 -39
  178. package/dist/unplugin.d.mts +15 -5
  179. package/dist/unplugin.mjs +53 -30
  180. package/dist/vite.d.mts +1 -0
  181. package/dist/vite.mjs +1 -1
  182. package/package.json +50 -47
  183. /package/dist/runtime/composables/{internal/useFilter.d.ts → useFilter.d.ts} +0 -0
package/README.md CHANGED
@@ -126,7 +126,7 @@ Thank you for considering contributing to Nuxt UI. Here are a few ways you can g
126
126
  - Suggestions: Have any thoughts to enhance Nuxt UI? We'd love to hear them! Check out the [contribution guide](https://ui.nuxt.com/docs/getting-started/contribution) to share your suggestions.
127
127
 
128
128
  > [!TIP]
129
- > We provide a [contributing skill](https://github.com/nuxt/ui/tree/v4/.claude/skills/contributing) for AI assistants to help you contribute to Nuxt UI. It will automatically guide you through component structure, theming patterns, testing conventions, and documentation guidelines when working in this repository.
129
+ > We provide contributing guidelines through [`AGENTS.md`](https://github.com/nuxt/ui/blob/v4/AGENTS.md) for AI assistants to help you contribute to Nuxt UI. It is automatically picked up by all AI coding agents and guides through component structure, theming patterns, testing conventions, and documentation guidelines.
130
130
 
131
131
  ## Local Development
132
132
 
package/dist/module.d.mts CHANGED
@@ -66,11 +66,18 @@ interface ModuleOptions {
66
66
  /**
67
67
  * Force the import of prose components even if `@nuxtjs/mdc` or `@nuxt/content` are not installed
68
68
  * @defaultValue false
69
+ * @see https://ui.nuxt.com/docs/getting-started/installation/nuxt#prose
70
+ */
71
+ prose?: boolean;
72
+ /**
73
+ * @deprecated Use `prose` instead
74
+ * @see https://ui.nuxt.com/docs/getting-started/installation/nuxt#mdc
69
75
  */
70
76
  mdc?: boolean;
71
77
  /**
72
78
  * Force the import of content & prose components even if `@nuxt/content` is not installed
73
79
  * @defaultValue false
80
+ * @see https://ui.nuxt.com/docs/getting-started/installation/nuxt#content
74
81
  */
75
82
  content?: boolean;
76
83
  /**
package/dist/module.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@nuxt/ui",
3
- "version": "4.5.1",
3
+ "version": "4.6.1",
4
4
  "docs": "https://ui.nuxt.com/docs/getting-started/installation/nuxt",
5
5
  "configKey": "ui",
6
6
  "compatibility": {
7
- "nuxt": ">=4.0.0"
7
+ "nuxt": ">=4.1.0"
8
8
  },
9
9
  "builder": {
10
10
  "@nuxt/module-builder": "1.0.2",
package/dist/module.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { defu } from 'defu';
2
- import { defineNuxtModule, createResolver, addPlugin, hasNuxtModule, addComponentsDir, addImportsDir, installModule } from '@nuxt/kit';
3
- import { d as defaultOptions, r as resolveColors, a as getDefaultConfig, b as addTemplates } from './shared/ui.DI_ypO2T.mjs';
2
+ import { defineNuxtModule, createResolver, addPlugin, hasNuxtModule, addComponentsDir, addImportsDir, addImports } from '@nuxt/kit';
3
+ import { d as defaultOptions, r as resolveColors, a as getDefaultConfig, p as publicComposables, b as addTemplates } from './shared/ui.DJUbBpE2.mjs';
4
4
  import '../dist/runtime/utils/index.js';
5
5
  import 'node:url';
6
6
  import 'scule';
@@ -11,7 +11,7 @@ import 'pathe';
11
11
  import 'tinyglobby';
12
12
 
13
13
  const name = "@nuxt/ui";
14
- const version = "4.5.1";
14
+ const version = "4.6.1";
15
15
 
16
16
  const module$1 = defineNuxtModule({
17
17
  meta: {
@@ -20,10 +20,76 @@ const module$1 = defineNuxtModule({
20
20
  docs: "https://ui.nuxt.com/docs/getting-started/installation/nuxt",
21
21
  configKey: "ui",
22
22
  compatibility: {
23
- nuxt: ">=4.0.0"
23
+ nuxt: ">=4.1.0"
24
24
  }
25
25
  },
26
26
  defaults: defaultOptions,
27
+ moduleDependencies(nuxt) {
28
+ const userUiOptions = nuxt.options.ui || {};
29
+ return {
30
+ "@nuxt/icon": {
31
+ defaults: {
32
+ cssLayer: "base"
33
+ }
34
+ },
35
+ ...userUiOptions.fonts !== false && {
36
+ "@nuxt/fonts": {
37
+ defaults: {
38
+ defaults: {
39
+ weights: [400, 500, 600, 700]
40
+ }
41
+ }
42
+ }
43
+ },
44
+ ...userUiOptions.colorMode !== false && {
45
+ "@nuxtjs/color-mode": {
46
+ defaults: {
47
+ classSuffix: "",
48
+ disableTransition: true
49
+ }
50
+ }
51
+ },
52
+ "@nuxtjs/mdc": {
53
+ optional: !userUiOptions.mdc && !userUiOptions.content,
54
+ defaults: {
55
+ highlight: {
56
+ theme: {
57
+ light: "material-theme-lighter",
58
+ default: "material-theme",
59
+ dark: "material-theme-palenight"
60
+ }
61
+ },
62
+ components: {
63
+ map: {
64
+ "accordion": "ProseAccordion",
65
+ "accordion-item": "ProseAccordionItem",
66
+ "badge": "ProseBadge",
67
+ "callout": "ProseCallout",
68
+ "card": "ProseCard",
69
+ "card-group": "ProseCardGroup",
70
+ "caution": "ProseCaution",
71
+ "code-collapse": "ProseCodeCollapse",
72
+ "code-group": "ProseCodeGroup",
73
+ "code-icon": "ProseCodeIcon",
74
+ "code-preview": "ProseCodePreview",
75
+ "code-tree": "ProseCodeTree",
76
+ "collapsible": "ProseCollapsible",
77
+ "field": "ProseField",
78
+ "field-group": "ProseFieldGroup",
79
+ "icon": "ProseIcon",
80
+ "kbd": "ProseKbd",
81
+ "note": "ProseNote",
82
+ "steps": "ProseSteps",
83
+ "tabs": "ProseTabs",
84
+ "tabs-item": "ProseTabsItem",
85
+ "tip": "ProseTip",
86
+ "warning": "ProseWarning"
87
+ }
88
+ }
89
+ }
90
+ }
91
+ };
92
+ },
27
93
  async setup(options, nuxt) {
28
94
  const { resolve } = createResolver(import.meta.url);
29
95
  options.theme = options.theme || {};
@@ -31,6 +97,7 @@ const module$1 = defineNuxtModule({
31
97
  nuxt.options.ui = options;
32
98
  nuxt.options.alias["#ui"] = resolve("./runtime");
33
99
  nuxt.options.appConfig.ui = defu(nuxt.options.appConfig.ui || {}, getDefaultConfig(options.theme));
100
+ nuxt.options.build.transpile.push("reka-ui");
34
101
  nuxt.options.app.rootAttrs = nuxt.options.app.rootAttrs || {};
35
102
  nuxt.options.app.rootAttrs.class = [nuxt.options.app.rootAttrs.class, `${options.theme?.prefix ? options.theme.prefix + ":" : ""}isolate`].filter(Boolean).join(" ");
36
103
  nuxt.hook("vite:extend", async ({ config }) => {
@@ -41,67 +108,8 @@ const module$1 = defineNuxtModule({
41
108
  if (nuxt.options.builder !== "@nuxt/vite-builder") {
42
109
  nuxt.options.postcss.plugins["@tailwindcss/postcss"] = {};
43
110
  }
44
- async function registerModule(name2, key, options2) {
45
- if (!hasNuxtModule(name2)) {
46
- await installModule(name2, defu(nuxt.options[key], options2));
47
- } else {
48
- nuxt.options[key] = defu(nuxt.options[key], options2);
49
- }
50
- }
51
- await registerModule("@nuxt/icon", "icon", {
52
- cssLayer: "base"
53
- });
54
- if (options.fonts) {
55
- await registerModule("@nuxt/fonts", "fonts", {
56
- defaults: {
57
- weights: [400, 500, 600, 700]
58
- }
59
- });
60
- }
61
- if (options.colorMode) {
62
- await registerModule("@nuxtjs/color-mode", "colorMode", {
63
- classSuffix: "",
64
- disableTransition: true
65
- });
66
- }
67
111
  addPlugin({ src: resolve("./runtime/plugins/colors") });
68
- if (hasNuxtModule("@nuxtjs/mdc") || options.mdc || (hasNuxtModule("@nuxt/content") || options.content)) {
69
- nuxt.options.mdc = defu(nuxt.options.mdc, {
70
- highlight: {
71
- theme: {
72
- light: "material-theme-lighter",
73
- default: "material-theme",
74
- dark: "material-theme-palenight"
75
- }
76
- },
77
- components: {
78
- map: {
79
- "accordion": "ProseAccordion",
80
- "accordion-item": "ProseAccordionItem",
81
- "badge": "ProseBadge",
82
- "callout": "ProseCallout",
83
- "card": "ProseCard",
84
- "card-group": "ProseCardGroup",
85
- "caution": "ProseCaution",
86
- "code-collapse": "ProseCodeCollapse",
87
- "code-group": "ProseCodeGroup",
88
- "code-icon": "ProseCodeIcon",
89
- "code-preview": "ProseCodePreview",
90
- "code-tree": "ProseCodeTree",
91
- "collapsible": "ProseCollapsible",
92
- "field": "ProseField",
93
- "field-group": "ProseFieldGroup",
94
- "icon": "ProseIcon",
95
- "kbd": "ProseKbd",
96
- "note": "ProseNote",
97
- "steps": "ProseSteps",
98
- "tabs": "ProseTabs",
99
- "tabs-item": "ProseTabsItem",
100
- "tip": "ProseTip",
101
- "warning": "ProseWarning"
102
- }
103
- }
104
- });
112
+ if (options.prose || options.mdc || options.content || hasNuxtModule("@nuxtjs/mdc") || hasNuxtModule("@nuxt/content")) {
105
113
  addComponentsDir({
106
114
  path: resolve("./runtime/components/prose"),
107
115
  pathPrefix: false,
@@ -109,14 +117,14 @@ const module$1 = defineNuxtModule({
109
117
  global: true
110
118
  });
111
119
  }
112
- if (hasNuxtModule("@nuxt/content") || options.content) {
120
+ if (options.content || hasNuxtModule("@nuxt/content")) {
113
121
  addComponentsDir({
114
122
  path: resolve("./runtime/components/content"),
115
123
  pathPrefix: false,
116
124
  prefix: options.prefix
117
125
  });
118
126
  }
119
- if (hasNuxtModule("@nuxtjs/color-mode")) {
127
+ if (options.colorMode || hasNuxtModule("@nuxtjs/color-mode")) {
120
128
  addComponentsDir({
121
129
  path: resolve("./runtime/components/color-mode"),
122
130
  pathPrefix: false,
@@ -131,7 +139,11 @@ const module$1 = defineNuxtModule({
131
139
  prefix: options.prefix,
132
140
  ignore: ["color-mode/**", "content/**", "prose/**"]
133
141
  });
134
- addImportsDir(resolve("./runtime/composables"));
142
+ addImports(
143
+ Object.entries(publicComposables).flatMap(
144
+ ([file, exports$1]) => exports$1.map((name2) => ({ name: name2, from: resolve(`./runtime/composables/${file}`) }))
145
+ )
146
+ );
135
147
  addTemplates(options, nuxt, resolve);
136
148
  }
137
149
  });
@@ -39,17 +39,15 @@ const { size } = useAvatarGroup(props);
39
39
  const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.avatar || {} })({
40
40
  size: size.value
41
41
  }));
42
- const sizePx = computed(() => ({
43
- "3xs": 16,
44
- "2xs": 20,
45
- "xs": 24,
46
- "sm": 28,
47
- "md": 32,
48
- "lg": 36,
49
- "xl": 40,
50
- "2xl": 44,
51
- "3xl": 48
52
- })[props.size || "md"]);
42
+ const rootClass = computed(() => ui.value.root({ class: [uiProp.value?.root, props.class] }));
43
+ const sizePx = computed(() => {
44
+ const sizeClass = rootClass.value.split(" ").find((c) => /^size-\d+$/.test(c));
45
+ if (sizeClass) {
46
+ const num = Number.parseFloat(sizeClass.split("-")[1] ?? "");
47
+ if (!Number.isNaN(num)) return num * 4;
48
+ }
49
+ return null;
50
+ });
53
51
  const error = ref(false);
54
52
  watch(() => props.src, () => {
55
53
  if (error.value) {
@@ -67,7 +65,7 @@ function onError() {
67
65
  :as="as.root"
68
66
  v-bind="props.chip ? typeof props.chip === 'object' ? { inset: true, ...props.chip } : { inset: true } : {}"
69
67
  data-slot="root"
70
- :class="ui.root({ class: [uiProp?.root, props.class] })"
68
+ :class="rootClass"
71
69
  :style="props.style"
72
70
  >
73
71
  <component
@@ -101,7 +101,7 @@ function onClose() {
101
101
  tabindex="-1"
102
102
  raw
103
103
  >
104
- <span class="absolute inset-0 " aria-hidden="true" />
104
+ <span class="absolute inset-0" aria-hidden="true" />
105
105
  </ULink>
106
106
 
107
107
  <UContainer data-slot="container" :class="ui.container({ class: uiProp?.container })">
@@ -5,9 +5,10 @@ import theme from "#build/ui/blog-post";
5
5
  <script setup>
6
6
  import { computed } from "vue";
7
7
  import { Primitive, useDateFormatter } from "reka-ui";
8
- import { useLocale, useAppConfig } from "#imports";
9
- import ImageComponent from "#build/ui-image-component";
8
+ import { useAppConfig } from "#imports";
9
+ import { useLocale } from "../composables/useLocale";
10
10
  import { useComponentUI } from "../composables/useComponentUI";
11
+ import ImageComponent from "#build/ui-image-component";
11
12
  import { getSlotChildrenText } from "../utils";
12
13
  import { tv } from "../utils/tv";
13
14
  import ULink from "./Link.vue";
@@ -86,8 +86,8 @@ export interface CalendarProps<R extends boolean = false, M extends boolean = fa
86
86
  class?: any;
87
87
  ui?: Calendar['slots'];
88
88
  }
89
- export interface CalendarEmits<R extends boolean, M extends boolean> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
90
- 'update:modelValue': [date: CalendarModelValue<R, M>];
89
+ export interface CalendarEmits<R extends boolean = false, M extends boolean = false> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
90
+ 'update:modelValue': [value: CalendarModelValue<R, M>];
91
91
  }
92
92
  export interface CalendarSlots {
93
93
  'heading'?: (props: {
@@ -102,7 +102,7 @@ declare const _default: typeof __VLS_export;
102
102
  export default _default;
103
103
  declare const __VLS_export: <R extends boolean, M extends boolean>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
104
104
  props: import("vue").PublicProps & __VLS_PrettifyLocal<CalendarProps<R, M> & {
105
- "onUpdate:modelValue"?: ((date: CalendarModelValue<R, M>) => any) | undefined;
105
+ "onUpdate:modelValue"?: ((value: CalendarModelValue<R, M>) => any) | undefined;
106
106
  "onUpdate:placeholder"?: ((...args: DateValue[]) => any) | undefined;
107
107
  "onUpdate:validModelValue"?: ((date: DateRange) => any) | undefined;
108
108
  "onUpdate:startValue"?: ((date: DateValue | undefined) => any) | undefined;
@@ -112,7 +112,7 @@ declare const __VLS_export: <R extends boolean, M extends boolean>(__VLS_props:
112
112
  expose: (exposed: {}) => void;
113
113
  attrs: any;
114
114
  slots: CalendarSlots;
115
- emit: ((evt: "update:modelValue", date: CalendarModelValue<R, M>) => void) & ((evt: "update:placeholder", ...args: [date: DateValue] & [date: DateValue]) => void) & ((evt: "update:validModelValue", date: DateRange) => void) & ((evt: "update:startValue", date: DateValue | undefined) => void);
115
+ emit: ((evt: "update:modelValue", value: CalendarModelValue<R, M>) => void) & ((evt: "update:placeholder", ...args: [date: DateValue] & [date: DateValue]) => void) & ((evt: "update:validModelValue", date: DateRange) => void) & ((evt: "update:startValue", date: DateValue | undefined) => void);
116
116
  }>) => import("vue").VNode & {
117
117
  __ctx?: Awaited<typeof __VLS_setup>;
118
118
  };
@@ -86,8 +86,8 @@ export interface CalendarProps<R extends boolean = false, M extends boolean = fa
86
86
  class?: any;
87
87
  ui?: Calendar['slots'];
88
88
  }
89
- export interface CalendarEmits<R extends boolean, M extends boolean> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
90
- 'update:modelValue': [date: CalendarModelValue<R, M>];
89
+ export interface CalendarEmits<R extends boolean = false, M extends boolean = false> extends Omit<CalendarRootEmits & RangeCalendarRootEmits, 'update:modelValue'> {
90
+ 'update:modelValue': [value: CalendarModelValue<R, M>];
91
91
  }
92
92
  export interface CalendarSlots {
93
93
  'heading'?: (props: {
@@ -102,7 +102,7 @@ declare const _default: typeof __VLS_export;
102
102
  export default _default;
103
103
  declare const __VLS_export: <R extends boolean, M extends boolean>(__VLS_props: NonNullable<Awaited<typeof __VLS_setup>>["props"], __VLS_ctx?: __VLS_PrettifyLocal<Pick<NonNullable<Awaited<typeof __VLS_setup>>, "attrs" | "emit" | "slots">>, __VLS_exposed?: NonNullable<Awaited<typeof __VLS_setup>>["expose"], __VLS_setup?: Promise<{
104
104
  props: import("vue").PublicProps & __VLS_PrettifyLocal<CalendarProps<R, M> & {
105
- "onUpdate:modelValue"?: ((date: CalendarModelValue<R, M>) => any) | undefined;
105
+ "onUpdate:modelValue"?: ((value: CalendarModelValue<R, M>) => any) | undefined;
106
106
  "onUpdate:placeholder"?: ((...args: DateValue[]) => any) | undefined;
107
107
  "onUpdate:validModelValue"?: ((date: DateRange) => any) | undefined;
108
108
  "onUpdate:startValue"?: ((date: DateValue | undefined) => any) | undefined;
@@ -112,7 +112,7 @@ declare const __VLS_export: <R extends boolean, M extends boolean>(__VLS_props:
112
112
  expose: (exposed: {}) => void;
113
113
  attrs: any;
114
114
  slots: CalendarSlots;
115
- emit: ((evt: "update:modelValue", date: CalendarModelValue<R, M>) => void) & ((evt: "update:placeholder", ...args: [date: DateValue] & [date: DateValue]) => void) & ((evt: "update:validModelValue", date: DateRange) => void) & ((evt: "update:startValue", date: DateValue | undefined) => void);
115
+ emit: ((evt: "update:modelValue", value: CalendarModelValue<R, M>) => void) & ((evt: "update:placeholder", ...args: [date: DateValue] & [date: DateValue]) => void) & ((evt: "update:validModelValue", date: DateRange) => void) & ((evt: "update:startValue", date: DateValue | undefined) => void);
116
116
  }>) => import("vue").VNode & {
117
117
  __ctx?: Awaited<typeof __VLS_setup>;
118
118
  };
@@ -6,9 +6,10 @@ import theme from "#build/ui/changelog-version";
6
6
  import { computed } from "vue";
7
7
  import { Primitive, useDateFormatter } from "reka-ui";
8
8
  import { createReusableTemplate } from "@vueuse/core";
9
- import { useLocale, useAppConfig } from "#imports";
10
- import ImageComponent from "#build/ui-image-component";
9
+ import { useAppConfig } from "#imports";
10
+ import { useLocale } from "../composables/useLocale";
11
11
  import { useComponentUI } from "../composables/useComponentUI";
12
+ import ImageComponent from "#build/ui-image-component";
12
13
  import { getSlotChildrenText } from "../utils";
13
14
  import { tv } from "../utils/tv";
14
15
  import ULink from "./Link.vue";
@@ -28,7 +28,7 @@ const springOptions = computed(() => defu(typeof props.indicatorMotion === "obje
28
28
  const scrollOptions = computed(() => typeof props.indicator === "object" ? props.indicator : {});
29
29
  const { scrollYProgress } = useScroll(scrollOptions.value);
30
30
  const y = useSpring(scrollYProgress, springOptions);
31
- const height = useTransform(() => `${y.get() * 100}%`);
31
+ const height = useTransform(() => `${Number(y.get()) * 100}%`);
32
32
  const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.changelogVersions || {} })());
33
33
  </script>
34
34
 
@@ -1,6 +1,6 @@
1
1
  import type { VNode } from 'vue';
2
2
  import type { AppConfig } from '@nuxt/schema';
3
- import type { UIMessage } from 'ai';
3
+ import type { UIMessage, FileUIPart } from 'ai';
4
4
  import theme from '#build/ui/chat-message';
5
5
  import type { AvatarProps, ButtonProps, IconProps } from '../types';
6
6
  import type { ComponentConfig } from '../types/tv';
@@ -53,6 +53,9 @@ export interface ChatMessageSlots {
53
53
  avatar: ChatMessageProps['avatar'];
54
54
  ui: ChatMessage['ui'];
55
55
  }): VNode[];
56
+ files?(props: {
57
+ parts: FileUIPart[];
58
+ }): VNode[];
56
59
  content?(props: ChatMessageProps): VNode[];
57
60
  actions?(props: {
58
61
  actions: ChatMessageProps['actions'];
@@ -32,6 +32,7 @@ const props = defineProps({
32
32
  const slots = defineSlots();
33
33
  const appConfig = useAppConfig();
34
34
  const uiProp = useComponentUI("chatMessage", props);
35
+ const fileParts = computed(() => props.parts?.filter((part) => part.type === "file") ?? []);
35
36
  const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.chatMessage || {} })({
36
37
  variant: props.variant,
37
38
  side: props.side,
@@ -43,6 +44,10 @@ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.chatMessage |
43
44
 
44
45
  <template>
45
46
  <Primitive :as="as" :data-role="role" data-slot="root" :class="ui.root({ class: [uiProp?.root, props.class] })">
47
+ <div v-if="!!slots.files && fileParts.length" data-slot="files" :class="ui.files({ class: uiProp?.files })">
48
+ <slot name="files" :parts="fileParts" />
49
+ </div>
50
+
46
51
  <div data-slot="container" :class="ui.container({ class: uiProp?.container })">
47
52
  <div v-if="icon || avatar || !!slots.leading" data-slot="leading" :class="ui.leading({ class: uiProp?.leading })">
48
53
  <slot name="leading" :avatar="avatar" :ui="ui">
@@ -1,6 +1,6 @@
1
1
  import type { VNode } from 'vue';
2
2
  import type { AppConfig } from '@nuxt/schema';
3
- import type { UIMessage } from 'ai';
3
+ import type { UIMessage, FileUIPart } from 'ai';
4
4
  import theme from '#build/ui/chat-message';
5
5
  import type { AvatarProps, ButtonProps, IconProps } from '../types';
6
6
  import type { ComponentConfig } from '../types/tv';
@@ -53,6 +53,9 @@ export interface ChatMessageSlots {
53
53
  avatar: ChatMessageProps['avatar'];
54
54
  ui: ChatMessage['ui'];
55
55
  }): VNode[];
56
+ files?(props: {
57
+ parts: FileUIPart[];
58
+ }): VNode[];
56
59
  content?(props: ChatMessageProps): VNode[];
57
60
  actions?(props: {
58
61
  actions: ChatMessageProps['actions'];
@@ -29,6 +29,12 @@ const props = defineProps({
29
29
  });
30
30
  const slots = defineSlots();
31
31
  const getProxySlots = () => omit(slots, ["default", "indicator", "viewport"]);
32
+ const showIndicator = computed(() => {
33
+ if (props.status === "submitted") return true;
34
+ if (props.status !== "streaming") return false;
35
+ const lastMessage = props.messages?.[props.messages.length - 1];
36
+ return lastMessage?.role === "assistant" && !lastMessage.parts?.length;
37
+ });
32
38
  const appConfig = useAppConfig();
33
39
  const uiProp = useComponentUI("chatMessages", props);
34
40
  const userProps = toRef(() => defu(props.user, { side: "right", variant: "soft" }));
@@ -67,6 +73,13 @@ function scrollToBottom(smooth = true) {
67
73
  }
68
74
  }
69
75
  watchThrottled([() => props.messages, () => props.status], ([_, status]) => {
76
+ if (!props.messages?.length) {
77
+ showAutoScroll.value = false;
78
+ userScrolledUp.value = false;
79
+ lastScrollTop.value = 0;
80
+ messagesRefs.value.clear();
81
+ return;
82
+ }
70
83
  if (status !== "streaming") {
71
84
  return;
72
85
  }
@@ -197,7 +210,7 @@ onMounted(() => {
197
210
  </slot>
198
211
 
199
212
  <UChatMessage
200
- v-if="status === 'submitted'"
213
+ v-if="showIndicator"
201
214
  id="indicator"
202
215
  role="assistant"
203
216
  v-bind="{ ...assistantProps, actions: void 0, parts: [] }"
@@ -8,6 +8,7 @@ import { Primitive, useForwardProps } from "reka-ui";
8
8
  import { reactivePick } from "@vueuse/core";
9
9
  import { useAppConfig } from "#imports";
10
10
  import { useComponentUI } from "../composables/useComponentUI";
11
+ import { useIMEGuard } from "../composables/useIMEGuard";
11
12
  import { useLocale } from "../composables/useLocale";
12
13
  import { omit, transformUI } from "../utils";
13
14
  import { tv } from "../utils/tv";
@@ -54,6 +55,9 @@ function blur(e) {
54
55
  textareaRef.value?.textareaRef?.blur();
55
56
  emits("close", e);
56
57
  }
58
+ const { onKeydown: onEnter, onCompositionEnd } = useIMEGuard((event) => {
59
+ submit(event);
60
+ });
57
61
  defineExpose({
58
62
  textareaRef: toRef(() => textareaRef.value?.textareaRef)
59
63
  });
@@ -76,7 +80,8 @@ defineExpose({
76
80
  :ui="transformUI(omit(ui, ['root', 'body', 'header', 'footer']), uiProp)"
77
81
  data-slot="body"
78
82
  :class="ui.body({ class: uiProp?.body })"
79
- @keydown.enter.exact.prevent="submit"
83
+ @keydown.enter.exact="onEnter"
84
+ @compositionend="onCompositionEnd"
80
85
  @keydown.esc="blur"
81
86
  >
82
87
  <template v-for="(_, name) in getProxySlots()" #[name]="slotData">
@@ -0,0 +1,78 @@
1
+ import type { CollapsibleRootProps } from 'reka-ui';
2
+ import type { VNode } from 'vue';
3
+ import type { AppConfig } from '@nuxt/schema';
4
+ import theme from '#build/ui/chat-reasoning';
5
+ import type { IconProps } from '../types';
6
+ import type { ChatShimmerProps } from './ChatShimmer.vue';
7
+ import type { ComponentConfig } from '../types/tv';
8
+ type ChatReasoning = ComponentConfig<typeof theme, AppConfig, 'chatReasoning'>;
9
+ export interface ChatReasoningProps extends Pick<CollapsibleRootProps, 'defaultOpen' | 'open' | 'disabled' | 'unmountOnHide'> {
10
+ /**
11
+ * The reasoning text content to display.
12
+ */
13
+ text?: string;
14
+ /**
15
+ * Whether the reasoning content is currently streaming.
16
+ * @defaultValue false
17
+ */
18
+ streaming?: boolean;
19
+ /**
20
+ * The duration in seconds that the AI spent reasoning.
21
+ * If not provided, it will be calculated automatically based on streaming time.
22
+ */
23
+ duration?: number;
24
+ /**
25
+ * The icon displayed next to the trigger.
26
+ * @IconifyIcon
27
+ */
28
+ icon?: IconProps['name'];
29
+ /**
30
+ * The position of the chevron icon.
31
+ * @defaultValue 'trailing'
32
+ */
33
+ chevron?: 'leading' | 'trailing';
34
+ /**
35
+ * The icon displayed as the chevron.
36
+ * @defaultValue appConfig.ui.icons.chevronDown
37
+ * @IconifyIcon
38
+ */
39
+ chevronIcon?: IconProps['name'];
40
+ /**
41
+ * The delay in milliseconds before auto-closing when streaming ends.
42
+ * Set to `0` to disable auto-close.
43
+ * @defaultValue 500
44
+ */
45
+ autoCloseDelay?: number;
46
+ /**
47
+ * Customize the [`ChatShimmer`](https://ui.nuxt.com/docs/components/chat-shimmer) component when streaming.
48
+ */
49
+ shimmer?: Partial<Omit<ChatShimmerProps, 'text'>>;
50
+ class?: any;
51
+ ui?: ChatReasoning['slots'];
52
+ }
53
+ export interface ChatReasoningEmits {
54
+ 'update:open': [value: boolean];
55
+ }
56
+ export interface ChatReasoningSlots {
57
+ default?(props: {
58
+ open: boolean;
59
+ }): VNode[];
60
+ }
61
+ declare const _default: typeof __VLS_export;
62
+ export default _default;
63
+ declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ChatReasoningProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
64
+ "update:open": (value: boolean) => any;
65
+ }, string, import("vue").PublicProps, Readonly<ChatReasoningProps> & Readonly<{
66
+ "onUpdate:open"?: ((value: boolean) => any) | undefined;
67
+ }>, {
68
+ open: boolean;
69
+ streaming: boolean;
70
+ unmountOnHide: boolean;
71
+ chevron: "leading" | "trailing";
72
+ autoCloseDelay: number;
73
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, ChatReasoningSlots>;
74
+ type __VLS_WithSlots<T, S> = T & {
75
+ new (): {
76
+ $slots: S;
77
+ };
78
+ };