1
- import * as React from 'react'
1
+ import React , { useState , useRef } from 'react'
2
2
import classNames from 'classnames'
3
3
import Highlight , { defaultProps } from 'prism-react-renderer'
4
4
import prismTheme from 'prism-react-renderer/themes/github'
5
5
import Loadable from 'react-loadable'
6
+ import ReactTooltip from 'react-tooltip'
7
+
6
8
import LoadingProvider from './loading'
9
+ import Icon from '../Icon'
7
10
8
11
// override background and default text color
9
12
prismTheme . plain = {
@@ -30,10 +33,30 @@ const LoadableComponent = Loadable({
30
33
} )
31
34
32
35
/* eslint-disable react/jsx-key */
33
- const CodeBlock = ( { children : exampleCode , className, containerClassName, ...props } ) => {
36
+ const CodeBlock = ( {
37
+ children : exampleCode ,
38
+ className,
39
+ containerClassName,
40
+ id = '' ,
41
+ copyable = false ,
42
+ ...props
43
+ } ) => {
34
44
const match = className . match ( / l a n g u a g e - ( \w * ) / )
35
45
const language = match ? match [ 1 ] : 'text'
36
46
47
+ const tooltipEl = useRef ( null )
48
+ const [ copySuccess , setCopySuccess ] = useState ( false )
49
+
50
+ const copyToClipboard = ( text ) => {
51
+ navigator . clipboard . writeText ( text )
52
+ setCopySuccess ( true )
53
+ ReactTooltip . show ( tooltipEl . current )
54
+ setTimeout ( ( ) => {
55
+ setCopySuccess ( false )
56
+ ReactTooltip . hide ( tooltipEl . current )
57
+ } , 2000 )
58
+ }
59
+
37
60
let title = ''
38
61
if ( className ?. includes ( 'title=' ) ) {
39
62
title = className . split ( 'title=' ) [ 1 ]
@@ -45,7 +68,7 @@ const CodeBlock = ({ children: exampleCode, className, containerClassName, ...pr
45
68
)
46
69
} else {
47
70
return (
48
- < div className = { classNames ( containerClassName , 'bg-qrigray-100' ) } >
71
+ < div className = { classNames ( containerClassName , 'bg-qrigray-100 group relative ' ) } >
49
72
{ title && (
50
73
< div className = 'border-b px-4 py-2 text-sm' >
51
74
{ title }
@@ -110,6 +133,33 @@ const CodeBlock = ({ children: exampleCode, className, containerClassName, ...pr
110
133
) }
111
134
</ Highlight >
112
135
</ div >
136
+ {
137
+ copyable && (
138
+ < >
139
+ < div
140
+ className = { classNames ( 'group-hover:visible absolute bottom-4 right-4 rounded bg-white p-1.5 text-center text-black hover:cursor-pointer' , {
141
+ invisible : ! copySuccess
142
+ } ) }
143
+ style = { { height : 34 , width : 34 } }
144
+ onClick = { ( ) => { copyToClipboard ( exampleCode ) } }
145
+ data-tip = 'Copied!'
146
+ data-for = { id }
147
+ data-event = 'noevent'
148
+ ref = { tooltipEl }
149
+ >
150
+ { ! copySuccess && < Icon icon = 'copy' size = 'sm' /> }
151
+ { copySuccess && < Icon icon = 'check' size = 'sm' className = 'text-green-600' /> }
152
+ </ div >
153
+ < ReactTooltip
154
+ id = { id }
155
+ effect = 'solid'
156
+ place = 'bottom'
157
+ padding = '2px'
158
+ className = 'codeblock-tooltip'
159
+ />
160
+ </ >
161
+ )
162
+ }
113
163
</ div >
114
164
)
115
165
}
0 commit comments