1
- import { MouseEvent , ReactNode , useCallback , useMemo } from "react"
1
+ import { MouseEvent , ReactNode , useCallback , useEffect , useMemo , useState } from "react"
2
2
import { Tooltip , TooltipContent , TooltipTrigger } from "@/components/ui/tooltip"
3
3
import { Badge } from "@/components/ui/badge"
4
4
import { SearchResult } from "@elastic/search-ui"
5
5
import { autoUnwrap } from "@/components/result/utils"
6
6
import { useCopyToClipboard } from "usehooks-ts"
7
+ import { CheckIcon } from "lucide-react"
7
8
8
9
export interface GenericResultViewTagProps {
9
10
/**
@@ -32,7 +33,7 @@ export interface GenericResultViewTagProps {
32
33
*/
33
34
singleValueMapper ?: ( value : string ) => ReactNode
34
35
onClick ?: ( e : MouseEvent < HTMLDivElement > , tagValue : ReactNode , fieldValue : string | string [ ] ) => void
35
- clickBehavior ?: "copy-text" | "follow-url"
36
+ clickBehavior ?: "copy-text" | "follow-url" | string
36
37
}
37
38
38
39
export function GenericResultViewTag ( {
@@ -45,6 +46,16 @@ export function GenericResultViewTag({
45
46
clickBehavior = "copy-text" ,
46
47
onClick
47
48
} : GenericResultViewTagProps ) {
49
+ const [ showCopiedNotice , setShowCopiedNotice ] = useState ( false )
50
+
51
+ useEffect ( ( ) => {
52
+ if ( showCopiedNotice ) {
53
+ setTimeout ( ( ) => {
54
+ setShowCopiedNotice ( false )
55
+ } , 1000 )
56
+ }
57
+ } , [ showCopiedNotice ] )
58
+
48
59
const fieldValue = useMemo ( ( ) => {
49
60
return autoUnwrap ( result [ field ] ) as string | string [ ]
50
61
} , [ field , result ] )
@@ -70,26 +81,44 @@ export function GenericResultViewTag({
70
81
const handleClick = useCallback (
71
82
( fieldValue : string | string [ ] , value : ReactNode , e : MouseEvent < HTMLDivElement > ) => {
72
83
if ( onClick ) onClick ( e , value , fieldValue )
73
- if ( clickBehavior === "copy-text" ) {
84
+ if ( clickBehavior === "copy-text" && ! showCopiedNotice ) {
74
85
copyTagValue ( e )
86
+ setShowCopiedNotice ( true )
75
87
} else if ( clickBehavior === "follow-url" && ! Array . isArray ( fieldValue ) ) {
76
88
window . open ( fieldValue , "_blank" )
77
89
}
78
90
} ,
79
- [ clickBehavior , copyTagValue , onClick ]
91
+ [ clickBehavior , copyTagValue , onClick , showCopiedNotice ]
80
92
)
81
93
94
+ const clickBehaviourText = useMemo ( ( ) => {
95
+ if ( onClick ) return null // We don't know what will happen on click...
96
+ if ( clickBehavior === "copy-text" ) {
97
+ return "Click to copy"
98
+ } else if ( clickBehavior === "follow-url" ) {
99
+ return "Click to open"
100
+ } else return null
101
+ } , [ clickBehavior , onClick ] )
102
+
82
103
const base = useCallback (
83
104
( fieldValue : string | string [ ] , value : ReactNode , key ?: string ) => {
84
105
return (
85
106
< Badge key = { key } variant = "secondary" className = "rfs-truncate" onClick = { ( e ) => handleClick ( fieldValue , value , e ) } >
86
107
< span className = "rfs-flex rfs-truncate" >
87
- { icon } { value }
108
+ { showCopiedNotice ? (
109
+ < >
110
+ < CheckIcon className = "rfs-size-4 rfs-mr-2" /> < span > Copied</ span >
111
+ </ >
112
+ ) : (
113
+ < >
114
+ { icon } { value }
115
+ </ >
116
+ ) }
88
117
</ span >
89
118
</ Badge >
90
119
)
91
120
} ,
92
- [ handleClick , icon ]
121
+ [ handleClick , icon , showCopiedNotice ]
93
122
)
94
123
95
124
if ( ! label ) return Array . isArray ( value ) ? value . map ( ( v , i ) => base ( fieldValue [ value . indexOf ( v ) ] , v , field + i ) ) : base ( fieldValue , value )
@@ -99,15 +128,21 @@ export function GenericResultViewTag({
99
128
return value . map ( ( entry , i ) => (
100
129
< Tooltip delayDuration = { 500 } key = { field + i } >
101
130
< TooltipTrigger > { base ( fieldValue [ value . indexOf ( entry ) ] , entry ) } </ TooltipTrigger >
102
- < TooltipContent > { label } </ TooltipContent >
131
+ < TooltipContent >
132
+ < div > { label } </ div >
133
+ < div className = "rfs-text-xs rfs-text-muted-foreground" > { clickBehaviourText } </ div >
134
+ </ TooltipContent >
103
135
</ Tooltip >
104
136
) )
105
137
}
106
138
107
139
return (
108
140
< Tooltip delayDuration = { 500 } >
109
141
< TooltipTrigger > { base ( fieldValue , value ) } </ TooltipTrigger >
110
- < TooltipContent > { label } </ TooltipContent >
142
+ < TooltipContent >
143
+ < div > { label } </ div >
144
+ < div className = "rfs-text-xs rfs-text-muted-foreground" > { clickBehaviourText } </ div >
145
+ </ TooltipContent >
111
146
</ Tooltip >
112
147
)
113
148
}
0 commit comments