@@ -3,9 +3,33 @@ import { useState, useEffect } from "react";
3
3
import { initHeadlessOmnibox } from "./headless.js" ;
4
4
import { HeadlessOmnibox } from "omnibox-js" ;
5
5
6
+ type SearchType = { id : string ; name : string , prefixQueryEvent : string } ;
7
+
8
+ function SearchTypeDropdown ( props : { searchTypes : SearchType [ ] ; onSearchTypeChange : ( newValue : string ) => void } ) {
9
+ const { searchTypes, onSearchTypeChange } = props ;
10
+ return (
11
+ < List . Dropdown
12
+ tooltip = "Select Search Type"
13
+ storeValue = { true }
14
+ onChange = { ( newValue ) => {
15
+ onSearchTypeChange ( newValue ) ;
16
+ } }
17
+ >
18
+ < List . Dropdown . Section >
19
+ { searchTypes . map ( ( searchType ) => (
20
+ < List . Dropdown . Item key = { searchType . id } title = { searchType . name } value = { searchType . prefixQueryEvent } />
21
+ ) ) }
22
+ </ List . Dropdown . Section >
23
+ </ List . Dropdown >
24
+ ) ;
25
+ }
26
+
6
27
export default function Command ( ) {
28
+ const [ searchText , setSearchText ] = useState ( "" ) ;
7
29
const [ searchResults , setSearchResults ] = useState < SearchResult [ ] > ( [ ] ) ;
8
30
const [ isLoading , setIsLoading ] = useState ( true ) ;
31
+
32
+ const [ prefixQueryEvent , setPrefixQueryEvent ] = useState ( "" ) ;
9
33
const [ headless , setHeadless ] = useState < HeadlessOmnibox | null > ( null ) ;
10
34
11
35
useEffect ( ( ) => {
@@ -18,6 +42,8 @@ export default function Command() {
18
42
} , [ ] ) ;
19
43
20
44
const handleSearch = async ( text : string ) => {
45
+ setSearchText ( text ) ;
46
+
21
47
if ( ! headless ) return ;
22
48
23
49
if ( text . length === 0 ) {
@@ -26,7 +52,12 @@ export default function Command() {
26
52
}
27
53
28
54
setIsLoading ( true ) ;
29
- const { results } = await headless . search ( text ) ;
55
+ const { results } = await headless . search ( prefixQueryEvent + text ) ;
56
+ // Remove pagination tip from the first result
57
+ const paginationTipRegex = / \s \| \s P a g e \s \[ \d + \/ \d + \] , \s a p p e n d \s ' .+ ?' \s t o \s ? p a g e \s d o w n / ;
58
+ if ( results . length > 0 ) {
59
+ results [ 0 ] . description = results [ 0 ] . description . replace ( paginationTipRegex , "" ) ;
60
+ }
30
61
setSearchResults (
31
62
results . map ( ( result ) => ( {
32
63
name : result . content ,
@@ -37,8 +68,26 @@ export default function Command() {
37
68
setIsLoading ( false ) ;
38
69
} ;
39
70
71
+ const searchTypes : SearchType [ ] = [
72
+ { id : "1" , name : "Std" , prefixQueryEvent : "" } ,
73
+ { id : "2" , name : "Docs" , prefixQueryEvent : "!" } ,
74
+ { id : "3" , name : "Crates" , prefixQueryEvent : "!!" } ,
75
+ { id : "4" , name : "Repository" , prefixQueryEvent : "!!!" } ,
76
+ ] ;
77
+ const onSearchTypeChange = ( newValue : string ) => {
78
+ setPrefixQueryEvent ( newValue ) ;
79
+ handleSearch ( searchText ) ;
80
+ } ;
81
+
40
82
return (
41
- < List isLoading = { isLoading } onSearchTextChange = { handleSearch } searchBarPlaceholder = "Search..." throttle >
83
+ < List
84
+ isLoading = { isLoading }
85
+ searchText = { searchText }
86
+ onSearchTextChange = { handleSearch }
87
+ searchBarPlaceholder = "Search..."
88
+ searchBarAccessory = { < SearchTypeDropdown searchTypes = { searchTypes } onSearchTypeChange = { onSearchTypeChange } /> }
89
+ throttle
90
+ >
42
91
{ searchResults . map ( ( searchResult ) => (
43
92
< SearchListItem key = { searchResult . url } searchResult = { searchResult } />
44
93
) ) }
0 commit comments