This repository has no description
1<script lang="ts">
2 import { resolve } from "$app/paths";
3 import GitFork from "$icon/git-fork";
4 import Globe from "$icon/globe";
5 import Star from "$icon/star";
6 import Avatar from "$lib/components/ui/Avatar.svelte";
7 import Button from "$lib/components/ui/Button.svelte";
8 import ButtonGroup from "$lib/components/ui/ButtonGroup.svelte";
9 import Tag from "$lib/components/ui/Tag.svelte";
10 import { getAuth } from "$lib/auth.svelte";
11 import StarButton from "./StarButton.svelte";
12 import type { RepoCounts, RepoInfo } from "./types";
13
14 interface Props {
15 repo: RepoInfo;
16 counts: RepoCounts;
17 viewerStarRkey?: string | null;
18 }
19
20 let { repo, counts, viewerStarRkey }: Props = $props();
21
22 const auth = getAuth();
23 const signedIn = $derived(Boolean(auth.currentDid));
24 const base = $derived(`/${repo.ownerHandle}/${repo.name}`);
25 const trimScheme = (url: string) => url.replace(/^https?:\/\//, "").replace(/\/$/, "");
26</script>
27
28{#snippet repoActions(className: string)}
29 <div class={className}>
30 {#if signedIn}
31 <StarButton
32 repoDid={repo.repoDid ?? ""}
33 repoOwnerHandle={repo.ownerHandle}
34 repoName={repo.name}
35 initialCount={counts.stars}
36 initialRkey={viewerStarRkey}
37 />
38 {:else}
39 <Button
40 href={resolve(`${base}/stars` as "/")}
41 variant="default"
42 size="sm"
43 icon={Star}
44 title="Starred by"
45 >
46 {counts.stars}
47 </Button>
48 {/if}
49
50 <ButtonGroup>
51 <Button
52 href={resolve(`${base}/fork` as "/")}
53 variant="default"
54 size="sm"
55 insetShadow={true}
56 icon={GitFork}
57 >
58 Fork
59 </Button>
60 <Button href={resolve(`${base}/forks` as "/")} variant="ghost" size="sm" title="Forked by">
61 {counts.forks}
62 </Button>
63 </ButtonGroup>
64 </div>
65{/snippet}
66
67<section class="mb-2 px-4 py-2">
68 <div class="mb-2 flex flex-col items-start justify-between gap-4 sm:flex-row">
69 <div class="flex min-w-0 flex-col gap-2">
70 <div class="flex flex-wrap items-center gap-2 typography-paragraph-large font-normal">
71 <a
72 href={resolve(`/${repo.ownerHandle}` as "/")}
73 class="flex items-center gap-2 text-foreground-default no-underline hover:underline"
74 >
75 <Avatar did={repo.ownerDid} handle={repo.ownerHandle} size="size-6" tiny />
76 {repo.ownerHandle}
77 </a>
78 <span class="text-foreground-subtle select-none">/</span>
79 <a
80 href={resolve(`/${repo.ownerHandle}/${repo.name}` as "/")}
81 class="font-bold text-foreground-default no-underline hover:underline"
82 >
83 {repo.name}
84 </a>
85 </div>
86
87 {#if repo.source}
88 <div class="flex flex-wrap items-center gap-1 text-sm text-foreground-muted">
89 <GitFork class="size-3 shrink-0" aria-hidden="true" />
90 <span>forked from</span>
91 <a
92 href={resolve(`/${repo.source.ownerHandle}/${repo.source.name}` as "/")}
93 class="underline"
94 >
95 {repo.source.ownerHandle}/{repo.source.name}
96 </a>
97 </div>
98 {/if}
99 </div>
100
101 {@render repoActions("flex shrink-0 items-start gap-2 hidden sm:flex")}
102 </div>
103
104 <div class="flex flex-wrap items-center gap-x-4 gap-y-2 typography-paragraph-small text-foreground-muted">
105 {#if repo.description}
106 <span>{repo.description}</span>
107 {:else}
108 <span class="italic">This repository has no description</span>
109 {/if}
110
111 {#if repo.website}
112 <span class="flex items-center gap-1">
113 <Globe class="size-4 shrink-0" aria-hidden="true" />
114 <a href={repo.website} rel="external ugc nofollow noopener noreferrer"
115 >{trimScheme(repo.website)}</a
116 >
117 </span>
118 {/if}
119
120 {#if repo.topics?.length}
121 <div class="flex flex-wrap items-center gap-1">
122 {#each repo.topics as topic (topic)}
123 <Tag color="gray">{topic}</Tag>
124 {/each}
125 </div>
126 {/if}
127 </div>
128
129 {@render repoActions("mt-2 grid grid-cols-2 items-center gap-2 sm:hidden")}
130</section>