@@ -3,13 +3,18 @@ import {
3
3
Avatar ,
4
4
Box ,
5
5
HStack ,
6
+ Icon ,
7
+ IconButton ,
6
8
Stack ,
7
9
useColorModeValue ,
8
10
} from "@chakra-ui/react" ;
9
11
import ReactMarkdown from "react-markdown" ;
10
12
import remarkGfm from "remark-gfm" ;
11
13
import PropTypes from "prop-types" ;
12
14
import { BeatLoader } from "react-spinners" ;
15
+ import SyntaxHighlighter from "react-syntax-highlighter" ;
16
+ import { dracula } from "react-syntax-highlighter/dist/esm/styles/prism" ;
17
+ import { TbCopy } from "react-icons/tb" ;
13
18
14
19
export default function ChatOuput ( { messages, isLoading, ...properties } ) {
15
20
const loaderColor = useColorModeValue ( "gray.100" , "white" ) ;
@@ -42,7 +47,34 @@ export default function ChatOuput({ messages, isLoading, ...properties }) {
42
47
>
43
48
< Avatar src = { agent ? "/chatbot.png" : "/user.png" } size = "xs" />
44
49
< Stack spacing = { 4 } fontSize = "sm" >
45
- < ReactMarkdown remarkPlugins = { [ remarkGfm ] } >
50
+ < ReactMarkdown
51
+ components = { {
52
+ pre : ( pre ) => {
53
+ const codeChunk = pre . node . children [ 0 ] . children [ 0 ] . value ;
54
+
55
+ const handleCopyCode = ( ) => {
56
+ navigator . clipboard . writeText ( codeChunk ) ;
57
+ } ;
58
+
59
+ return (
60
+ < Box position = "relative" >
61
+ < IconButton
62
+ position = "absolute"
63
+ top = { 4 }
64
+ right = { 2 }
65
+ size = "sm"
66
+ icon = { < Icon as = { TbCopy } fontSize = "lg" /> }
67
+ onClick = { ( ) => handleCopyCode ( ) }
68
+ />
69
+ < SyntaxHighlighter style = { dracula } >
70
+ { pre . children [ 0 ] . props . children [ 0 ] }
71
+ </ SyntaxHighlighter >
72
+ </ Box >
73
+ ) ;
74
+ } ,
75
+ } }
76
+ remarkPlugins = { [ remarkGfm ] }
77
+ >
46
78
{ response }
47
79
</ ReactMarkdown >
48
80
</ Stack >
0 commit comments