BranchSelector.tsx
Raw
1interface BranchSelectorProps {
2 repoName: string;
3 branches: string[];
4 tags?: string[];
5 currentRef: string;
6 view: "tree" | "commits" | "blob";
7 /** subpath for tree, full file path for blob */
8 path?: string;
9}
10
11export function BranchSelector({
12 repoName,
13 branches,
14 tags = [],
15 currentRef,
16 view,
17 path,
18}: BranchSelectorProps) {
19 if (branches.length === 0 && tags.length === 0) return "";
20 const isDetached =
21 !branches.includes(currentRef) && !tags.includes(currentRef);
22 const shortRef =
23 isDetached && currentRef.length > 8
24 ? currentRef.slice(0, 8)
25 : currentRef;
26 return (
27 <form
28 method="GET"
29 action={`/${repoName}/branch-switch`}
30 class="branch-selector"
31 >
32 <input type="hidden" name="view" value={view} />
33 {path && <input type="hidden" name="path" value={path} />}
34 <span class="branch-selector-icon">⎇</span>
35 <select
36 name="rev"
37 class="branch-select"
38 onchange="this.form.submit()"
39 >
40 {isDetached && (
41 <option value={currentRef} selected>
42 {shortRef} (detached)
43 </option>
44 )}
45 (
46 <optgroup label="Branches">
47 {branches.map((b) => (
48 <option
49 value={b}
50 selected={b === currentRef ? true : undefined}
51 >
52 {b}
53 </option>
54 ))}
55 </optgroup>
56 <optgroup label="Tags">
57 {tags.map((t) => (
58 <option
59 value={t}
60 selected={t === currentRef ? true : undefined}
61 >
62 {t}
63 </option>
64 ))}
65 </optgroup>
66 )
67 </select>
68 <noscript>
69 <button type="submit" class="btn btn-sm">
70 Go
71 </button>
72 </noscript>
73 </form>
74 );
75}
76