1
- import { CheckIcon } from "@heroicons/react/20/solid" ;
2
- import { useCallback , useEffect , useRef , useState } from "react" ;
1
+ import { useEffect , useRef , useState } from "react" ;
3
2
import { cn } from "~/utils/cn" ;
4
- import { Button } from "./Buttons" ;
5
- import { ClipboardCheckIcon , ClipboardIcon } from "lucide-react" ;
3
+ import { CopyButton } from "./CopyButton" ;
6
4
7
5
const variants = {
8
6
"primary/small" : {
9
7
container :
10
8
"flex items-center text-text-dimmed font-mono rounded border bg-charcoal-750 text-xs transition hover:bg-charcoal-700 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-transparent focus:outline-none focus:ring-0 focus:ring-transparent" ,
11
9
input :
12
10
"bg-transparent border-0 text-xs px-2 w-auto rounded-l h-6 leading-6 focus:ring-transparent" ,
13
- buttonVariant : "primary/small" as const ,
11
+ buttonVariant : "primary" as const ,
12
+ size : "small" as const ,
14
13
button : "rounded-l-none" ,
15
- iconSize : "h-3 w-3" ,
16
- iconPadding : "pl-1" ,
17
14
} ,
18
15
"secondary/small" : {
19
16
container :
20
17
"flex items-center text-text-dimmed font-mono rounded border bg-charcoal-750 text-xs transition hover:bg-charcoal-700 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-transparent focus:outline-none focus:ring-0 focus:ring-transparent" ,
21
18
input :
22
19
"bg-transparent border-0 text-xs px-2 w-auto rounded-l h-6 leading-6 focus:ring-transparent" ,
23
- buttonVariant : "tertiary/small" as const ,
20
+ buttonVariant : "tertiary" as const ,
21
+ size : "small" as const ,
24
22
button : "rounded-l-none border-l border-charcoal-750" ,
25
- iconSize : "h-3 w-3" ,
26
- iconPadding : "pl-1" ,
27
23
} ,
28
24
"tertiary/small" : {
29
25
container :
30
26
"group/clipboard flex items-center text-text-dimmed font-mono rounded bg-transparent border border-transparent text-xs transition duration-150 hover:border-charcoal-700 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-transparent focus:outline-none focus:ring-0 focus:ring-transparent" ,
31
27
input :
32
28
"bg-transparent border-0 text-xs px-2 w-auto rounded-l h-6 leading-6 focus:ring-transparent" ,
33
- buttonVariant : "minimal/small" as const ,
29
+ buttonVariant : "minimal" as const ,
30
+ size : "small" as const ,
34
31
button :
35
32
"rounded-l-none border-l border-transparent transition group-hover/clipboard:border-charcoal-700" ,
36
- iconSize : "h-3 w-3" ,
37
- iconPadding : "pl-1" ,
38
33
} ,
39
34
"primary/medium" : {
40
35
container :
41
36
"flex items-center text-text-dimmed font-mono rounded border bg-charcoal-750 text-sm transition hover:bg-charcoal-700 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-transparent focus:outline-none focus:ring-0 focus:ring-transparent" ,
42
37
input :
43
38
"bg-transparent border-0 text-sm px-3 w-auto rounded-l h-8 leading-6 focus:ring-transparent" ,
44
- buttonVariant : "primary/medium" as const ,
39
+ buttonVariant : "primary" as const ,
40
+ size : "medium" as const ,
45
41
button : "rounded-l-none" ,
46
- iconSize : "h-4 w-4" ,
47
- iconPadding : "pl-2" ,
48
42
} ,
49
43
"secondary/medium" : {
50
44
container :
51
45
"flex items-center text-text-dimmed font-mono rounded bg-charcoal-750 text-sm transition hover:bg-charcoal-700 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-transparent focus:outline-none focus:ring-0 focus:ring-transparent" ,
52
46
input :
53
47
"bg-transparent border-0 text-sm px-3 w-auto rounded-l h-8 leading-6 focus:ring-transparent" ,
54
- buttonVariant : "tertiary/medium" as const ,
48
+ buttonVariant : "tertiary" as const ,
49
+ size : "medium" as const ,
55
50
button : "rounded-l-none border-l border-charcoal-750" ,
56
- iconSize : "h-4 w-4" ,
57
- iconPadding : "pl-2" ,
58
51
} ,
59
52
"tertiary/medium" : {
60
53
container :
61
54
"group flex items-center text-text-dimmed font-mono rounded bg-transparent border border-transparent text-sm transition hover:border-charcoal-700 focus-visible:outline-none focus-visible:ring-0 focus-visible:ring-offset-0 focus:border-transparent focus:outline-none focus:ring-0 focus:ring-transparent" ,
62
55
input :
63
56
"bg-transparent border-0 text-sm px-3 w-auto rounded-l h-8 leading-6 focus:ring-transparent" ,
64
- buttonVariant : "minimal/medium" as const ,
57
+ buttonVariant : "minimal" as const ,
58
+ size : "medium" as const ,
65
59
button : "rounded-l-none border-l border-transparent transition group-hover:border-charcoal-700" ,
66
- iconSize : "h-4 w-4" ,
67
- iconPadding : "pl-2" ,
68
60
} ,
69
61
} ;
70
62
@@ -88,36 +80,19 @@ export function ClipboardField({
88
80
fullWidth = true ,
89
81
} : ClipboardFieldProps ) {
90
82
const [ isSecure , setIsSecure ] = useState ( secure !== undefined && secure ) ;
91
- const [ copied , setCopied ] = useState ( false ) ;
92
-
93
- const copy = useCallback (
94
- ( event : React . MouseEvent < HTMLButtonElement > ) => {
95
- event . preventDefault ( ) ;
96
- event . stopPropagation ( ) ;
97
- navigator . clipboard . writeText ( value ) ;
98
- setCopied ( true ) ;
99
- setTimeout ( ( ) => {
100
- setCopied ( false ) ;
101
- } , 1500 ) ;
102
- } ,
103
- [ value ]
104
- ) ;
83
+ const inputIcon = useRef < HTMLInputElement > ( null ) ;
84
+ const { container, input, buttonVariant, button, size } = variants [ variant ] ;
105
85
106
86
useEffect ( ( ) => {
107
87
setIsSecure ( secure !== undefined && secure ) ;
108
88
} , [ secure ] ) ;
109
89
110
- const { container, input, buttonVariant, button } = variants [ variant ] ;
111
- const iconClassName = variants [ variant ] . iconSize ;
112
- const iconPosition = variants [ variant ] . iconPadding ;
113
- const inputIcon = useRef < HTMLInputElement > ( null ) ;
114
-
115
90
return (
116
91
< span className = { cn ( container , fullWidth ? "w-full" : "max-w-fit" , className ) } >
117
92
{ icon && (
118
93
< span
119
94
onClick = { ( ) => inputIcon . current && inputIcon . current . focus ( ) }
120
- className = { cn ( iconPosition , "flex items-center" ) }
95
+ className = "flex items-center pl-1"
121
96
>
122
97
{ icon }
123
98
</ span >
@@ -132,51 +107,26 @@ export function ClipboardField({
132
107
fullWidth ? "w-full" : "max-w-fit" ,
133
108
input
134
109
) }
135
- // size={value.length}
136
- // maxLength={3}
137
110
onFocus = { ( e ) => {
138
111
if ( secure ) {
139
- setIsSecure ( ( i ) => false ) ;
112
+ setIsSecure ( false ) ;
140
113
}
141
114
e . currentTarget . select ( ) ;
142
115
} }
143
116
onBlur = { ( ) => {
144
117
if ( secure ) {
145
- setIsSecure ( ( i ) => true ) ;
118
+ setIsSecure ( true ) ;
146
119
}
147
120
} }
148
121
/>
149
- { iconButton ? (
150
- < Button
151
- variant = { buttonVariant }
152
- onClick = { copy }
153
- className = { cn ( "shrink grow-0 px-1.5" , button ) }
154
- >
155
- { copied ? (
156
- < ClipboardCheckIcon
157
- className = { cn (
158
- "h-4 w-4" ,
159
- buttonVariant === "primary/small" || buttonVariant === "primary/medium"
160
- ? "text-background-dimmed"
161
- : "text-green-500"
162
- ) }
163
- />
164
- ) : (
165
- < ClipboardIcon
166
- className = { cn (
167
- "h-4 w-4" ,
168
- buttonVariant === "primary/small" || buttonVariant === "primary/medium"
169
- ? "text-background-dimmed"
170
- : "text-text-dimmed"
171
- ) }
172
- />
173
- ) }
174
- </ Button >
175
- ) : (
176
- < Button variant = { buttonVariant } onClick = { copy } className = { cn ( "shrink-0 grow-0" , button ) } >
177
- { copied ? < CheckIcon className = "mx-[0.4rem] h-4 w-4 text-green-500" /> : "Copy" }
178
- </ Button >
179
- ) }
122
+ < CopyButton
123
+ value = { value }
124
+ variant = { iconButton ? "icon" : "button" }
125
+ buttonVariant = { buttonVariant }
126
+ size = { size }
127
+ buttonClassName = { button }
128
+ showTooltip = { false }
129
+ />
180
130
</ span >
181
131
) ;
182
132
}
0 commit comments