@@ -21,7 +21,11 @@ interface ResultsProps<TItem>
2121 title : string ;
2222 suggestion : AutocompleteState < TItem > [ 'suggestions' ] [ 0 ] ;
2323 renderIcon ( props : { item : TItem ; index : number } ) : React . ReactNode ;
24- renderAction ( props : { item : TItem } ) : React . ReactNode ;
24+ renderAction ( props : {
25+ item : TItem ;
26+ runDeleteTransition : ( cb : ( ) => void ) => void ;
27+ runFavoriteTransition : ( cb : ( ) => void ) => void ;
28+ } ) : React . ReactNode ;
2529 onItemClick ( item : TItem ) : void ;
2630 hitComponent ( props : {
2731 hit : DocSearchHit ;
@@ -36,95 +40,139 @@ export function Results<TItem extends StoredDocSearchHit>(
3640 return null ;
3741 }
3842
39- const Hit = props . hitComponent ;
40-
4143 return (
4244 < section className = "DocSearch-Hits" >
4345 < div className = "DocSearch-Hit-source" > { props . title } </ div >
4446
4547 < ul { ...props . getMenuProps ( ) } >
4648 { props . suggestion . items . map ( ( item , index ) => {
4749 return (
48- < li
49- key = { [ item . objectID , index ] . join ( ':' ) }
50- className = { [
51- 'DocSearch-Hit' ,
52- ( ( item as unknown ) as InternalDocSearchHit )
53- . __docsearch_parent && 'DocSearch-Hit--Child' ,
54- ]
55- . filter ( Boolean )
56- . join ( ' ' ) }
57- { ...props . getItemProps ( {
58- item,
59- source : props . suggestion . source ,
60- onClick ( ) {
61- props . onItemClick ( item ) ;
62- } ,
63- } ) }
64- >
65- < Hit hit = { item } >
66- < div className = "DocSearch-Hit-Container" >
67- { props . renderIcon ( { item, index } ) }
68-
69- { item . hierarchy [ item . type ] && item . type === 'lvl1' && (
70- < div className = "DocSearch-Hit-content-wrapper" >
71- < Snippet
72- className = "DocSearch-Hit-title"
73- hit = { item }
74- attribute = "hierarchy.lvl1"
75- />
76- { item . content && (
77- < Snippet
78- className = "DocSearch-Hit-path"
79- hit = { item }
80- attribute = "content"
81- />
82- ) }
83- </ div >
84- ) }
85-
86- { item . hierarchy [ item . type ] &&
87- ( item . type === 'lvl2' ||
88- item . type === 'lvl3' ||
89- item . type === 'lvl4' ||
90- item . type === 'lvl5' ||
91- item . type === 'lvl6' ) && (
92- < div className = "DocSearch-Hit-content-wrapper" >
93- < Snippet
94- className = "DocSearch-Hit-title"
95- hit = { item }
96- attribute = { `hierarchy.${ item . type } ` }
97- />
98- < Snippet
99- className = "DocSearch-Hit-path"
100- hit = { item }
101- attribute = "hierarchy.lvl1"
102- />
103- </ div >
104- ) }
105-
106- { item . type === 'content' && (
107- < div className = "DocSearch-Hit-content-wrapper" >
108- < Snippet
109- className = "DocSearch-Hit-title"
110- hit = { item }
111- attribute = "content"
112- />
113- < Snippet
114- className = "DocSearch-Hit-path"
115- hit = { item }
116- attribute = "hierarchy.lvl1"
117- />
118- </ div >
119- ) }
120-
121- { props . renderAction ( { item } ) }
122- </ div >
123- </ Hit >
124- </ li >
50+ < Result
51+ key = { [ props . title , item . objectID ] . join ( ':' ) }
52+ item = { item }
53+ index = { index }
54+ { ...props }
55+ />
12556 ) ;
12657 } ) }
12758 </ ul >
12859 </ section >
12960 ) ;
13061}
62+
63+ interface ResultProps < TItem > extends ResultsProps < TItem > {
64+ item : TItem ;
65+ index : number ;
66+ }
67+
68+ function Result < TItem extends StoredDocSearchHit > ( {
69+ item,
70+ index,
71+ renderIcon,
72+ renderAction,
73+ getItemProps,
74+ onItemClick,
75+ suggestion,
76+ hitComponent,
77+ } : ResultProps < TItem > ) {
78+ const [ isDeleting , setIsDeleting ] = React . useState ( false ) ;
79+ const [ isFavoriting , setIsFavoriting ] = React . useState ( false ) ;
80+ const action = React . useRef < ( ( ) => void ) | null > ( null ) ;
81+ const Hit = hitComponent ;
82+
83+ function runDeleteTransition ( cb : ( ) => void ) {
84+ setIsDeleting ( true ) ;
85+ action . current = cb ;
86+ }
87+
88+ function runFavoriteTransition ( cb : ( ) => void ) {
89+ setIsFavoriting ( true ) ;
90+ action . current = cb ;
91+ }
92+
93+ return (
94+ < li
95+ className = { [
96+ 'DocSearch-Hit' ,
97+ ( ( item as unknown ) as InternalDocSearchHit ) . __docsearch_parent &&
98+ 'DocSearch-Hit--Child' ,
99+ isDeleting && 'DocSearch-Hit--deleting' ,
100+ isFavoriting && 'DocSearch-Hit--favoriting' ,
101+ ]
102+ . filter ( Boolean )
103+ . join ( ' ' ) }
104+ onTransitionEnd = { ( ) => {
105+ if ( action . current ) {
106+ action . current ( ) ;
107+ }
108+ } }
109+ { ...getItemProps ( {
110+ item,
111+ source : suggestion . source ,
112+ onClick ( ) {
113+ onItemClick ( item ) ;
114+ } ,
115+ } ) }
116+ >
117+ < Hit hit = { item } >
118+ < div className = "DocSearch-Hit-Container" >
119+ { renderIcon ( { item, index } ) }
120+
121+ { item . hierarchy [ item . type ] && item . type === 'lvl1' && (
122+ < div className = "DocSearch-Hit-content-wrapper" >
123+ < Snippet
124+ className = "DocSearch-Hit-title"
125+ hit = { item }
126+ attribute = "hierarchy.lvl1"
127+ />
128+ { item . content && (
129+ < Snippet
130+ className = "DocSearch-Hit-path"
131+ hit = { item }
132+ attribute = "content"
133+ />
134+ ) }
135+ </ div >
136+ ) }
137+
138+ { item . hierarchy [ item . type ] &&
139+ ( item . type === 'lvl2' ||
140+ item . type === 'lvl3' ||
141+ item . type === 'lvl4' ||
142+ item . type === 'lvl5' ||
143+ item . type === 'lvl6' ) && (
144+ < div className = "DocSearch-Hit-content-wrapper" >
145+ < Snippet
146+ className = "DocSearch-Hit-title"
147+ hit = { item }
148+ attribute = { `hierarchy.${ item . type } ` }
149+ />
150+ < Snippet
151+ className = "DocSearch-Hit-path"
152+ hit = { item }
153+ attribute = "hierarchy.lvl1"
154+ />
155+ </ div >
156+ ) }
157+
158+ { item . type === 'content' && (
159+ < div className = "DocSearch-Hit-content-wrapper" >
160+ < Snippet
161+ className = "DocSearch-Hit-title"
162+ hit = { item }
163+ attribute = "content"
164+ />
165+ < Snippet
166+ className = "DocSearch-Hit-path"
167+ hit = { item }
168+ attribute = "hierarchy.lvl1"
169+ />
170+ </ div >
171+ ) }
172+
173+ { renderAction ( { item, runDeleteTransition, runFavoriteTransition } ) }
174+ </ div >
175+ </ Hit >
176+ </ li >
177+ ) ;
178+ }
0 commit comments