@nuxt/ui 4.6.1 → 4.7.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 (168) hide show
  1. package/README.md +7 -4
  2. package/cli/package.json +1 -1
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +3 -2
  5. package/dist/runtime/components/Accordion.d.vue.ts +6 -1
  6. package/dist/runtime/components/Accordion.vue +1 -1
  7. package/dist/runtime/components/Accordion.vue.d.ts +6 -1
  8. package/dist/runtime/components/AuthForm.d.vue.ts +22 -29
  9. package/dist/runtime/components/AuthForm.vue +8 -6
  10. package/dist/runtime/components/AuthForm.vue.d.ts +22 -29
  11. package/dist/runtime/components/Calendar.vue +4 -4
  12. package/dist/runtime/components/Card.d.vue.ts +4 -0
  13. package/dist/runtime/components/Card.vue +16 -2
  14. package/dist/runtime/components/Card.vue.d.ts +4 -0
  15. package/dist/runtime/components/ChatMessage.d.vue.ts +27 -17
  16. package/dist/runtime/components/ChatMessage.vue +10 -16
  17. package/dist/runtime/components/ChatMessage.vue.d.ts +27 -17
  18. package/dist/runtime/components/ChatMessages.d.vue.ts +27 -21
  19. package/dist/runtime/components/ChatMessages.vue +22 -23
  20. package/dist/runtime/components/ChatMessages.vue.d.ts +27 -21
  21. package/dist/runtime/components/ChatPromptSubmit.vue +3 -1
  22. package/dist/runtime/components/Checkbox.vue +5 -3
  23. package/dist/runtime/components/CommandPalette.d.vue.ts +18 -3
  24. package/dist/runtime/components/CommandPalette.vue +11 -7
  25. package/dist/runtime/components/CommandPalette.vue.d.ts +18 -3
  26. package/dist/runtime/components/ContextMenuContent.vue +68 -65
  27. package/dist/runtime/components/DashboardSearch.d.vue.ts +8 -37
  28. package/dist/runtime/components/DashboardSearch.vue +11 -10
  29. package/dist/runtime/components/DashboardSearch.vue.d.ts +8 -37
  30. package/dist/runtime/components/DashboardSidebar.vue +1 -5
  31. package/dist/runtime/components/Drawer.vue +44 -41
  32. package/dist/runtime/components/DropdownMenuContent.vue +90 -87
  33. package/dist/runtime/components/EditorEmojiMenu.d.vue.ts +1 -1
  34. package/dist/runtime/components/EditorEmojiMenu.vue +2 -0
  35. package/dist/runtime/components/EditorEmojiMenu.vue.d.ts +1 -1
  36. package/dist/runtime/components/EditorMentionMenu.d.vue.ts +1 -1
  37. package/dist/runtime/components/EditorMentionMenu.vue +2 -0
  38. package/dist/runtime/components/EditorMentionMenu.vue.d.ts +1 -1
  39. package/dist/runtime/components/EditorSuggestionMenu.d.vue.ts +1 -1
  40. package/dist/runtime/components/EditorSuggestionMenu.vue +2 -0
  41. package/dist/runtime/components/EditorSuggestionMenu.vue.d.ts +1 -1
  42. package/dist/runtime/components/FileUpload.vue +7 -5
  43. package/dist/runtime/components/Header.vue +1 -5
  44. package/dist/runtime/components/Input.vue +2 -2
  45. package/dist/runtime/components/InputDate.vue +6 -6
  46. package/dist/runtime/components/InputMenu.d.vue.ts +3 -3
  47. package/dist/runtime/components/InputMenu.vue +40 -38
  48. package/dist/runtime/components/InputMenu.vue.d.ts +3 -3
  49. package/dist/runtime/components/InputNumber.vue +2 -2
  50. package/dist/runtime/components/InputTags.vue +2 -2
  51. package/dist/runtime/components/InputTime.vue +2 -2
  52. package/dist/runtime/components/Link.vue +64 -8
  53. package/dist/runtime/components/Listbox.d.vue.ts +228 -0
  54. package/dist/runtime/components/Listbox.vue +242 -0
  55. package/dist/runtime/components/Listbox.vue.d.ts +228 -0
  56. package/dist/runtime/components/Modal.vue +13 -10
  57. package/dist/runtime/components/Popover.vue +7 -4
  58. package/dist/runtime/components/PricingTable.vue +60 -58
  59. package/dist/runtime/components/RadioGroup.vue +5 -3
  60. package/dist/runtime/components/Select.d.vue.ts +1 -1
  61. package/dist/runtime/components/Select.vue +84 -73
  62. package/dist/runtime/components/Select.vue.d.ts +1 -1
  63. package/dist/runtime/components/SelectMenu.d.vue.ts +3 -3
  64. package/dist/runtime/components/SelectMenu.vue +54 -52
  65. package/dist/runtime/components/SelectMenu.vue.d.ts +3 -3
  66. package/dist/runtime/components/Sidebar.vue +1 -4
  67. package/dist/runtime/components/Slideover.vue +67 -64
  68. package/dist/runtime/components/Table.d.vue.ts +1 -2
  69. package/dist/runtime/components/Table.vue +17 -29
  70. package/dist/runtime/components/Table.vue.d.ts +1 -2
  71. package/dist/runtime/components/Tabs.d.vue.ts +5 -1
  72. package/dist/runtime/components/Tabs.vue +2 -2
  73. package/dist/runtime/components/Tabs.vue.d.ts +5 -1
  74. package/dist/runtime/components/Textarea.d.vue.ts +1 -0
  75. package/dist/runtime/components/Textarea.vue +2 -1
  76. package/dist/runtime/components/Textarea.vue.d.ts +1 -0
  77. package/dist/runtime/components/Tooltip.vue +12 -9
  78. package/dist/runtime/components/content/ContentSearch.d.vue.ts +19 -35
  79. package/dist/runtime/components/content/ContentSearch.vue +10 -9
  80. package/dist/runtime/components/content/ContentSearch.vue.d.ts +19 -35
  81. package/dist/runtime/components/content/ContentToc.vue +19 -9
  82. package/dist/runtime/components/prose/Img.vue +2 -1
  83. package/dist/runtime/components/prose/Pre.vue +8 -3
  84. package/dist/runtime/components/prose/Prompt.d.vue.ts +32 -0
  85. package/dist/runtime/components/prose/Prompt.vue +88 -0
  86. package/dist/runtime/components/prose/Prompt.vue.d.ts +32 -0
  87. package/dist/runtime/composables/index.d.ts +1 -0
  88. package/dist/runtime/composables/index.js +1 -0
  89. package/dist/runtime/composables/useContentSearch.js +19 -5
  90. package/dist/runtime/composables/useEditorMenu.d.ts +5 -0
  91. package/dist/runtime/composables/useEditorMenu.js +3 -1
  92. package/dist/runtime/composables/useFieldGroup.d.ts +3 -0
  93. package/dist/runtime/composables/useFieldGroup.js +11 -1
  94. package/dist/runtime/composables/useResolvedVariants.d.ts +21 -0
  95. package/dist/runtime/composables/useResolvedVariants.js +14 -0
  96. package/dist/runtime/locale/ar.js +9 -0
  97. package/dist/runtime/locale/az.js +9 -0
  98. package/dist/runtime/locale/be.js +9 -0
  99. package/dist/runtime/locale/bg.js +9 -0
  100. package/dist/runtime/locale/bn.js +9 -0
  101. package/dist/runtime/locale/ca.js +9 -0
  102. package/dist/runtime/locale/ckb.js +10 -1
  103. package/dist/runtime/locale/cs.js +9 -0
  104. package/dist/runtime/locale/da.js +9 -0
  105. package/dist/runtime/locale/de.js +9 -0
  106. package/dist/runtime/locale/de_ch.js +9 -0
  107. package/dist/runtime/locale/el.js +9 -0
  108. package/dist/runtime/locale/en.js +10 -1
  109. package/dist/runtime/locale/es.js +9 -0
  110. package/dist/runtime/locale/et.js +9 -0
  111. package/dist/runtime/locale/eu.js +11 -2
  112. package/dist/runtime/locale/fa_ir.js +9 -0
  113. package/dist/runtime/locale/fi.js +9 -0
  114. package/dist/runtime/locale/fr.js +9 -0
  115. package/dist/runtime/locale/gl.js +9 -0
  116. package/dist/runtime/locale/he.js +9 -0
  117. package/dist/runtime/locale/hi.js +9 -0
  118. package/dist/runtime/locale/hr.js +9 -0
  119. package/dist/runtime/locale/hu.js +9 -0
  120. package/dist/runtime/locale/hy.js +9 -0
  121. package/dist/runtime/locale/id.js +9 -0
  122. package/dist/runtime/locale/is.js +9 -0
  123. package/dist/runtime/locale/it.js +9 -0
  124. package/dist/runtime/locale/ja.js +9 -0
  125. package/dist/runtime/locale/ka.js +9 -0
  126. package/dist/runtime/locale/kk.js +9 -0
  127. package/dist/runtime/locale/km.js +9 -0
  128. package/dist/runtime/locale/ko.js +9 -0
  129. package/dist/runtime/locale/ky.js +9 -0
  130. package/dist/runtime/locale/lb.js +11 -2
  131. package/dist/runtime/locale/lo.js +15 -6
  132. package/dist/runtime/locale/lt.js +9 -0
  133. package/dist/runtime/locale/mn.js +9 -0
  134. package/dist/runtime/locale/ms.js +9 -0
  135. package/dist/runtime/locale/nb_no.js +9 -0
  136. package/dist/runtime/locale/nl.js +9 -0
  137. package/dist/runtime/locale/pl.js +9 -0
  138. package/dist/runtime/locale/pt.js +9 -0
  139. package/dist/runtime/locale/pt_br.js +9 -0
  140. package/dist/runtime/locale/ro.js +9 -0
  141. package/dist/runtime/locale/ru.js +9 -0
  142. package/dist/runtime/locale/sk.js +9 -0
  143. package/dist/runtime/locale/sl.js +9 -0
  144. package/dist/runtime/locale/sq.js +9 -0
  145. package/dist/runtime/locale/sv.js +9 -0
  146. package/dist/runtime/locale/th.js +9 -0
  147. package/dist/runtime/locale/tj.js +9 -0
  148. package/dist/runtime/locale/tr.js +9 -0
  149. package/dist/runtime/locale/ug_cn.js +9 -0
  150. package/dist/runtime/locale/uk.js +9 -0
  151. package/dist/runtime/locale/ur.js +9 -0
  152. package/dist/runtime/locale/uz.js +9 -0
  153. package/dist/runtime/locale/vi.js +9 -0
  154. package/dist/runtime/locale/zh_cn.js +9 -0
  155. package/dist/runtime/locale/zh_tw.js +9 -0
  156. package/dist/runtime/plugins/colors.js +1 -1
  157. package/dist/runtime/types/index.d.ts +1 -0
  158. package/dist/runtime/types/index.js +1 -0
  159. package/dist/runtime/types/locale.d.ts +9 -0
  160. package/dist/runtime/types/prose.d.ts +1 -0
  161. package/dist/runtime/types/prose.js +1 -0
  162. package/dist/runtime/vue/overrides/inertia/Link.vue +3 -3
  163. package/dist/runtime/vue/overrides/none/Link.vue +3 -2
  164. package/dist/runtime/vue/overrides/vue-router/Link.vue +27 -31
  165. package/dist/shared/{ui.DJUbBpE2.mjs → ui.BIQuJqNV.mjs} +186 -34
  166. package/dist/unplugin.mjs +1 -1
  167. package/dist/vite.mjs +1 -1
  168. package/package.json +48 -39
@@ -1,11 +1,11 @@
1
1
  import type { VNode } from 'vue';
2
2
  import type { AppConfig } from '@nuxt/schema';
3
- import type { UIMessage, FileUIPart } from 'ai';
3
+ import type { UIDataTypes, UIMessage, UITools, 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';
7
7
  type ChatMessage = ComponentConfig<typeof theme, AppConfig, 'chatMessage'>;
8
- export interface ChatMessageProps extends UIMessage {
8
+ export interface ChatMessageProps<TMetadata = unknown, TDataParts extends UIDataTypes = UIDataTypes, TTools extends UITools = UITools> extends UIMessage<TMetadata, TDataParts, TTools> {
9
9
  /**
10
10
  * The element or component this component should render as.
11
11
  * @defaultValue 'article'
@@ -32,7 +32,7 @@ export interface ChatMessageProps extends UIMessage {
32
32
  * `{ size: 'xs', color: 'neutral', variant: 'ghost' }`{lang="ts-type"}
33
33
  */
34
34
  actions?: (Omit<ButtonProps, 'onClick'> & {
35
- onClick?: (e: MouseEvent, message: UIMessage) => void;
35
+ onClick?: (e: MouseEvent, message: UIMessage<TMetadata, TDataParts, TTools>) => void;
36
36
  })[];
37
37
  /**
38
38
  * Render the message in a compact style.
@@ -48,26 +48,36 @@ export interface ChatMessageProps extends UIMessage {
48
48
  class?: any;
49
49
  ui?: ChatMessage['slots'];
50
50
  }
51
- export interface ChatMessageSlots {
52
- leading?(props: {
53
- avatar: ChatMessageProps['avatar'];
51
+ export interface ChatMessageSlots<TMetadata = unknown, TDataParts extends UIDataTypes = UIDataTypes, TTools extends UITools = UITools> {
52
+ leading?(props: UIMessage<TMetadata, TDataParts, TTools> & {
53
+ avatar: ChatMessageProps<TMetadata, TDataParts, TTools>['avatar'];
54
54
  ui: ChatMessage['ui'];
55
55
  }): VNode[];
56
- files?(props: {
56
+ files?(props: Omit<UIMessage<TMetadata, TDataParts, TTools>, 'parts'> & {
57
57
  parts: FileUIPart[];
58
58
  }): VNode[];
59
- content?(props: ChatMessageProps): VNode[];
60
- actions?(props: {
61
- actions: ChatMessageProps['actions'];
59
+ content?(props: UIMessage<TMetadata, TDataParts, TTools> & {
60
+ content?: string;
61
+ }): VNode[];
62
+ actions?(props: UIMessage<TMetadata, TDataParts, TTools> & {
63
+ actions: ChatMessageProps<TMetadata, TDataParts, TTools>['actions'];
62
64
  }): VNode[];
63
65
  }
64
66
  declare const _default: typeof __VLS_export;
65
67
  export default _default;
66
- declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ChatMessageProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ChatMessageProps> & Readonly<{}>, {
67
- as: any;
68
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, ChatMessageSlots>;
69
- type __VLS_WithSlots<T, S> = T & {
70
- new (): {
71
- $slots: S;
72
- };
68
+ declare const __VLS_export: <TMetadata, TDataParts extends UIDataTypes, TTools extends UITools>(__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<{
69
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<ChatMessageProps<TMetadata, TDataParts, TTools>> & (typeof globalThis extends {
70
+ __VLS_PROPS_FALLBACK: infer P;
71
+ } ? P : {});
72
+ expose: (exposed: {}) => void;
73
+ attrs: any;
74
+ slots: ChatMessageSlots<TMetadata, TDataParts, TTools>;
75
+ emit: {};
76
+ }>) => import("vue").VNode & {
77
+ __ctx?: Awaited<typeof __VLS_setup>;
73
78
  };
79
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
80
+ [K in keyof T]: T[K];
81
+ } : {
82
+ [K in keyof T as K]: T[K];
83
+ }) & {};
@@ -1,12 +1,14 @@
1
1
  import type { VNode } from 'vue';
2
2
  import type { AppConfig } from '@nuxt/schema';
3
- import type { UIMessage, ChatStatus } from 'ai';
3
+ import type { UIDataTypes, UIMessage, UITools, ChatStatus } from 'ai';
4
4
  import theme from '#build/ui/chat-messages';
5
5
  import type { ButtonProps, ChatMessageProps, ChatMessageSlots, IconProps, LinkPropsKeys } from '../types';
6
6
  import type { ComponentConfig } from '../types/tv';
7
7
  type ChatMessages = ComponentConfig<typeof theme, AppConfig, 'chatMessages'>;
8
- export interface ChatMessagesProps {
9
- messages?: UIMessage[];
8
+ type MessageBase<T extends UIMessage[]> = T[number] extends UIMessage<infer M, infer D, infer U> ? UIMessage<M, D, U> : UIMessage<unknown, UIDataTypes, UITools>;
9
+ type PropsBase<T extends UIMessage[]> = MessageBase<T> extends UIMessage<infer M, infer D, infer U> ? ChatMessageProps<M, D, U> : never;
10
+ export interface ChatMessagesProps<T extends UIMessage[] = UIMessage[]> {
11
+ messages?: T;
10
12
  status?: ChatStatus;
11
13
  /**
12
14
  * Whether to automatically scroll to the bottom when a message is streaming.
@@ -34,12 +36,12 @@ export interface ChatMessagesProps {
34
36
  * The `user` messages props.
35
37
  * `{ side: 'right', variant: 'soft' }`{lang="ts-type"}
36
38
  */
37
- user?: Pick<ChatMessageProps, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
39
+ user?: Pick<PropsBase<T>, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
38
40
  /**
39
41
  * The `assistant` messages props.
40
42
  * `{ side: 'left', variant: 'naked' }`{lang="ts-type"}
41
43
  */
42
- assistant?: Pick<ChatMessageProps, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
44
+ assistant?: Pick<PropsBase<T>, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
43
45
  /**
44
46
  * Render the messages in a compact style.
45
47
  * This is done automatically when used inside a `UChatPalette`{lang="ts-type"}.
@@ -54,12 +56,7 @@ export interface ChatMessagesProps {
54
56
  class?: any;
55
57
  ui?: ChatMessages['slots'];
56
58
  }
57
- type ExtendSlotWithVersion<K extends keyof ChatMessageSlots> = Required<ChatMessageSlots>[K] extends (props: infer P) => VNode[] ? (props: P & {
58
- message: UIMessage;
59
- }) => VNode[] : Required<ChatMessageSlots>[K];
60
- export type ChatMessagesSlots = {
61
- [K in keyof ChatMessageSlots]?: ExtendSlotWithVersion<K>;
62
- } & {
59
+ export type ChatMessagesSlots<T extends UIMessage[] = UIMessage[]> = {
63
60
  default?(props?: {}): VNode[];
64
61
  indicator?(props: {
65
62
  ui: ChatMessages['ui'];
@@ -68,17 +65,26 @@ export type ChatMessagesSlots = {
68
65
  ui: ChatMessages['ui'];
69
66
  onClick: () => void;
70
67
  }): VNode[];
68
+ } & {
69
+ [K in keyof ChatMessageSlots]?: NonNullable<ChatMessageSlots[K]> extends (props: infer P) => VNode[] ? (props: P & {
70
+ message: MessageBase<T>;
71
+ }) => VNode[] : never;
71
72
  };
72
73
  declare const _default: typeof __VLS_export;
73
74
  export default _default;
74
- declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ChatMessagesProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ChatMessagesProps> & Readonly<{}>, {
75
- autoScroll: boolean | Omit<ButtonProps, LinkPropsKeys>;
76
- shouldAutoScroll: boolean;
77
- shouldScrollToBottom: boolean;
78
- spacingOffset: number;
79
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, ChatMessagesSlots>;
80
- type __VLS_WithSlots<T, S> = T & {
81
- new (): {
82
- $slots: S;
83
- };
75
+ declare const __VLS_export: <T extends UIMessage[] = UIMessage[]>(__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<{
76
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<ChatMessagesProps<T>> & (typeof globalThis extends {
77
+ __VLS_PROPS_FALLBACK: infer P;
78
+ } ? P : {});
79
+ expose: (exposed: {}) => void;
80
+ attrs: any;
81
+ slots: ChatMessagesSlots<T>;
82
+ emit: {};
83
+ }>) => import("vue").VNode & {
84
+ __ctx?: Awaited<typeof __VLS_setup>;
84
85
  };
86
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
87
+ [K in keyof T]: T[K];
88
+ } : {
89
+ [K in keyof T as K]: T[K];
90
+ }) & {};
@@ -6,7 +6,7 @@ import theme from "#build/ui/chat-messages";
6
6
  import { ref, computed, watch, nextTick, toRef, onMounted } from "vue";
7
7
  import { Presence } from "reka-ui";
8
8
  import { defu } from "defu";
9
- import { useElementBounding, useEventListener, watchThrottled } from "@vueuse/core";
9
+ import { useElementBounding, useEventListener, useMutationObserver, watchThrottled } from "@vueuse/core";
10
10
  import { useAppConfig } from "#imports";
11
11
  import { useComponentUI } from "../composables/useComponentUI";
12
12
  import { omit } from "../utils";
@@ -14,7 +14,7 @@ import { tv } from "../utils/tv";
14
14
  import UChatMessage from "./ChatMessage.vue";
15
15
  import UButton from "./Button.vue";
16
16
  const props = defineProps({
17
- messages: { type: Array, required: false },
17
+ messages: { type: null, required: false },
18
18
  status: { type: String, required: false },
19
19
  shouldAutoScroll: { type: Boolean, required: false, default: false },
20
20
  shouldScrollToBottom: { type: Boolean, required: false, default: true },
@@ -83,16 +83,7 @@ watchThrottled([() => props.messages, () => props.status], ([_, status]) => {
83
83
  if (status !== "streaming") {
84
84
  return;
85
85
  }
86
- if (!props.shouldAutoScroll) {
87
- checkScrollPosition();
88
- return;
89
- }
90
- nextTick(() => {
91
- if (!parent.value || userScrolledUp.value) return;
92
- if (parent.value.scrollHeight - parent.value.scrollTop - parent.value.clientHeight < 150) {
93
- scrollToBottom(false);
94
- }
95
- });
86
+ checkScrollPosition();
96
87
  }, { deep: true, throttle: 50, leading: true });
97
88
  watch(() => props.status, (status) => {
98
89
  if (status !== "submitted") {
@@ -184,6 +175,13 @@ onMounted(() => {
184
175
  }
185
176
  useEventListener(parent, "scroll", checkScrollPosition);
186
177
  useEventListener(window, "resize", () => nextTick(updateLastMessageHeight));
178
+ if (el.value) {
179
+ useMutationObserver(el, () => {
180
+ if (props.shouldAutoScroll && props.status === "streaming" && !userScrolledUp.value) {
181
+ scrollToBottom(false);
182
+ }
183
+ }, { childList: true, subtree: true });
184
+ }
187
185
  });
188
186
  </script>
189
187
 
@@ -196,17 +194,18 @@ onMounted(() => {
196
194
  :style="{ '--last-message-height': `${lastMessageHeight}px` }"
197
195
  >
198
196
  <slot>
199
- <UChatMessage
200
- v-for="message in messages"
201
- :key="message.id"
202
- v-bind="{ ...message.role === 'user' ? userProps : assistantProps, ...message }"
203
- :ref="(el) => registerMessageRef(message.id, el)"
204
- :compact="compact"
205
- >
206
- <template v-for="(_, name) in getProxySlots()" #[name]="slotData">
207
- <slot :name="name" v-bind="slotData" :message="message" />
208
- </template>
209
- </UChatMessage>
197
+ <template v-for="message in messages" :key="message.id">
198
+ <UChatMessage
199
+ v-if="message.parts?.length"
200
+ v-bind="{ ...message.role === 'user' ? userProps : assistantProps, ...message }"
201
+ :ref="(el) => registerMessageRef(message.id, el)"
202
+ :compact="compact"
203
+ >
204
+ <template v-for="(_, name) in getProxySlots()" #[name]="slotData">
205
+ <slot :name="name" v-bind="{ ...slotData, message }" />
206
+ </template>
207
+ </UChatMessage>
208
+ </template>
210
209
  </slot>
211
210
 
212
211
  <UChatMessage
@@ -1,12 +1,14 @@
1
1
  import type { VNode } from 'vue';
2
2
  import type { AppConfig } from '@nuxt/schema';
3
- import type { UIMessage, ChatStatus } from 'ai';
3
+ import type { UIDataTypes, UIMessage, UITools, ChatStatus } from 'ai';
4
4
  import theme from '#build/ui/chat-messages';
5
5
  import type { ButtonProps, ChatMessageProps, ChatMessageSlots, IconProps, LinkPropsKeys } from '../types';
6
6
  import type { ComponentConfig } from '../types/tv';
7
7
  type ChatMessages = ComponentConfig<typeof theme, AppConfig, 'chatMessages'>;
8
- export interface ChatMessagesProps {
9
- messages?: UIMessage[];
8
+ type MessageBase<T extends UIMessage[]> = T[number] extends UIMessage<infer M, infer D, infer U> ? UIMessage<M, D, U> : UIMessage<unknown, UIDataTypes, UITools>;
9
+ type PropsBase<T extends UIMessage[]> = MessageBase<T> extends UIMessage<infer M, infer D, infer U> ? ChatMessageProps<M, D, U> : never;
10
+ export interface ChatMessagesProps<T extends UIMessage[] = UIMessage[]> {
11
+ messages?: T;
10
12
  status?: ChatStatus;
11
13
  /**
12
14
  * Whether to automatically scroll to the bottom when a message is streaming.
@@ -34,12 +36,12 @@ export interface ChatMessagesProps {
34
36
  * The `user` messages props.
35
37
  * `{ side: 'right', variant: 'soft' }`{lang="ts-type"}
36
38
  */
37
- user?: Pick<ChatMessageProps, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
39
+ user?: Pick<PropsBase<T>, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
38
40
  /**
39
41
  * The `assistant` messages props.
40
42
  * `{ side: 'left', variant: 'naked' }`{lang="ts-type"}
41
43
  */
42
- assistant?: Pick<ChatMessageProps, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
44
+ assistant?: Pick<PropsBase<T>, 'icon' | 'avatar' | 'variant' | 'side' | 'actions' | 'ui'>;
43
45
  /**
44
46
  * Render the messages in a compact style.
45
47
  * This is done automatically when used inside a `UChatPalette`{lang="ts-type"}.
@@ -54,12 +56,7 @@ export interface ChatMessagesProps {
54
56
  class?: any;
55
57
  ui?: ChatMessages['slots'];
56
58
  }
57
- type ExtendSlotWithVersion<K extends keyof ChatMessageSlots> = Required<ChatMessageSlots>[K] extends (props: infer P) => VNode[] ? (props: P & {
58
- message: UIMessage;
59
- }) => VNode[] : Required<ChatMessageSlots>[K];
60
- export type ChatMessagesSlots = {
61
- [K in keyof ChatMessageSlots]?: ExtendSlotWithVersion<K>;
62
- } & {
59
+ export type ChatMessagesSlots<T extends UIMessage[] = UIMessage[]> = {
63
60
  default?(props?: {}): VNode[];
64
61
  indicator?(props: {
65
62
  ui: ChatMessages['ui'];
@@ -68,17 +65,26 @@ export type ChatMessagesSlots = {
68
65
  ui: ChatMessages['ui'];
69
66
  onClick: () => void;
70
67
  }): VNode[];
68
+ } & {
69
+ [K in keyof ChatMessageSlots]?: NonNullable<ChatMessageSlots[K]> extends (props: infer P) => VNode[] ? (props: P & {
70
+ message: MessageBase<T>;
71
+ }) => VNode[] : never;
71
72
  };
72
73
  declare const _default: typeof __VLS_export;
73
74
  export default _default;
74
- declare const __VLS_export: __VLS_WithSlots<import("vue").DefineComponent<ChatMessagesProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<ChatMessagesProps> & Readonly<{}>, {
75
- autoScroll: boolean | Omit<ButtonProps, LinkPropsKeys>;
76
- shouldAutoScroll: boolean;
77
- shouldScrollToBottom: boolean;
78
- spacingOffset: number;
79
- }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>, ChatMessagesSlots>;
80
- type __VLS_WithSlots<T, S> = T & {
81
- new (): {
82
- $slots: S;
83
- };
75
+ declare const __VLS_export: <T extends UIMessage[] = UIMessage[]>(__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<{
76
+ props: import("vue").PublicProps & __VLS_PrettifyLocal<ChatMessagesProps<T>> & (typeof globalThis extends {
77
+ __VLS_PROPS_FALLBACK: infer P;
78
+ } ? P : {});
79
+ expose: (exposed: {}) => void;
80
+ attrs: any;
81
+ slots: ChatMessagesSlots<T>;
82
+ emit: {};
83
+ }>) => import("vue").VNode & {
84
+ __ctx?: Awaited<typeof __VLS_setup>;
84
85
  };
86
+ type __VLS_PrettifyLocal<T> = (T extends any ? {
87
+ [K in keyof T]: T[K];
88
+ } : {
89
+ [K in keyof T as K]: T[K];
90
+ }) & {};
@@ -55,7 +55,8 @@ const slots = defineSlots();
55
55
  const { t } = useLocale();
56
56
  const appConfig = useAppConfig();
57
57
  const uiProp = useComponentUI("chatPromptSubmit", props);
58
- const buttonProps = useForwardProps(reactiveOmit(props, "icon", "color", "variant", "status", "streamingIcon", "streamingColor", "streamingVariant", "submittedIcon", "submittedColor", "submittedVariant", "errorIcon", "errorColor", "errorVariant", "class", "ui"));
58
+ const buttonProps = useForwardProps(reactiveOmit(props, "icon", "color", "variant", "status", "disabled", "streamingIcon", "streamingColor", "streamingVariant", "submittedIcon", "submittedColor", "submittedVariant", "errorIcon", "errorColor", "errorVariant", "class", "ui"));
59
+ const disabled = computed(() => props.status === "ready" ? props.disabled : false);
59
60
  const statusButtonProps = computed(() => ({
60
61
  ready: {
61
62
  icon: props.icon || appConfig.ui.icons.arrowUp,
@@ -96,6 +97,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.chatPromptSub
96
97
  v-bind="{
97
98
  ...buttonProps,
98
99
  ...statusButtonProps,
100
+ disabled,
99
101
  'aria-label': t('chatPromptSubmit.label'),
100
102
  ...$attrs
101
103
  }"
@@ -8,6 +8,7 @@ import { Primitive, CheckboxRoot, CheckboxIndicator, Label, useForwardPropsEmits
8
8
  import { reactivePick } from "@vueuse/core";
9
9
  import { useAppConfig } from "#imports";
10
10
  import { useComponentUI } from "../composables/useComponentUI";
11
+ import { useResolvedVariants } from "../composables/useResolvedVariants";
11
12
  import { useFormField } from "../composables/useFormField";
12
13
  import { tv } from "../utils/tv";
13
14
  import UIcon from "./Icon.vue";
@@ -41,6 +42,7 @@ const uiProp = useComponentUI("checkbox", props);
41
42
  const rootProps = useForwardPropsEmits(reactivePick(props, "required", "value", "defaultValue", "modelValue", "trueValue", "falseValue"), emits);
42
43
  const { id: _id, emitFormChange, emitFormInput, size, color, name, disabled, ariaAttrs } = useFormField(props);
43
44
  const id = _id.value ?? useId();
45
+ const { variant } = useResolvedVariants("checkbox", props, theme, ["variant"]);
44
46
  const attrs = useAttrs();
45
47
  const forwardedAttrs = computed(() => {
46
48
  const { "data-state": _, ...rest } = attrs;
@@ -49,7 +51,7 @@ const forwardedAttrs = computed(() => {
49
51
  const ui = computed(() => tv({ extend: tv(theme), ...appConfig.ui?.checkbox || {} })({
50
52
  size: size.value,
51
53
  color: color.value,
52
- variant: props.variant,
54
+ variant: variant.value,
53
55
  indicator: props.indicator,
54
56
  required: props.required,
55
57
  disabled: disabled.value
@@ -63,7 +65,7 @@ function onUpdate(value) {
63
65
  </script>
64
66
 
65
67
  <template>
66
- <Primitive :as="!variant || variant === 'list' ? as : Label" data-slot="root" :class="ui.root({ class: [uiProp?.root, props.class] })">
68
+ <Primitive :as="variant === 'list' ? as : Label" data-slot="root" :class="ui.root({ class: [uiProp?.root, props.class] })">
67
69
  <div data-slot="container" :class="ui.container({ class: uiProp?.container })">
68
70
  <CheckboxRoot
69
71
  :id="id"
@@ -84,7 +86,7 @@ function onUpdate(value) {
84
86
  </div>
85
87
 
86
88
  <div v-if="label || !!slots.label || (description || !!slots.description)" data-slot="wrapper" :class="ui.wrapper({ class: uiProp?.wrapper })">
87
- <component :is="!variant || variant === 'list' ? Label : 'p'" v-if="label || !!slots.label" :for="id" data-slot="label" :class="ui.label({ class: uiProp?.label })">
89
+ <component :is="variant === 'list' ? Label : 'p'" v-if="label || !!slots.label" :for="id" data-slot="label" :class="ui.label({ class: uiProp?.label })">
88
90
  <slot name="label" :label="label">
89
91
  {{ label }}
90
92
  </slot>
@@ -179,6 +179,13 @@ export interface CommandPaletteProps<G extends CommandPaletteGroup<T> = CommandP
179
179
  * @defaultValue false
180
180
  */
181
181
  preserveGroupOrder?: boolean;
182
+ /**
183
+ * Delay (in milliseconds) before the search term is passed to Fuse (debounced).
184
+ * Useful when indexing large datasets where fuzzy search becomes the bottleneck — the input stays responsive while Fuse and the result pipeline only re-run after typing settles.
185
+ * Set to `0` (the default) to disable.
186
+ * @defaultValue 0
187
+ */
188
+ searchDelay?: number;
182
189
  class?: any;
183
190
  ui?: CommandPalette['slots'];
184
191
  }
@@ -190,7 +197,15 @@ type SlotProps<T> = (props: {
190
197
  index: number;
191
198
  ui: CommandPalette['ui'];
192
199
  }) => VNode[];
193
- export type CommandPaletteSlots<T extends CommandPaletteItem = CommandPaletteItem> = {
200
+ type GroupSlotProps<T extends CommandPaletteItem = CommandPaletteItem, G extends CommandPaletteGroup<T> = CommandPaletteGroup<T>> = (props: {
201
+ group: G;
202
+ label: string;
203
+ ui: CommandPalette['ui'];
204
+ }) => VNode[];
205
+ type GroupSlots<T extends CommandPaletteItem = CommandPaletteItem, G extends CommandPaletteGroup<T> = CommandPaletteGroup<T>> = {
206
+ 'group-label'?: GroupSlotProps<T, G>;
207
+ } & Record<`${string}-group-label`, GroupSlotProps<T, G>>;
208
+ export type CommandPaletteSlots<T extends CommandPaletteItem = CommandPaletteItem, G extends CommandPaletteGroup<T> = CommandPaletteGroup<T>> = {
194
209
  'empty'?(props: {
195
210
  searchTerm: string;
196
211
  }): VNode[];
@@ -208,7 +223,7 @@ export type CommandPaletteSlots<T extends CommandPaletteItem = CommandPaletteIte
208
223
  'item-label'?: SlotProps<T>;
209
224
  'item-description'?: SlotProps<T>;
210
225
  'item-trailing'?: SlotProps<T>;
211
- } & Record<string, SlotProps<T>>;
226
+ } & Record<string, SlotProps<T>> & GroupSlots<T, G>;
212
227
  declare const _default: typeof __VLS_export;
213
228
  export default _default;
214
229
  declare const __VLS_export: <G extends CommandPaletteGroup<T>, T extends CommandPaletteItem>(__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<{
@@ -229,7 +244,7 @@ declare const __VLS_export: <G extends CommandPaletteGroup<T>, T extends Command
229
244
  } ? P : {});
230
245
  expose: (exposed: {}) => void;
231
246
  attrs: any;
232
- slots: CommandPaletteSlots<T>;
247
+ slots: CommandPaletteSlots<T, G>;
233
248
  emit: (((evt: "highlight", payload: {
234
249
  ref: HTMLElement;
235
250
  value: T;
@@ -6,7 +6,7 @@ import theme from "#build/ui/command-palette";
6
6
  import { computed, ref, useTemplateRef, toRef } from "vue";
7
7
  import { ListboxRoot, ListboxFilter, ListboxContent, ListboxGroup, ListboxGroupLabel, ListboxVirtualizer, ListboxItem, ListboxItemIndicator, useForwardPropsEmits } from "reka-ui";
8
8
  import { defu } from "defu";
9
- import { reactivePick, createReusableTemplate, refThrottled } from "@vueuse/core";
9
+ import { reactivePick, createReusableTemplate, refDebounced, refThrottled } from "@vueuse/core";
10
10
  import { useFuse } from "@vueuse/integrations/useFuse";
11
11
  import { useAppConfig } from "#imports";
12
12
  import { useComponentUI } from "../composables/useComponentUI";
@@ -46,6 +46,7 @@ const props = defineProps({
46
46
  labelKey: { type: null, required: false, default: "label" },
47
47
  descriptionKey: { type: null, required: false, default: "description" },
48
48
  preserveGroupOrder: { type: Boolean, required: false, default: false },
49
+ searchDelay: { type: Number, required: false, default: 0 },
49
50
  class: { type: null, required: false },
50
51
  ui: { type: Object, required: false },
51
52
  multiple: { type: Boolean, required: false },
@@ -113,20 +114,21 @@ const items = computed(() => groups.value?.filter((group) => {
113
114
  }
114
115
  return true;
115
116
  })?.flatMap((group) => group.items?.map((item) => ({ ...item, group: group.id })) || []) || []);
116
- const { results: fuseResults } = useFuse(searchTerm, items, fuse);
117
+ const fuseSearchTerm = refDebounced(searchTerm, () => props.searchDelay);
118
+ const { results: fuseResults } = useFuse(fuseSearchTerm, items, fuse);
117
119
  const throttledFuseResults = refThrottled(fuseResults, 16, true);
118
120
  function processGroupItems(group, items2) {
119
121
  let processedItems = items2;
120
122
  if (group?.postFilter && typeof group.postFilter === "function") {
121
- processedItems = group.postFilter(searchTerm.value, processedItems);
123
+ processedItems = group.postFilter(fuseSearchTerm.value, processedItems);
122
124
  }
123
125
  return {
124
126
  ...group,
125
127
  items: processedItems.slice(0, fuse.value.resultLimit).map((item) => {
126
128
  return {
127
129
  ...item,
128
- labelHtml: highlight(item, searchTerm.value, props.labelKey),
129
- suffixHtml: highlight(item, searchTerm.value, void 0, [props.labelKey])
130
+ labelHtml: highlight(item, fuseSearchTerm.value, props.labelKey),
131
+ suffixHtml: highlight(item, fuseSearchTerm.value, void 0, [props.labelKey])
130
132
  };
131
133
  })
132
134
  };
@@ -352,8 +354,10 @@ function onSelect(e, item) {
352
354
 
353
355
  <template v-else>
354
356
  <ListboxGroup v-for="group in filteredGroups" :key="`group-${group.id}`" data-slot="group" :class="ui.group({ class: uiProp?.group })">
355
- <ListboxGroupLabel v-if="get(group, props.labelKey)" data-slot="label" :class="ui.label({ class: uiProp?.label })">
356
- {{ get(group, props.labelKey) }}
357
+ <ListboxGroupLabel v-if="get(group, props.labelKey) || !!slots[group.slot ? `${group.slot}-group-label` : 'group-label']" data-slot="label" :class="ui.label({ class: uiProp?.label })">
358
+ <slot :name="group.slot ? `${group.slot}-group-label` : 'group-label'" :group="group" :label="get(group, props.labelKey)" :ui="ui">
359
+ {{ get(group, props.labelKey) }}
360
+ </slot>
357
361
  </ListboxGroupLabel>
358
362
 
359
363
  <ReuseItemTemplate
@@ -179,6 +179,13 @@ export interface CommandPaletteProps<G extends CommandPaletteGroup<T> = CommandP
179
179
  * @defaultValue false
180
180
  */
181
181
  preserveGroupOrder?: boolean;
182
+ /**
183
+ * Delay (in milliseconds) before the search term is passed to Fuse (debounced).
184
+ * Useful when indexing large datasets where fuzzy search becomes the bottleneck — the input stays responsive while Fuse and the result pipeline only re-run after typing settles.
185
+ * Set to `0` (the default) to disable.
186
+ * @defaultValue 0
187
+ */
188
+ searchDelay?: number;
182
189
  class?: any;
183
190
  ui?: CommandPalette['slots'];
184
191
  }
@@ -190,7 +197,15 @@ type SlotProps<T> = (props: {
190
197
  index: number;
191
198
  ui: CommandPalette['ui'];
192
199
  }) => VNode[];
193
- export type CommandPaletteSlots<T extends CommandPaletteItem = CommandPaletteItem> = {
200
+ type GroupSlotProps<T extends CommandPaletteItem = CommandPaletteItem, G extends CommandPaletteGroup<T> = CommandPaletteGroup<T>> = (props: {
201
+ group: G;
202
+ label: string;
203
+ ui: CommandPalette['ui'];
204
+ }) => VNode[];
205
+ type GroupSlots<T extends CommandPaletteItem = CommandPaletteItem, G extends CommandPaletteGroup<T> = CommandPaletteGroup<T>> = {
206
+ 'group-label'?: GroupSlotProps<T, G>;
207
+ } & Record<`${string}-group-label`, GroupSlotProps<T, G>>;
208
+ export type CommandPaletteSlots<T extends CommandPaletteItem = CommandPaletteItem, G extends CommandPaletteGroup<T> = CommandPaletteGroup<T>> = {
194
209
  'empty'?(props: {
195
210
  searchTerm: string;
196
211
  }): VNode[];
@@ -208,7 +223,7 @@ export type CommandPaletteSlots<T extends CommandPaletteItem = CommandPaletteIte
208
223
  'item-label'?: SlotProps<T>;
209
224
  'item-description'?: SlotProps<T>;
210
225
  'item-trailing'?: SlotProps<T>;
211
- } & Record<string, SlotProps<T>>;
226
+ } & Record<string, SlotProps<T>> & GroupSlots<T, G>;
212
227
  declare const _default: typeof __VLS_export;
213
228
  export default _default;
214
229
  declare const __VLS_export: <G extends CommandPaletteGroup<T>, T extends CommandPaletteItem>(__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<{
@@ -229,7 +244,7 @@ declare const __VLS_export: <G extends CommandPaletteGroup<T>, T extends Command
229
244
  } ? P : {});
230
245
  expose: (exposed: {}) => void;
231
246
  attrs: any;
232
- slots: CommandPaletteSlots<T>;
247
+ slots: CommandPaletteSlots<T, G>;
233
248
  emit: (((evt: "highlight", payload: {
234
249
  ref: HTMLElement;
235
250
  value: T;