@@ -7,9 +7,11 @@ const props = withDefaults(
77 packageName: string
88 version: SlimPackumentVersion
99 dependencies: DependencySize [] | null
10+ dependenciesLoading? : boolean
1011 size? : ' small' | ' medium'
1112 }>(),
1213 {
14+ dependenciesLoading: false ,
1315 size: ' medium' ,
1416 },
1517)
@@ -21,16 +23,14 @@ const highlightedIndex = shallowRef(-1)
2123const dropdownPosition = shallowRef <{ top: number ; left: number } | null >(null )
2224
2325const menuId = ' download-menu'
24- const menuItems = computed (() => {
25- const items = [{ id: ' package' , icon: ' i-lucide:package' }]
26- if (props .dependencies ?.length ) {
27- items .push ({
28- id: ' dependencies' ,
29- icon: ' i-lucide:list-tree' ,
30- })
31- }
32- return items
33- })
26+ const menuItems = computed (() => [
27+ { id: ' package' , icon: ' i-lucide:package' , disabled: false },
28+ {
29+ id: ' dependencies' ,
30+ icon: props .dependenciesLoading ? ' i-lucide:loader-circle' : ' i-lucide:list-tree' ,
31+ disabled: props .dependenciesLoading || ! props .dependencies ?.length ,
32+ },
33+ ])
3434
3535const prefersReducedMotion = useMediaQuery (' (prefers-reduced-motion: reduce)' )
3636
@@ -87,7 +87,7 @@ function handleKeydown(event: KeyboardEvent) {
8787 case ' Enter' :
8888 case ' ' :
8989 event .preventDefault ()
90- handleAction (menuItems .value [highlightedIndex .value ]?. id )
90+ handleAction (menuItems .value [highlightedIndex .value ])
9191 break
9292 case ' Escape' :
9393 event .preventDefault ()
@@ -100,10 +100,11 @@ function handleKeydown(event: KeyboardEvent) {
100100 }
101101}
102102
103- function handleAction(id : string | undefined ) {
104- if (id === ' package' ) {
103+ function handleAction(item : (typeof menuItems .value )[number ] | undefined ) {
104+ if (! item || item .disabled ) return
105+ if (item .id === ' package' ) {
105106 downloadPackage ()
106- } else if (id === ' dependencies' ) {
107+ } else if (item . id === ' dependencies' ) {
107108 downloadDependenciesScript ()
108109 }
109110 close ()
@@ -233,16 +234,26 @@ defineOptions({
233234 v-for =" (item, index) in menuItems"
234235 :key =" item.id"
235236 role =" menuitem"
236- class =" cursor-pointer flex items-center gap-2 px-3 py-1.5 text-sm text-fg-muted transition-colors duration-150"
237+ :aria-disabled =" item.disabled || undefined"
238+ class =" flex items-center gap-2 px-3 py-1.5 text-sm transition-colors duration-150"
237239 :class =" [
238- highlightedIndex === index
239- ? 'bg-bg-elevated text-fg'
240- : 'hover:bg-bg-elevated hover:text-fg',
240+ item.disabled
241+ ? 'cursor-default text-fg-muted/50'
242+ : highlightedIndex === index
243+ ? 'cursor-pointer bg-bg-elevated text-fg'
244+ : 'cursor-pointer text-fg-muted hover:bg-bg-elevated hover:text-fg',
241245 ]"
242- @click =" handleAction(item.id )"
246+ @click =" handleAction(item)"
243247 @mouseenter =" highlightedIndex = index"
244248 >
245- <span :class =" item.icon" class =" w-4 h-4" aria-hidden =" true" />
249+ <span
250+ :class =" [
251+ item.icon,
252+ { 'animate-spin': item.id === 'dependencies' && dependenciesLoading },
253+ ]"
254+ class =" w-4 h-4"
255+ aria-hidden =" true"
256+ />
246257 {{
247258 item.id === 'package'
248259 ? $t('package.download.package')
0 commit comments