/** * TabContextMenu - Right-click context menu for tab actions. * Supports close, close others, close all, bulk close for multi-select, * and split left/right for pane management. * Shows keyboard shortcut hints for actions that have them. */ import { useEffect, useRef } from 'react'; import { formatShortcut } from '@renderer/utils/stringUtils'; interface TabContextMenuProps { x: number; y: number; tabId: string; paneId: string; selectedCount: number; onClose: () => void; onCloseTab: () => void; onCloseOtherTabs: () => void; onCloseAllTabs: () => void; onCloseSelectedTabs?: () => void; onSplitRight: () => void; onSplitLeft: () => void; disableSplit: boolean; /** Whether this tab is a session tab (pin only applies to sessions) */ isSessionTab?: boolean; /** Whether this session is currently pinned in the sidebar */ isPinned?: boolean; /** Callback to toggle pin state */ onTogglePin?: () => void; /** Whether this session is currently hidden from the sidebar */ isHidden?: boolean; /** Callback to toggle hide state */ onToggleHide?: () => void; } export const TabContextMenu = ({ x, y, selectedCount, onClose, onCloseTab, onCloseOtherTabs, onCloseAllTabs, onCloseSelectedTabs, onSplitRight, onSplitLeft, disableSplit, isSessionTab, isPinned, onTogglePin, isHidden, onToggleHide, }: TabContextMenuProps): React.JSX.Element => { const menuRef = useRef(null); // Close on click-outside and Escape useEffect(() => { const handleMouseDown = (e: MouseEvent): void => { if (menuRef.current && !menuRef.current.contains(e.target as Node)) { onClose(); } }; const handleKeyDown = (e: KeyboardEvent): void => { if (e.key === 'Escape') onClose(); }; document.addEventListener('mousedown', handleMouseDown); document.addEventListener('keydown', handleKeyDown); return () => { document.removeEventListener('mousedown', handleMouseDown); document.removeEventListener('keydown', handleKeyDown); }; }, [onClose]); // Viewport clamping const menuWidth = 240; const menuHeight = selectedCount > 1 ? 220 : 196; const clampedX = Math.min(x, window.innerWidth - menuWidth - 8); const clampedY = Math.min(y, window.innerHeight - menuHeight - 8); const handleClick = (action: () => void) => () => { action(); onClose(); }; return (
{selectedCount > 1 && onCloseSelectedTabs ? ( ) : ( )}
{isSessionTab && onTogglePin && ( <>
)} {isSessionTab && onToggleHide && ( )}
); }; const MenuItem = ({ label, shortcut, onClick, disabled, }: { label: string; shortcut?: string; onClick: () => void; disabled?: boolean; }): React.JSX.Element => { return ( ); };