-
Notifications
You must be signed in to change notification settings - Fork 1.2k
/
pre.tsx
81 lines (76 loc) · 2.31 KB
/
pre.tsx
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
import React, {
ComponentProps,
ReactElement,
useCallback,
useRef,
useState,
useEffect
} from 'react'
import { CopyToClipboard } from './copy-to-clipboard'
import { Button } from './button'
import { WordWrapIcon } from '../icons'
export const Pre = ({
children,
className = '',
value,
filename,
...props
}: ComponentProps<'pre'> & {
filename?: string
value?: string
}): ReactElement => {
const preRef = useRef<HTMLPreElement | null>(null)
const [codeString, setCodeString] = useState(value)
const toggleWordWrap = useCallback(() => {
const htmlDataset = document.documentElement.dataset
const hasWordWrap = 'nextraWordWrap' in htmlDataset
if (hasWordWrap) {
delete htmlDataset.nextraWordWrap
} else {
htmlDataset.nextraWordWrap = ''
}
}, [])
useEffect(() => {
const codeEl = preRef.current?.querySelector('code')
if (codeEl?.textContent) {
setCodeString(codeEl.textContent)
}
}, [preRef])
return (
<>
{filename && (
<div className="nx-absolute nx-top-0 nx-z-[1] nx-w-full nx-truncate nx-rounded-t-xl nx-bg-primary-700/5 nx-py-2 nx-px-4 nx-text-xs nx-text-gray-700 dark:nx-bg-primary-300/10 dark:nx-text-gray-200">
{filename}
</div>
)}
<pre
className={[
'nx-bg-primary-700/5 nx-mb-4 nx-overflow-x-auto nx-rounded-xl nx-font-medium nx-subpixel-antialiased dark:nx-bg-primary-300/10 nx-text-[.9em]',
'contrast-more:nx-border contrast-more:nx-border-primary-900/20 contrast-more:nx-contrast-150 contrast-more:dark:nx-border-primary-100/40',
filename ? 'nx-pt-12 nx-pb-4' : 'nx-py-4',
className
].join(' ')}
ref={preRef}
{...props}
>
{children}
</pre>
<div
className={[
'nx-opacity-0 nx-transition [div:hover>&]:nx-opacity-100 focus-within:nx-opacity-100',
'nx-flex nx-gap-1 nx-absolute nx-m-[11px] nx-right-0',
filename ? 'nx-top-8' : 'nx-top-0'
].join(' ')}
>
<Button
onClick={toggleWordWrap}
className="md:nx-hidden"
title="Toggle word wrap"
>
<WordWrapIcon className="nx-pointer-events-none nx-h-4 nx-w-4" />
</Button>
{codeString && <CopyToClipboard value={codeString} />}
</div>
</>
)
}