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 name="rev" class="branch-select" data-autosubmit>
36 {isDetached && (
37 <option value={currentRef} selected>
38 {shortRef} (detached)
39 </option>
40 )}
41 <optgroup label="Branches">
42 {branches.map((b) => (
43 <option
44 value={b}
45 selected={b === currentRef ? true : undefined}
46 >
47 {b}
48 </option>
49 ))}
50 </optgroup>
51 {tags.length > 0 && (
52 <optgroup label="Tags">
53 {tags.map((t) => (
54 <option
55 value={t}
56 selected={t === currentRef ? true : undefined}
57 >
58 {t}
59 </option>
60 ))}
61 </optgroup>
62 )}
63 </select>
64 <noscript>
65 <button type="submit" class="btn btn-sm">
66 Go
67 </button>
68 </noscript>
69 </form>
70 );
71}
72