Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Svelte
at icy/tmrrpn
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104<script lang="ts"> import { resolve } from "$app/paths"; import File from "$icon/file"; import FileSymlink from "$icon/file-symlink"; import Folder from "$icon/folder"; import FolderInput from "$icon/folder-input"; import { splitMessage } from "$lib/api/repo"; import { navigatingTo } from "$lib/navPulse"; import TimeAgo from "$lib/components/ui/TimeAgo.svelte"; import type { TreeEntrySummary } from "./types"; import { encodePathSegments } from "./urls";
interface Props { ownerHandle: string; repoName: string; ref: string; entries: TreeEntrySummary[]; path?: string; withMessage?: boolean; }
let { ownerHandle, repoName, ref, entries, path = "", withMessage = false }: Props = $props();
const base = $derived(`/${ownerHandle}/${repoName}`); const encodedRef = $derived(encodeURIComponent(ref));
const linkFor = (entry: TreeEntrySummary) => { const target = path ? `${path}/${entry.name}` : entry.name; const kind = entry.kind === "directory" ? "tree" : "blob"; return `${base}/${kind}/${encodedRef}/${encodePathSegments(target)}`; };
// lucide puts fill="none" on the path itself, which beats anything inherited // from the svg, so the class has to reach the path const iconClassFor = (entry: TreeEntrySummary) => entry.kind === "directory" ? "size-4 shrink-0 [&_path]:fill-current" : "size-4 shrink-0";
const iconFor = (entry: TreeEntrySummary) => { switch (entry.kind) { case "directory": return Folder; case "submodule": return FolderInput; case "symlink": return FileSymlink; default: return File; } };</script>
<!-- the divider belongs to whatever column the tree is sat in --><div class="min-w-0"> {#each entries as entry (entry.name)} {@const Glyph = iconFor(entry)} {@const href = resolve(linkFor(entry) as "/")} <div class={`grid items-center gap-4 py-1 ${withMessage ? "grid-cols-12" : "grid-cols-3"}`} class:row-breathe={navigatingTo(href)} > <a {href} class={`flex min-w-0 items-center gap-2 text-foreground-default no-underline hover:underline ${ withMessage ? "col-span-8 md:col-span-4" : "col-span-2" }`} > <span class="text-foreground-muted"> <Glyph class={iconClassFor(entry)} aria-hidden="true" /> </span> <span class="truncate">{entry.name}</span> </a>
{#if withMessage} <div class="hidden min-w-0 md:col-span-6 md:block"> {#if entry.lastCommitHash && entry.lastCommitMessage} <a href={resolve(`${base}/commit/${entry.lastCommitHash}` as "/")} class="block truncate text-foreground-subtle no-underline hover:underline" > {splitMessage(entry.lastCommitMessage)[0]} </a> {/if} </div> {/if}
<div class={`text-right typography-paragraph-small text-foreground-subtle ${ withMessage ? "col-span-4 md:col-span-2" : "col-span-1" }`} > {#if entry.lastCommitHash && entry.lastCommitWhen} <a href={resolve(`${base}/commit/${entry.lastCommitHash}` as "/")} class="text-foreground-subtle no-underline hover:underline" title={entry.lastCommitMessage} > <TimeAgo value={entry.lastCommitWhen} /> </a> {/if} </div> </div> {/each}</div>