14
14
* limitations under the License.
15
15
*/
16
16
17
- import { useState , useEffect , useCallback } from 'react'
18
- import Tippy from '@tippyjs/react '
17
+ import { useState , useEffect , useRef } from 'react'
18
+ import Tooltip from '@Common/Tooltip/Tooltip '
19
19
import { copyToClipboard , noop , stopPropagation } from '../Helper'
20
20
import ClipboardProps from './types'
21
21
import { ReactComponent as ICCopy } from '../../Assets/Icon/ic-copy.svg'
@@ -25,73 +25,86 @@ import { ReactComponent as Check } from '../../Assets/Icon/ic-check.svg'
25
25
* @param content - Content to be copied
26
26
* @param copiedTippyText - Text to be shown in the tippy when the content is copied, default 'Copied!'
27
27
* @param duration - Duration for which the tippy should be shown, default 1000
28
- * @param trigger - To trigger the copy action outside the button, if set to true the content will be copied, use case being triggering the copy action from outside the component
29
- * @param setTrigger - Callback function to set the trigger outside the button
28
+ * @param copyToClipboardPromise - the promise returned by copyToClipboard util function
30
29
* @param rootClassName - additional classes to add to button
31
30
* @param iconSize - size of svg icon to be shown, default 16 (icon-dim-16)
32
31
*/
33
- export default function ClipboardButton ( {
32
+ export const ClipboardButton = ( {
34
33
content,
35
34
copiedTippyText = 'Copied!' ,
36
35
duration = 1000 ,
37
- trigger,
38
- setTrigger = noop ,
36
+ copyToClipboardPromise,
39
37
rootClassName = '' ,
40
38
iconSize = 16 ,
41
- } : ClipboardProps ) {
39
+ } : ClipboardProps ) => {
42
40
const [ copied , setCopied ] = useState < boolean > ( false )
43
- const [ enableTippy , setEnableTippy ] = useState < boolean > ( false )
41
+ const setCopiedFalseTimeoutRef = useRef < ReturnType < typeof setTimeout > > ( - 1 )
44
42
45
- const handleTextCopied = ( ) => {
43
+ const handleTriggerCopy = ( ) => {
46
44
setCopied ( true )
45
+
46
+ setCopiedFalseTimeoutRef . current = setTimeout ( ( ) => {
47
+ setCopied ( false )
48
+
49
+ setCopiedFalseTimeoutRef . current = - 1
50
+ } , duration )
47
51
}
48
- const isTriggerUndefined = typeof trigger === 'undefined'
49
52
50
- const handleEnableTippy = ( ) => setEnableTippy ( true )
51
- const handleDisableTippy = ( ) => setEnableTippy ( false )
52
- const handleCopyContent = useCallback (
53
- ( e ?) => {
54
- if ( e ) stopPropagation ( e )
55
- copyToClipboard ( content , handleTextCopied )
56
- } ,
57
- [ content ] ,
58
- )
59
- const iconClassName = `icon-dim-${ iconSize } dc__no-shrink`
53
+ const handleAwaitCopyToClipboardPromise = async ( shouldRunCopy ?: boolean ) => {
54
+ try {
55
+ if ( shouldRunCopy ) {
56
+ await copyToClipboard ( content )
57
+ } else {
58
+ await copyToClipboardPromise
59
+ }
60
60
61
- useEffect ( ( ) => {
62
- if ( ! copied ) return
61
+ handleTriggerCopy ( )
62
+ } catch {
63
+ noop ( )
64
+ }
65
+ }
63
66
64
- const timeout = setTimeout ( ( ) => {
65
- setCopied ( false )
66
- setTrigger ( false )
67
- } , duration )
67
+ const handleCopyContent = async ( e ?: React . MouseEvent ) => {
68
+ if ( e ) {
69
+ stopPropagation ( e )
70
+ }
68
71
69
- return ( ) => clearTimeout ( timeout )
70
- } , [ copied , duration , setTrigger ] )
72
+ await handleAwaitCopyToClipboardPromise ( true )
73
+ }
71
74
72
75
useEffect ( ( ) => {
73
- if ( ! isTriggerUndefined && trigger ) {
74
- setCopied ( true )
75
- handleCopyContent ( )
76
+ if ( ! copyToClipboardPromise ) {
77
+ return
76
78
}
77
- } , [ trigger , handleCopyContent ] )
79
+
80
+ handleAwaitCopyToClipboardPromise ( ) . catch ( noop )
81
+ } , [ copyToClipboardPromise ] )
82
+
83
+ useEffect (
84
+ ( ) => ( ) => {
85
+ if ( setCopiedFalseTimeoutRef . current > - 1 ) {
86
+ clearTimeout ( setCopiedFalseTimeoutRef . current )
87
+ }
88
+ } ,
89
+ [ ] ,
90
+ )
91
+
92
+ const iconClassName = `icon-dim-${ iconSize } dc__no-shrink`
93
+
78
94
return (
79
- < Tippy
80
- className = "default-tt"
81
- content = { copied ? copiedTippyText : 'Copy' }
82
- placement = "bottom"
83
- visible = { copied || enableTippy }
84
- arrow = { false }
85
- >
95
+ < Tooltip content = "Copy" alwaysShowTippyOnHover = { ! copied } >
96
+ { /* TODO: semantically buttons should not be nested; fix later */ }
86
97
< button
87
98
type = "button"
88
99
className = { `dc__outline-none-imp p-0 flex dc__transparent--unstyled dc__no-border ${ rootClassName } ` }
89
- onMouseEnter = { handleEnableTippy }
90
- onMouseLeave = { handleDisableTippy }
91
- onClick = { isTriggerUndefined && handleCopyContent }
100
+ onClick = { handleCopyContent }
92
101
>
93
- { copied ? < Check className = { iconClassName } /> : < ICCopy className = { iconClassName } /> }
102
+ < Tooltip content = { copiedTippyText } alwaysShowTippyOnHover visible = { copied } >
103
+ < div className = "flex" >
104
+ { copied ? < Check className = { iconClassName } /> : < ICCopy className = { iconClassName } /> }
105
+ </ div >
106
+ </ Tooltip >
94
107
</ button >
95
- </ Tippy >
108
+ </ Tooltip >
96
109
)
97
110
}
0 commit comments