39 lines
1.2 KiB
TypeScript
39 lines
1.2 KiB
TypeScript
import { useEvent } from '@/hooks/useEvent';
|
|
import React, { useState } from 'react';
|
|
import { Button } from './ui/button';
|
|
import { LuCopy, LuCopyCheck } from 'react-icons/lu';
|
|
import { toast } from 'sonner';
|
|
import { useTranslation } from '@i18next-toolkit/react';
|
|
import { ScrollBar } from './ui/scroll-area';
|
|
|
|
export const CodeBlock: React.FC<{
|
|
code: string;
|
|
}> = React.memo((props) => {
|
|
const [copied, setCopied] = useState(false);
|
|
const { t } = useTranslation();
|
|
|
|
const handleCopy = useEvent(() => {
|
|
window.navigator.clipboard.writeText(props.code);
|
|
|
|
toast(t('Copied into clipboard!'));
|
|
|
|
setCopied(true);
|
|
});
|
|
|
|
return (
|
|
<div className="group relative w-full overflow-auto">
|
|
<pre className="max-h-96 rounded-sm border border-zinc-800 bg-zinc-900 p-3 pr-12 text-sm">
|
|
<code>{props.code}</code>
|
|
</pre>
|
|
<Button
|
|
className="absolute right-1 top-1 bg-opacity-50 opacity-0 transition-opacity group-hover:opacity-100 dark:bg-opacity-50"
|
|
variant="outline"
|
|
size="icon"
|
|
Icon={copied ? LuCopyCheck : LuCopy}
|
|
onClick={handleCopy}
|
|
/>
|
|
</div>
|
|
);
|
|
});
|
|
CodeBlock.displayName = 'CodeBlock';
|