[READ-ONLY] a fast, modern browser for the npm registry
at main 113 lines 3.9 kB view raw
1<script setup lang="ts"> 2import type { DependencyDepth } from '#shared/types' 3 4const props = defineProps<{ 5 packageName: string 6 version: string 7}>() 8 9const { data: analysisData, status } = useDependencyAnalysis( 10 () => props.packageName, 11 () => props.version, 12) 13 14const isExpanded = shallowRef(false) 15const showAll = shallowRef(false) 16 17const hasDeprecated = computed( 18 () => analysisData.value?.deprecatedPackages && analysisData.value.deprecatedPackages.length > 0, 19) 20 21// Banner color - purple for deprecated 22const bannerColor = 'border-purple-600/40 bg-purple-500/10 text-purple-700 dark:text-purple-400' 23 24// Styling for each depth level 25const depthStyles = { 26 root: { 27 bg: 'bg-purple-500/5 border-is-2 border-is-purple-600', 28 text: 'text-fg', 29 }, 30 direct: { 31 bg: 'bg-purple-500/5 border-is-2 border-is-purple-500', 32 text: 'text-fg-muted', 33 }, 34 transitive: { 35 bg: 'bg-purple-500/5 border-is-2 border-is-purple-400', 36 text: 'text-fg-muted', 37 }, 38} as const 39 40function getDepthStyle(depth: DependencyDepth) { 41 return depthStyles[depth] || depthStyles.transitive 42} 43</script> 44 45<template> 46 <section v-if="status === 'success' && hasDeprecated" class="relative"> 47 <div class="rounded-lg border overflow-hidden" :class="bannerColor"> 48 <!-- Header --> 49 <button 50 type="button" 51 class="w-full flex items-center justify-between gap-3 px-4 py-3 text-start transition-colors duration-200 hover:bg-white/5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-accent/70" 52 :aria-expanded="isExpanded" 53 aria-controls="deprecated-tree-details" 54 @click="isExpanded = !isExpanded" 55 > 56 <span class="flex items-center gap-2 min-w-0"> 57 <span class="i-lucide:octagon-alert w-4 h-4 shrink-0" aria-hidden="true" /> 58 <span class="font-mono text-sm font-medium truncate"> 59 {{ $t('package.deprecated.tree_found', analysisData!.deprecatedPackages.length) }} 60 </span> 61 </span> 62 <span 63 class="i-lucide:chevron-down w-4 h-4 transition-transform duration-200 shrink-0" 64 :class="{ 'rotate-180': isExpanded }" 65 aria-hidden="true" 66 /> 67 </button> 68 69 <!-- Expandable details --> 70 <div 71 v-show="isExpanded" 72 id="deprecated-tree-details" 73 class="border-t border-border bg-bg-subtle" 74 > 75 <ul class="divide-y divide-border list-none m-0 p-0"> 76 <li 77 v-for="pkg in analysisData!.deprecatedPackages.slice(0, showAll ? undefined : 5)" 78 :key="`${pkg.name}@${pkg.version}`" 79 class="px-4 py-3" 80 :class="getDepthStyle(pkg.depth).bg" 81 > 82 <div class="flex items-center gap-2 mb-1"> 83 <!-- Path badge --> 84 <DependencyPathPopup v-if="pkg.path && pkg.path.length > 1" :path="pkg.path" /> 85 86 <NuxtLink 87 :to="packageRoute(pkg.name, pkg.version)" 88 class="font-mono text-sm font-medium hover:underline truncate py-4" 89 :class="getDepthStyle(pkg.depth).text" 90 > 91 {{ pkg.name }}@{{ pkg.version }} 92 </NuxtLink> 93 </div> 94 <p class="text-xs text-fg-muted m-0 line-clamp-2"> 95 {{ pkg.message }} 96 </p> 97 </li> 98 </ul> 99 100 <button 101 v-if="analysisData!.deprecatedPackages.length > 5 && !showAll" 102 type="button" 103 class="w-full px-4 py-2 text-xs font-mono text-fg-muted hover:text-fg border-t border-border transition-colors duration-200" 104 @click="showAll = true" 105 > 106 {{ 107 $t('package.deprecated.show_all', { count: analysisData!.deprecatedPackages.length }) 108 }} 109 </button> 110 </div> 111 </div> 112 </section> 113</template>