11import type { Component , ComputedRef , MaybeRefOrGetter } from 'vue'
22import { computed , inject , provide , toValue } from 'vue'
33import {
4+ BUBBLE_CONTENT_ATTRIBUTES_KEY ,
45 BUBBLE_CONTENT_FALLBACK_RENDERER_KEY ,
56 BUBBLE_CONTENT_PROP_FALLBACK_RENDERER_KEY ,
67 BUBBLE_CONTENT_RENDERER_MATCHES_KEY ,
78} from '../constants'
8- import type { BubbleContentRendererMatch , BubbleMessage , ChatMessageContentItem } from '../index.type'
9+ import type {
10+ BubbleAttributes ,
11+ BubbleContentAttributesConfig ,
12+ BubbleContentRendererMatch ,
13+ BubbleMessage ,
14+ ChatMessageContentItem ,
15+ } from '../index.type'
916import { defaultContentRendererMatches , defaultFallbackContentRenderer } from '../renderers/defaultRenderers'
1017import { useContentResolver } from './useContentResolver'
1118
1219export function setupBubbleContentRenderer ( renderers : {
1320 contentRendererMatches ?: MaybeRefOrGetter < Array < BubbleContentRendererMatch > >
21+ contentAttributes ?: MaybeRefOrGetter < BubbleContentAttributesConfig | undefined >
1422 fallbackContentRenderer ?: MaybeRefOrGetter < Component >
1523} ) : void {
16- const { contentRendererMatches, fallbackContentRenderer } = renderers
24+ const { contentRendererMatches, contentAttributes , fallbackContentRenderer } = renderers
1725 if ( contentRendererMatches ) {
1826 provide ( BUBBLE_CONTENT_RENDERER_MATCHES_KEY , contentRendererMatches )
1927 }
28+ if ( contentAttributes ) {
29+ provide ( BUBBLE_CONTENT_ATTRIBUTES_KEY , contentAttributes )
30+ }
2031 if ( fallbackContentRenderer ) {
2132 provide ( BUBBLE_CONTENT_FALLBACK_RENDERER_KEY , fallbackContentRenderer )
2233 }
@@ -38,8 +49,12 @@ export function setupBubblePropContentRenderer(renderers: {
3849export function useBubbleContentRenderer (
3950 message : MaybeRefOrGetter < BubbleMessage > ,
4051 contentIndex : number ,
41- ) : ComputedRef < Component > {
52+ ) : ComputedRef < {
53+ renderer : Component
54+ attributes ?: BubbleAttributes
55+ } > {
4256 const contentRendererMatches = inject ( BUBBLE_CONTENT_RENDERER_MATCHES_KEY , defaultContentRendererMatches )
57+ const contentAttributes = inject ( BUBBLE_CONTENT_ATTRIBUTES_KEY , undefined )
4358 const fallbackContentRenderer = inject ( BUBBLE_CONTENT_FALLBACK_RENDERER_KEY , undefined )
4459 const propFallbackContentRenderer = inject ( BUBBLE_CONTENT_PROP_FALLBACK_RENDERER_KEY , undefined )
4560 const contentResolver = useContentResolver ( )
@@ -50,12 +65,29 @@ export function useBubbleContentRenderer(
5065 const content = Array . isArray ( resolvedContent )
5166 ? ( resolvedContent . at ( contentIndex ?? 0 ) as ChatMessageContentItem )
5267 : { type : 'text' , text : resolvedContent || '' }
68+ const resolvedProviderAttributes = ( ( ) => {
69+ const attrs = toValue ( contentAttributes )
70+ if ( ! attrs ) {
71+ return undefined
72+ }
73+ return typeof attrs === 'function' ? attrs ( msg , content , contentIndex ) : attrs
74+ } ) ( )
5375 const match = toValue ( contentRendererMatches ) . find ( ( match ) => match . find ( msg , content , contentIndex ) )
5476 if ( match ) {
55- return match . renderer
77+ return {
78+ renderer : match . renderer ,
79+ attributes : {
80+ ...resolvedProviderAttributes ,
81+ ...match . attributes ,
82+ } ,
83+ }
5684 }
5785
5886 // Priority: prop-level > provider-level > default
59- return toValue ( propFallbackContentRenderer ) || toValue ( fallbackContentRenderer ) || defaultFallbackContentRenderer
87+ return {
88+ renderer :
89+ toValue ( propFallbackContentRenderer ) || toValue ( fallbackContentRenderer ) || defaultFallbackContentRenderer ,
90+ attributes : resolvedProviderAttributes ,
91+ }
6092 } )
6193}
0 commit comments