Spaces:
Running
Running
// Inspired by Chatbot-UI and modified to fit the needs of this project | |
// @see https://github.com/mckaywrigley/chatbot-ui/blob/main/components/Chat/ChatMessage.tsx | |
import { Message } from 'ai' | |
import remarkGfm from 'remark-gfm' | |
import remarkMath from 'remark-math' | |
import { cn } from '@/lib/utils' | |
import { CodeBlock } from '@/components/ui/codeblock' | |
import { MemoizedReactMarkdown } from '@/components/markdown' | |
import { IconOpenAI, IconUser } from '@/components/ui/icons' | |
import { ChatMessageActions } from '@/components/chat-message-actions' | |
export interface ChatMessageProps { | |
message: Message | |
} | |
export function ChatMessage({ message, ...props }: ChatMessageProps) { | |
return ( | |
<div | |
className={cn('group relative mb-4 flex items-start md:-ml-12')} | |
{...props} | |
> | |
<div | |
className={cn( | |
'flex size-8 shrink-0 select-none items-center justify-center rounded-md border shadow', | |
message.role === 'user' | |
? 'bg-background' | |
: 'bg-primary text-primary-foreground' | |
)} | |
> | |
{message.role === 'user' ? <IconUser /> : <IconOpenAI />} | |
</div> | |
<div className="flex-1 px-1 ml-4 space-y-2 overflow-hidden"> | |
<MemoizedReactMarkdown | |
className="prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0" | |
remarkPlugins={[remarkGfm, remarkMath]} | |
components={{ | |
p({ children }) { | |
return <p className="mb-2 last:mb-0">{children}</p> | |
}, | |
code({ node, inline, className, children, ...props }) { | |
if (children.length) { | |
if (children[0] == 'β') { | |
return ( | |
<span className="mt-1 cursor-default animate-pulse">β</span> | |
) | |
} | |
children[0] = (children[0] as string).replace('`β`', 'β') | |
} | |
const match = /language-(\w+)/.exec(className || '') | |
if (inline) { | |
return ( | |
<code className={className} {...props}> | |
{children} | |
</code> | |
) | |
} | |
return ( | |
<CodeBlock | |
key={Math.random()} | |
language={(match && match[1]) || ''} | |
value={String(children).replace(/\n$/, '')} | |
{...props} | |
/> | |
) | |
} | |
}} | |
> | |
{message.content} | |
</MemoizedReactMarkdown> | |
<ChatMessageActions message={message} /> | |
</div> | |
</div> | |
) | |
} | |