Something went wrong. Try again.
[READ-ONLY]
a fast, modern browser for the npm registry forked from npmx.dev/npmx.dev
Something went wrong. Try again.
3.4 kB · 110 lines
Vue
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111<script setup lang="ts">import type { PackageFileTree } from '#shared/types'import type { RouteLocationRaw } from 'vue-router'import type { RouteNamedMap } from 'vue-router/auto-routes'import { ADDITIONAL_ICONS, getFileIcon } from '~/utils/file-icons'
const props = defineProps<{ tree: PackageFileTree[] currentPath: string baseUrl: string baseRoute: Pick<RouteNamedMap['code'], 'params'> depth?: number}>()
const depth = computed(() => props.depth ?? 0)
// Check if a node or any of its children is currently selectedfunction isNodeActive(node: PackageFileTree): boolean { if (props.currentPath === node.path) return true if (props.currentPath.startsWith(node.path + '/')) return true return false}
// Build route object for a file pathfunction getFileRoute(nodePath: string): RouteLocationRaw { return { name: 'code', params: { org: props.baseRoute.params.org, packageName: props.baseRoute.params.packageName, version: props.baseRoute.params.version, filePath: nodePath ?? '', }, }}
const { toggleDir, isExpanded, autoExpandAncestors } = useFileTreeState(props.baseUrl)
// Auto-expand directories in the current pathwatch( () => props.currentPath, path => { if (path) { autoExpandAncestors(path) } }, { immediate: true },)</script>
<template> <ul class="list-none m-0 p-0" :class="depth === 0 ? 'py-2' : ''"> <li v-for="node in tree" :key="node.path"> <!-- Directory --> <template v-if="node.type === 'directory'"> <ButtonBase class="w-full justify-start! rounded-none! border-none!" block :aria-pressed="isNodeActive(node)" :style="{ paddingLeft: `${depth * 12 + 12}px` }" @click="toggleDir(node.path)" :classicon="isExpanded(node.path) ? 'i-lucide:chevron-down' : 'i-lucide:chevron-right'" > <svg class="size-[1em] me-1 shrink-0" :class="isExpanded(node.path) ? 'text-yellow-500' : 'text-yellow-600'" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" > <use :href="`/file-tree-sprite.svg#${isExpanded(node.path) ? ADDITIONAL_ICONS['folder-open'] : ADDITIONAL_ICONS['folder']}`" /> </svg> <span class="truncate">{{ node.name }}</span> </ButtonBase> <CodeFileTree v-if="isExpanded(node.path) && node.children" :tree="node.children" :current-path="currentPath" :base-url="baseUrl" :base-route="baseRoute" :depth="depth + 1" /> </template>
<!-- File --> <template v-else> <LinkBase variant="button-secondary" :to="getFileRoute(node.path)" :aria-current="currentPath === node.path" class="w-full justify-start! rounded-none! border-none!" block :style="{ paddingLeft: `${depth * 12 + 32}px` }" > <svg class="size-[1em] me-1 shrink-0" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true" > <use :href="`/file-tree-sprite.svg#${getFileIcon(node.name)}`" /> </svg> <span class="truncate">{{ node.name }}</span> </LinkBase> </template> </li> </ul></template>