@particle-academy/fancy-term 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/theme.ts","../src/hooks/use-terminal-fit.ts","../src/clipboard.ts","../src/copy-paste-mode.ts","../src/osc52.ts","../src/hooks/use-terminal.ts","../src/types.ts","../src/components/ShellSwitcher.tsx","../src/menu-position.ts","../src/components/TerminalContextMenu.tsx","../src/output-diff.ts","../src/shell-select.ts","../src/context-menu.ts","../src/components/Terminal.tsx","../src/hooks/use-terminal-session.ts","../src/copy-keybinding.ts"],"names":["useRef","useEffect","XTerm","FitAddon","useState","useId","useCallback","jsxs","jsx","useLayoutEffect","forwardRef","Terminal","useImperativeHandle","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { TerminalTheme } from \"./types\";\n\n/**\n * The default \"sexy\" Fancy dark terminal theme — a zinc surface, violet cursor,\n * and a balanced ANSI palette drawn from the react-fancy Tailwind v4 tokens.\n * Pass a `theme` prop / option to override.\n */\nexport const fancyDarkTheme: TerminalTheme = {\n background: \"#09090b\", // zinc-950\n foreground: \"#e4e4e7\", // zinc-200\n cursor: \"#8b5cf6\", // violet-500\n cursorAccent: \"#09090b\",\n selectionBackground: \"#3f3f46\", // zinc-700\n black: \"#18181b\",\n red: \"#f43f5e\",\n green: \"#10b981\",\n yellow: \"#f59e0b\",\n blue: \"#3b82f6\",\n magenta: \"#8b5cf6\",\n cyan: \"#22d3ee\",\n white: \"#e4e4e7\",\n brightBlack: \"#52525b\",\n brightRed: \"#fb7185\",\n brightGreen: \"#34d399\",\n brightYellow: \"#fbbf24\",\n brightBlue: \"#60a5fa\",\n brightMagenta: \"#a78bfa\",\n brightCyan: \"#67e8f9\",\n brightWhite: \"#fafafa\",\n};\n","import { useEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Run `fit` whenever the container resizes — and once it first has a real,\n * non-zero box. Guards the hidden-tab / late-mount 0×0 case: fitting a collapsed\n * container yields garbage rows/cols (or throws), so we simply skip until there\n * is layout to measure.\n */\nexport function useTerminalFit(\n ref: RefObject<HTMLElement | null>,\n fit: () => void,\n enabled = true,\n): void {\n const fitRef = useRef(fit);\n fitRef.current = fit;\n\n useEffect(() => {\n if (!enabled) return;\n const el = ref.current;\n if (!el) return;\n\n const run = () => {\n if (el.clientWidth > 0 && el.clientHeight > 0) fitRef.current();\n };\n\n const observer = new ResizeObserver(run);\n observer.observe(el);\n run(); // initial — fires once the box has layout\n\n return () => observer.disconnect();\n }, [ref, enabled]);\n}\n","// clipboard.ts — small, dependency-free clipboard helpers shared by the headless\n// hook (copy/paste primitives + the paste interceptor) and the component. Kept\n// pure where possible so the extraction logic is unit-testable without a DOM.\n\n/** What a paste / drop carried: plain text plus any files (e.g. pasted images). */\nexport interface ClipboardPayload {\n /** Plain text from the clipboard (or pasted selection). May be \"\". */\n text: string;\n /** Files present on the clipboard / drop — typically pasted/dropped images. */\n files: File[];\n /** Convenience: the subset of `files` whose MIME type is `image/*`. */\n images: File[];\n}\n\n/** True when a file looks like an image (by MIME type). */\nexport function isImageFile(f: { type?: string }): boolean {\n return typeof f.type === \"string\" && f.type.startsWith(\"image/\");\n}\n\n/**\n * Pull text + files out of a ClipboardEvent / DragEvent `dataTransfer`. The\n * DataTransferItemList is checked first (pasted screenshots only appear there in\n * some browsers), then `.files` as a fallback. Pure + null-safe.\n */\nexport function readDataTransfer(dt: DataTransfer | null | undefined): ClipboardPayload {\n const files: File[] = [];\n let text = \"\";\n if (dt) {\n try {\n text = dt.getData(\"text/plain\") ?? \"\";\n } catch {\n /* getData can throw in restricted contexts */\n }\n const items = dt.items;\n if (items) {\n for (let i = 0; i < items.length; i++) {\n const it = items[i];\n if (it && it.kind === \"file\") {\n const f = it.getAsFile();\n if (f) files.push(f);\n }\n }\n }\n if (files.length === 0 && dt.files) {\n for (let i = 0; i < dt.files.length; i++) files.push(dt.files[i]);\n }\n }\n return { text, files, images: files.filter(isImageFile) };\n}\n\n/** Write text to the system clipboard. Resolves false when unavailable/denied. */\nexport async function writeClipboardText(text: string): Promise<boolean> {\n try {\n const nav = typeof navigator !== \"undefined\" ? navigator : undefined;\n if (nav?.clipboard?.writeText) {\n await nav.clipboard.writeText(text);\n return true;\n }\n } catch {\n /* fall through to the legacy path */\n }\n // Legacy fallback for insecure contexts / older browsers.\n try {\n if (typeof document === \"undefined\") return false;\n const ta = document.createElement(\"textarea\");\n ta.value = text;\n ta.style.position = \"fixed\";\n ta.style.left = \"-9999px\";\n ta.style.opacity = \"0\";\n document.body.appendChild(ta);\n ta.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(ta);\n return ok;\n } catch {\n return false;\n }\n}\n\n/** Read text from the system clipboard. Resolves \"\" when unavailable/denied. */\nexport async function readClipboardText(): Promise<string> {\n try {\n const nav = typeof navigator !== \"undefined\" ? navigator : undefined;\n if (nav?.clipboard?.readText) return await nav.clipboard.readText();\n } catch {\n /* permission denied / unavailable */\n }\n return \"\";\n}\n\n/**\n * A host-supplied clipboard. Every copy/paste path in fancy-term — the copy\n * chord, the context menu, OSC 52, `handle.copySelection` / `handle.paste` —\n * routes through this, so an Electron host (where `navigator.clipboard` silently\n * no-ops in a sandboxed renderer) can bridge to its main-process clipboard over\n * IPC. `writeText` may return anything (a `Promise<void>` from IPC is fine);\n * `readText` returns the clipboard text.\n */\nexport interface ClipboardProvider {\n writeText: (text: string) => void | Promise<unknown>;\n readText: () => string | Promise<string>;\n}\n\n/** The default provider — `navigator.clipboard` with the legacy `execCommand` fallback. */\nexport const navigatorClipboard: ClipboardProvider = {\n writeText: (text) => writeClipboardText(text),\n readText: () => readClipboardText(),\n};\n\n/** The `clipboard` prop: `false` disables clipboard wiring; a provider object injects a host clipboard; `true`/omitted uses {@link navigatorClipboard}. */\nexport type ClipboardOption = boolean | ClipboardProvider;\n\n/** Normalize the `clipboard` prop into `{ enabled, provider }`, read live per call. */\nexport function resolveClipboard(clipboard: ClipboardOption | undefined): {\n enabled: boolean;\n provider: ClipboardProvider;\n} {\n if (clipboard === false) return { enabled: false, provider: navigatorClipboard };\n if (clipboard && typeof clipboard === \"object\") return { enabled: true, provider: clipboard };\n return { enabled: true, provider: navigatorClipboard };\n}\n\n/** Write via a provider, resolving `true` on success and `false` if it throws/rejects. */\nexport async function providerWrite(provider: ClipboardProvider, text: string): Promise<boolean> {\n try {\n await provider.writeText(text);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Read via a provider, resolving `\"\"` if it throws/rejects. */\nexport async function providerRead(provider: ClipboardProvider): Promise<string> {\n try {\n return (await provider.readText()) ?? \"\";\n } catch {\n return \"\";\n }\n}\n","// copy-paste-mode.ts — the pure decision layer for the `copyPaste` prop. Kept\n// DOM-free (like copy-keybinding.ts / shell-select.ts) so the behavior is\n// unit-testable without a live xterm. use-terminal.ts wires the resulting\n// behavior to real events.\n\n/**\n * The copy/paste convention the terminal follows:\n * - `contextmenu` — copy/paste via the right-click menu only (plus the always-on\n * Ctrl+Shift+C copy chord).\n * - `linux` — highlight-to-copy (X11 primary-selection style) + middle-click\n * paste. Right-click still opens the context menu.\n * - `winmac` — Ctrl/Cmd+C copies the selection (falling back to SIGINT when\n * nothing is selected), Ctrl/Cmd+V pastes.\n *\n * Omitting the prop keeps the historical default: the Ctrl+Shift+C chord and\n * Cmd+C-with-selection, no auto-copy, no mouse paste.\n */\nexport type CopyPasteMode = \"contextmenu\" | \"linux\" | \"winmac\";\n\n/** The resolved, event-agnostic behavior flags a {@link CopyPasteMode} implies. */\nexport interface CopyPasteBehavior {\n /** Auto-copy the selection to the clipboard as soon as it changes (linux). */\n selectToCopy: boolean;\n /** Paste on middle-mouse-button (linux). */\n middleClickPaste: boolean;\n /** (Ctrl|Cmd)+C copies the selection when one exists (winmac). */\n keyCopy: boolean;\n /** (Ctrl|Cmd)+V — and Ctrl+Shift+V — paste (winmac). */\n keyPaste: boolean;\n}\n\nexport function copyPasteBehavior(mode: CopyPasteMode | undefined): CopyPasteBehavior {\n switch (mode) {\n case \"linux\":\n return { selectToCopy: true, middleClickPaste: true, keyCopy: false, keyPaste: false };\n case \"winmac\":\n return { selectToCopy: false, middleClickPaste: false, keyCopy: true, keyPaste: true };\n case \"contextmenu\":\n default:\n return { selectToCopy: false, middleClickPaste: false, keyCopy: false, keyPaste: false };\n }\n}\n\n/** The subset of a KeyboardEvent the copy/paste decision reads. */\nexport interface KeyEventLike {\n type: string;\n key: string;\n ctrlKey: boolean;\n shiftKey: boolean;\n metaKey: boolean;\n}\n\n/**\n * Resolve a key event to a clipboard action, given the current selection state\n * and the active behavior. Returns `\"copy\"`, `\"paste\"`, or `null` (do nothing —\n * let the byte reach the shell). Only fires on `keydown`.\n *\n * Copy is honored across every mode for the terminal-safe **Ctrl+Shift+C** chord\n * and macOS **Cmd+C-with-selection**; `keyCopy` adds plain (Ctrl|Cmd)+C. Plain\n * Ctrl+C with no selection is never a copy — it stays SIGINT.\n */\nexport function resolveKeyAction(\n e: KeyEventLike,\n hasSelection: boolean,\n behavior: CopyPasteBehavior,\n): \"copy\" | \"paste\" | null {\n if (e.type !== \"keydown\") return null;\n const key = e.key.toLowerCase();\n\n if (key === \"c\") {\n if (e.ctrlKey && e.shiftKey && !e.metaKey) return \"copy\"; // Ctrl+Shift+C — always\n if (e.metaKey && !e.ctrlKey && hasSelection) return \"copy\"; // Cmd+C w/ selection — always (macOS)\n if (behavior.keyCopy && (e.ctrlKey || e.metaKey) && !e.shiftKey && hasSelection) return \"copy\";\n return null;\n }\n\n if (key === \"v\" && behavior.keyPaste) {\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey) return \"paste\"; // Ctrl/Cmd+V\n if (e.ctrlKey && e.shiftKey) return \"paste\"; // Ctrl+Shift+V (terminal-safe paste)\n return null;\n }\n\n return null;\n}\n","// osc52.ts — OSC 52 clipboard handling. Modern TUIs (Claude Code, tmux, vim /\n// neovim) copy their own selection with `ESC ] 52 ; <Pc> ; <Pd> BEL`. xterm.js\n// drops OSC 52 by default, so a program shows \"copied\" but nothing reaches the\n// system clipboard — a silent, confusing failure. We parse the sequence and\n// route it through the injectable clipboard provider.\n//\n// The parse + base64 codec are pure so they're unit-testable without a live\n// xterm; registerOsc52 wires them to an xterm instance.\n\nimport type { Terminal as XTerm } from \"@xterm/xterm\";\nimport type { IDisposable } from \"@xterm/xterm\";\nimport type { ClipboardProvider } from \"./clipboard\";\nimport { providerRead } from \"./clipboard\";\n\n/**\n * OSC 52 policy: `copy` allows programs to WRITE the clipboard (the common TUI\n * case), `read` allows a program to READ it back (a `?` request), `both` allows\n * either, `false` disables OSC 52 entirely. Read is the real exfiltration risk\n * (arbitrary terminal output could siphon your clipboard), so it must be opted\n * into explicitly.\n */\nexport type Osc52Mode = \"copy\" | \"read\" | \"both\" | false;\n\n/** A parsed OSC 52 request: which selection buffer, and write-a-payload vs read-request. */\nexport interface Osc52Request {\n /** The `Pc` field — clipboard selection(s), e.g. `\"c\"` (clipboard), `\"p\"` (primary). */\n selection: string;\n kind: \"write\" | \"read\";\n /** Decoded text for a write; `\"\"` for a read request. */\n data: string;\n}\n\n/** UTF-8-safe base64 encode (browser `btoa` operates on binary strings). */\nexport function encodeBase64(text: string): string {\n const bytes = new TextEncoder().encode(text);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return typeof btoa === \"function\" ? btoa(binary) : binary;\n}\n\n/** UTF-8-safe base64 decode; returns `\"\"` on malformed input. */\nexport function decodeBase64(b64: string): string {\n try {\n const binary = typeof atob === \"function\" ? atob(b64) : b64;\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n } catch {\n return \"\";\n }\n}\n\n/**\n * Parse an OSC 52 payload (the part after `ESC ] 52 ;`, i.e. `<Pc> ; <Pd>`).\n * `Pd === \"?\"` is a read request; otherwise `Pd` is base64 to write. Returns\n * `null` for a malformed payload (no `;`).\n */\nexport function parseOsc52(payload: string): Osc52Request | null {\n const semi = payload.indexOf(\";\");\n if (semi < 0) return null;\n const selection = payload.slice(0, semi);\n const pd = payload.slice(semi + 1);\n if (pd === \"?\") return { selection, kind: \"read\", data: \"\" };\n return { selection, kind: \"write\", data: decodeBase64(pd) };\n}\n\n/** Build the OSC 52 response a `read` request expects: `ESC ] 52 ; <Pc> ; <base64> BEL`. */\nexport function osc52Response(selection: string, text: string): string {\n return `\\x1b]52;${selection};${encodeBase64(text)}\\x07`;\n}\n\n/**\n * Register an OSC 52 handler on an xterm instance, routing writes/reads through\n * `provider` per `mode`. Returns the {@link IDisposable} (or `null` when\n * `mode === false`). The handler always returns `true` (consumed) so a\n * disallowed direction is swallowed rather than echoed as garbage.\n */\nexport function registerOsc52(\n term: XTerm,\n provider: () => ClipboardProvider,\n mode: () => Osc52Mode,\n): IDisposable | null {\n if (mode() === false) return null;\n\n return term.parser.registerOscHandler(52, (payload) => {\n const m = mode();\n if (m === false) return true;\n const req = parseOsc52(payload);\n if (!req) return false; // not ours / malformed — let xterm handle it\n\n if (req.kind === \"write\") {\n if (m === \"copy\" || m === \"both\") {\n void Promise.resolve(provider().writeText(req.data)).catch(() => {});\n }\n return true;\n }\n\n // read request (`?`)\n if (m === \"read\" || m === \"both\") {\n void providerRead(provider()).then((text) => {\n term.write(osc52Response(req.selection, text));\n });\n }\n return true;\n });\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\nimport { Terminal as XTerm } from \"@xterm/xterm\";\nimport { FitAddon } from \"@xterm/addon-fit\";\nimport { fancyDarkTheme } from \"../theme\";\nimport { useTerminalFit } from \"./use-terminal-fit\";\nimport { providerRead, providerWrite, readDataTransfer, resolveClipboard } from \"../clipboard\";\nimport { copyPasteBehavior, resolveKeyAction } from \"../copy-paste-mode\";\nimport { registerOsc52 } from \"../osc52\";\nimport type { TerminalHandle, TerminalOptions } from \"../types\";\n\nconst DEFAULT_FONT =\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace';\n\n/** A minimal externally-resolvable promise (Promise.withResolvers isn't universally available). */\nfunction makeDeferred<T>(): { promise: Promise<T>; resolve: (value: T) => void } {\n let resolve!: (value: T) => void;\n const promise = new Promise<T>((r) => {\n resolve = r;\n });\n return { promise, resolve };\n}\n\n/** Read the whole xterm buffer as plain text — what an agent \"sees\". */\nfunction readBuffer(term: XTerm | null): string {\n if (!term) return \"\";\n const buf = term.buffer.active;\n const lines: string[] = [];\n for (let i = 0; i < buf.length; i++) {\n const line = buf.getLine(i);\n if (line) lines.push(line.translateToString(true));\n }\n return lines.join(\"\\n\").replace(/\\n+$/, \"\");\n}\n\n/**\n * Create + own an xterm.js instance for a container, returning a stable\n * {@link TerminalHandle}. The headless engine layer behind `<Terminal>` — use it\n * directly when you want the terminal without the component shell (custom chrome,\n * an agent bridge host, tests). Options are read live, so changing them re-applies\n * without tearing down the terminal.\n */\nexport function useTerminal(\n containerRef: RefObject<HTMLElement | null>,\n options: TerminalOptions = {},\n): TerminalHandle {\n const xtermRef = useRef<XTerm | null>(null);\n const fitRef = useRef<FitAddon | null>(null);\n const optsRef = useRef(options);\n optsRef.current = options;\n\n // A re-armable \"xterm is open\" promise backing handle.ready.\n const readyRef = useRef(makeDeferred<XTerm>());\n\n // Stable handle — its methods always operate on the live xterm via the ref.\n const handleRef = useRef<TerminalHandle | null>(null);\n if (handleRef.current === null) {\n handleRef.current = {\n get xterm() {\n return xtermRef.current;\n },\n get ready() {\n return readyRef.current.promise;\n },\n write: (d) => xtermRef.current?.write(d),\n writeln: (d) => xtermRef.current?.writeln(d),\n clear: () => xtermRef.current?.clear(),\n reset: () => xtermRef.current?.reset(),\n fit: () => {\n const addon = fitRef.current;\n if (!addon) return;\n try {\n // Guard against an unmeasurable container / not-yet-rendered viewport:\n // proposeDimensions() returns undefined (or NaN) then, and fit() would\n // call xterm's resize(undefined,…), which console-errors \"cols must be\n // numeric\". Skip — the ResizeObserver fires again once it's measurable.\n // This matters most under `showShellBar`, whose extra layout pass races\n // the first fit.\n const dims = addon.proposeDimensions();\n if (\n !dims ||\n !Number.isFinite(dims.cols) ||\n !Number.isFinite(dims.rows) ||\n dims.cols < 1 ||\n dims.rows < 1\n ) {\n return;\n }\n addon.fit();\n } catch {\n /* container not measurable yet — ignore */\n }\n },\n focus: () => xtermRef.current?.focus(),\n getBuffer: () => readBuffer(xtermRef.current),\n getSelection: () => xtermRef.current?.getSelection() ?? \"\",\n copySelection: async () => {\n const sel = xtermRef.current?.getSelection() ?? \"\";\n if (!sel) return false;\n return providerWrite(resolveClipboard(optsRef.current.clipboard).provider, sel);\n },\n paste: async (text) => {\n const data = text ?? (await providerRead(resolveClipboard(optsRef.current.clipboard).provider));\n if (data) xtermRef.current?.paste(data);\n },\n selectAll: () => xtermRef.current?.selectAll(),\n clearSelection: () => xtermRef.current?.clearSelection(),\n // Shell selection is owned by the <Terminal> component layer (it needs the\n // `shells` list + onShellChange). The headless engine is shell-agnostic, so\n // these are no-ops here and get overridden when <Terminal> composes them.\n setShell: () => {},\n getShell: () => undefined,\n };\n }\n const handle = handleRef.current;\n\n // Create the engine once for the container.\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const o = optsRef.current;\n\n const term = new XTerm({\n theme: o.theme ?? fancyDarkTheme,\n // Only pass rows/cols when explicitly set. xterm validates these and\n // console-errors \"rows/cols must be numeric\" if handed `undefined`, rather\n // than falling back to its 80×24 default. Omit the keys instead.\n ...(typeof o.rows === \"number\" ? { rows: o.rows } : {}),\n ...(typeof o.cols === \"number\" ? { cols: o.cols } : {}),\n disableStdin: o.readOnly ?? false,\n cursorBlink: o.cursorBlink ?? true,\n cursorStyle: o.cursorStyle ?? \"block\",\n fontFamily: o.fontFamily ?? DEFAULT_FONT,\n fontSize: o.fontSize ?? 13,\n scrollback: o.scrollback ?? 1000,\n allowProposedApi: true,\n });\n const fitAddon = new FitAddon();\n term.loadAddon(fitAddon);\n term.open(el);\n xtermRef.current = term;\n fitRef.current = fitAddon;\n\n const dataSub = term.onData((d) => optsRef.current.onData?.(d));\n const resizeSub = term.onResize(({ cols, rows }) =>\n optsRef.current.onResize?.({ cols, rows }),\n );\n\n // Paste the system clipboard into the terminal (honors readOnly + bracketed\n // paste). Shared by the paste key chord and middle-click paste.\n const pasteFromClipboard = async () => {\n const oo = optsRef.current;\n if (oo.readOnly) return;\n const text = await providerRead(resolveClipboard(oo.clipboard).provider);\n if (text) xtermRef.current?.paste(text);\n };\n\n // ── Clipboard wiring (gated by `clipboard !== false`, read live) ──────────\n // Copy/paste key chords resolved by the active `copyPaste` mode: Ctrl+Shift+C\n // always copies; plain Ctrl+C stays SIGINT unless winmac + selection; winmac\n // also binds Ctrl/Cmd+V paste. Returning false consumes the event.\n term.attachCustomKeyEventHandler((e) => {\n const oo = optsRef.current;\n const clip = resolveClipboard(oo.clipboard);\n if (!clip.enabled) return true;\n const action = resolveKeyAction(e, term.hasSelection(), copyPasteBehavior(oo.copyPaste));\n if (action === \"copy\") {\n void providerWrite(clip.provider, term.getSelection());\n return false;\n }\n if (action === \"paste\") {\n void pasteFromClipboard();\n return false;\n }\n return true;\n });\n\n // OSC 52 — terminal programs (Claude Code, tmux, vim) copy/read the clipboard\n // via `ESC ] 52`. Routed through the live provider; off when clipboard === false.\n const oscDisposable = registerOsc52(\n term,\n () => resolveClipboard(optsRef.current.clipboard).provider,\n () => {\n const oo = optsRef.current;\n return resolveClipboard(oo.clipboard).enabled ? (oo.osc52 ?? \"copy\") : false;\n },\n );\n\n // linux mode: auto-copy the selection as it changes (X11 primary-selection).\n const selectionSub = term.onSelectionChange(() => {\n const oo = optsRef.current;\n const clip = resolveClipboard(oo.clipboard);\n if (clip.enabled && copyPasteBehavior(oo.copyPaste).selectToCopy && term.hasSelection()) {\n void providerWrite(clip.provider, term.getSelection());\n }\n });\n\n // linux mode: middle-click pastes.\n const onMouseDown = (ev: MouseEvent) => {\n const oo = optsRef.current;\n if (ev.button !== 1) return;\n if (!resolveClipboard(oo.clipboard).enabled) return;\n if (!copyPasteBehavior(oo.copyPaste).middleClickPaste) return;\n ev.preventDefault();\n void pasteFromClipboard();\n };\n el.addEventListener(\"mousedown\", onMouseDown);\n\n // Paste: a capture-phase listener on the container runs before xterm's own\n // textarea handler. We do NOT preventDefault for text, so xterm pastes it\n // exactly once natively — we only surface the payload (esp. pasted images)\n // via onPaste. The host returning false (or a read-only terminal) suppresses\n // the native text paste.\n const onPasteEvent = (e: ClipboardEvent) => {\n const o2 = optsRef.current;\n if (resolveClipboard(o2.clipboard).enabled === false) return;\n if (o2.readOnly) {\n e.preventDefault();\n return;\n }\n const payload = readDataTransfer(e.clipboardData);\n if (o2.onPaste?.(payload) === false) e.preventDefault();\n };\n el.addEventListener(\"paste\", onPasteEvent, true);\n\n if (o.initialOutput) term.write(o.initialOutput);\n // Route through the guarded handle.fit() (proposeDimensions check) so a\n // not-yet-laid-out container never triggers an xterm resize(undefined).\n if (o.fit ?? true) handle.fit();\n\n // The terminal is open + attached — signal readiness so consumers wiring\n // addons don't have to poll handle.xterm.\n optsRef.current.onReady?.(term);\n readyRef.current.resolve(term);\n\n return () => {\n el.removeEventListener(\"paste\", onPasteEvent, true);\n el.removeEventListener(\"mousedown\", onMouseDown);\n oscDisposable?.dispose();\n selectionSub.dispose();\n dataSub.dispose();\n resizeSub.dispose();\n term.dispose();\n xtermRef.current = null;\n fitRef.current = null;\n // Re-arm readiness for a potential remount (container change).\n readyRef.current = makeDeferred<XTerm>();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [containerRef]);\n\n // Re-apply reactive options without tearing the terminal down.\n useEffect(() => {\n const t = xtermRef.current;\n if (!t) return;\n if (options.theme) t.options.theme = options.theme;\n if (options.readOnly !== undefined) t.options.disableStdin = options.readOnly;\n if (options.cursorBlink !== undefined) t.options.cursorBlink = options.cursorBlink;\n if (options.cursorStyle) t.options.cursorStyle = options.cursorStyle;\n if (options.fontSize) t.options.fontSize = options.fontSize;\n if (options.fontFamily) t.options.fontFamily = options.fontFamily;\n }, [options.theme, options.readOnly, options.cursorBlink, options.cursorStyle, options.fontSize, options.fontFamily]);\n\n // Auto-fit on container resize (0×0-guarded).\n useTerminalFit(containerRef, () => handle.fit(), options.fit ?? true);\n\n return handle;\n}\n","import type { HTMLAttributes } from \"react\";\nimport type { ITheme, Terminal as XTerm } from \"@xterm/xterm\";\nimport type { ClipboardOption, ClipboardPayload } from \"./clipboard\";\nimport type { CopyPasteMode } from \"./copy-paste-mode\";\nimport type { Osc52Mode } from \"./osc52\";\nimport type { TerminalContextMenuConfig } from \"./context-menu\";\n\n/** xterm.js color theme (re-exported for ergonomic typing). */\nexport type TerminalTheme = ITheme;\n\nexport type CursorStyle = \"block\" | \"underline\" | \"bar\";\n\n/**\n * A selectable shell / profile. Fully JSON-friendly (primitives only) so an agent\n * can emit it. fancy-term owns the *selected-shell state + UI + events*; the\n * `command` / `args` / `cwd` fields are **host hints** — fancy-term never spawns a\n * shell, the host reconnects its PTY/command backend to the chosen profile.\n */\nexport interface ShellProfile {\n /** Stable key, e.g. `\"powershell\"`. */\n id: string;\n /** Display label, e.g. `\"PowerShell\"`. */\n label: string;\n /** Optional short glyph / emoji / single char (kept JSON-friendly — no ReactNode). */\n icon?: string;\n /** Host hint — the executable, e.g. `\"pwsh\"` / `\"cmd.exe\"`. */\n command?: string;\n /** Host hint — launch args. */\n args?: string[];\n /** Host hint — working directory. */\n cwd?: string;\n}\n\n/**\n * Imperative handle exposed via the `<Terminal>` ref and returned by\n * {@link useTerminal}. The same surface an MCP bridge drives so an embedded\n * agent reads the buffer + writes input without DOM-scraping.\n */\nexport interface TerminalHandle {\n /** The underlying xterm.js instance — escape hatch for addons / advanced use. Null before mount. */\n readonly xterm: XTerm | null;\n /**\n * Resolves with the xterm instance once it's opened + measured. Because\n * `xterm` is null until the container lays out, a consumer that must wire an\n * addon can `await handle.ready` instead of polling. Re-armed if the terminal\n * is torn down + recreated (e.g. a container change).\n */\n readonly ready: Promise<XTerm>;\n /** Write raw data (ANSI escape sequences honored) to the terminal. */\n write: (data: string) => void;\n /** Write data followed by CRLF. */\n writeln: (data: string) => void;\n /** Clear the viewport (keeps scrollback). */\n clear: () => void;\n /** Full reset — clears scrollback + terminal state. */\n reset: () => void;\n /** Re-fit to the container (no-op when the box is 0-size or fit is off). */\n fit: () => void;\n /** Focus the terminal input. */\n focus: () => void;\n /** The full buffer as plain text — what an agent \"sees\". */\n getBuffer: () => string;\n /** The current text selection, or \"\" when nothing is selected. */\n getSelection: () => string;\n /** Copy the current selection to the system clipboard. Resolves false when there's nothing selected or the clipboard is unavailable. */\n copySelection: () => Promise<boolean>;\n /** Paste text into the terminal. With no argument, reads the system clipboard. Honors xterm's bracketed-paste mode. */\n paste: (text?: string) => Promise<void>;\n /** Select the entire buffer. */\n selectAll: () => void;\n /** Clear the current selection. */\n clearSelection: () => void;\n /**\n * Switch the active shell by id. Resolves the matching {@link ShellProfile}\n * from `shells` and fires `onShellChange`; in uncontrolled mode it also updates\n * the internal selection. No-op when the id isn't in `shells`.\n */\n setShell: (id: string) => void;\n /** The active shell id, or `undefined` when no shell is selected. */\n getShell: () => string | undefined;\n}\n\n/** Engine options shared by `<Terminal>` and {@link useTerminal}. */\nexport interface TerminalOptions {\n /** xterm color theme. Omit for the built-in Fancy dark theme. */\n theme?: TerminalTheme;\n /** Fixed grid size. Omit + leave `fit` on to size from the container. */\n rows?: number;\n cols?: number;\n /** Auto-fit to the container via the fit addon + ResizeObserver. Default true. */\n fit?: boolean;\n /** Block stdin (display-only terminal). Default false. */\n readOnly?: boolean;\n /** Blink the cursor. Default true. */\n cursorBlink?: boolean;\n /** Cursor shape. Default \"block\". */\n cursorStyle?: CursorStyle;\n /** Monospace font stack. */\n fontFamily?: string;\n /** Font size in px. Default 13. */\n fontSize?: number;\n /** Scrollback lines. Default 1000. */\n scrollback?: number;\n /** Data written once on mount, before any controlled `output`. */\n initialOutput?: string;\n /** User keystrokes / paste data (xterm `onData`). Wire to your PTY/command backend. */\n onData?: (data: string) => void;\n /** Notified on terminal resize. */\n onResize?: (size: { cols: number; rows: number }) => void;\n /**\n * Clipboard wiring — gates the Ctrl+Shift+C / Cmd+C copy chord, the paste\n * interceptor ({@link onPaste}), the context-menu copy/paste, and OSC 52.\n *\n * - `true` / omitted — enabled, backed by `navigator.clipboard`.\n * - `false` — disabled (no copy chord / OSC 52; native text paste still works).\n * - a `{ writeText, readText }` **provider** — every copy/paste path routes\n * through it. Supply this in a sandboxed Electron renderer, where\n * `navigator.clipboard` silently no-ops, to bridge to the main-process\n * clipboard over IPC.\n */\n clipboard?: ClipboardOption;\n /**\n * OSC 52 clipboard policy — lets terminal programs (Claude Code, tmux, vim)\n * set/read the system clipboard via `ESC ] 52`. `\"copy\"` (default) allows\n * writes only; `\"read\"` / `\"both\"` also answer read requests (an exfiltration\n * risk — opt in deliberately); `false` disables it. Routed through the same\n * clipboard provider as {@link clipboard}; a no-op when clipboard is `false`.\n * Default `\"copy\"`.\n */\n osc52?: Osc52Mode;\n /**\n * Copy/paste UX convention: `\"contextmenu\"` (menu + Ctrl+Shift+C),\n * `\"linux\"` (highlight-to-copy + middle-click paste), or `\"winmac\"`\n * (Ctrl/Cmd+C copies the selection, Ctrl/Cmd+V pastes). Omit for the historical\n * default (Ctrl+Shift+C + Cmd+C-with-selection). Ctrl+Shift+C always copies.\n */\n copyPaste?: CopyPasteMode;\n /**\n * Called once the xterm instance is opened + attached — the imperative twin of\n * {@link TerminalHandle.ready}. Use it to load an addon without racing the\n * container layout (where `handle.xterm` is still null).\n */\n onReady?: (xterm: XTerm) => void;\n /**\n * Fired on every paste with the clipboard payload — `{ text, files, images }`.\n * Plain text still pastes into the terminal natively; this is where a host\n * receives pasted **images** (a shell can't render them) to upload / hand to an\n * agent / write a path. Return `false` to fully consume the paste (suppress the\n * default text paste — e.g. to transform it, then call `handle.paste(...)`).\n */\n onPaste?: (payload: ClipboardPayload) => void | boolean;\n}\n\nexport interface TerminalProps extends TerminalOptions, Omit<HTMLAttributes<HTMLDivElement>, \"onInput\" | \"onResize\" | \"onPaste\" | \"contextMenu\" | \"children\"> {\n /**\n * The controlled output buffer. The component diffs against the previous value\n * and writes only the appended delta, so a host can drive the terminal from\n * React state — e.g. streaming command output via fancy-query's\n * `useFancyStream`. Replacing it with a non-extending string resets + rewrites.\n */\n output?: string;\n\n /**\n * The shells / profiles a host offers. fancy-term renders the selector and\n * tracks the choice; the host reacts (reconnects its PTY to the chosen shell).\n * Spread {@link BUILTIN_SHELLS} for sensible presets, but the host owns the list.\n */\n shells?: ShellProfile[];\n /** Controlled active-shell id. Omit for uncontrolled (internal) selection. */\n activeShell?: string;\n /** Fired when the user (or `setShell`) switches shells. */\n onShellChange?: (id: string, profile: ShellProfile) => void;\n /**\n * Render the built-in `<ShellSwitcher>` toolbar above the xterm surface when\n * `shells` is provided. Default `false` — opt-in so existing layout is unchanged.\n */\n showShellBar?: boolean;\n\n /**\n * The right-click selection context menu. `false` disables it; `true` / omitted\n * gives the default Copy / Paste / Select all / Clear menu; an array replaces\n * the items; a `(ctx, defaults) => items` function lets you add/remove/reorder\n * (e.g. append a \"Send to agent\" item). See {@link TerminalContextMenuConfig}.\n */\n contextMenu?: TerminalContextMenuConfig;\n}\n\n/**\n * Resolve a shell id to its {@link ShellProfile} within a list. Pure helper —\n * the single place `setShell` / `<ShellSwitcher>` / the session hook agree on\n * what \"switch to id X\" means.\n */\nexport function resolveShell(\n shells: ShellProfile[] | undefined,\n id: string | undefined,\n): ShellProfile | undefined {\n if (!shells || id === undefined) return undefined;\n return shells.find((s) => s.id === id);\n}\n\n/**\n * A small set of sensible built-in shell presets a host can spread / filter.\n * `command` / `args` are host hints only — fancy-term never spawns them.\n */\nexport const BUILTIN_SHELLS: readonly ShellProfile[] = [\n { id: \"cmd\", label: \"Command Prompt\", icon: \">_\", command: \"cmd.exe\" },\n { id: \"powershell\", label: \"Windows PowerShell\", icon: \"PS\", command: \"powershell.exe\" },\n { id: \"pwsh\", label: \"PowerShell\", icon: \"PS\", command: \"pwsh\" },\n {\n id: \"git-bash\",\n label: \"Git Bash\",\n icon: \"\",\n command: \"C:\\\\Program Files\\\\Git\\\\bin\\\\bash.exe\",\n args: [\"--login\", \"-i\"],\n },\n { id: \"bash\", label: \"Bash\", icon: \"$\", command: \"bash\" },\n { id: \"zsh\", label: \"Zsh\", icon: \"%\", command: \"zsh\" },\n] as const;\n","import {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n} from \"react\";\nimport { resolveShell, type ShellProfile } from \"../types\";\n\nexport interface ShellSwitcherProps {\n /** The available shells / profiles. */\n shells: ShellProfile[];\n /** Controlled selected shell id. */\n value?: string;\n /** Fired when a shell is picked. */\n onChange: (id: string, profile: ShellProfile) => void;\n className?: string;\n style?: CSSProperties;\n /** Disable the control. */\n disabled?: boolean;\n}\n\nconst PANEL_BG = \"#18181b\"; // zinc-900\nconst BORDER = \"#3f3f46\"; // zinc-700\nconst FG = \"#e4e4e7\"; // zinc-200\nconst MUTED = \"#a1a1aa\"; // zinc-400\nconst ACCENT = \"#8b5cf6\"; // violet-500\nconst HOVER_BG = \"#27272a\"; // zinc-800\n\n/**\n * Compact, accessible shell picker styled to the Fancy dark theme. Self-contained\n * (zero third-party deps) — a button that toggles a listbox of `shells`.\n *\n * Stable handles for agents: the root carries `data-fancy-shell-switcher` and each\n * option carries `data-shell-id`, so a bridge can pick a shell without DOM-guessing.\n *\n * Controlled: pass `value` + `onChange`. Keyboard accessible (Arrow / Enter / Esc).\n */\nexport function ShellSwitcher({\n shells,\n value,\n onChange,\n className,\n style,\n disabled,\n}: ShellSwitcherProps) {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(0);\n const rootRef = useRef<HTMLDivElement>(null);\n const listId = useId();\n\n const selected = resolveShell(shells, value);\n const selectedIndex = selected ? shells.indexOf(selected) : -1;\n\n // Close on outside click.\n useEffect(() => {\n if (!open) return;\n const onDocClick = (e: MouseEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDocClick);\n return () => document.removeEventListener(\"mousedown\", onDocClick);\n }, [open]);\n\n const openMenu = useCallback(() => {\n if (disabled) return;\n setActiveIndex(selectedIndex >= 0 ? selectedIndex : 0);\n setOpen(true);\n }, [disabled, selectedIndex]);\n\n const pick = useCallback(\n (i: number) => {\n const profile = shells[i];\n if (!profile) return;\n onChange(profile.id, profile);\n setOpen(false);\n },\n [shells, onChange],\n );\n\n const onButtonKeyDown = (e: KeyboardEvent) => {\n if (disabled) return;\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\" || e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n openMenu();\n }\n };\n\n const onListKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActiveIndex((i) => Math.min(shells.length - 1, i + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActiveIndex((i) => Math.max(0, i - 1));\n } else if (e.key === \"Home\") {\n e.preventDefault();\n setActiveIndex(0);\n } else if (e.key === \"End\") {\n e.preventDefault();\n setActiveIndex(shells.length - 1);\n } else if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n pick(activeIndex);\n }\n };\n\n const buttonStyle: CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n height: 26,\n padding: \"0 8px\",\n fontSize: 12,\n lineHeight: 1,\n fontFamily: \"inherit\",\n color: FG,\n background: PANEL_BG,\n border: `1px solid ${BORDER}`,\n borderRadius: 6,\n cursor: disabled ? \"default\" : \"pointer\",\n opacity: disabled ? 0.6 : 1,\n userSelect: \"none\",\n };\n\n return (\n <div\n ref={rootRef}\n data-fancy-shell-switcher=\"\"\n data-active-shell={value ?? undefined}\n className={className}\n style={{ position: \"relative\", display: \"inline-block\", ...style }}\n >\n <button\n type=\"button\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-label=\"Select shell\"\n disabled={disabled}\n style={buttonStyle}\n onClick={() => (open ? setOpen(false) : openMenu())}\n onKeyDown={onButtonKeyDown}\n >\n {selected?.icon ? (\n <span aria-hidden=\"true\" style={{ color: ACCENT }}>\n {selected.icon}\n </span>\n ) : null}\n <span>{selected?.label ?? \"Select shell\"}</span>\n <span aria-hidden=\"true\" style={{ color: MUTED, fontSize: 9 }}>\n ▼\n </span>\n </button>\n\n {open ? (\n <ul\n role=\"listbox\"\n id={listId}\n aria-label=\"Shells\"\n tabIndex={-1}\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus\n onKeyDown={onListKeyDown}\n ref={(el) => el?.focus()}\n style={{\n position: \"absolute\",\n zIndex: 50,\n top: \"calc(100% + 4px)\",\n left: 0,\n minWidth: \"100%\",\n margin: 0,\n padding: 4,\n listStyle: \"none\",\n background: PANEL_BG,\n border: `1px solid ${BORDER}`,\n borderRadius: 8,\n boxShadow: \"0 8px 24px rgba(0,0,0,0.45)\",\n outline: \"none\",\n }}\n >\n {shells.map((s, i) => {\n const isSelected = s.id === value;\n const isActive = i === activeIndex;\n return (\n <li\n key={s.id}\n role=\"option\"\n aria-selected={isSelected}\n data-shell-id={s.id}\n onMouseEnter={() => setActiveIndex(i)}\n onClick={() => pick(i)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 8px\",\n fontSize: 12,\n borderRadius: 5,\n color: FG,\n cursor: \"pointer\",\n background: isActive ? HOVER_BG : \"transparent\",\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{\n width: 18,\n textAlign: \"center\",\n color: isSelected ? ACCENT : MUTED,\n }}\n >\n {s.icon ?? \"\"}\n </span>\n <span style={{ flex: 1 }}>{s.label}</span>\n {isSelected ? (\n <span aria-hidden=\"true\" style={{ color: ACCENT, fontSize: 11 }}>\n ✓\n </span>\n ) : null}\n </li>\n );\n })}\n </ul>\n ) : null}\n </div>\n );\n}\n","// menu-position.ts — clamp a fixed-position menu so it never spills off-screen.\n// Pure helper (unit-testable); the component measures its own rect and applies it.\n\nexport interface MenuPoint {\n x: number;\n y: number;\n}\nexport interface MenuSize {\n width: number;\n height: number;\n}\n\n/**\n * Clamp a menu's top-left so the whole menu stays inside the viewport (minus a\n * margin). Pushes left/up when it would overflow the right/bottom edge, and never\n * goes past the top-left margin. Pure.\n */\nexport function clampMenuPosition(\n at: MenuPoint,\n menu: MenuSize,\n viewport: MenuSize,\n margin = 8,\n): MenuPoint {\n const maxX = Math.max(margin, viewport.width - menu.width - margin);\n const maxY = Math.max(margin, viewport.height - menu.height - margin);\n return {\n x: Math.min(Math.max(margin, at.x), maxX),\n y: Math.min(Math.max(margin, at.y), maxY),\n };\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { clampMenuPosition } from \"../menu-position\";\nimport type {\n TerminalContextMenuContext,\n TerminalContextMenuItem,\n} from \"../context-menu\";\n\n/**\n * The terminal selection context menu. Deliberately plain React + inline styles\n * (fancy-term has no react-fancy dependency) styled to match the shell bar. It\n * closes on click-outside + Escape, and clamps itself inside the viewport on\n * mount so a right-click near an edge never spills off-screen.\n */\nexport function TerminalContextMenu({\n at,\n items,\n ctx,\n onClose,\n}: {\n at: { x: number; y: number };\n items: TerminalContextMenuItem[];\n ctx: TerminalContextMenuContext;\n onClose: () => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [pos, setPos] = useState(at);\n\n // Clamp once we can measure the rendered menu.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || typeof window === \"undefined\") return;\n const r = el.getBoundingClientRect();\n setPos(\n clampMenuPosition(\n at,\n { width: r.width, height: r.height },\n { width: window.innerWidth, height: window.innerHeight },\n ),\n );\n }, [at]);\n\n // Dismiss on click-outside + Escape (capture so it wins over the surface).\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"mousedown\", onDown, true);\n document.addEventListener(\"keydown\", onKey, true);\n return () => {\n document.removeEventListener(\"mousedown\", onDown, true);\n document.removeEventListener(\"keydown\", onKey, true);\n };\n }, [onClose]);\n\n return (\n <div\n ref={ref}\n data-fancy-terminal-menu=\"\"\n role=\"menu\"\n style={{\n position: \"fixed\",\n left: pos.x,\n top: pos.y,\n zIndex: 2147483000,\n minWidth: 176,\n padding: 4,\n background: \"#18181b\",\n border: \"1px solid #3f3f46\",\n borderRadius: 8,\n boxShadow: \"0 10px 32px -8px rgba(0,0,0,.6)\",\n color: \"#e4e4e7\",\n font: '13px/1.4 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n userSelect: \"none\",\n }}\n >\n {items.map((it) =>\n it.separator ? (\n <div\n key={it.id}\n role=\"separator\"\n style={{ height: 1, margin: \"4px 6px\", background: \"#3f3f46\" }}\n />\n ) : (\n <button\n key={it.id}\n type=\"button\"\n role=\"menuitem\"\n data-menu-item={it.id}\n disabled={it.disabled}\n onClick={() => {\n if (it.disabled) return;\n it.onSelect?.(ctx);\n onClose();\n }}\n onMouseEnter={(e) => {\n if (!it.disabled) e.currentTarget.style.background = \"#27272a\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 9,\n width: \"100%\",\n textAlign: \"left\",\n padding: \"6px 9px\",\n border: \"none\",\n borderRadius: 5,\n background: \"transparent\",\n color: it.disabled ? \"#52525b\" : \"inherit\",\n cursor: it.disabled ? \"default\" : \"pointer\",\n font: \"inherit\",\n }}\n >\n <span style={{ width: 16, textAlign: \"center\", opacity: 0.8 }}>\n {it.icon ?? \"\"}\n </span>\n <span style={{ flex: 1 }}>{it.label}</span>\n </button>\n ),\n )}\n </div>\n );\n}\n","/**\n * Decide what to push to the terminal when the controlled `output` changes.\n * Terminals are append-only streams, so the common case (output grew) writes\n * only the delta; a value that no longer extends what we've written means a\n * wholesale replace, so reset + rewrite. Returns null when nothing changed.\n */\nexport function diffOutput(\n written: string,\n next: string,\n): { reset: boolean; write: string } | null {\n if (next === written) return null;\n if (next.startsWith(written)) return { reset: false, write: next.slice(written.length) };\n return { reset: true, write: next };\n}\n","import { resolveShell, type ShellProfile } from \"./types\";\n\n/**\n * Pure decision for \"select shell `id`\": resolves the profile and reports whether\n * the selection actually changed. The single source of truth shared by\n * `<Terminal>`'s `setShell`, `<ShellSwitcher>`, and `useTerminalSession`, so the\n * interactive behavior is unit-testable without a DOM.\n *\n * Returns `null` when the id isn't in `shells` (a no-op — unknown shell).\n */\nexport function decideShellSelect(\n shells: ShellProfile[] | undefined,\n current: string | undefined,\n id: string,\n): { profile: ShellProfile; changed: boolean } | null {\n const profile = resolveShell(shells, id);\n if (!profile) return null;\n return { profile, changed: current !== id };\n}\n\n/**\n * Pure decision for a session shell switch. The session hook holds the buffer +\n * the transport, so it only needs to know: did the shell change? If so it must\n * reset the buffer (to `initial`) and reconnect the transport. Extracted so the\n * reset-and-reconnect contract is unit-testable without rendering the hook.\n */\nexport function decideShellSwitch(\n current: string | undefined,\n next: string | undefined,\n): { changed: boolean } {\n return { changed: current !== next };\n}\n","// context-menu.ts — the model for the customizable terminal selection menu.\n// Pure data + a resolver; the rendering lives in TerminalContextMenu.tsx.\n\n/** Context handed to the menu at right-click time + to custom item builders. */\nexport interface TerminalContextMenuContext {\n /** Whether there is a non-empty text selection. */\n hasSelection: boolean;\n /** The selected text (or \"\"). */\n selection: string;\n /** Whether the terminal is read-only (paste / clear are dropped by default). */\n readOnly: boolean;\n}\n\n/** A single menu entry. `onSelect` runs on click; set `separator` for a divider. */\nexport interface TerminalContextMenuItem {\n /** Stable id (used as the React key + a `data-menu-item` handle). */\n id: string;\n /** Visible label. Ignored for separators. */\n label?: string;\n /** Optional leading glyph / emoji / short string (JSON-friendly — no ReactNode). */\n icon?: string;\n /** Greyed-out + non-interactive. */\n disabled?: boolean;\n /** Render a divider instead of a clickable item. */\n separator?: boolean;\n /** Invoked on click with the menu context. */\n onSelect?: (ctx: TerminalContextMenuContext) => void;\n}\n\n/** The actions the built-in items dispatch to (wired by the component). */\nexport interface TerminalMenuActions {\n copy: () => void;\n paste: () => void;\n selectAll: () => void;\n clear: () => void;\n}\n\n/**\n * The `contextMenu` prop shape:\n * - `false` — disable the menu entirely.\n * - `true` / omitted — the default Copy / Paste / Select all / Clear menu.\n * - an array — replace the default items wholesale.\n * - a function — receives the context **and the default items** so you can\n * add/remove/reorder (e.g. append a \"Send to agent\" item).\n */\nexport type TerminalContextMenuConfig =\n | boolean\n | TerminalContextMenuItem[]\n | ((\n ctx: TerminalContextMenuContext,\n defaults: TerminalContextMenuItem[],\n ) => TerminalContextMenuItem[]);\n\n/** The built-in Copy / Paste / Select all / Clear items, contextual to selection + readOnly. */\nexport function defaultMenuItems(\n ctx: TerminalContextMenuContext,\n actions: TerminalMenuActions,\n): TerminalContextMenuItem[] {\n const items: TerminalContextMenuItem[] = [\n { id: \"copy\", label: \"Copy\", icon: \"⧉\", disabled: !ctx.hasSelection, onSelect: actions.copy },\n ];\n if (!ctx.readOnly) {\n items.push({ id: \"paste\", label: \"Paste\", icon: \"⎘\", onSelect: actions.paste });\n }\n items.push({ id: \"select-all\", label: \"Select all\", onSelect: actions.selectAll });\n if (!ctx.readOnly) {\n items.push({ id: \"sep-default\", separator: true });\n items.push({ id: \"clear\", label: \"Clear\", onSelect: actions.clear });\n }\n return items;\n}\n\n/**\n * Resolve the configured menu into the final item list, or `null` when disabled.\n * Empty results (e.g. a function that filtered everything out) also resolve to\n * `null` so the caller can skip opening an empty menu.\n */\nexport function resolveMenuItems(\n config: TerminalContextMenuConfig | undefined,\n ctx: TerminalContextMenuContext,\n actions: TerminalMenuActions,\n): TerminalContextMenuItem[] | null {\n if (config === false) return null;\n const defaults = defaultMenuItems(ctx, actions);\n const items =\n config === undefined || config === true\n ? defaults\n : Array.isArray(config)\n ? config\n : config(ctx, defaults);\n return items.length > 0 ? items : null;\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useTerminal } from \"../hooks/use-terminal\";\nimport { ShellSwitcher } from \"./ShellSwitcher\";\nimport { TerminalContextMenu } from \"./TerminalContextMenu\";\nimport { diffOutput } from \"../output-diff\";\nimport { decideShellSelect } from \"../shell-select\";\nimport { resolveMenuItems, type TerminalContextMenuContext, type TerminalContextMenuItem } from \"../context-menu\";\nimport type { TerminalHandle, TerminalProps } from \"../types\";\n\n/**\n * Human+ `<Terminal>` — a controlled, themeable xterm.js terminal.\n *\n * - **Authoring surface:** terse, controlled (`output` + `onData`), JSON-friendly\n * props (rows/cols, theme tokens, initial buffer), a stable `data-fancy-terminal`\n * handle, and a ref exposing {@link TerminalHandle} (write/clear/fit/getBuffer/…).\n * - **Inhabited surface:** the same handle is what an MCP bridge drives, so an\n * embedded agent reads the buffer + writes input without DOM-scraping.\n *\n * The parent must have a height — the terminal fits its container (like any xterm\n * surface); a 0-height parent collapses it.\n *\n * ```tsx\n * const [out, setOut] = useState(\"\");\n * <div style={{ height: 360 }}>\n * <Terminal output={out} onData={(d) => backend.send(d)} />\n * </div>\n * ```\n */\nexport const Terminal = forwardRef<TerminalHandle, TerminalProps>(function Terminal(\n {\n output,\n theme,\n rows,\n cols,\n fit = true,\n readOnly,\n cursorBlink,\n cursorStyle,\n fontFamily,\n fontSize,\n scrollback,\n initialOutput,\n onData,\n onResize,\n shells,\n activeShell,\n onShellChange,\n showShellBar = false,\n clipboard,\n osc52,\n copyPaste,\n onReady,\n onPaste,\n contextMenu,\n className,\n style,\n ...rest\n },\n ref,\n) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Selected shell: controlled by `activeShell` when provided, else internal.\n const isShellControlled = activeShell !== undefined;\n const [internalShell, setInternalShell] = useState<string | undefined>(undefined);\n const shellId = isShellControlled ? activeShell : internalShell;\n\n // Read shell state live so the stable handle's setShell/getShell never go stale.\n const shellStateRef = useRef({ shells, shellId, isShellControlled, onShellChange });\n shellStateRef.current = { shells, shellId, isShellControlled, onShellChange };\n\n const selectShell = useCallback((id: string) => {\n const s = shellStateRef.current;\n const decision = decideShellSelect(s.shells, s.shellId, id);\n if (!decision) return; // unknown id — no-op\n if (!s.isShellControlled) setInternalShell(id);\n s.onShellChange?.(id, decision.profile);\n }, []);\n\n const handle = useTerminal(containerRef, {\n theme,\n rows,\n cols,\n fit,\n readOnly,\n cursorBlink,\n cursorStyle,\n fontFamily,\n fontSize,\n scrollback,\n // `initialOutput` is for uncontrolled use; with a controlled `output` the\n // diffing effect below owns the buffer, so don't double-write.\n initialOutput: output === undefined ? initialOutput : undefined,\n onData,\n onResize,\n clipboard,\n osc52,\n copyPaste,\n onReady,\n onPaste,\n });\n\n // Delegate `xterm` / `ready` as live getters rather than spreading `handle`\n // (object spread would snapshot the getters — capturing xterm === null before\n // the container is measured, the exact race consumers hit). Methods are stable.\n useImperativeHandle(\n ref,\n (): TerminalHandle => ({\n get xterm() {\n return handle.xterm;\n },\n get ready() {\n return handle.ready;\n },\n write: handle.write,\n writeln: handle.writeln,\n clear: handle.clear,\n reset: handle.reset,\n fit: handle.fit,\n focus: handle.focus,\n getBuffer: handle.getBuffer,\n getSelection: handle.getSelection,\n copySelection: handle.copySelection,\n paste: handle.paste,\n selectAll: handle.selectAll,\n clearSelection: handle.clearSelection,\n setShell: selectShell,\n getShell: () => shellStateRef.current.shellId,\n }),\n [handle, selectShell],\n );\n\n // Controlled output: write only the appended delta; reset + rewrite if the\n // value diverges from what we've already written (a wholesale replace).\n const written = useRef(\"\");\n useEffect(() => {\n if (output === undefined) return;\n const change = diffOutput(written.current, output);\n if (!change) return;\n if (change.reset) handle.reset();\n handle.write(change.write);\n written.current = output;\n }, [output, handle]);\n\n // Right-click selection context menu (Copy / Paste / Select all / Clear by\n // default; customizable via the `contextMenu` prop).\n const [menu, setMenu] = useState<{\n at: { x: number; y: number };\n items: TerminalContextMenuItem[];\n ctx: TerminalContextMenuContext;\n } | null>(null);\n\n const openMenu = useCallback(\n (e: React.MouseEvent) => {\n if (contextMenu === false) return;\n e.preventDefault();\n const selection = handle.getSelection();\n const ctx: TerminalContextMenuContext = {\n hasSelection: selection.length > 0,\n selection,\n readOnly: !!readOnly,\n };\n const items = resolveMenuItems(contextMenu, ctx, {\n copy: () => void handle.copySelection(),\n paste: () => void handle.paste(),\n selectAll: () => handle.selectAll(),\n clear: () => handle.clear(),\n });\n if (items) setMenu({ at: { x: e.clientX, y: e.clientY }, items, ctx });\n },\n [contextMenu, handle, readOnly],\n );\n\n const menuNode = menu ? (\n <TerminalContextMenu at={menu.at} items={menu.items} ctx={menu.ctx} onClose={() => setMenu(null)} />\n ) : null;\n\n const surface = (\n <div\n ref={containerRef}\n data-fancy-terminal=\"\"\n onContextMenu={openMenu}\n data-readonly={readOnly ? \"\" : undefined}\n data-fancy-terminal-shell={shellId ?? undefined}\n // When the shell bar is shown the wrapper owns the box; the surface flexes.\n style={\n showShellBar && shells\n ? { width: \"100%\", flex: 1, minHeight: 0 }\n : { width: \"100%\", height: \"100%\", ...style }\n }\n {...(showShellBar && shells ? {} : rest)}\n />\n );\n\n if (!showShellBar || !shells) {\n return (\n <>\n {surface}\n {menuNode}\n </>\n );\n }\n\n return (\n <div\n data-fancy-terminal-shell={shellId ?? undefined}\n className={className}\n style={{ display: \"flex\", flexDirection: \"column\", width: \"100%\", height: \"100%\", ...style }}\n {...rest}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"4px 6px\",\n background: \"#09090b\",\n borderBottom: \"1px solid #27272a\",\n }}\n >\n <ShellSwitcher\n shells={shells}\n value={shellId}\n onChange={(id) => selectShell(id)}\n disabled={readOnly}\n />\n </div>\n {surface}\n {menuNode}\n </div>\n );\n});\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { decideShellSwitch } from \"../shell-select\";\n\n/**\n * A streamed terminal backend — a PTY, an SSH session, or a command runner.\n * `subscribe` pushes output chunks (wire it to an Echo channel or a fancy-query\n * `useFancyStream` feed); `send` forwards the user's keystrokes upstream.\n */\nexport interface TerminalSessionTransport {\n /** Forward user input / keystrokes to the backend. */\n send: (data: string) => void | Promise<void>;\n /** Subscribe to backend output chunks; return an unsubscribe function. */\n subscribe: (onChunk: (chunk: string) => void) => (() => void) | void;\n /**\n * Optional — called when the active shell changes (and once on mount if a\n * `shell` is provided). The host (re)connects its PTY/command backend to the\n * chosen shell here. Transports that don't care about shells can omit it; the\n * hook stays fully backward compatible.\n */\n connect?: (shell: string | undefined) => void | Promise<void>;\n}\n\nexport interface UseTerminalSessionOptions {\n transport: TerminalSessionTransport;\n /** Replayed history written before live output starts. */\n initial?: string;\n /** The active shell id. Changing it resets the buffer + calls `transport.connect`. */\n shell?: string;\n}\n\nexport interface TerminalSessionApi {\n /** Accumulated output — feed to `<Terminal output={output} />`. */\n output: string;\n /** Forward keystrokes upstream — wire to `<Terminal onData={sendData} />`. */\n sendData: (data: string) => void;\n /** Append a chunk locally (e.g. a client-side echo or banner). */\n append: (chunk: string) => void;\n /** Clear the local buffer. */\n clear: () => void;\n /** The active shell id (controlled by `options.shell` when provided). */\n shell: string | undefined;\n /**\n * Switch shells: resets the buffer (back to `initial`) and tells the transport\n * to reconnect via `transport.connect(id)`. In controlled mode (`options.shell`\n * set) this still fires `connect`; pass the new id down via `options.shell` to\n * reflect it. No-op when the id matches the current shell.\n */\n switchShell: (id: string | undefined) => void;\n}\n\n/**\n * Bind a `<Terminal>` to a streamed backend: accumulates incoming output into a\n * controlled buffer and forwards keystrokes upstream — the glue between the\n * display surface and a PTY/command channel.\n *\n * ```tsx\n * const session = useTerminalSession({\n * transport: {\n * send: (d) => echo.private(`pty.${id}`).whisper(\"stdin\", { d }),\n * subscribe: (onChunk) => {\n * const ch = echo.private(`pty.${id}`).listen(\".stdout\", (e) => onChunk(e.chunk));\n * return () => echo.leave(`pty.${id}`);\n * },\n * },\n * });\n * <Terminal output={session.output} onData={session.sendData} />\n * ```\n */\nexport function useTerminalSession(options: UseTerminalSessionOptions): TerminalSessionApi {\n const initial = options.initial ?? \"\";\n const [output, setOutput] = useState(initial);\n\n // In uncontrolled mode `switchShell` drives this; in controlled mode the\n // `options.shell` effect keeps it in sync.\n const [internalShell, setInternalShell] = useState<string | undefined>(options.shell);\n const shell = options.shell !== undefined ? options.shell : internalShell;\n\n const transportRef = useRef(options.transport);\n transportRef.current = options.transport;\n const initialRef = useRef(initial);\n initialRef.current = initial;\n\n useEffect(() => {\n const unsub = transportRef.current.subscribe((chunk) => setOutput((o) => o + chunk));\n return () => {\n if (typeof unsub === \"function\") unsub();\n };\n // subscribe once; the transport is read live via the ref.\n }, []);\n\n // Connect on mount + whenever the active shell changes. Resetting the buffer\n // is owned by switchShell (uncontrolled) / this effect (controlled).\n const connectedShell = useRef<string | undefined>(undefined);\n const mounted = useRef(false);\n useEffect(() => {\n // On mount: connect once (even if shell is undefined, for parity).\n if (!mounted.current) {\n mounted.current = true;\n connectedShell.current = shell;\n void transportRef.current.connect?.(shell);\n return;\n }\n if (!decideShellSwitch(connectedShell.current, shell).changed) return;\n connectedShell.current = shell;\n setOutput(initialRef.current); // reset the buffer for the new shell\n void transportRef.current.connect?.(shell);\n }, [shell]);\n\n const sendData = useCallback((data: string) => {\n void transportRef.current.send(data);\n }, []);\n\n const append = useCallback((chunk: string) => setOutput((o) => o + chunk), []);\n const clear = useCallback(() => setOutput(\"\"), []);\n\n const switchShell = useCallback((id: string | undefined) => {\n // Uncontrolled: flip internal state, the effect above does reset + connect.\n // Controlled (options.shell set): still drive a reset + connect now so the\n // host sees the switch immediately even before it echoes options.shell back.\n setInternalShell((cur) => (cur === id ? cur : id));\n if (!decideShellSwitch(connectedShell.current, id).changed) return;\n connectedShell.current = id;\n setOutput(initialRef.current);\n void transportRef.current.connect?.(id);\n }, []);\n\n return { output, sendData, append, clear, shell, switchShell };\n}\n","// copy-keybinding.ts — the pure \"should this key event copy the selection?\"\n// decision, kept separate (like shell-select.ts) so it's unit-testable without\n// a DOM or a live xterm.\n\n/** The subset of a KeyboardEvent the copy decision reads. */\nexport interface CopyKeyEvent {\n type: string;\n key: string;\n ctrlKey: boolean;\n shiftKey: boolean;\n metaKey: boolean;\n}\n\n/**\n * Whether a key event should copy the current selection to the clipboard.\n *\n * - **Ctrl+Shift+C** (Windows / Linux terminal convention) — always.\n * - **Cmd / Meta+C** (macOS) — only when there is a selection.\n * - **Plain Ctrl+C is never a copy** — it must stay SIGINT.\n *\n * Only fires on `keydown`. When this returns true the caller copies the\n * selection and consumes the event (returns `false` from xterm's\n * `attachCustomKeyEventHandler` so no control byte is sent).\n */\nexport function shouldCopyEvent(e: CopyKeyEvent, hasSelection: boolean): boolean {\n if (e.type !== \"keydown\") return false;\n if (e.key !== \"c\" && e.key !== \"C\") return false;\n // Ctrl+Shift+C — the terminal-safe copy chord (plain Ctrl+C stays SIGINT).\n if (e.ctrlKey && e.shiftKey && !e.metaKey) return true;\n // Cmd+C on macOS — only with a selection, so it never swallows an empty copy.\n if (e.metaKey && !e.ctrlKey && hasSelection) return true;\n return false;\n}\n"]}
1
+ {"version":3,"sources":["../src/theme.ts","../src/hooks/use-terminal-fit.ts","../src/clipboard.ts","../src/copy-paste-mode.ts","../src/osc52.ts","../src/hooks/use-terminal.ts","../src/types.ts","../src/components/ShellSwitcher.tsx","../src/menu-position.ts","../src/components/TerminalContextMenu.tsx","../src/output-diff.ts","../src/shell-select.ts","../src/context-menu.ts","../src/selection-snapshot.ts","../src/components/Terminal.tsx","../src/hooks/use-terminal-session.ts","../src/copy-keybinding.ts"],"names":["useRef","useEffect","XTerm","FitAddon","useState","useId","useCallback","jsxs","jsx","useLayoutEffect","forwardRef","Terminal","useImperativeHandle","Fragment"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { TerminalTheme } from \"./types\";\n\n/**\n * The default \"sexy\" Fancy dark terminal theme — a zinc surface, violet cursor,\n * and a balanced ANSI palette drawn from the react-fancy Tailwind v4 tokens.\n * Pass a `theme` prop / option to override.\n */\nexport const fancyDarkTheme: TerminalTheme = {\n background: \"#09090b\", // zinc-950\n foreground: \"#e4e4e7\", // zinc-200\n cursor: \"#8b5cf6\", // violet-500\n cursorAccent: \"#09090b\",\n selectionBackground: \"#3f3f46\", // zinc-700\n black: \"#18181b\",\n red: \"#f43f5e\",\n green: \"#10b981\",\n yellow: \"#f59e0b\",\n blue: \"#3b82f6\",\n magenta: \"#8b5cf6\",\n cyan: \"#22d3ee\",\n white: \"#e4e4e7\",\n brightBlack: \"#52525b\",\n brightRed: \"#fb7185\",\n brightGreen: \"#34d399\",\n brightYellow: \"#fbbf24\",\n brightBlue: \"#60a5fa\",\n brightMagenta: \"#a78bfa\",\n brightCyan: \"#67e8f9\",\n brightWhite: \"#fafafa\",\n};\n","import { useEffect, useRef, type RefObject } from \"react\";\n\n/**\n * Run `fit` whenever the container resizes — and once it first has a real,\n * non-zero box. Guards the hidden-tab / late-mount 0×0 case: fitting a collapsed\n * container yields garbage rows/cols (or throws), so we simply skip until there\n * is layout to measure.\n */\nexport function useTerminalFit(\n ref: RefObject<HTMLElement | null>,\n fit: () => void,\n enabled = true,\n): void {\n const fitRef = useRef(fit);\n fitRef.current = fit;\n\n useEffect(() => {\n if (!enabled) return;\n const el = ref.current;\n if (!el) return;\n\n const run = () => {\n if (el.clientWidth > 0 && el.clientHeight > 0) fitRef.current();\n };\n\n const observer = new ResizeObserver(run);\n observer.observe(el);\n run(); // initial — fires once the box has layout\n\n return () => observer.disconnect();\n }, [ref, enabled]);\n}\n","// clipboard.ts — small, dependency-free clipboard helpers shared by the headless\n// hook (copy/paste primitives + the paste interceptor) and the component. Kept\n// pure where possible so the extraction logic is unit-testable without a DOM.\n\n/** What a paste / drop carried: plain text plus any files (e.g. pasted images). */\nexport interface ClipboardPayload {\n /** Plain text from the clipboard (or pasted selection). May be \"\". */\n text: string;\n /** Files present on the clipboard / drop — typically pasted/dropped images. */\n files: File[];\n /** Convenience: the subset of `files` whose MIME type is `image/*`. */\n images: File[];\n}\n\n/** True when a file looks like an image (by MIME type). */\nexport function isImageFile(f: { type?: string }): boolean {\n return typeof f.type === \"string\" && f.type.startsWith(\"image/\");\n}\n\n/**\n * Pull text + files out of a ClipboardEvent / DragEvent `dataTransfer`. The\n * DataTransferItemList is checked first (pasted screenshots only appear there in\n * some browsers), then `.files` as a fallback. Pure + null-safe.\n */\nexport function readDataTransfer(dt: DataTransfer | null | undefined): ClipboardPayload {\n const files: File[] = [];\n let text = \"\";\n if (dt) {\n try {\n text = dt.getData(\"text/plain\") ?? \"\";\n } catch {\n /* getData can throw in restricted contexts */\n }\n const items = dt.items;\n if (items) {\n for (let i = 0; i < items.length; i++) {\n const it = items[i];\n if (it && it.kind === \"file\") {\n const f = it.getAsFile();\n if (f) files.push(f);\n }\n }\n }\n if (files.length === 0 && dt.files) {\n for (let i = 0; i < dt.files.length; i++) files.push(dt.files[i]);\n }\n }\n return { text, files, images: files.filter(isImageFile) };\n}\n\n/** Write text to the system clipboard. Resolves false when unavailable/denied. */\nexport async function writeClipboardText(text: string): Promise<boolean> {\n try {\n const nav = typeof navigator !== \"undefined\" ? navigator : undefined;\n if (nav?.clipboard?.writeText) {\n await nav.clipboard.writeText(text);\n return true;\n }\n } catch {\n /* fall through to the legacy path */\n }\n // Legacy fallback for insecure contexts / older browsers.\n try {\n if (typeof document === \"undefined\") return false;\n const ta = document.createElement(\"textarea\");\n ta.value = text;\n ta.style.position = \"fixed\";\n ta.style.left = \"-9999px\";\n ta.style.opacity = \"0\";\n document.body.appendChild(ta);\n ta.select();\n const ok = document.execCommand(\"copy\");\n document.body.removeChild(ta);\n return ok;\n } catch {\n return false;\n }\n}\n\n/** Read text from the system clipboard. Resolves \"\" when unavailable/denied. */\nexport async function readClipboardText(): Promise<string> {\n try {\n const nav = typeof navigator !== \"undefined\" ? navigator : undefined;\n if (nav?.clipboard?.readText) return await nav.clipboard.readText();\n } catch {\n /* permission denied / unavailable */\n }\n return \"\";\n}\n\n/**\n * A host-supplied clipboard. Every copy/paste path in fancy-term — the copy\n * chord, the context menu, OSC 52, `handle.copySelection` / `handle.paste` —\n * routes through this, so an Electron host (where `navigator.clipboard` silently\n * no-ops in a sandboxed renderer) can bridge to its main-process clipboard over\n * IPC. `writeText` may return anything (a `Promise<void>` from IPC is fine);\n * `readText` returns the clipboard text.\n */\nexport interface ClipboardProvider {\n writeText: (text: string) => void | Promise<unknown>;\n readText: () => string | Promise<string>;\n}\n\n/** The default provider — `navigator.clipboard` with the legacy `execCommand` fallback. */\nexport const navigatorClipboard: ClipboardProvider = {\n writeText: (text) => writeClipboardText(text),\n readText: () => readClipboardText(),\n};\n\n/** The `clipboard` prop: `false` disables clipboard wiring; a provider object injects a host clipboard; `true`/omitted uses {@link navigatorClipboard}. */\nexport type ClipboardOption = boolean | ClipboardProvider;\n\n/** Normalize the `clipboard` prop into `{ enabled, provider }`, read live per call. */\nexport function resolveClipboard(clipboard: ClipboardOption | undefined): {\n enabled: boolean;\n provider: ClipboardProvider;\n} {\n if (clipboard === false) return { enabled: false, provider: navigatorClipboard };\n if (clipboard && typeof clipboard === \"object\") return { enabled: true, provider: clipboard };\n return { enabled: true, provider: navigatorClipboard };\n}\n\n/** Write via a provider, resolving `true` on success and `false` if it throws/rejects. */\nexport async function providerWrite(provider: ClipboardProvider, text: string): Promise<boolean> {\n try {\n await provider.writeText(text);\n return true;\n } catch {\n return false;\n }\n}\n\n/** Read via a provider, resolving `\"\"` if it throws/rejects. */\nexport async function providerRead(provider: ClipboardProvider): Promise<string> {\n try {\n return (await provider.readText()) ?? \"\";\n } catch {\n return \"\";\n }\n}\n","// copy-paste-mode.ts — the pure decision layer for the `copyPaste` prop. Kept\n// DOM-free (like copy-keybinding.ts / shell-select.ts) so the behavior is\n// unit-testable without a live xterm. use-terminal.ts wires the resulting\n// behavior to real events.\n\n/**\n * The copy/paste convention the terminal follows:\n * - `contextmenu` — copy/paste via the right-click menu only (plus the always-on\n * Ctrl+Shift+C copy chord).\n * - `linux` — highlight-to-copy (X11 primary-selection style) + middle-click\n * paste. Right-click still opens the context menu.\n * - `winmac` — Ctrl/Cmd+C copies the selection (falling back to SIGINT when\n * nothing is selected), Ctrl/Cmd+V pastes.\n *\n * Omitting the prop keeps the historical default: the Ctrl+Shift+C chord and\n * Cmd+C-with-selection, no auto-copy, no mouse paste.\n */\nexport type CopyPasteMode = \"contextmenu\" | \"linux\" | \"winmac\";\n\n/** The resolved, event-agnostic behavior flags a {@link CopyPasteMode} implies. */\nexport interface CopyPasteBehavior {\n /** Auto-copy the selection to the clipboard as soon as it changes (linux). */\n selectToCopy: boolean;\n /** Paste on middle-mouse-button (linux). */\n middleClickPaste: boolean;\n /** (Ctrl|Cmd)+C copies the selection when one exists (winmac). */\n keyCopy: boolean;\n /** (Ctrl|Cmd)+V — and Ctrl+Shift+V — paste (winmac). */\n keyPaste: boolean;\n}\n\nexport function copyPasteBehavior(mode: CopyPasteMode | undefined): CopyPasteBehavior {\n switch (mode) {\n case \"linux\":\n return { selectToCopy: true, middleClickPaste: true, keyCopy: false, keyPaste: false };\n case \"winmac\":\n return { selectToCopy: false, middleClickPaste: false, keyCopy: true, keyPaste: true };\n case \"contextmenu\":\n default:\n return { selectToCopy: false, middleClickPaste: false, keyCopy: false, keyPaste: false };\n }\n}\n\n/** The subset of a KeyboardEvent the copy/paste decision reads. */\nexport interface KeyEventLike {\n type: string;\n key: string;\n ctrlKey: boolean;\n shiftKey: boolean;\n metaKey: boolean;\n}\n\n/**\n * Resolve a key event to a clipboard action, given the current selection state\n * and the active behavior. Returns `\"copy\"`, `\"paste\"`, or `null` (do nothing —\n * let the byte reach the shell). Only fires on `keydown`.\n *\n * Copy is honored across every mode for the terminal-safe **Ctrl+Shift+C** chord\n * and macOS **Cmd+C-with-selection**; `keyCopy` adds plain (Ctrl|Cmd)+C. Plain\n * Ctrl+C with no selection is never a copy — it stays SIGINT.\n */\nexport function resolveKeyAction(\n e: KeyEventLike,\n hasSelection: boolean,\n behavior: CopyPasteBehavior,\n): \"copy\" | \"paste\" | null {\n if (e.type !== \"keydown\") return null;\n const key = e.key.toLowerCase();\n\n if (key === \"c\") {\n if (e.ctrlKey && e.shiftKey && !e.metaKey) return \"copy\"; // Ctrl+Shift+C — always\n if (e.metaKey && !e.ctrlKey && hasSelection) return \"copy\"; // Cmd+C w/ selection — always (macOS)\n if (behavior.keyCopy && (e.ctrlKey || e.metaKey) && !e.shiftKey && hasSelection) return \"copy\";\n return null;\n }\n\n if (key === \"v\" && behavior.keyPaste) {\n if ((e.ctrlKey || e.metaKey) && !e.shiftKey) return \"paste\"; // Ctrl/Cmd+V\n if (e.ctrlKey && e.shiftKey) return \"paste\"; // Ctrl+Shift+V (terminal-safe paste)\n return null;\n }\n\n return null;\n}\n","// osc52.ts — OSC 52 clipboard handling. Modern TUIs (Claude Code, tmux, vim /\n// neovim) copy their own selection with `ESC ] 52 ; <Pc> ; <Pd> BEL`. xterm.js\n// drops OSC 52 by default, so a program shows \"copied\" but nothing reaches the\n// system clipboard — a silent, confusing failure. We parse the sequence and\n// route it through the injectable clipboard provider.\n//\n// The parse + base64 codec are pure so they're unit-testable without a live\n// xterm; registerOsc52 wires them to an xterm instance.\n\nimport type { Terminal as XTerm } from \"@xterm/xterm\";\nimport type { IDisposable } from \"@xterm/xterm\";\nimport type { ClipboardProvider } from \"./clipboard\";\nimport { providerRead } from \"./clipboard\";\n\n/**\n * OSC 52 policy: `copy` allows programs to WRITE the clipboard (the common TUI\n * case), `read` allows a program to READ it back (a `?` request), `both` allows\n * either, `false` disables OSC 52 entirely. Read is the real exfiltration risk\n * (arbitrary terminal output could siphon your clipboard), so it must be opted\n * into explicitly.\n */\nexport type Osc52Mode = \"copy\" | \"read\" | \"both\" | false;\n\n/** A parsed OSC 52 request: which selection buffer, and write-a-payload vs read-request. */\nexport interface Osc52Request {\n /** The `Pc` field — clipboard selection(s), e.g. `\"c\"` (clipboard), `\"p\"` (primary). */\n selection: string;\n kind: \"write\" | \"read\";\n /** Decoded text for a write; `\"\"` for a read request. */\n data: string;\n}\n\n/** UTF-8-safe base64 encode (browser `btoa` operates on binary strings). */\nexport function encodeBase64(text: string): string {\n const bytes = new TextEncoder().encode(text);\n let binary = \"\";\n for (let i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);\n return typeof btoa === \"function\" ? btoa(binary) : binary;\n}\n\n/** UTF-8-safe base64 decode; returns `\"\"` on malformed input. */\nexport function decodeBase64(b64: string): string {\n try {\n const binary = typeof atob === \"function\" ? atob(b64) : b64;\n const bytes = new Uint8Array(binary.length);\n for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n } catch {\n return \"\";\n }\n}\n\n/**\n * Parse an OSC 52 payload (the part after `ESC ] 52 ;`, i.e. `<Pc> ; <Pd>`).\n * `Pd === \"?\"` is a read request; otherwise `Pd` is base64 to write. Returns\n * `null` for a malformed payload (no `;`).\n */\nexport function parseOsc52(payload: string): Osc52Request | null {\n const semi = payload.indexOf(\";\");\n if (semi < 0) return null;\n const selection = payload.slice(0, semi);\n const pd = payload.slice(semi + 1);\n if (pd === \"?\") return { selection, kind: \"read\", data: \"\" };\n return { selection, kind: \"write\", data: decodeBase64(pd) };\n}\n\n/** Build the OSC 52 response a `read` request expects: `ESC ] 52 ; <Pc> ; <base64> BEL`. */\nexport function osc52Response(selection: string, text: string): string {\n return `\\x1b]52;${selection};${encodeBase64(text)}\\x07`;\n}\n\n/**\n * Register an OSC 52 handler on an xterm instance, routing writes/reads through\n * `provider` per `mode`. Returns the {@link IDisposable} (or `null` when\n * `mode === false`). The handler always returns `true` (consumed) so a\n * disallowed direction is swallowed rather than echoed as garbage.\n */\nexport function registerOsc52(\n term: XTerm,\n provider: () => ClipboardProvider,\n mode: () => Osc52Mode,\n): IDisposable | null {\n if (mode() === false) return null;\n\n return term.parser.registerOscHandler(52, (payload) => {\n const m = mode();\n if (m === false) return true;\n const req = parseOsc52(payload);\n if (!req) return false; // not ours / malformed — let xterm handle it\n\n if (req.kind === \"write\") {\n if (m === \"copy\" || m === \"both\") {\n void Promise.resolve(provider().writeText(req.data)).catch(() => {});\n }\n return true;\n }\n\n // read request (`?`)\n if (m === \"read\" || m === \"both\") {\n void providerRead(provider()).then((text) => {\n term.write(osc52Response(req.selection, text));\n });\n }\n return true;\n });\n}\n","import { useEffect, useRef, type RefObject } from \"react\";\nimport { Terminal as XTerm } from \"@xterm/xterm\";\nimport { FitAddon } from \"@xterm/addon-fit\";\nimport { fancyDarkTheme } from \"../theme\";\nimport { useTerminalFit } from \"./use-terminal-fit\";\nimport { providerRead, providerWrite, readDataTransfer, resolveClipboard } from \"../clipboard\";\nimport { copyPasteBehavior, resolveKeyAction } from \"../copy-paste-mode\";\nimport { registerOsc52 } from \"../osc52\";\nimport type { TerminalHandle, TerminalOptions } from \"../types\";\n\nconst DEFAULT_FONT =\n 'ui-monospace, SFMono-Regular, \"SF Mono\", Menlo, Consolas, \"Liberation Mono\", monospace';\n\n/** A minimal externally-resolvable promise (Promise.withResolvers isn't universally available). */\nfunction makeDeferred<T>(): { promise: Promise<T>; resolve: (value: T) => void } {\n let resolve!: (value: T) => void;\n const promise = new Promise<T>((r) => {\n resolve = r;\n });\n return { promise, resolve };\n}\n\n/** Read the whole xterm buffer as plain text — what an agent \"sees\". */\nfunction readBuffer(term: XTerm | null): string {\n if (!term) return \"\";\n const buf = term.buffer.active;\n const lines: string[] = [];\n for (let i = 0; i < buf.length; i++) {\n const line = buf.getLine(i);\n if (line) lines.push(line.translateToString(true));\n }\n return lines.join(\"\\n\").replace(/\\n+$/, \"\");\n}\n\n/**\n * Create + own an xterm.js instance for a container, returning a stable\n * {@link TerminalHandle}. The headless engine layer behind `<Terminal>` — use it\n * directly when you want the terminal without the component shell (custom chrome,\n * an agent bridge host, tests). Options are read live, so changing them re-applies\n * without tearing down the terminal.\n */\nexport function useTerminal(\n containerRef: RefObject<HTMLElement | null>,\n options: TerminalOptions = {},\n): TerminalHandle {\n const xtermRef = useRef<XTerm | null>(null);\n const fitRef = useRef<FitAddon | null>(null);\n const optsRef = useRef(options);\n optsRef.current = options;\n\n // A re-armable \"xterm is open\" promise backing handle.ready.\n const readyRef = useRef(makeDeferred<XTerm>());\n\n // Stable handle — its methods always operate on the live xterm via the ref.\n const handleRef = useRef<TerminalHandle | null>(null);\n if (handleRef.current === null) {\n handleRef.current = {\n get xterm() {\n return xtermRef.current;\n },\n get ready() {\n return readyRef.current.promise;\n },\n write: (d) => xtermRef.current?.write(d),\n writeln: (d) => xtermRef.current?.writeln(d),\n clear: () => xtermRef.current?.clear(),\n reset: () => xtermRef.current?.reset(),\n fit: () => {\n const addon = fitRef.current;\n if (!addon) return;\n try {\n // Guard against an unmeasurable container / not-yet-rendered viewport:\n // proposeDimensions() returns undefined (or NaN) then, and fit() would\n // call xterm's resize(undefined,…), which console-errors \"cols must be\n // numeric\". Skip — the ResizeObserver fires again once it's measurable.\n // This matters most under `showShellBar`, whose extra layout pass races\n // the first fit.\n const dims = addon.proposeDimensions();\n if (\n !dims ||\n !Number.isFinite(dims.cols) ||\n !Number.isFinite(dims.rows) ||\n dims.cols < 1 ||\n dims.rows < 1\n ) {\n return;\n }\n addon.fit();\n } catch {\n /* container not measurable yet — ignore */\n }\n },\n focus: () => xtermRef.current?.focus(),\n getBuffer: () => readBuffer(xtermRef.current),\n getSelection: () => xtermRef.current?.getSelection() ?? \"\",\n copySelection: async () => {\n const sel = xtermRef.current?.getSelection() ?? \"\";\n if (!sel) return false;\n return providerWrite(resolveClipboard(optsRef.current.clipboard).provider, sel);\n },\n paste: async (text) => {\n const data = text ?? (await providerRead(resolveClipboard(optsRef.current.clipboard).provider));\n if (data) xtermRef.current?.paste(data);\n },\n selectAll: () => xtermRef.current?.selectAll(),\n clearSelection: () => xtermRef.current?.clearSelection(),\n // Shell selection is owned by the <Terminal> component layer (it needs the\n // `shells` list + onShellChange). The headless engine is shell-agnostic, so\n // these are no-ops here and get overridden when <Terminal> composes them.\n setShell: () => {},\n getShell: () => undefined,\n };\n }\n const handle = handleRef.current;\n\n // Create the engine once for the container.\n useEffect(() => {\n const el = containerRef.current;\n if (!el) return;\n const o = optsRef.current;\n\n const term = new XTerm({\n theme: o.theme ?? fancyDarkTheme,\n // Only pass rows/cols when explicitly set. xterm validates these and\n // console-errors \"rows/cols must be numeric\" if handed `undefined`, rather\n // than falling back to its 80×24 default. Omit the keys instead.\n ...(typeof o.rows === \"number\" ? { rows: o.rows } : {}),\n ...(typeof o.cols === \"number\" ? { cols: o.cols } : {}),\n disableStdin: o.readOnly ?? false,\n cursorBlink: o.cursorBlink ?? true,\n cursorStyle: o.cursorStyle ?? \"block\",\n fontFamily: o.fontFamily ?? DEFAULT_FONT,\n fontSize: o.fontSize ?? 13,\n scrollback: o.scrollback ?? 1000,\n allowProposedApi: true,\n });\n const fitAddon = new FitAddon();\n term.loadAddon(fitAddon);\n term.open(el);\n xtermRef.current = term;\n fitRef.current = fitAddon;\n\n const dataSub = term.onData((d) => optsRef.current.onData?.(d));\n const resizeSub = term.onResize(({ cols, rows }) =>\n optsRef.current.onResize?.({ cols, rows }),\n );\n\n // Paste the system clipboard into the terminal (honors readOnly + bracketed\n // paste). Shared by the paste key chord and middle-click paste.\n const pasteFromClipboard = async () => {\n const oo = optsRef.current;\n if (oo.readOnly) return;\n const text = await providerRead(resolveClipboard(oo.clipboard).provider);\n if (text) xtermRef.current?.paste(text);\n };\n\n // ── Clipboard wiring (gated by `clipboard !== false`, read live) ──────────\n // Copy/paste key chords resolved by the active `copyPaste` mode: Ctrl+Shift+C\n // always copies; plain Ctrl+C stays SIGINT unless winmac + selection; winmac\n // also binds Ctrl/Cmd+V paste. Returning false consumes the event.\n term.attachCustomKeyEventHandler((e) => {\n const oo = optsRef.current;\n const clip = resolveClipboard(oo.clipboard);\n if (!clip.enabled) return true;\n const action = resolveKeyAction(e, term.hasSelection(), copyPasteBehavior(oo.copyPaste));\n if (action === \"copy\") {\n void providerWrite(clip.provider, term.getSelection());\n return false;\n }\n if (action === \"paste\") {\n void pasteFromClipboard();\n return false;\n }\n return true;\n });\n\n // OSC 52 — terminal programs (Claude Code, tmux, vim) copy/read the clipboard\n // via `ESC ] 52`. Routed through the live provider; off when clipboard === false.\n const oscDisposable = registerOsc52(\n term,\n () => resolveClipboard(optsRef.current.clipboard).provider,\n () => {\n const oo = optsRef.current;\n return resolveClipboard(oo.clipboard).enabled ? (oo.osc52 ?? \"copy\") : false;\n },\n );\n\n // linux mode: auto-copy the selection as it changes (X11 primary-selection).\n const selectionSub = term.onSelectionChange(() => {\n const oo = optsRef.current;\n const clip = resolveClipboard(oo.clipboard);\n if (clip.enabled && copyPasteBehavior(oo.copyPaste).selectToCopy && term.hasSelection()) {\n void providerWrite(clip.provider, term.getSelection());\n }\n });\n\n // linux mode: middle-click pastes.\n const onMouseDown = (ev: MouseEvent) => {\n const oo = optsRef.current;\n if (ev.button !== 1) return;\n if (!resolveClipboard(oo.clipboard).enabled) return;\n if (!copyPasteBehavior(oo.copyPaste).middleClickPaste) return;\n ev.preventDefault();\n void pasteFromClipboard();\n };\n el.addEventListener(\"mousedown\", onMouseDown);\n\n // Paste: a capture-phase listener on the container runs before xterm's own\n // textarea handler. We do NOT preventDefault for text, so xterm pastes it\n // exactly once natively — we only surface the payload (esp. pasted images)\n // via onPaste. The host returning false (or a read-only terminal) suppresses\n // the native text paste.\n const onPasteEvent = (e: ClipboardEvent) => {\n const o2 = optsRef.current;\n if (resolveClipboard(o2.clipboard).enabled === false) return;\n if (o2.readOnly) {\n e.preventDefault();\n return;\n }\n const payload = readDataTransfer(e.clipboardData);\n if (o2.onPaste?.(payload) === false) e.preventDefault();\n };\n el.addEventListener(\"paste\", onPasteEvent, true);\n\n if (o.initialOutput) term.write(o.initialOutput);\n // Route through the guarded handle.fit() (proposeDimensions check) so a\n // not-yet-laid-out container never triggers an xterm resize(undefined).\n if (o.fit ?? true) handle.fit();\n\n // The terminal is open + attached — signal readiness so consumers wiring\n // addons don't have to poll handle.xterm.\n optsRef.current.onReady?.(term);\n readyRef.current.resolve(term);\n\n return () => {\n el.removeEventListener(\"paste\", onPasteEvent, true);\n el.removeEventListener(\"mousedown\", onMouseDown);\n oscDisposable?.dispose();\n selectionSub.dispose();\n dataSub.dispose();\n resizeSub.dispose();\n term.dispose();\n xtermRef.current = null;\n fitRef.current = null;\n // Re-arm readiness for a potential remount (container change).\n readyRef.current = makeDeferred<XTerm>();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [containerRef]);\n\n // Re-apply reactive options without tearing the terminal down.\n useEffect(() => {\n const t = xtermRef.current;\n if (!t) return;\n if (options.theme) t.options.theme = options.theme;\n if (options.readOnly !== undefined) t.options.disableStdin = options.readOnly;\n if (options.cursorBlink !== undefined) t.options.cursorBlink = options.cursorBlink;\n if (options.cursorStyle) t.options.cursorStyle = options.cursorStyle;\n if (options.fontSize) t.options.fontSize = options.fontSize;\n if (options.fontFamily) t.options.fontFamily = options.fontFamily;\n }, [options.theme, options.readOnly, options.cursorBlink, options.cursorStyle, options.fontSize, options.fontFamily]);\n\n // Auto-fit on container resize (0×0-guarded).\n useTerminalFit(containerRef, () => handle.fit(), options.fit ?? true);\n\n return handle;\n}\n","import type { HTMLAttributes } from \"react\";\nimport type { ITheme, Terminal as XTerm } from \"@xterm/xterm\";\nimport type { ClipboardOption, ClipboardPayload } from \"./clipboard\";\nimport type { CopyPasteMode } from \"./copy-paste-mode\";\nimport type { Osc52Mode } from \"./osc52\";\nimport type { TerminalContextMenuConfig } from \"./context-menu\";\n\n/** xterm.js color theme (re-exported for ergonomic typing). */\nexport type TerminalTheme = ITheme;\n\nexport type CursorStyle = \"block\" | \"underline\" | \"bar\";\n\n/**\n * A selectable shell / profile. Fully JSON-friendly (primitives only) so an agent\n * can emit it. fancy-term owns the *selected-shell state + UI + events*; the\n * `command` / `args` / `cwd` fields are **host hints** — fancy-term never spawns a\n * shell, the host reconnects its PTY/command backend to the chosen profile.\n */\nexport interface ShellProfile {\n /** Stable key, e.g. `\"powershell\"`. */\n id: string;\n /** Display label, e.g. `\"PowerShell\"`. */\n label: string;\n /** Optional short glyph / emoji / single char (kept JSON-friendly — no ReactNode). */\n icon?: string;\n /** Host hint — the executable, e.g. `\"pwsh\"` / `\"cmd.exe\"`. */\n command?: string;\n /** Host hint — launch args. */\n args?: string[];\n /** Host hint — working directory. */\n cwd?: string;\n}\n\n/**\n * Imperative handle exposed via the `<Terminal>` ref and returned by\n * {@link useTerminal}. The same surface an MCP bridge drives so an embedded\n * agent reads the buffer + writes input without DOM-scraping.\n */\nexport interface TerminalHandle {\n /** The underlying xterm.js instance — escape hatch for addons / advanced use. Null before mount. */\n readonly xterm: XTerm | null;\n /**\n * Resolves with the xterm instance once it's opened + measured. Because\n * `xterm` is null until the container lays out, a consumer that must wire an\n * addon can `await handle.ready` instead of polling. Re-armed if the terminal\n * is torn down + recreated (e.g. a container change).\n */\n readonly ready: Promise<XTerm>;\n /** Write raw data (ANSI escape sequences honored) to the terminal. */\n write: (data: string) => void;\n /** Write data followed by CRLF. */\n writeln: (data: string) => void;\n /** Clear the viewport (keeps scrollback). */\n clear: () => void;\n /** Full reset — clears scrollback + terminal state. */\n reset: () => void;\n /** Re-fit to the container (no-op when the box is 0-size or fit is off). */\n fit: () => void;\n /** Focus the terminal input. */\n focus: () => void;\n /** The full buffer as plain text — what an agent \"sees\". */\n getBuffer: () => string;\n /** The current text selection, or \"\" when nothing is selected. */\n getSelection: () => string;\n /** Copy the current selection to the system clipboard. Resolves false when there's nothing selected or the clipboard is unavailable. */\n copySelection: () => Promise<boolean>;\n /** Paste text into the terminal. With no argument, reads the system clipboard. Honors xterm's bracketed-paste mode. */\n paste: (text?: string) => Promise<void>;\n /** Select the entire buffer. */\n selectAll: () => void;\n /** Clear the current selection. */\n clearSelection: () => void;\n /**\n * Switch the active shell by id. Resolves the matching {@link ShellProfile}\n * from `shells` and fires `onShellChange`; in uncontrolled mode it also updates\n * the internal selection. No-op when the id isn't in `shells`.\n */\n setShell: (id: string) => void;\n /** The active shell id, or `undefined` when no shell is selected. */\n getShell: () => string | undefined;\n}\n\n/** Engine options shared by `<Terminal>` and {@link useTerminal}. */\nexport interface TerminalOptions {\n /** xterm color theme. Omit for the built-in Fancy dark theme. */\n theme?: TerminalTheme;\n /** Fixed grid size. Omit + leave `fit` on to size from the container. */\n rows?: number;\n cols?: number;\n /** Auto-fit to the container via the fit addon + ResizeObserver. Default true. */\n fit?: boolean;\n /** Block stdin (display-only terminal). Default false. */\n readOnly?: boolean;\n /** Blink the cursor. Default true. */\n cursorBlink?: boolean;\n /** Cursor shape. Default \"block\". */\n cursorStyle?: CursorStyle;\n /** Monospace font stack. */\n fontFamily?: string;\n /** Font size in px. Default 13. */\n fontSize?: number;\n /** Scrollback lines. Default 1000. */\n scrollback?: number;\n /** Data written once on mount, before any controlled `output`. */\n initialOutput?: string;\n /** User keystrokes / paste data (xterm `onData`). Wire to your PTY/command backend. */\n onData?: (data: string) => void;\n /** Notified on terminal resize. */\n onResize?: (size: { cols: number; rows: number }) => void;\n /**\n * Clipboard wiring — gates the Ctrl+Shift+C / Cmd+C copy chord, the paste\n * interceptor ({@link onPaste}), the context-menu copy/paste, and OSC 52.\n *\n * - `true` / omitted — enabled, backed by `navigator.clipboard`.\n * - `false` — disabled (no copy chord / OSC 52; native text paste still works).\n * - a `{ writeText, readText }` **provider** — every copy/paste path routes\n * through it. Supply this in a sandboxed Electron renderer, where\n * `navigator.clipboard` silently no-ops, to bridge to the main-process\n * clipboard over IPC.\n */\n clipboard?: ClipboardOption;\n /**\n * OSC 52 clipboard policy — lets terminal programs (Claude Code, tmux, vim)\n * set/read the system clipboard via `ESC ] 52`. `\"copy\"` (default) allows\n * writes only; `\"read\"` / `\"both\"` also answer read requests (an exfiltration\n * risk — opt in deliberately); `false` disables it. Routed through the same\n * clipboard provider as {@link clipboard}; a no-op when clipboard is `false`.\n * Default `\"copy\"`.\n */\n osc52?: Osc52Mode;\n /**\n * Copy/paste UX convention: `\"contextmenu\"` (menu + Ctrl+Shift+C),\n * `\"linux\"` (highlight-to-copy + middle-click paste), or `\"winmac\"`\n * (Ctrl/Cmd+C copies the selection, Ctrl/Cmd+V pastes). Omit for the historical\n * default (Ctrl+Shift+C + Cmd+C-with-selection). Ctrl+Shift+C always copies.\n */\n copyPaste?: CopyPasteMode;\n /**\n * Called once the xterm instance is opened + attached — the imperative twin of\n * {@link TerminalHandle.ready}. Use it to load an addon without racing the\n * container layout (where `handle.xterm` is still null).\n */\n onReady?: (xterm: XTerm) => void;\n /**\n * Fired on every paste with the clipboard payload — `{ text, files, images }`.\n * Plain text still pastes into the terminal natively; this is where a host\n * receives pasted **images** (a shell can't render them) to upload / hand to an\n * agent / write a path. Return `false` to fully consume the paste (suppress the\n * default text paste — e.g. to transform it, then call `handle.paste(...)`).\n */\n onPaste?: (payload: ClipboardPayload) => void | boolean;\n}\n\nexport interface TerminalProps extends TerminalOptions, Omit<HTMLAttributes<HTMLDivElement>, \"onInput\" | \"onResize\" | \"onPaste\" | \"contextMenu\" | \"children\"> {\n /**\n * The controlled output buffer. The component diffs against the previous value\n * and writes only the appended delta, so a host can drive the terminal from\n * React state — e.g. streaming command output via fancy-query's\n * `useFancyStream`. Replacing it with a non-extending string resets + rewrites.\n */\n output?: string;\n\n /**\n * The shells / profiles a host offers. fancy-term renders the selector and\n * tracks the choice; the host reacts (reconnects its PTY to the chosen shell).\n * Spread {@link BUILTIN_SHELLS} for sensible presets, but the host owns the list.\n */\n shells?: ShellProfile[];\n /** Controlled active-shell id. Omit for uncontrolled (internal) selection. */\n activeShell?: string;\n /** Fired when the user (or `setShell`) switches shells. */\n onShellChange?: (id: string, profile: ShellProfile) => void;\n /**\n * Render the built-in `<ShellSwitcher>` toolbar above the xterm surface when\n * `shells` is provided. Default `false` — opt-in so existing layout is unchanged.\n */\n showShellBar?: boolean;\n\n /**\n * The right-click selection context menu. `false` disables it; `true` / omitted\n * gives the default Copy / Paste / Select all / Clear menu; an array replaces\n * the items; a `(ctx, defaults) => items` function lets you add/remove/reorder\n * (e.g. append a \"Send to agent\" item). See {@link TerminalContextMenuConfig}.\n */\n contextMenu?: TerminalContextMenuConfig;\n}\n\n/**\n * Resolve a shell id to its {@link ShellProfile} within a list. Pure helper —\n * the single place `setShell` / `<ShellSwitcher>` / the session hook agree on\n * what \"switch to id X\" means.\n */\nexport function resolveShell(\n shells: ShellProfile[] | undefined,\n id: string | undefined,\n): ShellProfile | undefined {\n if (!shells || id === undefined) return undefined;\n return shells.find((s) => s.id === id);\n}\n\n/**\n * A small set of sensible built-in shell presets a host can spread / filter.\n * `command` / `args` are host hints only — fancy-term never spawns them.\n */\nexport const BUILTIN_SHELLS: readonly ShellProfile[] = [\n { id: \"cmd\", label: \"Command Prompt\", icon: \">_\", command: \"cmd.exe\" },\n { id: \"powershell\", label: \"Windows PowerShell\", icon: \"PS\", command: \"powershell.exe\" },\n { id: \"pwsh\", label: \"PowerShell\", icon: \"PS\", command: \"pwsh\" },\n {\n id: \"git-bash\",\n label: \"Git Bash\",\n icon: \"\",\n command: \"C:\\\\Program Files\\\\Git\\\\bin\\\\bash.exe\",\n args: [\"--login\", \"-i\"],\n },\n { id: \"bash\", label: \"Bash\", icon: \"$\", command: \"bash\" },\n { id: \"zsh\", label: \"Zsh\", icon: \"%\", command: \"zsh\" },\n] as const;\n","import {\n useCallback,\n useEffect,\n useId,\n useRef,\n useState,\n type CSSProperties,\n type KeyboardEvent,\n} from \"react\";\nimport { resolveShell, type ShellProfile } from \"../types\";\n\nexport interface ShellSwitcherProps {\n /** The available shells / profiles. */\n shells: ShellProfile[];\n /** Controlled selected shell id. */\n value?: string;\n /** Fired when a shell is picked. */\n onChange: (id: string, profile: ShellProfile) => void;\n className?: string;\n style?: CSSProperties;\n /** Disable the control. */\n disabled?: boolean;\n}\n\nconst PANEL_BG = \"#18181b\"; // zinc-900\nconst BORDER = \"#3f3f46\"; // zinc-700\nconst FG = \"#e4e4e7\"; // zinc-200\nconst MUTED = \"#a1a1aa\"; // zinc-400\nconst ACCENT = \"#8b5cf6\"; // violet-500\nconst HOVER_BG = \"#27272a\"; // zinc-800\n\n/**\n * Compact, accessible shell picker styled to the Fancy dark theme. Self-contained\n * (zero third-party deps) — a button that toggles a listbox of `shells`.\n *\n * Stable handles for agents: the root carries `data-fancy-shell-switcher` and each\n * option carries `data-shell-id`, so a bridge can pick a shell without DOM-guessing.\n *\n * Controlled: pass `value` + `onChange`. Keyboard accessible (Arrow / Enter / Esc).\n */\nexport function ShellSwitcher({\n shells,\n value,\n onChange,\n className,\n style,\n disabled,\n}: ShellSwitcherProps) {\n const [open, setOpen] = useState(false);\n const [activeIndex, setActiveIndex] = useState(0);\n const rootRef = useRef<HTMLDivElement>(null);\n const listId = useId();\n\n const selected = resolveShell(shells, value);\n const selectedIndex = selected ? shells.indexOf(selected) : -1;\n\n // Close on outside click.\n useEffect(() => {\n if (!open) return;\n const onDocClick = (e: MouseEvent) => {\n if (rootRef.current && !rootRef.current.contains(e.target as Node)) setOpen(false);\n };\n document.addEventListener(\"mousedown\", onDocClick);\n return () => document.removeEventListener(\"mousedown\", onDocClick);\n }, [open]);\n\n const openMenu = useCallback(() => {\n if (disabled) return;\n setActiveIndex(selectedIndex >= 0 ? selectedIndex : 0);\n setOpen(true);\n }, [disabled, selectedIndex]);\n\n const pick = useCallback(\n (i: number) => {\n const profile = shells[i];\n if (!profile) return;\n onChange(profile.id, profile);\n setOpen(false);\n },\n [shells, onChange],\n );\n\n const onButtonKeyDown = (e: KeyboardEvent) => {\n if (disabled) return;\n if (e.key === \"ArrowDown\" || e.key === \"ArrowUp\" || e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n openMenu();\n }\n };\n\n const onListKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n setOpen(false);\n return;\n }\n if (e.key === \"ArrowDown\") {\n e.preventDefault();\n setActiveIndex((i) => Math.min(shells.length - 1, i + 1));\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault();\n setActiveIndex((i) => Math.max(0, i - 1));\n } else if (e.key === \"Home\") {\n e.preventDefault();\n setActiveIndex(0);\n } else if (e.key === \"End\") {\n e.preventDefault();\n setActiveIndex(shells.length - 1);\n } else if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n pick(activeIndex);\n }\n };\n\n const buttonStyle: CSSProperties = {\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: 6,\n height: 26,\n padding: \"0 8px\",\n fontSize: 12,\n lineHeight: 1,\n fontFamily: \"inherit\",\n color: FG,\n background: PANEL_BG,\n border: `1px solid ${BORDER}`,\n borderRadius: 6,\n cursor: disabled ? \"default\" : \"pointer\",\n opacity: disabled ? 0.6 : 1,\n userSelect: \"none\",\n };\n\n return (\n <div\n ref={rootRef}\n data-fancy-shell-switcher=\"\"\n data-active-shell={value ?? undefined}\n className={className}\n style={{ position: \"relative\", display: \"inline-block\", ...style }}\n >\n <button\n type=\"button\"\n aria-haspopup=\"listbox\"\n aria-expanded={open}\n aria-label=\"Select shell\"\n disabled={disabled}\n style={buttonStyle}\n onClick={() => (open ? setOpen(false) : openMenu())}\n onKeyDown={onButtonKeyDown}\n >\n {selected?.icon ? (\n <span aria-hidden=\"true\" style={{ color: ACCENT }}>\n {selected.icon}\n </span>\n ) : null}\n <span>{selected?.label ?? \"Select shell\"}</span>\n <span aria-hidden=\"true\" style={{ color: MUTED, fontSize: 9 }}>\n ▼\n </span>\n </button>\n\n {open ? (\n <ul\n role=\"listbox\"\n id={listId}\n aria-label=\"Shells\"\n tabIndex={-1}\n // Autofocus is deliberate: this list only renders once the switcher\n // is opened by an explicit user action, so focus is going where the\n // person just asked to be. (This used to carry an\n // `eslint-disable jsx-a11y/no-autofocus`, but jsx-a11y has never been\n // a dependency here — it silenced a rule that did not exist, and\n // broke linting once ESLint was actually turned on.)\n autoFocus\n onKeyDown={onListKeyDown}\n ref={(el) => el?.focus()}\n style={{\n position: \"absolute\",\n zIndex: 50,\n top: \"calc(100% + 4px)\",\n left: 0,\n minWidth: \"100%\",\n margin: 0,\n padding: 4,\n listStyle: \"none\",\n background: PANEL_BG,\n border: `1px solid ${BORDER}`,\n borderRadius: 8,\n boxShadow: \"0 8px 24px rgba(0,0,0,0.45)\",\n outline: \"none\",\n }}\n >\n {shells.map((s, i) => {\n const isSelected = s.id === value;\n const isActive = i === activeIndex;\n return (\n <li\n key={s.id}\n role=\"option\"\n aria-selected={isSelected}\n data-shell-id={s.id}\n onMouseEnter={() => setActiveIndex(i)}\n onClick={() => pick(i)}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"6px 8px\",\n fontSize: 12,\n borderRadius: 5,\n color: FG,\n cursor: \"pointer\",\n background: isActive ? HOVER_BG : \"transparent\",\n }}\n >\n <span\n aria-hidden=\"true\"\n style={{\n width: 18,\n textAlign: \"center\",\n color: isSelected ? ACCENT : MUTED,\n }}\n >\n {s.icon ?? \"\"}\n </span>\n <span style={{ flex: 1 }}>{s.label}</span>\n {isSelected ? (\n <span aria-hidden=\"true\" style={{ color: ACCENT, fontSize: 11 }}>\n ✓\n </span>\n ) : null}\n </li>\n );\n })}\n </ul>\n ) : null}\n </div>\n );\n}\n","// menu-position.ts — clamp a fixed-position menu so it never spills off-screen.\n// Pure helper (unit-testable); the component measures its own rect and applies it.\n\nexport interface MenuPoint {\n x: number;\n y: number;\n}\nexport interface MenuSize {\n width: number;\n height: number;\n}\n\n/**\n * Clamp a menu's top-left so the whole menu stays inside the viewport (minus a\n * margin). Pushes left/up when it would overflow the right/bottom edge, and never\n * goes past the top-left margin. Pure.\n */\nexport function clampMenuPosition(\n at: MenuPoint,\n menu: MenuSize,\n viewport: MenuSize,\n margin = 8,\n): MenuPoint {\n const maxX = Math.max(margin, viewport.width - menu.width - margin);\n const maxY = Math.max(margin, viewport.height - menu.height - margin);\n return {\n x: Math.min(Math.max(margin, at.x), maxX),\n y: Math.min(Math.max(margin, at.y), maxY),\n };\n}\n","import { useEffect, useLayoutEffect, useRef, useState } from \"react\";\nimport { clampMenuPosition } from \"../menu-position\";\nimport type {\n TerminalContextMenuContext,\n TerminalContextMenuItem,\n} from \"../context-menu\";\n\n/**\n * The terminal selection context menu. Deliberately plain React + inline styles\n * (fancy-term has no react-fancy dependency) styled to match the shell bar. It\n * closes on click-outside + Escape, and clamps itself inside the viewport on\n * mount so a right-click near an edge never spills off-screen.\n */\nexport function TerminalContextMenu({\n at,\n items,\n ctx,\n onClose,\n}: {\n at: { x: number; y: number };\n items: TerminalContextMenuItem[];\n ctx: TerminalContextMenuContext;\n onClose: () => void;\n}) {\n const ref = useRef<HTMLDivElement>(null);\n const [pos, setPos] = useState(at);\n\n // Clamp once we can measure the rendered menu.\n useLayoutEffect(() => {\n const el = ref.current;\n if (!el || typeof window === \"undefined\") return;\n const r = el.getBoundingClientRect();\n setPos(\n clampMenuPosition(\n at,\n { width: r.width, height: r.height },\n { width: window.innerWidth, height: window.innerHeight },\n ),\n );\n }, [at]);\n\n // Dismiss on click-outside + Escape (capture so it wins over the surface).\n useEffect(() => {\n const onDown = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) onClose();\n };\n const onKey = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") onClose();\n };\n document.addEventListener(\"mousedown\", onDown, true);\n document.addEventListener(\"keydown\", onKey, true);\n return () => {\n document.removeEventListener(\"mousedown\", onDown, true);\n document.removeEventListener(\"keydown\", onKey, true);\n };\n }, [onClose]);\n\n return (\n <div\n ref={ref}\n data-fancy-terminal-menu=\"\"\n role=\"menu\"\n style={{\n position: \"fixed\",\n left: pos.x,\n top: pos.y,\n zIndex: 2147483000,\n minWidth: 176,\n padding: 4,\n background: \"#18181b\",\n border: \"1px solid #3f3f46\",\n borderRadius: 8,\n boxShadow: \"0 10px 32px -8px rgba(0,0,0,.6)\",\n color: \"#e4e4e7\",\n font: '13px/1.4 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", sans-serif',\n userSelect: \"none\",\n }}\n >\n {items.map((it) =>\n it.separator ? (\n <div\n key={it.id}\n role=\"separator\"\n style={{ height: 1, margin: \"4px 6px\", background: \"#3f3f46\" }}\n />\n ) : (\n <button\n key={it.id}\n type=\"button\"\n role=\"menuitem\"\n data-menu-item={it.id}\n disabled={it.disabled}\n onClick={() => {\n if (it.disabled) return;\n it.onSelect?.(ctx);\n onClose();\n }}\n onMouseEnter={(e) => {\n if (!it.disabled) e.currentTarget.style.background = \"#27272a\";\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.background = \"transparent\";\n }}\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 9,\n width: \"100%\",\n textAlign: \"left\",\n padding: \"6px 9px\",\n border: \"none\",\n borderRadius: 5,\n background: \"transparent\",\n color: it.disabled ? \"#52525b\" : \"inherit\",\n cursor: it.disabled ? \"default\" : \"pointer\",\n font: \"inherit\",\n }}\n >\n <span style={{ width: 16, textAlign: \"center\", opacity: 0.8 }}>\n {it.icon ?? \"\"}\n </span>\n <span style={{ flex: 1 }}>{it.label}</span>\n </button>\n ),\n )}\n </div>\n );\n}\n","/**\n * Decide what to push to the terminal when the controlled `output` changes.\n * Terminals are append-only streams, so the common case (output grew) writes\n * only the delta; a value that no longer extends what we've written means a\n * wholesale replace, so reset + rewrite. Returns null when nothing changed.\n */\nexport function diffOutput(\n written: string,\n next: string,\n): { reset: boolean; write: string } | null {\n if (next === written) return null;\n if (next.startsWith(written)) return { reset: false, write: next.slice(written.length) };\n return { reset: true, write: next };\n}\n","import { resolveShell, type ShellProfile } from \"./types\";\n\n/**\n * Pure decision for \"select shell `id`\": resolves the profile and reports whether\n * the selection actually changed. The single source of truth shared by\n * `<Terminal>`'s `setShell`, `<ShellSwitcher>`, and `useTerminalSession`, so the\n * interactive behavior is unit-testable without a DOM.\n *\n * Returns `null` when the id isn't in `shells` (a no-op — unknown shell).\n */\nexport function decideShellSelect(\n shells: ShellProfile[] | undefined,\n current: string | undefined,\n id: string,\n): { profile: ShellProfile; changed: boolean } | null {\n const profile = resolveShell(shells, id);\n if (!profile) return null;\n return { profile, changed: current !== id };\n}\n\n/**\n * Pure decision for a session shell switch. The session hook holds the buffer +\n * the transport, so it only needs to know: did the shell change? If so it must\n * reset the buffer (to `initial`) and reconnect the transport. Extracted so the\n * reset-and-reconnect contract is unit-testable without rendering the hook.\n */\nexport function decideShellSwitch(\n current: string | undefined,\n next: string | undefined,\n): { changed: boolean } {\n return { changed: current !== next };\n}\n","// context-menu.ts — the model for the customizable terminal selection menu.\n// Pure data + a resolver; the rendering lives in TerminalContextMenu.tsx.\n\n/** Context handed to the menu at right-click time + to custom item builders. */\nexport interface TerminalContextMenuContext {\n /** Whether there is a non-empty text selection. */\n hasSelection: boolean;\n /** The selected text (or \"\"). */\n selection: string;\n /** Whether the terminal is read-only (paste / clear are dropped by default). */\n readOnly: boolean;\n}\n\n/** A single menu entry. `onSelect` runs on click; set `separator` for a divider. */\nexport interface TerminalContextMenuItem {\n /** Stable id (used as the React key + a `data-menu-item` handle). */\n id: string;\n /** Visible label. Ignored for separators. */\n label?: string;\n /** Optional leading glyph / emoji / short string (JSON-friendly — no ReactNode). */\n icon?: string;\n /** Greyed-out + non-interactive. */\n disabled?: boolean;\n /** Render a divider instead of a clickable item. */\n separator?: boolean;\n /** Invoked on click with the menu context. */\n onSelect?: (ctx: TerminalContextMenuContext) => void;\n}\n\n/** The actions the built-in items dispatch to (wired by the component). */\nexport interface TerminalMenuActions {\n /**\n * Receives the menu's {@link TerminalContextMenuContext} so it can copy the\n * selection **snapshotted when the menu opened** — by click time the live\n * xterm selection is often already cleared (a mouse-reporting TUI's redraw\n * clears it right after the right-click), so re-reading it copies nothing.\n */\n copy: (ctx: TerminalContextMenuContext) => void;\n paste: () => void;\n selectAll: () => void;\n clear: () => void;\n}\n\n/**\n * The `contextMenu` prop shape:\n * - `false` — disable the menu entirely.\n * - `true` / omitted — the default Copy / Paste / Select all / Clear menu.\n * - an array — replace the default items wholesale.\n * - a function — receives the context **and the default items** so you can\n * add/remove/reorder (e.g. append a \"Send to agent\" item).\n */\nexport type TerminalContextMenuConfig =\n | boolean\n | TerminalContextMenuItem[]\n | ((\n ctx: TerminalContextMenuContext,\n defaults: TerminalContextMenuItem[],\n ) => TerminalContextMenuItem[]);\n\n/** The built-in Copy / Paste / Select all / Clear items, contextual to selection + readOnly. */\nexport function defaultMenuItems(\n ctx: TerminalContextMenuContext,\n actions: TerminalMenuActions,\n): TerminalContextMenuItem[] {\n const items: TerminalContextMenuItem[] = [\n { id: \"copy\", label: \"Copy\", icon: \"⧉\", disabled: !ctx.hasSelection, onSelect: actions.copy },\n ];\n if (!ctx.readOnly) {\n items.push({ id: \"paste\", label: \"Paste\", icon: \"⎘\", onSelect: actions.paste });\n }\n items.push({ id: \"select-all\", label: \"Select all\", onSelect: actions.selectAll });\n if (!ctx.readOnly) {\n items.push({ id: \"sep-default\", separator: true });\n items.push({ id: \"clear\", label: \"Clear\", onSelect: actions.clear });\n }\n return items;\n}\n\n/**\n * Resolve the configured menu into the final item list, or `null` when disabled.\n * Empty results (e.g. a function that filtered everything out) also resolve to\n * `null` so the caller can skip opening an empty menu.\n */\nexport function resolveMenuItems(\n config: TerminalContextMenuConfig | undefined,\n ctx: TerminalContextMenuContext,\n actions: TerminalMenuActions,\n): TerminalContextMenuItem[] | null {\n if (config === false) return null;\n const defaults = defaultMenuItems(ctx, actions);\n const items =\n config === undefined || config === true\n ? defaults\n : Array.isArray(config)\n ? config\n : config(ctx, defaults);\n return items.length > 0 ? items : null;\n}\n","// selection-snapshot.ts — pure decision layer for the context-menu selection\n// snapshot (#2). Over a mouse-reporting TUI (Claude Code, tmux, vim with mouse\n// mode) a right-click is forwarded to the app, whose redraw asynchronously\n// clears xterm's selection — often between the selecting drag and the menu\n// opening, and almost always before the user clicks Copy. So the component\n// keeps a snapshot of the selection, maintained at pointer time (capture\n// phase, before xterm or the app can react), and the menu falls back to it\n// whenever the live selection has already been cleared.\n\n/** The bits of a pointer event the snapshot decision needs. */\nexport interface SnapshotPointerEvent {\n type: \"mousedown\" | \"mouseup\";\n /** 0 = left, 1 = middle, 2 = right. */\n button: number;\n}\n\n/**\n * Compute the next selection snapshot after a pointer event on the terminal\n * surface.\n *\n * - A fresh **left press** starts a new gesture — drop the snapshot (the live\n * selection still reads the *old* text at capture time, so it must not win).\n * - Otherwise a **non-empty live selection** always refreshes the snapshot\n * (drag-select completes on left mouseup; a right press re-captures while\n * the selection is still alive).\n * - An **empty** live selection keeps the previous snapshot — that's exactly\n * the TUI-cleared-it-under-us case the snapshot exists for.\n */\nexport function nextSelectionSnapshot(\n prev: string,\n event: SnapshotPointerEvent,\n liveSelection: string,\n): string {\n if (event.type === \"mousedown\" && event.button === 0) return \"\";\n return liveSelection || prev;\n}\n","import {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from \"react\";\nimport { useTerminal } from \"../hooks/use-terminal\";\nimport { ShellSwitcher } from \"./ShellSwitcher\";\nimport { TerminalContextMenu } from \"./TerminalContextMenu\";\nimport { diffOutput } from \"../output-diff\";\nimport { decideShellSelect } from \"../shell-select\";\nimport { providerWrite, resolveClipboard } from \"../clipboard\";\nimport { resolveMenuItems, type TerminalContextMenuContext, type TerminalContextMenuItem } from \"../context-menu\";\nimport { nextSelectionSnapshot } from \"../selection-snapshot\";\nimport type { TerminalHandle, TerminalProps } from \"../types\";\n\n/**\n * Human+ `<Terminal>` — a controlled, themeable xterm.js terminal.\n *\n * - **Authoring surface:** terse, controlled (`output` + `onData`), JSON-friendly\n * props (rows/cols, theme tokens, initial buffer), a stable `data-fancy-terminal`\n * handle, and a ref exposing {@link TerminalHandle} (write/clear/fit/getBuffer/…).\n * - **Inhabited surface:** the same handle is what an MCP bridge drives, so an\n * embedded agent reads the buffer + writes input without DOM-scraping.\n *\n * The parent must have a height — the terminal fits its container (like any xterm\n * surface); a 0-height parent collapses it.\n *\n * ```tsx\n * const [out, setOut] = useState(\"\");\n * <div style={{ height: 360 }}>\n * <Terminal output={out} onData={(d) => backend.send(d)} />\n * </div>\n * ```\n */\nexport const Terminal = forwardRef<TerminalHandle, TerminalProps>(function Terminal(\n {\n output,\n theme,\n rows,\n cols,\n fit = true,\n readOnly,\n cursorBlink,\n cursorStyle,\n fontFamily,\n fontSize,\n scrollback,\n initialOutput,\n onData,\n onResize,\n shells,\n activeShell,\n onShellChange,\n showShellBar = false,\n clipboard,\n osc52,\n copyPaste,\n onReady,\n onPaste,\n contextMenu,\n className,\n style,\n ...rest\n },\n ref,\n) {\n const containerRef = useRef<HTMLDivElement>(null);\n\n // Selected shell: controlled by `activeShell` when provided, else internal.\n const isShellControlled = activeShell !== undefined;\n const [internalShell, setInternalShell] = useState<string | undefined>(undefined);\n const shellId = isShellControlled ? activeShell : internalShell;\n\n // Read shell state live so the stable handle's setShell/getShell never go stale.\n const shellStateRef = useRef({ shells, shellId, isShellControlled, onShellChange });\n shellStateRef.current = { shells, shellId, isShellControlled, onShellChange };\n\n const selectShell = useCallback((id: string) => {\n const s = shellStateRef.current;\n const decision = decideShellSelect(s.shells, s.shellId, id);\n if (!decision) return; // unknown id — no-op\n if (!s.isShellControlled) setInternalShell(id);\n s.onShellChange?.(id, decision.profile);\n }, []);\n\n const handle = useTerminal(containerRef, {\n theme,\n rows,\n cols,\n fit,\n readOnly,\n cursorBlink,\n cursorStyle,\n fontFamily,\n fontSize,\n scrollback,\n // `initialOutput` is for uncontrolled use; with a controlled `output` the\n // diffing effect below owns the buffer, so don't double-write.\n initialOutput: output === undefined ? initialOutput : undefined,\n onData,\n onResize,\n clipboard,\n osc52,\n copyPaste,\n onReady,\n onPaste,\n });\n\n // Delegate `xterm` / `ready` as live getters rather than spreading `handle`\n // (object spread would snapshot the getters — capturing xterm === null before\n // the container is measured, the exact race consumers hit). Methods are stable.\n useImperativeHandle(\n ref,\n (): TerminalHandle => ({\n get xterm() {\n return handle.xterm;\n },\n get ready() {\n return handle.ready;\n },\n write: handle.write,\n writeln: handle.writeln,\n clear: handle.clear,\n reset: handle.reset,\n fit: handle.fit,\n focus: handle.focus,\n getBuffer: handle.getBuffer,\n getSelection: handle.getSelection,\n copySelection: handle.copySelection,\n paste: handle.paste,\n selectAll: handle.selectAll,\n clearSelection: handle.clearSelection,\n setShell: selectShell,\n getShell: () => shellStateRef.current.shellId,\n }),\n [handle, selectShell],\n );\n\n // Controlled output: write only the appended delta; reset + rewrite if the\n // value diverges from what we've already written (a wholesale replace).\n const written = useRef(\"\");\n useEffect(() => {\n if (output === undefined) return;\n const change = diffOutput(written.current, output);\n if (!change) return;\n if (change.reset) handle.reset();\n handle.write(change.write);\n written.current = output;\n }, [output, handle]);\n\n // Right-click selection context menu (Copy / Paste / Select all / Clear by\n // default; customizable via the `contextMenu` prop).\n const [menu, setMenu] = useState<{\n at: { x: number; y: number };\n items: TerminalContextMenuItem[];\n ctx: TerminalContextMenuContext;\n } | null>(null);\n\n // #2 — over a mouse-reporting TUI (Claude Code, tmux, vim) the app's redraw\n // asynchronously clears xterm's selection right after a right-click, so both\n // late reads lose: at `contextmenu` time the selection may already be gone,\n // and by the time the user clicks Copy it almost always is. Track a snapshot\n // at pointer time (capture phase — before xterm / the app can react) and use\n // it as the menu's source of truth whenever the live selection is empty.\n const selectionSnapshot = useRef(\"\");\n const trackSelection = useCallback(\n (e: React.MouseEvent) => {\n selectionSnapshot.current = nextSelectionSnapshot(\n selectionSnapshot.current,\n { type: e.type as \"mousedown\" | \"mouseup\", button: e.button },\n handle.getSelection(),\n );\n },\n [handle],\n );\n\n const openMenu = useCallback(\n (e: React.MouseEvent) => {\n if (contextMenu === false) return;\n e.preventDefault();\n const selection = handle.getSelection() || selectionSnapshot.current;\n const ctx: TerminalContextMenuContext = {\n hasSelection: selection.length > 0,\n selection,\n readOnly: !!readOnly,\n };\n const items = resolveMenuItems(contextMenu, ctx, {\n // Copy writes the SNAPSHOTTED selection through the active clipboard\n // provider — never a click-time re-read, which copies \"\" over a TUI\n // (falling back to the live selection only when the snapshot is empty).\n copy: (c) => {\n const text = c.selection || handle.getSelection();\n if (text) void providerWrite(resolveClipboard(clipboard).provider, text);\n },\n paste: () => void handle.paste(),\n selectAll: () => handle.selectAll(),\n clear: () => handle.clear(),\n });\n if (items) setMenu({ at: { x: e.clientX, y: e.clientY }, items, ctx });\n },\n [contextMenu, handle, readOnly, clipboard],\n );\n\n const menuNode = menu ? (\n <TerminalContextMenu at={menu.at} items={menu.items} ctx={menu.ctx} onClose={() => setMenu(null)} />\n ) : null;\n\n const surface = (\n <div\n ref={containerRef}\n data-fancy-terminal=\"\"\n onMouseDownCapture={trackSelection}\n onMouseUpCapture={trackSelection}\n onContextMenu={openMenu}\n data-readonly={readOnly ? \"\" : undefined}\n data-fancy-terminal-shell={shellId ?? undefined}\n // When the shell bar is shown the wrapper owns the box; the surface flexes.\n style={\n showShellBar && shells\n ? { width: \"100%\", flex: 1, minHeight: 0 }\n : { width: \"100%\", height: \"100%\", ...style }\n }\n {...(showShellBar && shells ? {} : rest)}\n />\n );\n\n if (!showShellBar || !shells) {\n return (\n <>\n {surface}\n {menuNode}\n </>\n );\n }\n\n return (\n <div\n data-fancy-terminal-shell={shellId ?? undefined}\n className={className}\n style={{ display: \"flex\", flexDirection: \"column\", width: \"100%\", height: \"100%\", ...style }}\n {...rest}\n >\n <div\n style={{\n display: \"flex\",\n alignItems: \"center\",\n gap: 8,\n padding: \"4px 6px\",\n background: \"#09090b\",\n borderBottom: \"1px solid #27272a\",\n }}\n >\n <ShellSwitcher\n shells={shells}\n value={shellId}\n onChange={(id) => selectShell(id)}\n disabled={readOnly}\n />\n </div>\n {surface}\n {menuNode}\n </div>\n );\n});\n","import { useCallback, useEffect, useRef, useState } from \"react\";\nimport { decideShellSwitch } from \"../shell-select\";\n\n/**\n * A streamed terminal backend — a PTY, an SSH session, or a command runner.\n * `subscribe` pushes output chunks (wire it to an Echo channel or a fancy-query\n * `useFancyStream` feed); `send` forwards the user's keystrokes upstream.\n */\nexport interface TerminalSessionTransport {\n /** Forward user input / keystrokes to the backend. */\n send: (data: string) => void | Promise<void>;\n /** Subscribe to backend output chunks; return an unsubscribe function. */\n subscribe: (onChunk: (chunk: string) => void) => (() => void) | void;\n /**\n * Optional — called when the active shell changes (and once on mount if a\n * `shell` is provided). The host (re)connects its PTY/command backend to the\n * chosen shell here. Transports that don't care about shells can omit it; the\n * hook stays fully backward compatible.\n */\n connect?: (shell: string | undefined) => void | Promise<void>;\n}\n\nexport interface UseTerminalSessionOptions {\n transport: TerminalSessionTransport;\n /** Replayed history written before live output starts. */\n initial?: string;\n /** The active shell id. Changing it resets the buffer + calls `transport.connect`. */\n shell?: string;\n}\n\nexport interface TerminalSessionApi {\n /** Accumulated output — feed to `<Terminal output={output} />`. */\n output: string;\n /** Forward keystrokes upstream — wire to `<Terminal onData={sendData} />`. */\n sendData: (data: string) => void;\n /** Append a chunk locally (e.g. a client-side echo or banner). */\n append: (chunk: string) => void;\n /** Clear the local buffer. */\n clear: () => void;\n /** The active shell id (controlled by `options.shell` when provided). */\n shell: string | undefined;\n /**\n * Switch shells: resets the buffer (back to `initial`) and tells the transport\n * to reconnect via `transport.connect(id)`. In controlled mode (`options.shell`\n * set) this still fires `connect`; pass the new id down via `options.shell` to\n * reflect it. No-op when the id matches the current shell.\n */\n switchShell: (id: string | undefined) => void;\n}\n\n/**\n * Bind a `<Terminal>` to a streamed backend: accumulates incoming output into a\n * controlled buffer and forwards keystrokes upstream — the glue between the\n * display surface and a PTY/command channel.\n *\n * ```tsx\n * const session = useTerminalSession({\n * transport: {\n * send: (d) => echo.private(`pty.${id}`).whisper(\"stdin\", { d }),\n * subscribe: (onChunk) => {\n * const ch = echo.private(`pty.${id}`).listen(\".stdout\", (e) => onChunk(e.chunk));\n * return () => echo.leave(`pty.${id}`);\n * },\n * },\n * });\n * <Terminal output={session.output} onData={session.sendData} />\n * ```\n */\nexport function useTerminalSession(options: UseTerminalSessionOptions): TerminalSessionApi {\n const initial = options.initial ?? \"\";\n const [output, setOutput] = useState(initial);\n\n // In uncontrolled mode `switchShell` drives this; in controlled mode the\n // `options.shell` effect keeps it in sync.\n const [internalShell, setInternalShell] = useState<string | undefined>(options.shell);\n const shell = options.shell !== undefined ? options.shell : internalShell;\n\n const transportRef = useRef(options.transport);\n transportRef.current = options.transport;\n const initialRef = useRef(initial);\n initialRef.current = initial;\n\n useEffect(() => {\n const unsub = transportRef.current.subscribe((chunk) => setOutput((o) => o + chunk));\n return () => {\n if (typeof unsub === \"function\") unsub();\n };\n // subscribe once; the transport is read live via the ref.\n }, []);\n\n // Connect on mount + whenever the active shell changes. Resetting the buffer\n // is owned by switchShell (uncontrolled) / this effect (controlled).\n const connectedShell = useRef<string | undefined>(undefined);\n const mounted = useRef(false);\n useEffect(() => {\n // On mount: connect once (even if shell is undefined, for parity).\n if (!mounted.current) {\n mounted.current = true;\n connectedShell.current = shell;\n void transportRef.current.connect?.(shell);\n return;\n }\n if (!decideShellSwitch(connectedShell.current, shell).changed) return;\n connectedShell.current = shell;\n setOutput(initialRef.current); // reset the buffer for the new shell\n void transportRef.current.connect?.(shell);\n }, [shell]);\n\n const sendData = useCallback((data: string) => {\n void transportRef.current.send(data);\n }, []);\n\n const append = useCallback((chunk: string) => setOutput((o) => o + chunk), []);\n const clear = useCallback(() => setOutput(\"\"), []);\n\n const switchShell = useCallback((id: string | undefined) => {\n // Uncontrolled: flip internal state, the effect above does reset + connect.\n // Controlled (options.shell set): still drive a reset + connect now so the\n // host sees the switch immediately even before it echoes options.shell back.\n setInternalShell((cur) => (cur === id ? cur : id));\n if (!decideShellSwitch(connectedShell.current, id).changed) return;\n connectedShell.current = id;\n setOutput(initialRef.current);\n void transportRef.current.connect?.(id);\n }, []);\n\n return { output, sendData, append, clear, shell, switchShell };\n}\n","// copy-keybinding.ts — the pure \"should this key event copy the selection?\"\n// decision, kept separate (like shell-select.ts) so it's unit-testable without\n// a DOM or a live xterm.\n\n/** The subset of a KeyboardEvent the copy decision reads. */\nexport interface CopyKeyEvent {\n type: string;\n key: string;\n ctrlKey: boolean;\n shiftKey: boolean;\n metaKey: boolean;\n}\n\n/**\n * Whether a key event should copy the current selection to the clipboard.\n *\n * - **Ctrl+Shift+C** (Windows / Linux terminal convention) — always.\n * - **Cmd / Meta+C** (macOS) — only when there is a selection.\n * - **Plain Ctrl+C is never a copy** — it must stay SIGINT.\n *\n * Only fires on `keydown`. When this returns true the caller copies the\n * selection and consumes the event (returns `false` from xterm's\n * `attachCustomKeyEventHandler` so no control byte is sent).\n */\nexport function shouldCopyEvent(e: CopyKeyEvent, hasSelection: boolean): boolean {\n if (e.type !== \"keydown\") return false;\n if (e.key !== \"c\" && e.key !== \"C\") return false;\n // Ctrl+Shift+C — the terminal-safe copy chord (plain Ctrl+C stays SIGINT).\n if (e.ctrlKey && e.shiftKey && !e.metaKey) return true;\n // Cmd+C on macOS — only with a selection, so it never swallows an empty copy.\n if (e.metaKey && !e.ctrlKey && hasSelection) return true;\n return false;\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -143,7 +143,13 @@ interface TerminalContextMenuItem {
143
143
  }
144
144
  /** The actions the built-in items dispatch to (wired by the component). */
145
145
  interface TerminalMenuActions {
146
- copy: () => void;
146
+ /**
147
+ * Receives the menu's {@link TerminalContextMenuContext} so it can copy the
148
+ * selection **snapshotted when the menu opened** — by click time the live
149
+ * xterm selection is often already cleared (a mouse-reporting TUI's redraw
150
+ * clears it right after the right-click), so re-reading it copies nothing.
151
+ */
152
+ copy: (ctx: TerminalContextMenuContext) => void;
147
153
  paste: () => void;
148
154
  selectAll: () => void;
149
155
  clear: () => void;
@@ -537,4 +543,24 @@ interface MenuSize {
537
543
  */
538
544
  declare function clampMenuPosition(at: MenuPoint, menu: MenuSize, viewport: MenuSize, margin?: number): MenuPoint;
539
545
 
540
- export { BUILTIN_SHELLS, type ClipboardOption, type ClipboardPayload, type ClipboardProvider, type CopyKeyEvent, type CopyPasteBehavior, type CopyPasteMode, type CursorStyle, type KeyEventLike, type Osc52Mode, type Osc52Request, type ShellProfile, ShellSwitcher, type ShellSwitcherProps, Terminal, TerminalContextMenu, type TerminalContextMenuConfig, type TerminalContextMenuContext, type TerminalContextMenuItem, type TerminalHandle, type TerminalMenuActions, type TerminalOptions, type TerminalProps, type TerminalSessionApi, type TerminalSessionTransport, type TerminalTheme, type UseTerminalSessionOptions, clampMenuPosition, copyPasteBehavior, decodeBase64, defaultMenuItems, encodeBase64, fancyDarkTheme, isImageFile, navigatorClipboard, osc52Response, parseOsc52, registerOsc52, resolveClipboard, resolveKeyAction, resolveMenuItems, resolveShell, shouldCopyEvent, useTerminal, useTerminalFit, useTerminalSession };
546
+ /** The bits of a pointer event the snapshot decision needs. */
547
+ interface SnapshotPointerEvent {
548
+ type: "mousedown" | "mouseup";
549
+ /** 0 = left, 1 = middle, 2 = right. */
550
+ button: number;
551
+ }
552
+ /**
553
+ * Compute the next selection snapshot after a pointer event on the terminal
554
+ * surface.
555
+ *
556
+ * - A fresh **left press** starts a new gesture — drop the snapshot (the live
557
+ * selection still reads the *old* text at capture time, so it must not win).
558
+ * - Otherwise a **non-empty live selection** always refreshes the snapshot
559
+ * (drag-select completes on left mouseup; a right press re-captures while
560
+ * the selection is still alive).
561
+ * - An **empty** live selection keeps the previous snapshot — that's exactly
562
+ * the TUI-cleared-it-under-us case the snapshot exists for.
563
+ */
564
+ declare function nextSelectionSnapshot(prev: string, event: SnapshotPointerEvent, liveSelection: string): string;
565
+
566
+ export { BUILTIN_SHELLS, type ClipboardOption, type ClipboardPayload, type ClipboardProvider, type CopyKeyEvent, type CopyPasteBehavior, type CopyPasteMode, type CursorStyle, type KeyEventLike, type Osc52Mode, type Osc52Request, type ShellProfile, ShellSwitcher, type ShellSwitcherProps, type SnapshotPointerEvent, Terminal, TerminalContextMenu, type TerminalContextMenuConfig, type TerminalContextMenuContext, type TerminalContextMenuItem, type TerminalHandle, type TerminalMenuActions, type TerminalOptions, type TerminalProps, type TerminalSessionApi, type TerminalSessionTransport, type TerminalTheme, type UseTerminalSessionOptions, clampMenuPosition, copyPasteBehavior, decodeBase64, defaultMenuItems, encodeBase64, fancyDarkTheme, isImageFile, navigatorClipboard, nextSelectionSnapshot, osc52Response, parseOsc52, registerOsc52, resolveClipboard, resolveKeyAction, resolveMenuItems, resolveShell, shouldCopyEvent, useTerminal, useTerminalFit, useTerminalSession };