[READ-ONLY] a fast, modern browser for the npm registry
at main 135 lines 4.6 kB view raw
1<script setup lang="ts"> 2const route = useRoute() 3const router = useRouter() 4const { searchProvider } = useSearchProvider() 5const searchProviderValue = computed(() => { 6 const p = normalizeSearchParam(route.query.p) 7 if (p === 'npm' || searchProvider.value === 'npm') return 'npm' 8 return 'algolia' 9}) 10 11const isOpen = shallowRef(false) 12const toggleRef = useTemplateRef('toggleRef') 13 14onClickOutside(toggleRef, () => { 15 isOpen.value = false 16}) 17 18useEventListener('keydown', event => { 19 if (event.key === 'Escape' && isOpen.value) { 20 isOpen.value = false 21 } 22}) 23</script> 24 25<template> 26 <div ref="toggleRef" class="relative"> 27 <ButtonBase 28 :aria-label="$t('settings.data_source.label')" 29 :aria-expanded="isOpen" 30 aria-haspopup="true" 31 size="small" 32 class="border-none w-8 h-8 !px-0 justify-center" 33 classicon="i-lucide:settings" 34 @click="isOpen = !isOpen" 35 /> 36 37 <Transition 38 enter-active-class="transition-all duration-150" 39 leave-active-class="transition-all duration-100" 40 enter-from-class="opacity-0 translate-y-1" 41 leave-to-class="opacity-0 translate-y-1" 42 > 43 <div 44 v-if="isOpen" 45 class="absolute inset-ie-0 top-full pt-2 w-72 z-50" 46 role="menu" 47 :aria-label="$t('settings.data_source.label')" 48 > 49 <div 50 class="bg-bg-subtle/80 backdrop-blur-sm border border-border-subtle rounded-lg shadow-lg shadow-bg-elevated/50 overflow-hidden p-1" 51 > 52 <!-- npm Registry option --> 53 <button 54 type="button" 55 role="menuitem" 56 class="w-full flex items-start gap-3 px-3 py-2.5 rounded-md text-start transition-colors hover:bg-bg-muted" 57 :class="[searchProviderValue !== 'algolia' ? 'bg-bg-muted' : '']" 58 @click=" 59 () => { 60 searchProvider = 'npm' 61 router.push({ query: { ...route.query, p: 'npm' } }) 62 isOpen = false 63 } 64 " 65 > 66 <span 67 class="i-simple-icons:npm w-4 h-4 mt-0.5 shrink-0" 68 :class="searchProviderValue !== 'algolia' ? 'text-accent' : 'text-fg-muted'" 69 aria-hidden="true" 70 /> 71 <div class="min-w-0 flex-1"> 72 <div 73 class="text-sm font-medium" 74 :class="searchProviderValue !== 'algolia' ? 'text-fg' : 'text-fg-muted'" 75 > 76 {{ $t('settings.data_source.npm') }} 77 </div> 78 <p class="text-xs text-fg-subtle mt-0.5"> 79 {{ $t('settings.data_source.npm_description') }} 80 </p> 81 </div> 82 </button> 83 84 <!-- Algolia option --> 85 <button 86 type="button" 87 role="menuitem" 88 class="w-full flex items-start gap-3 px-3 py-2.5 rounded-md text-start transition-colors hover:bg-bg-muted mt-1" 89 :class="[searchProviderValue === 'algolia' ? 'bg-bg-muted' : '']" 90 @click=" 91 () => { 92 searchProvider = 'algolia' 93 router.push({ query: { ...route.query, p: undefined } }) 94 isOpen = false 95 } 96 " 97 > 98 <span 99 class="i-simple-icons:algolia w-4 h-4 mt-0.5 shrink-0" 100 :class="searchProviderValue === 'algolia' ? 'text-accent' : 'text-fg-muted'" 101 aria-hidden="true" 102 /> 103 <div class="min-w-0 flex-1"> 104 <div 105 class="text-sm font-medium" 106 :class="searchProviderValue === 'algolia' ? 'text-fg' : 'text-fg-muted'" 107 > 108 {{ $t('settings.data_source.algolia') }} 109 </div> 110 <p class="text-xs text-fg-subtle mt-0.5"> 111 {{ $t('settings.data_source.algolia_description') }} 112 </p> 113 </div> 114 </button> 115 116 <!-- Algolia attribution --> 117 <div 118 v-if="searchProviderValue === 'algolia'" 119 class="border-t border-border mx-1 mt-1 pt-2 pb-1" 120 > 121 <a 122 href="https://www.algolia.com/developers" 123 target="_blank" 124 rel="noopener noreferrer" 125 class="text-xs text-fg-subtle hover:text-fg-muted transition-colors inline-flex items-center gap-1 px-2" 126 > 127 {{ $t('search.algolia_disclaimer') }} 128 <span class="i-lucide:external-link w-3 h-3" aria-hidden="true" /> 129 </a> 130 </div> 131 </div> 132 </div> 133 </Transition> 134 </div> 135</template>