@ -41,33 +41,12 @@ function classNames(...classes) {
return classes . filter ( Boolean ) . join ( " " ) ;
}
function useProviderState ( ) {
const key = "search-name" ;
const [ value , setValue ] = useState ( providers . google ) ;
useEffect ( ( ) => {
const storedName = localStorage . getItem ( key ) ;
let storedProvider = null ;
if ( storedName ) {
storedProvider = Object . values ( providers ) . find ( ( el ) => el . name === storedName ) ;
if ( storedProvider ) {
setValue ( storedProvider ) ;
}
}
} , [ ] ) ;
return [
value ,
( val ) => {
setValue ( val ) ;
localStorage . setItem ( key , val . name ) ;
} ,
] ;
}
function getAvailableProviderIds ( options ) {
if ( options . providers && Array . isArray ( options . providers ) ) {
return Object . keys ( providers ) . filter ( ( value ) => options . providers . includes ( value ) ) ;
if ( options . provider && Array . isArray ( options . provider ) ) {
return Object . keys ( searchProviders ) . filter ( ( value ) => options . provider . includes ( value ) ) ;
}
if ( options . provider && searchProviders [ options . provider ] ) {
return [ options . provider ] ;
}
return null ;
}
@ -75,19 +54,34 @@ function getAvailableProviderIds(options) {
export default function Search ( { options } ) {
const { t } = useTranslation ( ) ;
const provider = searchProviders [ options . provider ] ;
const availableProviderIds = getAvailableProviderIds ( options ) ;
const key = "search-name" ;
const [ query , setQuery ] = useState ( "" ) ;
const [ selectedProvider , setSelectedProvider ] = useProviderState ( ) ;
const [ selectedProvider , setSelectedProvider ] = use State( searchProviders [ availableProviderIds [ 0 ] ? ? searchProviders . google ] ) ;
const availableProviderIds = getAvailableProviderIds ( options ) ;
if ( ! provider && ! availableProviderIds ) {
useEffect ( ( ) => {
const storedName = localStorage . getItem ( key ) ;
let storedProvider = null ;
let storedProviderKey = null ;
if ( storedName ) {
storedProvider = Object . values ( searchProviders ) . find ( ( el ) => el . name === storedName ) ;
storedProviderKey = Object . keys ( searchProviders ) . find ( ( pkey ) => searchProviders [ pkey ] === storedProvider ) ;
if ( storedProvider && availableProviderIds . includes ( storedProviderKey ) ) {
setSelectedProvider ( storedProvider ) ;
}
}
} , [ availableProviderIds ] ) ;
if ( ! availableProviderIds ) {
return null ;
}
function handleSubmit ( event ) {
const q = encodeURIComponent ( query ) ;
const url = provider ? provider . url : selectedProvider . url ;
const url = { selectedProvider } ;
if ( url ) {
window . open ( ` ${ url } ${ q } ` , options . target || "_blank" ) ;
} else {
@ -99,72 +93,10 @@ export default function Search({ options }) {
setQuery ( "" ) ;
}
const multiProviders = ( ) => (
< Listbox as = "div" value = { selectedProvider } onChange = { setSelectedProvider } className = "relative text-left" >
< div >
< Listbox.Button
className = "
absolute right - 0.5 bottom - 0.5 rounded - r - md px - 4 py - 2 border - 1
text - white font - medium text - sm
bg - theme - 600 / 40 dark : bg - white / 10
focus : ring - theme - 500 dark : focus : ring - white / 50 "
>
< selectedProvider.icon className = "text-white w-3 h-3" / >
< span className = "sr-only" > { t ( "search.search" ) } < / span >
< / Listbox.Button >
< / div >
< Transition
as = { Fragment }
enter = "transition ease-out duration-100"
enterFrom = "transform opacity-0 scale-95"
enterTo = "transform opacity-100 scale-100"
leave = "transition ease-in duration-75"
leaveFrom = "transform opacity-100 scale-100"
leaveTo = "transform opacity-0 scale-95"
>
< Listbox.Options
className = " absolute right - 0 z - 10 mt - 1 origin - top - right rounded - md
bg - theme - 100 dark : bg - theme - 600 shadow - lg
ring - 1 ring - black ring - opacity - 5 focus : outline - none "
>
< div className = "flex flex-col" >
{ availableProviderIds . map ( ( providerId ) => {
const p = providers [ providerId ] ;
return (
< Listbox.Option key = { providerId } value = { p } as = { Fragment } >
{ ( { active } ) => (
< li
className = { classNames (
"rounded-md cursor-pointer" ,
active ? "bg-theme-600/10 dark:bg-white/10 dark:text-gray-900" : "dark:text-gray-100"
) }
>
< p.icon className = "h-4 w-4 mx-4 my-2" / >
< / li >
) }
< / Listbox.Option >
) ;
} ) }
< / div >
< / Listbox.Options >
< / Transition >
< / Listbox >
) ;
const singleProvider = ( ) => (
< button
type = "submit"
className = "
absolute right - 0.5 bottom - 0.5 rounded - r - md px - 4 py - 2 border - 1
text - white font - medium text - sm
bg - theme - 600 / 40 dark : bg - white / 10
focus : ring - theme - 500 dark : focus : ring - white / 50 "
>
< provider.icon className = "text-white w-3 h-3" / >
< span className = "sr-only" > { t ( "search.search" ) } < / span >
< / button >
) ;
const onChangeProvider = ( provider ) => {
setSelectedProvider ( provider ) ;
localStorage . setItem ( key , provider . name ) ;
}
return (
< form className = "flex-col relative h-8 my-4 min-w-fit grow first:ml-0 ml-4" onSubmit = { handleSubmit } >
@ -188,7 +120,55 @@ export default function Search({ options }) {
/ / e s l i n t - d i s a b l e - n e x t - l i n e j s x - a 1 1 y / n o - a u t o f o c u s
autoFocus = { options . focus }
/ >
{ provider ? singleProvider ( ) : multiProviders ( ) }
< Listbox as = "div" value = { selectedProvider } onChange = { onChangeProvider } className = "relative text-left" disabled = { availableProviderIds ? . length === 1 } >
< div >
< Listbox.Button
className = "
absolute right - 0.5 bottom - 0.5 rounded - r - md px - 4 py - 2 border - 1
text - white font - medium text - sm
bg - theme - 600 / 40 dark : bg - white / 10
focus : ring - theme - 500 dark : focus : ring - white / 50 "
>
< selectedProvider.icon className = "text-white w-3 h-3" / >
< span className = "sr-only" > { t ( "search.search" ) } < / span >
< / Listbox.Button >
< / div >
< Transition
as = { Fragment }
enter = "transition ease-out duration-100"
enterFrom = "transform opacity-0 scale-95"
enterTo = "transform opacity-100 scale-100"
leave = "transition ease-in duration-75"
leaveFrom = "transform opacity-100 scale-100"
leaveTo = "transform opacity-0 scale-95"
>
< Listbox.Options
className = " absolute right - 0 z - 10 mt - 1 origin - top - right rounded - md
bg - theme - 100 dark : bg - theme - 600 shadow - lg
ring - 1 ring - black ring - opacity - 5 focus : outline - none "
>
< div className = "flex flex-col" >
{ availableProviderIds . map ( ( providerId ) => {
const p = searchProviders [ providerId ] ;
return (
< Listbox.Option key = { providerId } value = { p } as = { Fragment } >
{ ( { active } ) => (
< li
className = { classNames (
"rounded-md cursor-pointer" ,
active ? "bg-theme-600/10 dark:bg-white/10 dark:text-gray-900" : "dark:text-gray-100"
) }
>
< p.icon className = "h-4 w-4 mx-4 my-2" / >
< / li >
) }
< / Listbox.Option >
) ;
} ) }
< / div >
< / Listbox.Options >
< / Transition >
< / Listbox >
< / form >
) ;
}