/** * @file WorkspaceRowMenu — the sidebar workspace row's context menu, opened at * the pointer (right-click) or under the row's `⋯` button. Every item is an * existing call: Rename (the row's inline field), New workspace here (the * Add modal prefilled), Copy path, and Reset/Remove through `DestructiveLaneModal` — Reset only on a * managed lane — plus Move to group (the sidebar's own groups, * `lib/workspaceGroups.ts`: one of them, a new one, or out of its group). The * server's guards are the real ones; the menu only hides * what the lane's kind or tool makes meaningless. The shell (position, * Escape / outside-click close) is `ContextMenu`. * @author Nguyễn Ngọc Trí Vĩ */ import { useTranslation } from "react-i18next"; import type { Lane } from "../../lib/types"; import { Check } from "lucide-react"; import { ContextMenu, MenuItem, MenuSeparator } from "../ContextMenu"; import type { WorkspaceGroup } from "../../lib/workspaceGroups"; import { copyText } from "../../lib/clipboard"; export type WorkspaceMenuAction = "rename" | "new-here" | "reset" | "remove"; export function WorkspaceRowMenu({ lane, x, y, onClose, onAction, groups = [], groupId = null, onGroup, }: { lane: Lane; x: number; y: number; onClose: () => void; /** Items the tree itself carries out (rename field, modals). */ onAction: (action: WorkspaceMenuAction) => void; /** The sidebar's groups and the one this workspace is in. */ groups?: WorkspaceGroup[]; groupId?: string | null; /** Move it: to a group's id, out of its group (null), or into a new group ("new"). */ onGroup?: (target: string | null | "new") => void; }) { const { t } = useTranslation("lanes"); return ( onAction("rename")}>{t("menu.rename")} onAction("new-here")}>{t("menu.newHere")} { onClose(); void copyText(lane.cwd); }} > {t("menu.copyPath")} {onGroup && ( <>
{t("menu.moveToGroup")}
{groups.map((g) => ( onGroup(g.id)} > {g.name} ))} onGroup("new")}> {t("menu.newGroupWith")} {groupId && ( onGroup(null)}> {t("menu.removeFromGroup")} )} )} {lane.kind === "managed" && ( onAction("reset")}> {t("menu.reset")} )} onAction("remove")}> {t("menu.remove")}
); }