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 const topics = $derived([...new Set(repo.topics ?? [])]);
27</script>
28
29{#snippet repoActions(className: string)}
30 <div class={className}>
31 {#if signedIn}
32 <StarButton
33 repoDid={repo.repoDid ?? ""}
34 repoOwnerHandle={repo.ownerHandle}
35 repoName={repo.name}
36 initialCount={counts.stars}
37 initialRkey={viewerStarRkey}
38 />
39 {:else}
40 <Button
41 href={resolve(`${base}/stars` as "/")}
42 variant="default"
43 size="sm"
44 icon={Star}
45 title="Starred by"
46 >
47 {counts.stars}
48 </Button>
49 {/if}
50
51 <ButtonGroup class="flex-1">
52 <Button
53 href={resolve(`${base}/fork` as "/")}
54 variant="default"
55 size="sm"
56 insetShadow={true}
57 icon={GitFork}
58 class="flex-1"
59 >
60 Fork
61 </Button>
62 <Button href={resolve(`${base}/forks` as "/")} variant="ghost" size="sm" title="Forked by">
63 {counts.forks}
64 </Button>
65 </ButtonGroup>
66 </div>
67{/snippet}
68
69<section class="mb-2 px-4 py-2">
70 <div class="mb-2 flex flex-col items-start justify-between gap-4 sm:flex-row">
71 <div class="flex min-w-0 flex-col gap-2">
72 <div class="flex flex-wrap items-center gap-2 typography-paragraph-large font-normal">
73 <a
74 href={resolve(`/${repo.ownerHandle}` as "/")}
75 class="flex items-center gap-2 text-foreground-default no-underline hover:underline"
76 >
77 <Avatar did={repo.ownerDid} handle={repo.ownerHandle} size="size-6" tiny />
78 {repo.ownerHandle}
79 </a>
80 <span class="text-foreground-subtle select-none">/</span>
81 <a
82 href={resolve(`/${repo.ownerHandle}/${repo.name}` as "/")}
83 class="font-bold text-foreground-default no-underline hover:underline"
84 >
85 {repo.name}
86 </a>
87 </div>
88
89 {#if repo.source}
90 <div
91 class="flex flex-wrap items-center gap-1 typography-paragraph-small text-foreground-muted"
92 >
93 <GitFork class="size-3 shrink-0" aria-hidden="true" />
94 <span>forked from</span>
95 <a
96 href={resolve(`/${repo.source.ownerHandle}/${repo.source.name}` as "/")}
97 class="underline"
98 >
99 {repo.source.ownerHandle}/{repo.source.name}
100 </a>
101 </div>
102 {/if}
103 </div>
104
105 {@render repoActions("hidden shrink-0 items-start gap-2 sm:flex")}
106 </div>
107
108 <div
109 class="flex flex-wrap items-center justify gap-x-4 gap-y-2 typography-paragraph-small text-foreground-muted"
110 >
111 {#if repo.description}
112 <span>{repo.description}</span>
113 {:else}
114 <span class="italic">This repository has no description</span>
115 {/if}
116
117 {#if repo.website}
118 <span class="flex items-center gap-1">
119 <Globe class="size-4 shrink-0" aria-hidden="true" />
120 <a href={repo.website} rel="external ugc nofollow noopener noreferrer"
121 >{trimScheme(repo.website)}</a
122 >
123 </span>
124 {/if}
125
126 {#if topics.length}
127 <div class="flex flex-wrap items-center gap-1">
128 {#each topics as topic (topic)}
129 <Tag color="gray">{topic}</Tag>
130 {/each}
131 </div>
132 {/if}
133 </div>
134
135 {@render repoActions("mt-2 flex flex-wrap items-start justify-end gap-2 sm:hidden")}
136</section>