~james/core

core/web/src/lib/components/repo/LanguageStats.svelte -rw-r--r-- 3.6 KiB
452f17b7 — james chore(import): snapshot james.dad.town/core at f70c71c7696a 16 hours ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<script lang="ts">
	import { formatBytes } from "#lib/api/blob.ts";
	import ColorBall from "#lib/components/ui/ColorBall.svelte";
	import Card from "#lib/components/ui/Card.svelte";
	import Tooltip from "#lib/components/ui/Tooltip.svelte";
	import {
		LANGUAGE_COLORS,
		LANGUAGE_COLOR_FALLBACK
	} from "#lib/components/repo/languageColors.ts";
	import type { LanguageSlice } from "#lib/components/repo/types.ts";

	interface Props {
		languages: LanguageSlice[];
	}

	let { languages }: Props = $props();

	const totalSize = $derived(languages.reduce((sum, language) => sum + language.size, 0));
	const colorFor = (name: string) => LANGUAGE_COLORS[name] ?? LANGUAGE_COLOR_FALLBACK;
	const percent = (language: LanguageSlice) =>
		language.share < 1 ? "<1" : String(language.percentage);
</script>

<Card padding="none" class="flex flex-col gap-lg p-md">
	{#if languages.length === 0}
		<div class="flex flex-col gap-2xs">
			<p class="font-medium text-foreground-default">No languages detected</p>
			<p class="typography-paragraph-small text-foreground-muted">
				Language stats appear once the default branch contains source files.
			</p>
		</div>
	{:else}
		<dl class="flex flex-wrap gap-x-xl gap-y-sm">
			<div class="flex flex-col gap-3xs">
				<dt class="typography-paragraph-small text-foreground-muted">Languages</dt>
				<dd class="typography-heading-4 tabular-nums">{languages.length}</dd>
			</div>
			<div class="flex flex-col gap-3xs">
				<dt class="typography-paragraph-small text-foreground-muted">Total size</dt>
				<dd class="typography-heading-4 tabular-nums">{formatBytes(totalSize)}</dd>
			</div>
			<div class="flex flex-col gap-3xs">
				<dt class="typography-paragraph-small text-foreground-muted">Primary language</dt>
				<dd class="typography-heading-4">{languages[0]?.name}</dd>
			</div>
		</dl>

		<div class="flex h-2 gap-px overflow-hidden rounded-full">
			{#each languages as language (language.name)}
				<div style:flex={`${language.share} 0 2px`}>
					<Tooltip
						class="block h-full"
						content={`${language.name}: ${percent(language)}%, ${formatBytes(language.size)}`}
						delay={0}
						group
					>
						<span class="block h-full" style:background-color={colorFor(language.name)}
						></span>
					</Tooltip>
				</div>
			{/each}
		</div>

		<table class="w-full typography-paragraph-small">
			<thead class="text-foreground-muted">
				<tr>
					<th class="pb-xs text-left font-normal">Language</th>
					<th class="pb-xs text-right font-normal">Size</th>
					<th class="pb-xs text-right font-normal">Share</th>
					<td class="hidden w-1/3 md:table-cell" aria-hidden="true"></td>
				</tr>
			</thead>
			<tbody class="divide-y divide-border-default">
				{#each languages as language (language.name)}
					<tr class="group">
						<td class="py-xs group-last:pb-0">
							<span class="flex items-center gap-xs">
								<ColorBall color={colorFor(language.name)} class="size-2.5" />
								{language.name}
							</span>
						</td>
						<td
							class="py-xs text-right text-foreground-muted tabular-nums group-last:pb-0"
						>
							{formatBytes(language.size)}
						</td>
						<td class="py-xs pl-md text-right tabular-nums group-last:pb-0"
							>{percent(language)}%</td
						>
						<td
							class="hidden py-xs pl-md group-last:pb-0 md:table-cell"
							aria-hidden="true"
						>
							<div class="h-1 overflow-hidden rounded-full bg-background-inset">
								<div
									class="h-full rounded-full"
									style:background-color={colorFor(language.name)}
									style:width={`max(${language.share}%, 2px)`}
								></div>
							</div>
						</td>
					</tr>
				{/each}
			</tbody>
		</table>
	{/if}
</Card>