File size: 4,045 Bytes
4114d85 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
import { IconClipboard, IconDownload } from '@tabler/icons'
import { memo, useState } from 'react'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { oneDark } from 'react-syntax-highlighter/dist/esm/styles/prism'
import PropTypes from 'prop-types'
import { Box, IconButton, Popover, Typography } from '@mui/material'
import { useTheme } from '@mui/material/styles'
const programmingLanguages = {
javascript: '.js',
python: '.py',
java: '.java',
c: '.c',
cpp: '.cpp',
'c++': '.cpp',
'c#': '.cs',
ruby: '.rb',
php: '.php',
swift: '.swift',
'objective-c': '.m',
kotlin: '.kt',
typescript: '.ts',
go: '.go',
perl: '.pl',
rust: '.rs',
scala: '.scala',
haskell: '.hs',
lua: '.lua',
shell: '.sh',
sql: '.sql',
html: '.html',
css: '.css'
}
export const CodeBlock = memo(({ language, chatflowid, isDialog, value }) => {
const theme = useTheme()
const [anchorEl, setAnchorEl] = useState(null)
const openPopOver = Boolean(anchorEl)
const handleClosePopOver = () => {
setAnchorEl(null)
}
const copyToClipboard = (event) => {
if (!navigator.clipboard || !navigator.clipboard.writeText) {
return
}
navigator.clipboard.writeText(value)
setAnchorEl(event.currentTarget)
setTimeout(() => {
handleClosePopOver()
}, 1500)
}
const downloadAsFile = () => {
const fileExtension = programmingLanguages[language] || '.file'
const suggestedFileName = `file-${chatflowid}${fileExtension}`
const fileName = suggestedFileName
if (!fileName) {
// user pressed cancel on prompt
return
}
const blob = new Blob([value], { type: 'text/plain' })
const url = URL.createObjectURL(blob)
const link = document.createElement('a')
link.download = fileName
link.href = url
link.style.display = 'none'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
URL.revokeObjectURL(url)
}
return (
<div style={{ width: isDialog ? '' : 300 }}>
<Box sx={{ color: 'white', background: theme.palette?.common.dark, p: 1, borderTopLeftRadius: 10, borderTopRightRadius: 10 }}>
<div style={{ display: 'flex', flexDirection: 'row', alignItems: 'center' }}>
{language}
<div style={{ flex: 1 }}></div>
<IconButton size='small' title='Copy' color='success' onClick={copyToClipboard}>
<IconClipboard />
</IconButton>
<Popover
open={openPopOver}
anchorEl={anchorEl}
onClose={handleClosePopOver}
anchorOrigin={{
vertical: 'top',
horizontal: 'right'
}}
transformOrigin={{
vertical: 'top',
horizontal: 'left'
}}
>
<Typography variant='h6' sx={{ pl: 1, pr: 1, color: 'white', background: theme.palette.success.dark }}>
Copied!
</Typography>
</Popover>
<IconButton size='small' title='Download' color='primary' onClick={downloadAsFile}>
<IconDownload />
</IconButton>
</div>
</Box>
<SyntaxHighlighter language={language} style={oneDark} customStyle={{ margin: 0 }}>
{value}
</SyntaxHighlighter>
</div>
)
})
CodeBlock.displayName = 'CodeBlock'
CodeBlock.propTypes = {
language: PropTypes.string,
chatflowid: PropTypes.string,
isDialog: PropTypes.bool,
value: PropTypes.string
}
|