Vectrum
Sign In
46 lines · 1.3 KB · TypeScript
"use client";

import { useRouter } from "next/navigation";
import { Select } from "@unlocalhosted/metalui";
import { encodePath } from "@/lib/format";
import { BranchIcon, CommitIcon } from "./icons";

/** Switches branch while staying on the same path. `kind` is the URL section (tree, blob, commits). */
export function BranchSelect({
  base,
  kind,
  current,
  branches,
  path = "",
}: {
  base: string;
  kind: "tree" | "blob" | "commits";
  current: string;
  branches: string[];
  path?: string;
}) {
  const router = useRouter();
  const values = branches.includes(current) ? branches : [current, ...branches];
  // A ref that isn't a branch (a commit) reads as its short sha with the commit glyph.
  const options = values.map((b) => {
    const isBranch = branches.includes(b);
    return {
      value: b,
      label: !isBranch && /^[0-9a-f]{40}$/i.test(b) ? b.slice(0, 7) : b,
      lead: isBranch ? <BranchIcon /> : <CommitIcon />,
    };
  });
  return (
    <Select
      aria-label="Switch branches"
      options={options}
      value={current}
      className="max-w-56"
      onValueChange={(value) => {
        if (value === current) return;
        const suffix = path ? `/${encodePath(path)}` : "";
        router.push(`${base}/${kind}/${encodePath(value)}${suffix}`);
      }}
    />
  );
}