react-garden
Version:
React + TypeScript + ThreeJS app using Material UI on NextJS, Apollo Client, GraphQL + WordPress REST APIs, for ThreeD web development.. a part of the threed.ai code family.
139 lines (124 loc) • 4.43 kB
JavaScript
// ** React Imports
import { useState, useEffect } from 'react'
// ** MUI Imports
import Box from '@mui/material/Box'
import Card from '@mui/material/Card'
import Tooltip from '@mui/material/Tooltip'
import Divider from '@mui/material/Divider'
import Collapse from '@mui/material/Collapse'
import IconButton from '@mui/material/IconButton'
import CardHeader from '@mui/material/CardHeader'
import CardContent from '@mui/material/CardContent'
import ToggleButton from '@mui/material/ToggleButton'
import useMediaQuery from '@mui/material/useMediaQuery'
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup'
// ** Icons Imports
import CodeTags from 'mdi-material-ui/CodeTags'
import ContentCopy from 'mdi-material-ui/ContentCopy'
import LanguageJavascript from 'mdi-material-ui/LanguageJavascript'
import LanguageTypescript from 'mdi-material-ui/LanguageTypescript'
// ** Third Party Components
import Prism from 'prismjs'
import toast from 'react-hot-toast'
// ** Hooks
import useClipboard from '~/@core/hooks/useClipboard'
const CardSnippet = props => {
// ** Props
const { id, sx, code, title, children, className } = props
// ** States
const [showCode, setShowCode] = useState(false)
const [tabValue, setTabValue] = useState(code.tsx !== null ? 'tsx' : 'jsx')
// ** Hooks
const clipboard = useClipboard()
const hidden = useMediaQuery(theme => theme.breakpoints.down('md'))
// ** Highlight code on mount
useEffect(() => {
Prism.highlightAll()
}, [showCode, tabValue])
const codeToCopy = () => {
if (code.tsx !== null && tabValue === 'tsx') {
return code.tsx.props.children.props.children
} else if (code.jsx !== null && tabValue === 'jsx') {
return code.jsx.props.children.props.children
} else {
return ''
}
}
const handleClick = () => {
clipboard.copy(codeToCopy())
toast.success('The source code has been copied to your clipboard.', {
duration: 2000
})
}
const renderCode = () => {
if (code[tabValue] !== null) {
return code[tabValue]
} else {
return null
}
}
return (
<Card
className={className}
sx={{ '& .MuiCardHeader-action': { lineHeight: 0.8 }, ...sx }}
id={id || `card-snippet--${title.toLowerCase().replace(/ /g, '-')}`}
>
<CardHeader
title={title}
titleTypographyProps={{ variant: 'h6' }}
{...(hidden
? {}
: {
action: (
<IconButton onClick={() => setShowCode(!showCode)}>
<CodeTags fontSize='small' />
</IconButton>
)
})}
/>
<CardContent>{children}</CardContent>
{hidden ? null : (
<Collapse in={showCode}>
<Divider sx={{ my: 0 }} />
<CardContent sx={{ position: 'relative', '& pre': { m: '0 !important', maxHeight: 500 } }}>
<Box sx={{ mb: 4, display: 'flex', alignItems: 'center', justifyContent: 'flex-end' }}>
<ToggleButtonGroup
exclusive
size='small'
color='primary'
value={tabValue}
onChange={(e, newValue) => (newValue !== null ? setTabValue(newValue) : null)}
>
{code.tsx !== null ? (
<ToggleButton value='tsx'>
<LanguageTypescript fontSize='small' />
</ToggleButton>
) : null}
{code.jsx !== null ? (
<ToggleButton value='jsx'>
<LanguageJavascript fontSize='small' />
</ToggleButton>
) : null}
</ToggleButtonGroup>
</Box>
<Tooltip title='Copy the source' placement='top'>
<IconButton
onClick={handleClick}
sx={{
top: '5rem',
right: '2.5625rem',
position: 'absolute',
color: theme => theme.palette.grey[100]
}}
>
<ContentCopy fontSize='small' />
</IconButton>
</Tooltip>
<Box>{renderCode()}</Box>
</CardContent>
</Collapse>
)}
</Card>
)
}
export default CardSnippet