import { forwardRef, useState } from 'react'; import Avatar from '../components/Avatar'; import remarkGfm from 'remark-gfm'; import { FEEDBACK, MESSAGE_TYPE } from './conversationModels'; import classes from './ConversationBubble.module.css'; import Alert from './../assets/alert.svg'; import { ReactComponent as Like } from './../assets/like.svg'; import { ReactComponent as Dislike } from './../assets/dislike.svg'; import { ReactComponent as Copy } from './../assets/copy.svg'; import { ReactComponent as CheckMark } from './../assets/checkmark.svg'; import ReactMarkdown from 'react-markdown'; import copy from 'copy-to-clipboard'; 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 }[]; } >(function ConversationBubble( { message, type, className, feedback, handleFeedback, sources }, ref, ) { const [openSource, setOpenSource] = useState(null); const [copied, setCopied] = useState(false); const handleCopyClick = (text: string) => { copy(text); setCopied(true); // Reset copied to false after a few seconds setTimeout(() => { setCopied(false); }, 3000); }; const [isCopyHovered, setIsCopyHovered] = useState(false); 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 )} {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' ? null : ( <>
Sources:
{sources?.map((source, index) => (
setOpenSource(openSource === index ? null : index) } >

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

))}
)}
{copied ? ( setIsCopyHovered(true)} onMouseLeave={() => setIsCopyHovered(false)} /> ) : ( { handleCopyClick(message); }} onMouseEnter={() => setIsCopyHovered(true)} onMouseLeave={() => setIsCopyHovered(false)} > )}
{ 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;