1
- import { FC } from 'react'
1
+ import { FC , useState } from 'react'
2
2
3
3
import { Button , Card , Layout , Link , SkeletonList , Spacer , Tag , Text } from '@/components'
4
4
import { useTranslation } from '@/context'
@@ -23,7 +23,7 @@ export interface SearchResultItem {
23
23
line_num : number
24
24
before : string
25
25
after : string
26
- segments : Array < {
26
+ fragments : Array < {
27
27
pre : string
28
28
match : string
29
29
post : string
@@ -40,6 +40,7 @@ export const SearchResultsList: FC<SearchResultsListProps> = ({
40
40
} ) => {
41
41
const { t } = useTranslation ( )
42
42
const { results } = useSearchResultsStore ( )
43
+ const [ expandedItems , setExpandedItems ] = useState < Record < string , boolean > > ( { } )
43
44
44
45
if ( isLoading ) {
45
46
return < SkeletonList />
@@ -70,8 +71,8 @@ export const SearchResultsList: FC<SearchResultsListProps> = ({
70
71
{ results . map ( item => (
71
72
< Card . Root key = { `${ item . repo_path } /${ item . file_name } ` } tabIndex = { 0 } >
72
73
< Layout . Vertical gap = "sm" >
73
- < Layout . Horizontal gap = "sm " >
74
- < Tag value = { item . repo_path } icon = "repository" />
74
+ < Layout . Horizontal gap = "xs " >
75
+ < Tag value = { item . repo_path } icon = "repository" showIcon = { true } size = { 'sm' } />
75
76
< Link
76
77
to = { toRepoFileDetails ( { repoPath : item . repo_path , filePath : item . file_name , branch : item . repo_branch } ) }
77
78
>
@@ -81,25 +82,53 @@ export const SearchResultsList: FC<SearchResultsListProps> = ({
81
82
82
83
{ item . matches && item . matches . length > 1 && (
83
84
< Layout . Vertical gap = "sm" >
84
- { item . matches . slice ( 0 , 3 ) . map ( ( match , matchIndex ) => (
85
- < div key = { `match-${ matchIndex } ` } >
86
- < Text variant = "body-normal" > Line { match . line_num } </ Text >
87
- < pre className = { cn ( 'bg-cn-background-1 p-1 mt-1 overflow-x-scroll rounded' ) } >
88
- < code >
89
- { match . before }
90
- { match . segments ?. map ( ( segment , segIndex ) => (
91
- < span key = { `seg-${ segIndex } ` } >
92
- { segment . pre }
93
- < span className = { cn ( 'bg-yellow-100/30' ) } > { segment . match } </ span >
94
- { segment . post }
95
- </ span >
96
- ) ) }
97
- { match . after }
98
- </ code >
99
- </ pre >
100
- </ div >
101
- ) ) }
102
- { item . matches ?. length > 3 && < Text variant = "body-normal" > +{ item . matches . length - 3 } more</ Text > }
85
+ { item . matches
86
+ . slice ( 0 , expandedItems [ `${ item . repo_path } /${ item . file_name } ` ] ? undefined : 3 )
87
+ . map ( match => (
88
+ < div key = { `${ match . before } -${ match . fragments . join ( '' ) } -${ match . after } ` } >
89
+ < pre className = { cn ( 'bg-cn-background-1 p-1 mt-1 overflow-x-scroll rounded' ) } >
90
+ < code className = "monospace" >
91
+ { match . before . trim ( ) . length > 0 && (
92
+ < >
93
+ { match . line_num - 1 } { match . before }
94
+ < br />
95
+ </ >
96
+ ) }
97
+ { match . line_num } { ' ' }
98
+ { match . fragments ?. map ( ( segment , segIndex ) => (
99
+ < span key = { `seg-${ segIndex } ` } >
100
+ { segment . pre }
101
+ < mark > { segment . match } </ mark >
102
+ { segment . post }
103
+ </ span >
104
+ ) ) }
105
+ { match . after . trim ( ) . length > 0 && (
106
+ < >
107
+ < br />
108
+ { match . line_num + 1 } { match . after }
109
+ </ >
110
+ ) }
111
+ </ code >
112
+ </ pre >
113
+ </ div >
114
+ ) ) }
115
+ { item . matches ?. length > 3 && (
116
+ < Text
117
+ variant = "body-normal"
118
+ className = "text-cn-primary cursor-pointer hover:underline"
119
+ onClick = { ( ) => {
120
+ const key = `${ item . repo_path } /${ item . file_name } `
121
+ setExpandedItems ( prev => ( {
122
+ ...prev ,
123
+ [ key ] : ! prev [ key ]
124
+ } ) )
125
+ } }
126
+ >
127
+ { expandedItems [ `${ item . repo_path } /${ item . file_name } ` ]
128
+ ? t ( 'views:search.showLess' , '- Show Less' )
129
+ : t ( 'views:search.showMore' , `+${ item . matches . length - 3 } more` ) }
130
+ </ Text >
131
+ ) }
103
132
</ Layout . Vertical >
104
133
) }
105
134
</ Layout . Vertical >
0 commit comments