import { forwardRef, useState } from 'react'; import Avatar from '../components/Avatar'; import CopyButton from '../components/CopyButton'; import remarkGfm from 'remark-gfm'; import { FEEDBACK, MESSAGE_TYPE } from './conversationModels'; import classes from './ConversationBubble.module.css'; import Alert from './../assets/alert.svg'; import Like from './../assets/like.svg?react'; import Dislike from './../assets/dislike.svg?react'; import ReactMarkdown from 'react-markdown'; import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; import { vscDarkPlus } from 'react-syntax-highlighter/dist/cjs/styles/prism'; import DocsGPT3 from '../assets/cute_docsgpt3.svg'; const DisableSourceFE = import.meta.env.VITE_DISABLE_SOURCE_FE || false; const ConversationBubble = forwardRef< HTMLDivElement, { message: string; type: MESSAGE_TYPE; className?: string; feedback?: FEEDBACK; handleFeedback?: (feedback: FEEDBACK) => void; sources?: { title: string; text: string; source: string }[]; retryBtn?: React.ReactElement; } >(function ConversationBubble( { message, type, className, feedback, handleFeedback, sources, retryBtn }, ref, ) { const [openSource, setOpenSource] = useState(null); const [isLikeHovered, setIsLikeHovered] = useState(false); const [isDislikeHovered, setIsDislikeHovered] = useState(false); const [isLikeClicked, setIsLikeClicked] = useState(false); const [isDislikeClicked, setIsDislikeClicked] = useState(false); let bubble; if (type === 'QUESTION') { bubble = (
{message}
); } else { bubble = (
} />
{type === 'ERROR' && ( <> alert
{retryBtn}
)} {String(children).replace(/\n$/, '')}
) : ( {children} ); }, ul({ children }) { return (
    {children}
); }, ol({ children }) { return (
    {children}
); }, table({ children }) { return (
{children}
); }, thead({ children }) { return ( {children} ); }, tr({ children }) { return ( {children} ); }, td({ children }) { return {children}; }, th({ children }) { return {children}; }, }} > {message} {DisableSourceFE || type === 'ERROR' || !sources || sources.length === 0 ? null : ( <>
Sources:
{sources?.map((source, index) => (
source.source !== 'local' ? window.open( source.source, '_blank', 'noopener, noreferrer', ) : setOpenSource(openSource === index ? null : index) } >

{index + 1}. {source.title.substring(0, 45)}

))}
)}
{handleFeedback && ( <>
{ handleFeedback?.('LIKE'); setIsLikeClicked(true); setIsDislikeClicked(false); }} onMouseEnter={() => setIsLikeHovered(true)} onMouseLeave={() => setIsLikeHovered(false)} >
{ handleFeedback?.('DISLIKE'); setIsDislikeClicked(true); setIsLikeClicked(false); }} onMouseEnter={() => setIsDislikeHovered(true)} onMouseLeave={() => setIsDislikeHovered(false)} >
)}
{sources && openSource !== null && sources[openSource] && (

Source: {sources[openSource].title}

{sources[openSource].text}

)} ); } return bubble; }); export default ConversationBubble;