[READ-ONLY] a fast, modern browser for the npm registry
at main 76 lines 2.4 kB view raw
1import { normalizeSearchParam } from '#shared/utils/url' 2import { debounce } from 'perfect-debounce' 3 4// Pages that have their own local filter using ?q 5const pagesWithLocalFilter = new Set(['~username', 'org']) 6 7export function useGlobalSearch() { 8 const { searchProvider } = useSearchProvider() 9 const searchProviderValue = computed(() => { 10 const p = normalizeSearchParam(route.query.p) 11 if (p === 'npm' || searchProvider.value === 'npm') return 'npm' 12 return 'algolia' 13 }) 14 const router = useRouter() 15 const route = useRoute() 16 const searchQuery = useState<string>('search-query', () => { 17 if (pagesWithLocalFilter.has(route.name as string)) { 18 return '' 19 } 20 return normalizeSearchParam(route.query.q) 21 }) 22 23 // clean search input when navigating away from search page 24 watch( 25 () => route.query.q, 26 urlQuery => { 27 const value = normalizeSearchParam(urlQuery) 28 if (!value) searchQuery.value = '' 29 if (!searchQuery.value) searchQuery.value = value 30 }, 31 ) 32 const updateUrlQueryImpl = (value: string, provider: 'npm' | 'algolia') => { 33 const isSameQuery = route.query.q === value && route.query.p === provider 34 // Don't navigate away from pages that use ?q for local filtering 35 if (pagesWithLocalFilter.has(route.name as string) || isSameQuery) { 36 return 37 } 38 39 if (route.name === 'search') { 40 router.replace({ 41 query: { 42 ...route.query, 43 q: value || undefined, 44 p: provider === 'npm' ? 'npm' : undefined, 45 }, 46 }) 47 return 48 } 49 router.push({ 50 name: 'search', 51 query: { 52 q: value, 53 p: provider === 'npm' ? 'npm' : undefined, 54 }, 55 }) 56 } 57 const updateUrlQuery = debounce(updateUrlQueryImpl, 250) 58 59 function flushUpdateUrlQuery() { 60 updateUrlQuery.flush() 61 } 62 63 const searchQueryValue = computed({ 64 get: () => searchQuery.value, 65 set: async (value: string) => { 66 searchQuery.value = value 67 68 // Leading debounce implementation as it doesn't work properly out of the box (https://github.com/unjs/perfect-debounce/issues/43) 69 if (!updateUrlQuery.isPending()) { 70 updateUrlQueryImpl(value, searchProvider.value) 71 } 72 updateUrlQuery(value, searchProvider.value) 73 }, 74 }) 75 return { model: searchQueryValue, provider: searchProviderValue, flushUpdateUrlQuery } 76}