Skip to content

Commit 4f3231c

Browse files
committed
chore(ChatMessage/ChatMessages): add generics
1 parent 63c0a5f commit 4f3231c

File tree

2 files changed

+22
-21
lines changed

2 files changed

+22
-21
lines changed

src/runtime/components/ChatMessage.vue

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
<script lang="ts">
22
import type { AppConfig } from '@nuxt/schema'
3-
import type { UIMessage } from 'ai'
3+
import type { UIDataTypes, UIMessage, UITools } from 'ai'
44
import theme from '#build/ui/chat-message'
55
import type { AvatarProps, ButtonProps, IconProps } from '../types'
66
import type { ComponentConfig } from '../types/tv'
77
88
type ChatMessage = ComponentConfig<typeof theme, AppConfig, 'chatMessage'>
99
10-
export interface ChatMessageProps extends UIMessage {
10+
export interface ChatMessageProps<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools>
11+
extends UIMessage<METADATA, DATA_PARTS, TOOLS> {
1112
/**
1213
* The element or component this component should render as.
1314
* @defaultValue 'article'
@@ -31,7 +32,7 @@ export interface ChatMessageProps extends UIMessage {
3132
* The `label` will be used in a tooltip.
3233
* `{ size: 'xs', color: 'neutral', variant: 'ghost' }`{lang="ts-type"}
3334
*/
34-
actions?: (Omit<ButtonProps, 'onClick'> & { onClick?: (e: MouseEvent, message: UIMessage) => void })[]
35+
actions?: (Omit<ButtonProps, 'onClick'> & { onClick?: (e: MouseEvent, message: UIMessage<METADATA, DATA_PARTS, TOOLS>) => void })[]
3536
/**
3637
* Render the message in a compact style.
3738
* This is done automatically when used inside a `UChatPalette`{lang="ts-type"}.
@@ -47,14 +48,14 @@ export interface ChatMessageProps extends UIMessage {
4748
ui?: ChatMessage['slots']
4849
}
4950
50-
export interface ChatMessageSlots {
51-
leading(props: { avatar: ChatMessageProps['avatar'], ui: ChatMessage['ui'] }): any
52-
content(props: ChatMessageProps): any
53-
actions(props: { actions: ChatMessageProps['actions'] }): any
51+
export interface ChatMessageSlots<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools> {
52+
leading(props: { avatar: ChatMessageProps<METADATA, DATA_PARTS, TOOLS>['avatar'], ui: ChatMessage['ui'] }): any
53+
content(props: ChatMessageProps<METADATA, DATA_PARTS, TOOLS>): any
54+
actions(props: { actions: ChatMessageProps<METADATA, DATA_PARTS, TOOLS>['actions'] }): any
5455
}
5556
</script>
5657

57-
<script setup lang="ts">
58+
<script setup lang="ts" generic="METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools">
5859
import { computed } from 'vue'
5960
import { Primitive } from 'reka-ui'
6061
import { useAppConfig } from '#imports'
@@ -65,10 +66,10 @@ import UTooltip from './Tooltip.vue'
6566
import UAvatar from './Avatar.vue'
6667
import UIcon from './Icon.vue'
6768
68-
const props = withDefaults(defineProps<ChatMessageProps>(), {
69+
const props = withDefaults(defineProps<ChatMessageProps<METADATA, DATA_PARTS, TOOLS>>(), {
6970
as: 'article'
7071
})
71-
const slots = defineSlots<ChatMessageSlots>()
72+
const slots = defineSlots<ChatMessageSlots<METADATA, DATA_PARTS, TOOLS>>()
7273
7374
const appConfig = useAppConfig() as ChatMessage['AppConfig']
7475
@@ -105,7 +106,7 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.chatMessage
105106
<template v-else>
106107
<template v-for="(part, index) in parts" :key="`${id}-${part.type}-${index}`">
107108
<template v-if="part.type === 'text'">
108-
{{ part.text }}
109+
{{ (part as any).text }}
109110
</template>
110111
</template>
111112
</template>

src/runtime/components/ChatMessages.vue

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<script lang="ts">
22
import type { AppConfig } from '@nuxt/schema'
3-
import type { UIMessage, ChatStatus } from 'ai'
3+
import type { UIMessage, ChatStatus, UIDataTypes, UITools } from 'ai'
44
import theme from '#build/ui/chat-messages'
55
import type { ButtonProps, ChatMessageProps, ChatMessageSlots, IconProps } from '../types'
66
import type { ComponentConfig } from '../types/tv'
77
88
type ChatMessages = ComponentConfig<typeof theme, AppConfig, 'chatMessages'>
99
10-
export interface ChatMessagesProps {
11-
messages?: UIMessage[]
10+
export interface ChatMessagesProps<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools> {
11+
messages?: UIMessage<METADATA, DATA_PARTS, TOOLS>[]
1212
status?: ChatStatus
1313
/**
1414
* Whether to automatically scroll to the bottom when a message is streaming.
@@ -57,21 +57,21 @@ export interface ChatMessagesProps {
5757
ui?: ChatMessages['slots']
5858
}
5959
60-
type ExtendSlotWithVersion<K extends keyof ChatMessageSlots>
60+
type ExtendSlotWithVersion<K extends keyof ChatMessageSlots, METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools>
6161
= ChatMessageSlots[K] extends (props: infer P) => any
62-
? (props: P & { message: UIMessage }) => any
62+
? (props: P & { message: UIMessage<METADATA, DATA_PARTS, TOOLS> }) => any
6363
: ChatMessageSlots[K]
6464
65-
export type ChatMessagesSlots = {
66-
[K in keyof ChatMessageSlots]: ExtendSlotWithVersion<K>
65+
export type ChatMessagesSlots<METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools> = {
66+
[K in keyof ChatMessageSlots]: ExtendSlotWithVersion<K, METADATA, DATA_PARTS, TOOLS>
6767
} & {
6868
default(props?: {}): any
6969
indicator(props: { ui: ChatMessages['ui'] }): any
7070
viewport(props: { ui: ChatMessages['ui'], onClick: () => void }): any
7171
}
7272
</script>
7373
74-
<script setup lang="ts">
74+
<script setup lang="ts" generic="METADATA = unknown, DATA_PARTS extends UIDataTypes = UIDataTypes, TOOLS extends UITools = UITools">
7575
import type { ComponentPublicInstance } from 'vue'
7676
import { ref, computed, watch, nextTick, toRef, onMounted } from 'vue'
7777
import { Presence } from 'reka-ui'
@@ -83,13 +83,13 @@ import { tv } from '../utils/tv'
8383
import UChatMessage from './ChatMessage.vue'
8484
import UButton from './Button.vue'
8585
86-
const props = withDefaults(defineProps<ChatMessagesProps>(), {
86+
const props = withDefaults(defineProps<ChatMessagesProps<METADATA, DATA_PARTS, TOOLS>>(), {
8787
autoScroll: true,
8888
shouldAutoScroll: false,
8989
shouldScrollToBottom: true,
9090
spacingOffset: 0
9191
})
92-
const slots = defineSlots<ChatMessagesSlots>()
92+
const slots = defineSlots<ChatMessagesSlots<METADATA, DATA_PARTS, TOOLS>>()
9393
9494
const getProxySlots = () => omit(slots, ['default', 'indicator', 'viewport'])
9595

0 commit comments

Comments
 (0)