2cc492bb88
GET /git/refs lists local branches (upstream, ahead/behind, last commit, merged, held by a worktree, protected), remote branches grouped by remote and tags (target, annotated message/tagger/date). New writes in server/lib/git-refs.js, dispatched from git-ops.js: branch-rename, branch-upstream (set/unset), tag-create (light/annotated), tag-delete (confirm), tag-push (one tag to origin, no --tags, no force), and branch-create with a looked-up from + switch on a clean tree. Every ref is looked up, never passed through; repo-wide writes are repo-root only (ESUBDIR) and refused during any operation (EMERGING). Client: git/BranchManager + TagManager dialog opened from the git bar's tags icon, en+vi (gitRefs namespace), keyboard navigable. # Conflicts: # CLAUDE.md # client/src/components/lanes/LaneGitBar.tsx # docs/API.md # server/__tests__/lanes-api.test.js # server/routes/lanes.js
42 lines
1.8 KiB
TypeScript
42 lines
1.8 KiB
TypeScript
/**
|
|
* @file Shared bits of the Branches panel (`BranchManager`, `TagManager`): the
|
|
* small button and input classes, the write runner's type, and the arrow-key
|
|
* walk over a list's rows.
|
|
* @author Nguyễn Ngọc Trí Vĩ <vinnt@smartgift.vn>
|
|
*/
|
|
|
|
import type { KeyboardEvent } from "react";
|
|
import type { GitRefAction, GitRefBody } from "../../../lib/api";
|
|
|
|
/** Runs one write; resolves true when it succeeded (the list is then re-read). */
|
|
export type RunRefAction = (
|
|
action: GitRefAction,
|
|
body: GitRefBody,
|
|
done?: string
|
|
) => Promise<boolean>;
|
|
|
|
export const smallBtn =
|
|
"inline-flex items-center gap-1 rounded border border-border-light px-1.5 py-0.5 text-[11px] text-fg-secondary transition-colors hover:bg-surface-3 hover:text-fg-primary disabled:cursor-not-allowed disabled:opacity-40";
|
|
export const smallInput =
|
|
"min-w-0 flex-1 rounded border border-border-light bg-surface-0 px-2 py-0.5 font-mono text-[11px] text-fg-primary placeholder:text-fg-muted focus:border-accent focus:outline-none";
|
|
|
|
/** Arrow-key walk over the rows of a list (`[data-ref-row]`), Home/End too. */
|
|
export function onListKeys(e: KeyboardEvent<HTMLElement>) {
|
|
if (!["ArrowDown", "ArrowUp", "Home", "End"].includes(e.key)) return;
|
|
// Inside a text field the arrows and Home/End move the caret.
|
|
if ((e.target as HTMLElement).closest("input, textarea, select")) return;
|
|
const rows = [...e.currentTarget.querySelectorAll<HTMLElement>("[data-ref-row]")];
|
|
if (!rows.length) return;
|
|
const at = rows.indexOf(document.activeElement as HTMLElement);
|
|
const next =
|
|
e.key === "Home"
|
|
? 0
|
|
: e.key === "End"
|
|
? rows.length - 1
|
|
: e.key === "ArrowDown"
|
|
? Math.min(rows.length - 1, at + 1)
|
|
: Math.max(0, at - 1);
|
|
e.preventDefault();
|
|
rows[next]?.focus();
|
|
}
|