silvery 0.17.0 → 0.17.2

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.
Files changed (171) hide show
  1. package/dist/UPNG-AVSMjiFE.mjs +5076 -0
  2. package/dist/UPNG-AVSMjiFE.mjs.map +1 -0
  3. package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs +6 -0
  4. package/dist/__vite-browser-external-2447137e-D3GdsvS_.mjs.map +1 -0
  5. package/dist/animation-C_PTO0uH.mjs +304 -0
  6. package/dist/animation-C_PTO0uH.mjs.map +1 -0
  7. package/dist/ansi-CXLE_pt1.mjs +71 -0
  8. package/dist/ansi-CXLE_pt1.mjs.map +1 -0
  9. package/dist/ansi-zmNzgkPB.d.mts +49 -0
  10. package/dist/ansi-zmNzgkPB.d.mts.map +1 -0
  11. package/dist/apng-DCWY913R.mjs +3 -0
  12. package/dist/apng-ENBAJk-H.mjs +70 -0
  13. package/dist/apng-ENBAJk-H.mjs.map +1 -0
  14. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  15. package/dist/backend-CkIkIHR-.mjs +13396 -0
  16. package/dist/backend-CkIkIHR-.mjs.map +1 -0
  17. package/dist/backends-CkvbG3js.mjs +1181 -0
  18. package/dist/backends-CkvbG3js.mjs.map +1 -0
  19. package/dist/backends-CyJqNLeK.mjs +3 -0
  20. package/dist/chunk-BSw8zbkd.mjs +37 -0
  21. package/dist/cli-B-k7Bm56.mjs +4 -0
  22. package/dist/context-QreF3UHr.mjs +64 -0
  23. package/dist/context-QreF3UHr.mjs.map +1 -0
  24. package/dist/derive-D7bFJdfU.d.mts +28 -0
  25. package/dist/derive-D7bFJdfU.d.mts.map +1 -0
  26. package/dist/devtools-CscuKaDK.mjs +89 -0
  27. package/dist/devtools-CscuKaDK.mjs.map +1 -0
  28. package/dist/devtools-D4oGc6LY.mjs +2 -0
  29. package/dist/eta-DLiVPaSD.mjs +110 -0
  30. package/dist/eta-DLiVPaSD.mjs.map +1 -0
  31. package/dist/flexily-zero-adapter-DmG4Ge8t.mjs +3376 -0
  32. package/dist/flexily-zero-adapter-DmG4Ge8t.mjs.map +1 -0
  33. package/dist/flexily-zero-adapter-GHwEW11s.mjs +2 -0
  34. package/dist/gif-BaJNREpP.mjs +3 -0
  35. package/dist/gif-Bp6fIyN3.mjs +73 -0
  36. package/dist/gif-Bp6fIyN3.mjs.map +1 -0
  37. package/dist/gifenc-GiVCZ9-3.mjs +730 -0
  38. package/dist/gifenc-GiVCZ9-3.mjs.map +1 -0
  39. package/dist/image-Dx7gYjkq.mjs +346 -0
  40. package/dist/image-Dx7gYjkq.mjs.map +1 -0
  41. package/dist/index-CBcSpGSM.d.mts +3416 -0
  42. package/dist/index-CBcSpGSM.d.mts.map +1 -0
  43. package/dist/index-DCVL3jHo.d.mts +634 -0
  44. package/dist/index-DCVL3jHo.d.mts.map +1 -0
  45. package/dist/index-p-wBs_wH.d.mts +175 -0
  46. package/dist/index-p-wBs_wH.d.mts.map +1 -0
  47. package/dist/index.d.mts +7296 -0
  48. package/dist/index.d.mts.map +1 -0
  49. package/dist/index.mjs +9399 -0
  50. package/dist/index.mjs.map +1 -0
  51. package/dist/key-mapping-BsUHe_nk.mjs +3 -0
  52. package/dist/key-mapping-DsyfLEdC.mjs +132 -0
  53. package/dist/key-mapping-DsyfLEdC.mjs.map +1 -0
  54. package/dist/layout-engine-B3dsnVLU.mjs +50 -0
  55. package/dist/layout-engine-B3dsnVLU.mjs.map +1 -0
  56. package/dist/layout-engine-D_lSR4i9.mjs +2 -0
  57. package/dist/multi-progress-C0-rkn86.d.mts +180 -0
  58. package/dist/multi-progress-C0-rkn86.d.mts.map +1 -0
  59. package/dist/multi-progress-CQVB9lES.mjs +219 -0
  60. package/dist/multi-progress-CQVB9lES.mjs.map +1 -0
  61. package/dist/node-Dedx-6xF.mjs +1085 -0
  62. package/dist/node-Dedx-6xF.mjs.map +1 -0
  63. package/dist/pipeline-DDOPrjuY.mjs +4387 -0
  64. package/dist/pipeline-DDOPrjuY.mjs.map +1 -0
  65. package/dist/progress-bar-COPSBlT9.mjs +155 -0
  66. package/dist/progress-bar-COPSBlT9.mjs.map +1 -0
  67. package/dist/reconciler-2lp5VXK7.mjs +16506 -0
  68. package/dist/reconciler-2lp5VXK7.mjs.map +1 -0
  69. package/dist/render-string-BXvxTg5P.mjs +201 -0
  70. package/dist/render-string-BXvxTg5P.mjs.map +1 -0
  71. package/dist/render-string-hvfpVtoP.mjs +2 -0
  72. package/dist/resvg-js-V6oMi8CY.mjs +203 -0
  73. package/dist/resvg-js-V6oMi8CY.mjs.map +1 -0
  74. package/dist/runtime-BjDHNTxJ.mjs +8723 -0
  75. package/dist/runtime-BjDHNTxJ.mjs.map +1 -0
  76. package/dist/runtime.d.mts +2 -0
  77. package/dist/runtime.mjs +3 -0
  78. package/dist/spinner-Cgej6Vnb.d.mts +127 -0
  79. package/dist/spinner-Cgej6Vnb.d.mts.map +1 -0
  80. package/dist/spinner-DSByknyx.mjs +298 -0
  81. package/dist/spinner-DSByknyx.mjs.map +1 -0
  82. package/dist/src-9B5k0JmY.mjs +1629 -0
  83. package/dist/src-9B5k0JmY.mjs.map +1 -0
  84. package/dist/src-C9f3hiVG.mjs +3620 -0
  85. package/dist/src-C9f3hiVG.mjs.map +1 -0
  86. package/dist/src-fJVbhdn-.mjs +816 -0
  87. package/dist/src-fJVbhdn-.mjs.map +1 -0
  88. package/dist/theme.d.mts +115 -0
  89. package/dist/theme.d.mts.map +1 -0
  90. package/dist/theme.mjs +8 -0
  91. package/dist/theme.mjs.map +1 -0
  92. package/dist/types-Bhj5QkIQ.mjs +13 -0
  93. package/dist/types-Bhj5QkIQ.mjs.map +1 -0
  94. package/dist/types-CDgkE-Rw.d.mts +241 -0
  95. package/dist/types-CDgkE-Rw.d.mts.map +1 -0
  96. package/dist/ui/animation.d.mts +2 -0
  97. package/dist/ui/animation.mjs +2 -0
  98. package/dist/ui/ansi.d.mts +2 -0
  99. package/dist/ui/ansi.mjs +2 -0
  100. package/dist/ui/cli.d.mts +5 -0
  101. package/dist/ui/cli.mjs +7 -0
  102. package/dist/ui/display.d.mts +35 -0
  103. package/dist/ui/display.d.mts.map +1 -0
  104. package/dist/ui/display.mjs +123 -0
  105. package/dist/ui/display.mjs.map +1 -0
  106. package/dist/ui/image.d.mts +2 -0
  107. package/dist/ui/image.mjs +2 -0
  108. package/dist/ui/input.d.mts +184 -0
  109. package/dist/ui/input.d.mts.map +1 -0
  110. package/dist/ui/input.mjs +285 -0
  111. package/dist/ui/input.mjs.map +1 -0
  112. package/dist/ui/progress.d.mts +249 -0
  113. package/dist/ui/progress.d.mts.map +1 -0
  114. package/dist/ui/progress.mjs +858 -0
  115. package/dist/ui/progress.mjs.map +1 -0
  116. package/dist/ui/react.d.mts +280 -0
  117. package/dist/ui/react.d.mts.map +1 -0
  118. package/dist/ui/react.mjs +413 -0
  119. package/dist/ui/react.mjs.map +1 -0
  120. package/dist/ui/utils.d.mts +86 -0
  121. package/dist/ui/utils.d.mts.map +1 -0
  122. package/dist/ui/utils.mjs +2 -0
  123. package/dist/ui/wrappers.d.mts +3 -0
  124. package/dist/ui/wrappers.mjs +2 -0
  125. package/dist/ui.d.mts +6 -0
  126. package/dist/ui.mjs +7 -0
  127. package/dist/useLatest-BMIYXd6e.d.mts +154 -0
  128. package/dist/useLatest-BMIYXd6e.d.mts.map +1 -0
  129. package/dist/useLayout-BG2cGl15.mjs +139 -0
  130. package/dist/useLayout-BG2cGl15.mjs.map +1 -0
  131. package/dist/with-text-input-CmHf_9d6.d.mts +284 -0
  132. package/dist/with-text-input-CmHf_9d6.d.mts.map +1 -0
  133. package/dist/wrapper-Dqh0zi2W.mjs +3527 -0
  134. package/dist/wrapper-Dqh0zi2W.mjs.map +1 -0
  135. package/dist/wrappers-hhL8EQ_n.mjs +810 -0
  136. package/dist/wrappers-hhL8EQ_n.mjs.map +1 -0
  137. package/dist/yoga-adapter-BJ9SOhTY.mjs +245 -0
  138. package/dist/yoga-adapter-BJ9SOhTY.mjs.map +1 -0
  139. package/dist/yoga-adapter-Daq6-dw1.mjs +2 -0
  140. package/package.json +48 -75
  141. package/CHANGELOG.md +0 -319
  142. package/dist/chalk.js +0 -4
  143. package/dist/index.js +0 -270
  144. package/dist/ink.js +0 -142
  145. package/dist/runtime.js +0 -135
  146. package/dist/theme.js +0 -7
  147. package/dist/ui/animation.js +0 -3
  148. package/dist/ui/ansi.js +0 -3
  149. package/dist/ui/cli.js +0 -9
  150. package/dist/ui/display.js +0 -4
  151. package/dist/ui/image.js +0 -4
  152. package/dist/ui/input.js +0 -3
  153. package/dist/ui/progress.js +0 -9
  154. package/dist/ui/react.js +0 -4
  155. package/dist/ui/utils.js +0 -3
  156. package/dist/ui/wrappers.js +0 -15
  157. package/dist/ui.js +0 -18
  158. package/src/index.ts +0 -73
  159. package/src/runtime.ts +0 -4
  160. package/src/theme.ts +0 -4
  161. package/src/ui/animation.ts +0 -2
  162. package/src/ui/ansi.ts +0 -2
  163. package/src/ui/cli.ts +0 -3
  164. package/src/ui/display.ts +0 -2
  165. package/src/ui/image.ts +0 -2
  166. package/src/ui/input.ts +0 -2
  167. package/src/ui/progress.ts +0 -2
  168. package/src/ui/react.ts +0 -2
  169. package/src/ui/utils.ts +0 -2
  170. package/src/ui/wrappers.ts +0 -2
  171. package/src/ui.ts +0 -4
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backends-CkvbG3js.mjs","names":[],"sources":["../../termless/src/spawn.ts","../../termless/src/pty.ts","../../termless/src/svg.ts","../../termless/src/png.ts","../../termless/src/views.ts","../../termless/src/terminal.ts","../../termless/src/backends.ts"],"sourcesContent":["/**\n * Portable PTY spawn abstraction.\n *\n * Detects the runtime (Bun vs Node.js) and uses the appropriate PTY backend:\n * - Bun: native `Bun.spawn()` with `terminal` option\n * - Node.js: `node-pty` (optional peer dependency — throws if not installed)\n */\n\nimport { createRequire } from \"node:module\"\n\nexport interface PortablePtyProcess {\n /** Write data to the PTY stdin. */\n write(data: string): void\n /** Resize the PTY. */\n resize(cols: number, rows: number): void\n /** Close/destroy the PTY write channel. */\n closePty(): void\n /** Send a signal to the process (default: SIGTERM). */\n kill(signal?: number): void\n /** The process exit code (null if still running). */\n readonly exitCode: number | null\n /** A promise that resolves with the exit code when the process exits. */\n readonly exited: Promise<number>\n /** The process ID. */\n readonly pid: number\n}\n\nexport interface PortablePtySpawnOptions {\n argv: string[]\n cols: number\n rows: number\n cwd?: string\n env?: Record<string, string>\n onData: (data: Uint8Array) => void\n}\n\nconst isBun = typeof globalThis.Bun !== \"undefined\"\n\n/**\n * Spawn a process with a PTY, using the appropriate runtime backend.\n *\n * - On Bun: uses `Bun.spawn()` with the `terminal` option (built-in PTY support).\n * - On Node.js: uses `node-pty` (loaded via createRequire). Throws a clear error if not installed.\n */\nexport function spawnPortablePty(options: PortablePtySpawnOptions): PortablePtyProcess {\n if (isBun) {\n return spawnBunPty(options)\n }\n return spawnNodePty(options)\n}\n\n/**\n * Pre-load node-pty for Node.js environments.\n *\n * Call this once at startup if you want to verify node-pty is available before\n * the first spawn attempt. On Bun, this is a no-op.\n *\n * Not required -- spawnPortablePty() loads node-pty on demand. But calling this\n * early gives a better error message at startup instead of at first spawn.\n */\nexport async function preloadNodePty(): Promise<void> {\n if (isBun) return\n loadNodePty() // will throw if not installed\n}\n\n// ── Bun implementation ──\n\nfunction spawnBunPty(options: PortablePtySpawnOptions): PortablePtyProcess {\n const { argv, cols, rows, cwd, env, onData } = options\n\n const proc = Bun.spawn(argv, {\n cwd,\n env: { ...process.env, ...env },\n terminal: {\n cols,\n rows,\n data: (_terminal: unknown, data: Uint8Array) => {\n try {\n onData(data)\n } catch {\n // Swallow callback errors to prevent crashing the event loop.\n }\n },\n },\n })\n\n const pty = proc.terminal as {\n write: (data: string) => void\n close: () => void\n resize: (cols: number, rows: number) => void\n }\n\n return {\n write(data: string): void {\n pty.write(data)\n },\n resize(newCols: number, newRows: number): void {\n pty.resize(newCols, newRows)\n },\n closePty(): void {\n try {\n pty.close()\n } catch {\n // Ignore cleanup errors\n }\n },\n kill(signal?: number): void {\n proc.kill(signal)\n },\n get exitCode(): number | null {\n return proc.exitCode\n },\n get exited(): Promise<number> {\n return proc.exited\n },\n get pid(): number {\n return proc.pid\n },\n }\n}\n\n// ── Node.js implementation (node-pty) ──\n\n/** Minimal interface matching what we use from node-pty's IPty. */\ninterface NodePtyInstance {\n write(data: string): void\n resize(cols: number, rows: number): void\n kill(signal?: string): void\n destroy(): void\n onData: (callback: (data: string) => void) => { dispose(): void }\n onExit: (callback: (e: { exitCode: number; signal?: number }) => void) => { dispose(): void }\n pid: number\n}\n\n/** Minimal interface for the node-pty module. */\ninterface NodePtyModule {\n spawn(\n file: string,\n args: string[],\n options: {\n name?: string\n cols: number\n rows: number\n cwd?: string\n env?: Record<string, string>\n },\n ): NodePtyInstance\n}\n\n/**\n * Load node-pty synchronously using createRequire.\n *\n * node-pty is a CommonJS native addon, so createRequire is the correct way\n * to load it from ESM. This keeps spawnPortablePty() synchronous.\n */\nfunction loadNodePty(): NodePtyModule {\n try {\n const nodeRequire = createRequire(import.meta.url)\n return nodeRequire(\"node-pty\") as NodePtyModule\n } catch {\n throw new Error(\n \"node-pty is required for PTY support on Node.js but was not found.\\n\" +\n \"Install it with: npm install node-pty\\n\" +\n \"Note: node-pty requires native compilation tools (Python, C++ compiler).\",\n )\n }\n}\n\nfunction spawnNodePty(options: PortablePtySpawnOptions): PortablePtyProcess {\n const { argv, cols, rows, cwd, env, onData } = options\n\n const nodePty = loadNodePty()\n\n const ptyProcess = nodePty.spawn(argv[0]!, argv.slice(1), {\n name: \"xterm-256color\",\n cols,\n rows,\n cwd,\n env: { ...process.env, ...env } as Record<string, string>,\n })\n\n // Bridge node-pty's string-based onData to Uint8Array\n const encoder = new TextEncoder()\n ptyProcess.onData((data: string) => {\n try {\n onData(encoder.encode(data))\n } catch {\n // Swallow callback errors to prevent crashing the event loop.\n }\n })\n\n // Track exit\n let _exitCode: number | null = null\n let _exitResolve: ((code: number) => void) | null = null\n const exitedPromise = new Promise<number>((resolve) => {\n _exitResolve = resolve\n })\n ptyProcess.onExit((e: { exitCode: number }) => {\n _exitCode = e.exitCode\n _exitResolve?.(e.exitCode)\n })\n\n return {\n write(data: string): void {\n ptyProcess.write(data)\n },\n resize(newCols: number, newRows: number): void {\n ptyProcess.resize(newCols, newRows)\n },\n closePty(): void {\n try {\n ptyProcess.destroy()\n } catch {\n // Ignore cleanup errors\n }\n },\n kill(signal?: number): void {\n // node-pty uses string signals\n const sig = signal === 9 ? \"SIGKILL\" : \"SIGTERM\"\n try {\n ptyProcess.kill(sig)\n } catch {\n // Ignore if already dead\n }\n },\n get exitCode(): number | null {\n return _exitCode\n },\n get exited(): Promise<number> {\n return exitedPromise\n },\n get pid(): number {\n return ptyProcess.pid\n },\n }\n}\n","/**\n * PTY module for termless.\n *\n * Spawns a child process with a pseudo-terminal and bridges its I/O to a\n * TerminalBackend via callbacks. Works on both Bun (native PTY) and Node.js\n * (via node-pty optional peer dependency).\n */\n\nimport { spawnPortablePty, type PortablePtyProcess } from \"./spawn.ts\"\n\n// ── Types ──\n\nexport interface PtyHandle {\n /** Write raw data to the PTY (forwarded to the child process stdin). */\n write(data: string): void\n /** Resize the PTY dimensions. */\n resize(cols: number, rows: number): void\n /** Whether the child process is still running. */\n readonly alive: boolean\n /** Exit info string (e.g., \"exit=0\") when process has exited, null otherwise. */\n readonly exitInfo: string | null\n /** Gracefully close the PTY: SIGTERM, wait 2s, SIGKILL if needed. */\n close(): Promise<void>\n}\n\nexport interface PtySpawnOptions {\n /** Command to execute as [program, ...args]. Spawned directly without a shell. */\n command: string[]\n /** Additional environment variables (merged with process.env). */\n env?: Record<string, string>\n /** Working directory for the child process. */\n cwd?: string\n /** Terminal columns. */\n cols: number\n /** Terminal rows. */\n rows: number\n /** Callback invoked when the child process writes output data. */\n onData: (data: Uint8Array) => void\n}\n\nexport interface PtyShellOptions {\n /** Shell command string to execute via `bash -c`. Use when you need shell features (pipes, globbing, etc.). */\n shellCommand: string\n /** Additional environment variables (merged with process.env). */\n env?: Record<string, string>\n /** Working directory for the child process. */\n cwd?: string\n /** Terminal columns. */\n cols: number\n /** Terminal rows. */\n rows: number\n /** Callback invoked when the child process writes output data. */\n onData: (data: Uint8Array) => void\n}\n\n// ── Implementation ──\n\n/**\n * Spawn a child process with a PTY and return a handle for interacting with it.\n *\n * The command is spawned directly (no shell wrapper) to avoid shell injection.\n * Sets FORCE_COLOR=1 and TERM=xterm-256color to ensure proper color output.\n *\n * Runtime support:\n * - Bun: uses native `Bun.spawn()` with `terminal` option (built-in PTY)\n * - Node.js: uses `node-pty` (must be installed as a peer dependency)\n */\nexport function spawnPty(options: PtySpawnOptions | PtyShellOptions): PtyHandle {\n const { env, cwd, cols, rows, onData } = options\n\n // Determine the argv: direct command or shell-wrapped\n const argv = \"shellCommand\" in options ? [\"bash\", \"-c\", options.shellCommand] : options.command\n\n const proc: PortablePtyProcess = spawnPortablePty({\n argv,\n cols,\n rows,\n cwd,\n env: {\n FORCE_COLOR: \"1\",\n TERM: \"xterm-256color\",\n ...env,\n },\n onData,\n })\n\n let closed = false\n let exitCode: number | null = null\n\n // Track exit code (fire-and-forget)\n void (async () => {\n try {\n exitCode = await proc.exited\n } catch {\n // Process may have been killed before exit\n }\n })()\n\n async function close(): Promise<void> {\n if (closed) return\n closed = true\n\n // Close PTY write channel\n proc.closePty()\n\n // SIGTERM, then wait up to 2s, then SIGKILL\n try {\n proc.kill()\n const exited = await Promise.race([\n proc.exited.then(() => true as const),\n new Promise<false>((resolve) => setTimeout(() => resolve(false), 2000)),\n ])\n if (!exited) {\n proc.kill(9) // SIGKILL\n }\n } catch {\n // Ignore cleanup errors\n }\n }\n\n return {\n write(data: string): void {\n if (closed) throw new Error(\"PTY is closed\")\n proc.write(data)\n },\n\n resize(newCols: number, newRows: number): void {\n if (closed) throw new Error(\"PTY is closed\")\n proc.resize(newCols, newRows)\n },\n\n get alive(): boolean {\n return !closed && proc.exitCode === null\n },\n\n get exitInfo(): string | null {\n if (exitCode !== null) return `exit=${exitCode}`\n return null\n },\n\n close,\n }\n}\n","/**\n * SVG screenshot renderer for termless.\n *\n * Converts a terminal cell grid (TerminalReadable) into an SVG string.\n * Pure function with no side effects — suitable for snapshots, docs, and debugging.\n *\n * Supports VHS-style visual polish: padding, border radius, window bar\n * (macOS traffic light dots), margin, and margin fill color.\n */\n\nimport type { TerminalReadable, SvgScreenshotOptions, SvgTheme, Cell, RGB, CursorState, WindowBar } from \"./types.ts\"\n\n// ── Defaults ──\n\nconst DEFAULT_FONT_FAMILY = \"'Menlo', 'Monaco', 'Courier New', monospace\"\nconst DEFAULT_FONT_SIZE = 16\nconst DEFAULT_CELL_WIDTH = 9.6\nconst DEFAULT_CELL_HEIGHT = 20\n\nconst DEFAULT_THEME: Required<Pick<SvgTheme, \"foreground\" | \"background\" | \"cursor\">> = {\n foreground: \"#d4d4d4\",\n background: \"#1e1e1e\",\n cursor: \"#aeafad\",\n}\n\n// ── Color helpers ──\n\nexport function rgbToHex(color: RGB): string {\n const r = color.r.toString(16).padStart(2, \"0\")\n const g = color.g.toString(16).padStart(2, \"0\")\n const b = color.b.toString(16).padStart(2, \"0\")\n return `#${r}${g}${b}`\n}\n\nexport function rgbToString(color: RGB | null, fallback: string): string {\n return color ? rgbToHex(color) : fallback\n}\n\n// ── XML escaping ──\n\nfunction escapeXml(text: string): string {\n return text\n .replace(/&/g, \"&amp;\")\n .replace(/</g, \"&lt;\")\n .replace(/>/g, \"&gt;\")\n .replace(/\"/g, \"&quot;\")\n .replace(/'/g, \"&apos;\")\n}\n\n// ── Span grouping for text rendering ──\n\ninterface TextSpan {\n text: string\n fill: string\n bold: boolean\n italic: boolean\n dim: boolean\n underline: boolean\n strikethrough: boolean\n startCol: number\n}\n\nfunction cellFgBg(cell: Cell, themeFg: string, themeBg: string): { fg: string; bg: string } {\n let fg = rgbToString(cell.fg, themeFg)\n let bg = rgbToString(cell.bg, themeBg)\n if (cell.inverse) {\n ;[fg, bg] = [bg, fg]\n }\n return { fg, bg }\n}\n\nfunction spansMatch(\n a: TextSpan,\n fg: string,\n bold: boolean,\n italic: boolean,\n dim: boolean,\n underline: boolean,\n strikethrough: boolean,\n): boolean {\n return (\n a.fill === fg &&\n a.bold === bold &&\n a.italic === italic &&\n a.dim === dim &&\n a.underline === underline &&\n a.strikethrough === strikethrough\n )\n}\n\n// ── Background rect merging ──\n\ninterface BgRect {\n x: number\n y: number\n width: number\n height: number\n fill: string\n}\n\nfunction buildBgRects(\n lines: Cell[][],\n cellWidth: number,\n cellHeight: number,\n themeFg: string,\n themeBg: string,\n): BgRect[] {\n const rects: BgRect[] = []\n for (let row = 0; row < lines.length; row++) {\n const cells = lines[row]\n let runStart = -1\n let runColor = \"\"\n\n for (let col = 0; col < cells!.length; col++) {\n const cell = cells![col]!\n const { bg } = cellFgBg(cell, themeFg, themeBg)\n const hasCustomBg = bg !== themeBg\n\n if (hasCustomBg) {\n if (runStart >= 0 && runColor === bg) {\n // Continue the current run\n } else {\n // Flush previous run if any\n if (runStart >= 0) {\n rects.push({\n x: runStart * cellWidth,\n y: row * cellHeight,\n width: (col - runStart) * cellWidth,\n height: cellHeight,\n fill: runColor,\n })\n }\n runStart = col\n runColor = bg\n }\n } else {\n // No custom bg — flush any active run\n if (runStart >= 0) {\n rects.push({\n x: runStart * cellWidth,\n y: row * cellHeight,\n width: (col - runStart) * cellWidth,\n height: cellHeight,\n fill: runColor,\n })\n runStart = -1\n runColor = \"\"\n }\n }\n }\n\n // Flush trailing run\n if (runStart >= 0) {\n rects.push({\n x: runStart * cellWidth,\n y: row * cellHeight,\n width: (cells!.length - runStart) * cellWidth,\n height: cellHeight,\n fill: runColor,\n })\n }\n }\n return rects\n}\n\n// ── Text span building ──\n\nfunction buildTextSpans(cells: Cell[], themeFg: string, themeBg: string): TextSpan[] {\n const spans: TextSpan[] = []\n\n for (let col = 0; col < cells.length; col++) {\n const cell = cells[col]!\n\n // Skip continuation cell of a wide character (the second cell).\n // A wide char's first cell has wide=true and non-empty text.\n // The second cell typically has empty text — skip it.\n if (cell.char === \"\" && col > 0 && cells[col - 1]?.wide) {\n continue\n }\n\n const { fg } = cellFgBg(cell, themeFg, themeBg)\n const char = cell.char || \" \"\n const underline = cell.underline !== false\n\n const current = spans.length > 0 ? spans[spans.length - 1] : null\n if (current && spansMatch(current, fg, cell.bold, cell.italic, cell.dim, underline, cell.strikethrough)) {\n current.text += char\n } else {\n spans.push({\n text: char,\n fill: fg,\n bold: cell.bold,\n italic: cell.italic,\n dim: cell.dim,\n underline,\n strikethrough: cell.strikethrough,\n startCol: col,\n })\n }\n }\n\n return spans\n}\n\n// ── Resolved options ──\n\ninterface ResolvedOptions {\n fontFamily: string\n fontSize: number\n cellWidth: number\n cellHeight: number\n themeFg: string\n themeBg: string\n themeCursor: string\n padding: number\n borderRadius: number\n windowBar: WindowBar\n windowBarSize: number\n margin: number\n marginFill: string | null\n}\n\nfunction resolveOptions(options?: SvgScreenshotOptions): ResolvedOptions {\n return {\n fontFamily: options?.fontFamily ?? DEFAULT_FONT_FAMILY,\n fontSize: options?.fontSize ?? DEFAULT_FONT_SIZE,\n cellWidth: options?.cellWidth ?? DEFAULT_CELL_WIDTH,\n cellHeight: options?.cellHeight ?? DEFAULT_CELL_HEIGHT,\n themeFg: options?.theme?.foreground ?? DEFAULT_THEME.foreground,\n themeBg: options?.theme?.background ?? DEFAULT_THEME.background,\n themeCursor: options?.theme?.cursor ?? DEFAULT_THEME.cursor,\n padding: options?.padding ?? 0,\n borderRadius: options?.borderRadius ?? 0,\n windowBar: options?.windowBar ?? \"none\",\n windowBarSize: options?.windowBarSize ?? 40,\n margin: options?.margin ?? 0,\n marginFill: options?.marginFill ?? null,\n }\n}\n\n// ── Span → tspan conversion ──\n\nfunction spanToTspan(span: TextSpan, cellWidth: number, themeFg: string): string {\n const attrs: string[] = [`x=\"${span.startCol * cellWidth}\"`]\n if (span.fill !== themeFg) attrs.push(`fill=\"${span.fill}\"`)\n if (span.bold) attrs.push(`font-weight=\"bold\"`)\n if (span.italic) attrs.push(`font-style=\"italic\"`)\n if (span.dim) attrs.push(`opacity=\"0.5\"`)\n\n const decorations: string[] = []\n if (span.underline) decorations.push(\"underline\")\n if (span.strikethrough) decorations.push(\"line-through\")\n if (decorations.length > 0) attrs.push(`text-decoration=\"${decorations.join(\" \")}\"`)\n\n return `<tspan ${attrs.join(\" \")}>${escapeXml(span.text)}</tspan>`\n}\n\n// ── Text row rendering ──\n\nfunction renderTextRows(lines: Cell[][], opts: ResolvedOptions): string[] {\n const parts: string[] = []\n const { cellHeight, cellWidth, fontSize, fontFamily, themeFg, themeBg } = opts\n\n for (let row = 0; row < lines.length; row++) {\n const cells = lines[row]\n if (!cells || cells.length === 0) continue\n\n const spans = buildTextSpans(cells, themeFg, themeBg)\n if (spans.length === 0) continue\n\n // Baseline: top of cell + font size (approximate ascent for monospace)\n const y = row * cellHeight + fontSize\n parts.push(`<text x=\"0\" y=\"${y}\" font-family=\"${escapeXml(fontFamily)}\" font-size=\"${fontSize}\" fill=\"${themeFg}\">`)\n\n for (const span of spans) {\n parts.push(spanToTspan(span, cellWidth, themeFg))\n }\n\n parts.push(`</text>`)\n }\n\n return parts\n}\n\n// ── Cursor rendering ──\n\nfunction renderCursor(cursor: CursorState, opts: ResolvedOptions): string | null {\n if (!cursor.visible) return null\n\n const cx = cursor.x * opts.cellWidth\n const cy = cursor.y * opts.cellHeight\n\n // Default to block if backend doesn't report cursor style\n const style = cursor.style ?? \"block\"\n\n switch (style) {\n case \"block\":\n return `<rect x=\"${cx}\" y=\"${cy}\" width=\"${opts.cellWidth}\" height=\"${opts.cellHeight}\" fill=\"${opts.themeCursor}\" opacity=\"0.5\"/>`\n case \"underline\":\n return `<rect x=\"${cx}\" y=\"${cy + opts.cellHeight - 2}\" width=\"${opts.cellWidth}\" height=\"2\" fill=\"${opts.themeCursor}\"/>`\n case \"beam\":\n return `<rect x=\"${cx}\" y=\"${cy}\" width=\"2\" height=\"${opts.cellHeight}\" fill=\"${opts.themeCursor}\"/>`\n }\n}\n\n// ── Window bar rendering ──\n\nfunction renderWindowBar(barWidth: number, barHeight: number, style: WindowBar, borderRadius: number): string[] {\n if (style === \"none\") return []\n\n const parts: string[] = []\n\n // Window bar background — use only top border radius\n parts.push(\n `<rect width=\"${barWidth}\" height=\"${barHeight}\" rx=\"${borderRadius}\" ry=\"${borderRadius}\" fill=\"#333333\"/>`,\n )\n // Cover the bottom corners so only top has border radius\n if (borderRadius > 0) {\n parts.push(`<rect y=\"${barHeight - borderRadius}\" width=\"${barWidth}\" height=\"${borderRadius}\" fill=\"#333333\"/>`)\n }\n\n // Traffic light dots\n const dotRadius = 6\n const dotY = barHeight / 2\n const dotStartX = 20\n\n if (style === \"rings\") {\n // Outlined circles (like inactive/unfocused window)\n parts.push(\n `<circle cx=\"${dotStartX}\" cy=\"${dotY}\" r=\"${dotRadius}\" fill=\"none\" stroke=\"#ff5f57\" stroke-width=\"1.5\"/>`,\n )\n parts.push(\n `<circle cx=\"${dotStartX + 20}\" cy=\"${dotY}\" r=\"${dotRadius}\" fill=\"none\" stroke=\"#febc2e\" stroke-width=\"1.5\"/>`,\n )\n parts.push(\n `<circle cx=\"${dotStartX + 40}\" cy=\"${dotY}\" r=\"${dotRadius}\" fill=\"none\" stroke=\"#28c840\" stroke-width=\"1.5\"/>`,\n )\n } else {\n // Filled circles (colorful — like active/focused window)\n parts.push(`<circle cx=\"${dotStartX}\" cy=\"${dotY}\" r=\"${dotRadius}\" fill=\"#ff5f57\"/>`)\n parts.push(`<circle cx=\"${dotStartX + 20}\" cy=\"${dotY}\" r=\"${dotRadius}\" fill=\"#febc2e\"/>`)\n parts.push(`<circle cx=\"${dotStartX + 40}\" cy=\"${dotY}\" r=\"${dotRadius}\" fill=\"#28c840\"/>`)\n }\n\n return parts\n}\n\n// ── Main renderer ──\n\nexport function screenshotSvg(terminal: TerminalReadable, options?: SvgScreenshotOptions): string {\n const opts = resolveOptions(options)\n const {\n cellWidth,\n cellHeight,\n themeFg,\n themeBg,\n padding,\n borderRadius,\n windowBar,\n windowBarSize,\n margin,\n marginFill,\n } = opts\n\n const lines = terminal.getLines()\n const rows = lines.length\n const cols = rows > 0 ? Math.max(...lines.map((l) => l.length)) : 0\n\n // Terminal content dimensions\n const contentWidth = cols * cellWidth\n const contentHeight = rows * cellHeight\n\n // Detect whether any visual chrome is active\n const hasChrome = padding > 0 || borderRadius > 0 || windowBar !== \"none\" || margin > 0\n\n // Fast path: no chrome — produce the classic minimal SVG (backward-compatible)\n if (!hasChrome) {\n const totalWidth = contentWidth\n const totalHeight = contentHeight\n const parts: string[] = []\n\n parts.push(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${totalWidth}\" height=\"${totalHeight}\">`)\n parts.push(`<rect width=\"100%\" height=\"100%\" fill=\"${themeBg}\"/>`)\n\n for (const rect of buildBgRects(lines, cellWidth, cellHeight, themeFg, themeBg)) {\n parts.push(\n `<rect x=\"${rect.x}\" y=\"${rect.y}\" width=\"${rect.width}\" height=\"${rect.height}\" fill=\"${rect.fill}\"/>`,\n )\n }\n\n parts.push(...renderTextRows(lines, opts))\n\n const cursorSvg = renderCursor(terminal.getCursor(), opts)\n if (cursorSvg) parts.push(cursorSvg)\n\n parts.push(`</svg>`)\n return parts.join(\"\\n\")\n }\n\n // Chrome path: padding, border radius, window bar, margin\n const barHeight = windowBar !== \"none\" ? windowBarSize : 0\n const innerWidth = contentWidth + padding * 2\n const innerHeight = contentHeight + padding * 2 + barHeight\n const totalWidth = innerWidth + margin * 2\n const totalHeight = innerHeight + margin * 2\n\n const parts: string[] = []\n\n parts.push(`<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${totalWidth}\" height=\"${totalHeight}\">`)\n\n // Outer margin fill\n if (margin > 0 && marginFill) {\n parts.push(`<rect width=\"100%\" height=\"100%\" fill=\"${marginFill}\"/>`)\n }\n\n // Clip path for border radius\n if (borderRadius > 0) {\n parts.push(`<defs>`)\n parts.push(`<clipPath id=\"terminal-clip\">`)\n parts.push(\n `<rect x=\"${margin}\" y=\"${margin}\" width=\"${innerWidth}\" height=\"${innerHeight}\" rx=\"${borderRadius}\" ry=\"${borderRadius}\"/>`,\n )\n parts.push(`</clipPath>`)\n parts.push(`</defs>`)\n parts.push(`<g clip-path=\"url(#terminal-clip)\">`)\n }\n\n // Terminal background rect\n const bgAttrs =\n borderRadius > 0\n ? `x=\"${margin}\" y=\"${margin}\" width=\"${innerWidth}\" height=\"${innerHeight}\" rx=\"${borderRadius}\" ry=\"${borderRadius}\"`\n : `x=\"${margin}\" y=\"${margin}\" width=\"${innerWidth}\" height=\"${innerHeight}\"`\n parts.push(`<rect ${bgAttrs} fill=\"${themeBg}\"/>`)\n\n // Window bar\n if (windowBar !== \"none\") {\n parts.push(`<g transform=\"translate(${margin}, ${margin})\">`)\n parts.push(...renderWindowBar(innerWidth, barHeight, windowBar, borderRadius))\n parts.push(`</g>`)\n }\n\n // Content group — offset by margin + padding + window bar\n const contentOffsetX = margin + padding\n const contentOffsetY = margin + padding + barHeight\n parts.push(`<g transform=\"translate(${contentOffsetX}, ${contentOffsetY})\">`)\n\n for (const rect of buildBgRects(lines, cellWidth, cellHeight, themeFg, themeBg)) {\n parts.push(`<rect x=\"${rect.x}\" y=\"${rect.y}\" width=\"${rect.width}\" height=\"${rect.height}\" fill=\"${rect.fill}\"/>`)\n }\n\n parts.push(...renderTextRows(lines, opts))\n\n const cursorSvg = renderCursor(terminal.getCursor(), opts)\n if (cursorSvg) parts.push(cursorSvg)\n\n parts.push(`</g>`)\n\n if (borderRadius > 0) {\n parts.push(`</g>`)\n }\n\n parts.push(`</svg>`)\n return parts.join(\"\\n\")\n}\n","/**\n * PNG screenshot renderer for termless.\n *\n * Renders the terminal as SVG via screenshotSvg(), then rasterizes to PNG\n * using @resvg/resvg-js (optional dependency). Throws a clear error if\n * @resvg/resvg-js is not installed.\n */\n\nimport type { TerminalReadable, SvgScreenshotOptions } from \"./types.ts\"\nimport { screenshotSvg } from \"./svg.ts\"\n\nexport interface PngScreenshotOptions extends SvgScreenshotOptions {\n /** Render scale factor (default: 2 for retina-quality output). */\n scale?: number\n}\n\n// Lazy-cached import of @resvg/resvg-js\nlet resvgModule: { Resvg: any } | null = null\n\nasync function loadResvg() {\n if (resvgModule) return resvgModule\n try {\n resvgModule = await import(\"@resvg/resvg-js\")\n return resvgModule\n } catch {\n throw new Error(\"screenshotPng() requires @resvg/resvg-js. Install it:\\n\" + \" bun add -d @resvg/resvg-js\")\n }\n}\n\n/**\n * Render a terminal screenshot as a PNG buffer.\n *\n * Requires `@resvg/resvg-js` as an optional dependency:\n * bun add -d @resvg/resvg-js\n */\nexport async function screenshotPng(terminal: TerminalReadable, options?: PngScreenshotOptions): Promise<Uint8Array> {\n const svg = screenshotSvg(terminal, options)\n const scale = options?.scale ?? 2\n\n const { Resvg } = await loadResvg()\n\n const resvg = new Resvg(svg, {\n fitTo: { mode: \"zoom\" as const, value: scale },\n font: {\n loadSystemFonts: true,\n defaultFontFamily: \"Menlo\",\n },\n })\n return resvg.render().asPng()\n}\n","/**\n * View factories for composable terminal regions.\n *\n * Views are lightweight wrappers that read from a TerminalReadable on demand.\n * All row-based views are lazy — they recompute buffer offsets on every access\n * so auto-retry matchers see fresh data when polled across time.\n */\n\nimport type { Cell, CellView, RegionView, RowView, TerminalReadable, UnderlineStyle } from \"./types.ts\"\n\n// ── Helpers ──\n\n/** Convert a Cell[] to trimmed text. */\nfunction cellsToText(cells: Cell[]): string {\n return cells\n .map((c) => c.char || \" \")\n .join(\"\")\n .trimEnd()\n}\n\n/** Get rows of text from a TerminalReadable for an absolute row range. */\nfunction getRowTexts(readable: TerminalReadable, startRow: number, endRow: number): string[] {\n const lines: string[] = []\n for (let i = startRow; i < endRow; i++) {\n lines.push(cellsToText(readable.getLine(i)))\n }\n return lines\n}\n\n/**\n * Create a lazy RegionView from a row-range resolver.\n * The resolver is called on every getText()/getLines() access,\n * so the view always reflects current terminal state.\n */\nfunction createLazyRegionView(\n readable: TerminalReadable,\n resolveRange: () => [start: number, end: number],\n): RegionView {\n return {\n getText(): string {\n const [start, end] = resolveRange()\n return getRowTexts(readable, start, end).join(\"\\n\")\n },\n getLines(): string[] {\n const [start, end] = resolveRange()\n return getRowTexts(readable, start, end)\n },\n containsText(text: string): boolean {\n return this.getText().includes(text)\n },\n }\n}\n\n// ── CellView ──\n\n/** Create a CellView from a Cell with positional context. */\nexport function createCellView(cell: Cell, row: number, col: number): CellView {\n return {\n char: cell.char,\n row,\n col,\n fg: cell.fg,\n bg: cell.bg,\n bold: cell.bold,\n dim: cell.dim,\n italic: cell.italic,\n underline: cell.underline,\n underlineColor: cell.underlineColor,\n strikethrough: cell.strikethrough,\n inverse: cell.inverse,\n blink: cell.blink,\n hidden: cell.hidden,\n wide: cell.wide,\n continuation: cell.continuation,\n hyperlink: cell.hyperlink,\n }\n}\n\n// ── RegionView ──\n\n/** Create a RegionView for a fixed absolute row range [startRow, endRow). */\nexport function createRegionView(readable: TerminalReadable, startRow: number, endRow: number): RegionView {\n return createLazyRegionView(readable, () => [startRow, endRow])\n}\n\n// ── RowView ──\n\n/** Create a RowView for an absolute row position. screenRow is the display row number. */\nexport function createRowView(readable: TerminalReadable, absRow: number, screenRow: number): RowView {\n return {\n get row() {\n return screenRow\n },\n get cells() {\n return readable.getLine(absRow)\n },\n getText(): string {\n return cellsToText(readable.getLine(absRow))\n },\n getLines(): string[] {\n return [this.getText()]\n },\n containsText(text: string): boolean {\n return this.getText().includes(text)\n },\n cellAt(col: number): CellView {\n return createCellView(readable.getCell(absRow, col), screenRow, col)\n },\n }\n}\n\n// ── Specialized Region Views ──\n\n/**\n * Screen view: the fixed rows × cols grid at the bottom of the buffer.\n * In alt mode, this is the entire alt buffer.\n */\nexport function createScreenView(readable: TerminalReadable): RegionView {\n return createLazyRegionView(readable, () => {\n const { totalLines, screenLines } = readable.getScrollback()\n const base = totalLines - screenLines\n return [base, base + screenLines]\n })\n}\n\n/**\n * Scrollback view: history lines above the screen.\n * Empty in alt screen mode.\n * @param n - If provided, only the last N scrollback lines.\n */\nexport function createScrollbackView(readable: TerminalReadable, n?: number): RegionView {\n return createLazyRegionView(readable, () => {\n const { totalLines, screenLines } = readable.getScrollback()\n const base = totalLines - screenLines\n if (base <= 0) return [0, 0]\n const start = n != null ? Math.max(0, base - n) : 0\n return [start, base]\n })\n}\n\n/**\n * Buffer view: everything (scrollback + screen).\n * Uses readable.getText() directly — not row-based.\n */\nexport function createBufferView(readable: TerminalReadable): RegionView {\n return {\n getText(): string {\n return readable.getText()\n },\n getLines(): string[] {\n return readable.getText().split(\"\\n\")\n },\n containsText(text: string): boolean {\n return readable.getText().includes(text)\n },\n }\n}\n\n/**\n * Viewport view: what's visible at the current scroll position.\n * At bottom (viewportOffset = totalLines - screenLines): same as screen.\n * Scrolled up: shows older scrollback lines.\n */\nexport function createViewportView(readable: TerminalReadable): RegionView {\n return createLazyRegionView(readable, () => {\n const { viewportOffset, screenLines } = readable.getScrollback()\n return [viewportOffset, viewportOffset + screenLines]\n })\n}\n\n/**\n * Range view: a rectangular region of the screen.\n * Coordinates are screen-relative. Uses getTextRange() — not row-based.\n */\nexport function createRangeView(\n readable: TerminalReadable,\n r1: number,\n c1: number,\n r2: number,\n c2: number,\n): RegionView {\n return {\n getText(): string {\n const { totalLines, screenLines } = readable.getScrollback()\n const base = totalLines - screenLines\n return readable.getTextRange(base + r1, c1, base + r2, c2)\n },\n getLines(): string[] {\n return this.getText().split(\"\\n\")\n },\n containsText(text: string): boolean {\n return this.getText().includes(text)\n },\n }\n}\n","/**\n * Terminal — high-level API wrapping a TerminalBackend + optional PTY.\n *\n * Provides the main createTerminal() factory that composes a backend with\n * optional process spawning, key input, text search, and screenshot capabilities.\n */\n\nimport type {\n Cell,\n CellView,\n CursorState,\n PngScreenshotOptions,\n RegionView,\n RowView,\n ScrollbackState,\n SvgScreenshotOptions,\n Terminal,\n TerminalBackend,\n TerminalCreateOptions,\n TerminalMode,\n TextPosition,\n MouseOptions,\n MouseModifiers,\n} from \"./types.ts\"\nimport { parseKey, keyToAnsi } from \"./key-mapping.ts\"\nimport { spawnPty, type PtyHandle } from \"./pty.ts\"\nimport { screenshotSvg } from \"./svg.ts\"\nimport { screenshotPng } from \"./png.ts\"\nimport {\n createBufferView,\n createCellView,\n createRangeView,\n createRowView,\n createScreenView,\n createScrollbackView,\n createViewportView,\n} from \"./views.ts\"\n\n// ── Constants ──\n\nconst POLL_INTERVAL = 50\nconst DEFAULT_COLS = 80\nconst DEFAULT_ROWS = 24\nconst DEFAULT_WAIT_TIMEOUT = 5000\nconst DEFAULT_STABLE_MS = 200\n\n// ── Text encoder (shared) ──\n\nconst encoder = new TextEncoder()\n\n// ── Factory ──\n\n/**\n * Create a Terminal instance wrapping a backend with optional PTY support.\n *\n * The terminal initializes the backend immediately and provides methods for:\n * - Feeding data directly (no PTY)\n * - Spawning a child process with a PTY\n * - Sending key presses and typed text to the PTY\n * - Waiting for terminal content to appear or stabilize\n * - Searching terminal text\n * - Taking SVG and PNG screenshots\n */\nexport function createTerminal(options: TerminalCreateOptions): Terminal {\n const { backend, scrollbackLimit } = options\n let cols = options.cols ?? DEFAULT_COLS\n let rows = options.rows ?? DEFAULT_ROWS\n\n // Initialize the backend\n backend.init({ cols, rows, scrollbackLimit })\n\n let ptyHandle: PtyHandle | null = null\n let closed = false\n\n // ── OSC 52 clipboard capture ──\n\n /** OSC 52 regex: \\x1b]52;c;<base64>\\x07 or \\x1b]52;c;<base64>\\x1b\\\\ */\n const osc52Re = /\\x1b\\]52;[a-z]*;([A-Za-z0-9+/=]+)(?:\\x07|\\x1b\\\\)/g\n\n const clipboardWrites: string[] = []\n\n function scanOsc52(data: string): void {\n osc52Re.lastIndex = 0\n let match: RegExpExecArray | null\n while ((match = osc52Re.exec(data)) !== null) {\n try {\n const decoded = atob(match[1]!)\n clipboardWrites.push(decoded)\n } catch {\n // Ignore invalid base64\n }\n }\n }\n\n // ── TerminalReadable delegation ──\n\n function getText(): string {\n return backend.getText()\n }\n\n function getTextRange(startRow: number, startCol: number, endRow: number, endCol: number): string {\n return backend.getTextRange(startRow, startCol, endRow, endCol)\n }\n\n function getCell(row: number, col: number): Cell {\n return backend.getCell(row, col)\n }\n\n function getLine(row: number): Cell[] {\n return backend.getLine(row)\n }\n\n function getLines(): Cell[][] {\n return backend.getLines()\n }\n\n function getCursor(): CursorState {\n return backend.getCursor()\n }\n\n function getMode(mode: TerminalMode): boolean {\n return backend.getMode(mode)\n }\n\n function getTitle(): string {\n return backend.getTitle()\n }\n\n function getScrollback(): ScrollbackState {\n return backend.getScrollback()\n }\n\n // ── Data feed ──\n\n function feed(data: Uint8Array | string): void {\n if (closed) throw new Error(\"Terminal is closed\")\n const text = typeof data === \"string\" ? data : new TextDecoder().decode(data)\n scanOsc52(text)\n const bytes = typeof data === \"string\" ? encoder.encode(data) : data\n backend.feed(bytes)\n }\n\n // ── PTY lifecycle ──\n\n async function spawn(command: string[], spawnOpts?: { env?: Record<string, string>; cwd?: string }): Promise<void> {\n if (closed) throw new Error(\"Terminal is closed\")\n if (ptyHandle) throw new Error(\"Terminal already has a spawned process\")\n\n ptyHandle = spawnPty({\n command,\n env: spawnOpts?.env,\n cwd: spawnOpts?.cwd,\n cols,\n rows,\n onData: (data) => {\n scanOsc52(new TextDecoder().decode(data))\n backend.feed(data)\n },\n })\n\n // Wire emulator→PTY response path (e.g., cursor position reports, DA responses)\n backend.onResponse = (data) => {\n if (ptyHandle?.alive) {\n ptyHandle.write(new TextDecoder().decode(data))\n }\n }\n }\n\n // ── Input ──\n\n function press(key: string): void {\n if (closed) throw new Error(\"Terminal is closed\")\n if (!ptyHandle) throw new Error(\"No PTY spawned — call spawn() first\")\n\n const desc = parseKey(key)\n const encoded = backend.encodeKey(desc)\n\n // encodeKey returns backend-specific encoding; fall back to ANSI if empty\n if (encoded.length > 0) {\n ptyHandle.write(new TextDecoder().decode(encoded))\n } else {\n const ansi = keyToAnsi(desc)\n if (ansi) ptyHandle.write(ansi)\n }\n }\n\n function type(text: string): void {\n if (closed) throw new Error(\"Terminal is closed\")\n if (!ptyHandle) throw new Error(\"No PTY spawned — call spawn() first\")\n ptyHandle.write(text)\n }\n\n // ── Mouse (SGR mode 1006) ──\n\n /** Encode SGR button byte: button number + modifier bits. */\n function sgrButton(options?: MouseOptions): number {\n let btn = options?.button ?? 0\n if (options?.shift) btn += 4\n if (options?.alt) btn += 8\n if (options?.ctrl) btn += 16\n return btn\n }\n\n function requirePty(): PtyHandle {\n if (closed) throw new Error(\"Terminal is closed\")\n if (!ptyHandle) throw new Error(\"No PTY spawned — call spawn() first\")\n return ptyHandle\n }\n\n function click(x: number, y: number, options?: MouseOptions): void {\n const pty = requirePty()\n const col = x + 1\n const row = y + 1\n const btn = sgrButton(options)\n pty.write(`\\x1b[<${btn};${col};${row}M`) // press\n pty.write(`\\x1b[<${btn};${col};${row}m`) // release\n }\n\n async function dblclick(x: number, y: number, options?: MouseOptions & { delay?: number }): Promise<void> {\n const delay = options?.delay ?? 50\n click(x, y, options)\n await new Promise((r) => setTimeout(r, delay))\n click(x, y, options)\n }\n\n function mouseDown(x: number, y: number, options?: MouseOptions): void {\n const pty = requirePty()\n const btn = sgrButton(options)\n pty.write(`\\x1b[<${btn};${x + 1};${y + 1}M`)\n }\n\n function mouseUp(x: number, y: number, options?: MouseOptions): void {\n const pty = requirePty()\n const btn = sgrButton(options)\n pty.write(`\\x1b[<${btn};${x + 1};${y + 1}m`)\n }\n\n function mouseMove(x: number, y: number, options?: MouseOptions): void {\n const pty = requirePty()\n // SGR motion: button 32 + modifier bits (drag with no button = just move)\n const btn = 32 + sgrButton(options)\n pty.write(`\\x1b[<${btn};${x + 1};${y + 1}M`)\n }\n\n function wheel(deltaX: number, deltaY: number, options?: { x?: number; y?: number } & MouseModifiers): void {\n const pty = requirePty()\n const col = (options?.x ?? 0) + 1\n const row = (options?.y ?? 0) + 1\n let mods = 0\n if (options?.shift) mods += 4\n if (options?.alt) mods += 8\n if (options?.ctrl) mods += 16\n // SGR wheel: button 64=up, 65=down. Horizontal: future extension.\n if (deltaY < 0) {\n for (let i = 0; i < Math.abs(deltaY); i++) pty.write(`\\x1b[<${64 + mods};${col};${row}M`)\n } else if (deltaY > 0) {\n for (let i = 0; i < deltaY; i++) pty.write(`\\x1b[<${65 + mods};${col};${row}M`)\n }\n }\n\n // ── Waiting ──\n\n /** @deprecated Use `await expect(term.screen).toContainText(\"text\", { timeout })` instead. */\n async function waitFor(text: string, timeout = DEFAULT_WAIT_TIMEOUT): Promise<void> {\n const start = Date.now()\n while (Date.now() - start < timeout) {\n if (getText().includes(text)) return\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL))\n }\n throw new Error(`Timeout waiting for \"${text}\" after ${timeout}ms`)\n }\n\n async function waitForStable(stableMs = DEFAULT_STABLE_MS, timeout = DEFAULT_WAIT_TIMEOUT): Promise<void> {\n const start = Date.now()\n let lastContent = \"\"\n let stableStart = Date.now()\n\n while (Date.now() - start < timeout) {\n const content = getText()\n if (content === lastContent) {\n if (Date.now() - stableStart >= stableMs) return\n } else {\n lastContent = content\n stableStart = Date.now()\n }\n await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL))\n }\n throw new Error(`Terminal did not stabilize within ${timeout}ms`)\n }\n\n // ── Search ──\n\n function find(text: string): TextPosition | null {\n const content = getText()\n const lines = content.split(\"\\n\")\n for (let row = 0; row < lines.length; row++) {\n const col = lines[row]!.indexOf(text)\n if (col !== -1) {\n return { row, col, text }\n }\n }\n return null\n }\n\n function findAll(pattern: RegExp): TextPosition[] {\n const content = getText()\n const lines = content.split(\"\\n\")\n const results: TextPosition[] = []\n\n for (let row = 0; row < lines.length; row++) {\n const line = lines[row]!\n // Use a new regex per line to reset lastIndex for global patterns\n const re = new RegExp(pattern.source, pattern.flags.includes(\"g\") ? pattern.flags : `${pattern.flags}g`)\n let match: RegExpExecArray | null\n while ((match = re.exec(line)) !== null) {\n results.push({ row, col: match.index, text: match[0] })\n // Prevent infinite loop on zero-length matches\n if (match[0].length === 0) re.lastIndex++\n }\n }\n\n return results\n }\n\n // ── Screenshot ──\n\n function screenshot(svgOptions?: SvgScreenshotOptions): string {\n return screenshotSvg(terminal, svgOptions)\n }\n\n function screenshotAsPng(pngOptions?: PngScreenshotOptions): Promise<Uint8Array> {\n return screenshotPng(terminal, pngOptions)\n }\n\n // ── Resize ──\n\n function resize(newCols: number, newRows: number): void {\n if (closed) throw new Error(\"Terminal is closed\")\n cols = newCols\n rows = newRows\n backend.resize(newCols, newRows)\n if (ptyHandle?.alive) {\n ptyHandle.resize(newCols, newRows)\n }\n }\n\n // ── Cleanup ──\n\n async function close(): Promise<void> {\n if (closed) return\n closed = true\n\n // Disconnect emulator→PTY response path\n backend.onResponse = undefined\n\n if (ptyHandle) {\n await ptyHandle.close()\n ptyHandle = null\n }\n\n backend.destroy()\n }\n\n // ── Terminal object ──\n\n const terminal: Terminal = {\n get cols() {\n return cols\n },\n get rows() {\n return rows\n },\n get backend() {\n return backend\n },\n\n // TerminalReadable\n getText,\n getTextRange,\n getCell,\n getLine,\n getLines,\n getCursor,\n getMode,\n getTitle,\n getScrollback,\n\n // Region selectors\n get screen(): RegionView {\n return createScreenView(backend)\n },\n get scrollback(): RegionView {\n return createScrollbackView(backend)\n },\n get buffer(): RegionView {\n return createBufferView(backend)\n },\n get viewport(): RegionView {\n return createViewportView(backend)\n },\n row(n: number): RowView {\n const { totalLines, screenLines } = backend.getScrollback()\n const base = totalLines - screenLines\n const screenRow = n >= 0 ? n : screenLines + n\n return createRowView(backend, base + screenRow, screenRow)\n },\n cell(r: number, c: number): CellView {\n const { totalLines, screenLines } = backend.getScrollback()\n const base = totalLines - screenLines\n const screenRow = r >= 0 ? r : screenLines + r\n return createCellView(backend.getCell(base + screenRow, c), screenRow, c)\n },\n range(r1: number, c1: number, r2: number, c2: number): RegionView {\n return createRangeView(backend, r1, c1, r2, c2)\n },\n firstRow(): RowView {\n return this.row(0)\n },\n lastRow(): RowView {\n return this.row(-1)\n },\n\n // Data feed\n feed,\n\n // PTY\n spawn,\n get alive() {\n return ptyHandle?.alive ?? false\n },\n get exitInfo() {\n return ptyHandle?.exitInfo ?? null\n },\n\n // Input — keyboard\n press,\n type,\n\n // Clipboard\n clipboardWrites,\n\n // Input — mouse\n click,\n dblclick,\n mouseDown,\n mouseUp,\n mouseMove,\n wheel,\n\n // Waiting\n waitFor,\n waitForStable,\n\n // Search\n find,\n findAll,\n\n // Screenshot\n screenshotSvg: screenshot,\n screenshotPng: screenshotAsPng,\n\n // Resize\n resize,\n\n // Cleanup\n close,\n [Symbol.asyncDispose]: close,\n }\n\n return terminal\n}\n","/**\n * Backend registry — one function, everything derived.\n *\n * @example\n * ```typescript\n * import { backend } from \"termless\"\n *\n * const b = await backend(\"ghostty\")\n * const b = await backend(\"xtermjs\", { version: \"5.4.0\" })\n * ```\n */\n\nimport { readFileSync, existsSync, readdirSync, mkdirSync, writeFileSync } from \"node:fs\"\nimport { dirname, join } from \"node:path\"\nimport { homedir } from \"node:os\"\nimport { fileURLToPath } from \"node:url\"\nimport { execSync } from \"node:child_process\"\nimport type { TerminalBackend, TerminalOptions, Terminal } from \"./types.ts\"\nimport { createTerminal } from \"./terminal.ts\"\n\n// ═══════════════════════════════════════════════════════\n// Manifest\n// ═══════════════════════════════════════════════════════\n\nexport interface BackendEntry {\n package: string\n upstream: string | null\n version: string | null\n type: \"js\" | \"wasm\" | \"native\" | \"os\"\n default?: boolean\n platforms?: string[]\n label?: string\n description?: string\n url?: string\n caveat?: string\n slug?: string\n terminal?: {\n name: string\n description: string\n body?: string\n url?: string\n repo?: string\n author?: string\n }\n}\n\nexport interface Manifest {\n version: string\n backends: Record<string, BackendEntry>\n}\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\nconst MANIFEST_PATH = join(__dirname, \"..\", \"backends.json\")\n\nlet _manifest: Manifest | null = null\n\nexport function manifest(): Manifest {\n if (_manifest) return _manifest\n const raw = JSON.parse(readFileSync(MANIFEST_PATH, \"utf-8\")) as any\n // Normalize: map upstreamVersion → version for cleaner access\n const backends: Record<string, BackendEntry> = {}\n for (const [name, entry] of Object.entries(raw.backends) as [string, any][]) {\n backends[name] = {\n package: entry.package,\n upstream: entry.upstream ?? null,\n version: entry.upstreamVersion ?? null,\n type: entry.type,\n default: entry.default,\n platforms: entry.platforms,\n label: entry.label,\n description: entry.description,\n url: entry.url,\n caveat: entry.caveat,\n slug: entry.slug,\n terminal: entry.terminal,\n }\n }\n _manifest = { version: raw.version, backends }\n return _manifest\n}\n\n// ═══════════════════════════════════════════════════════\n// Backend types — polymorphic on js/wasm/native/os\n// ═══════════════════════════════════════════════════════\n\ninterface BackendType {\n /** Check if the backend is built and ready to use. */\n isReady(pkgDir: string): boolean\n /** Build the backend from source. No-op if already ready. */\n build(pkgDir: string): void\n /** Resolve (import + initialize) the backend. */\n resolve(packageName: string, opts?: Partial<TerminalOptions>): Promise<TerminalBackend>\n}\n\nfunction hasFilesWithExt(dir: string, ext: string, subdirs: string[] = []): boolean {\n const dirs = [dir, ...subdirs.map((s) => join(dir, s))]\n for (const d of dirs) {\n if (!existsSync(d)) continue\n try {\n for (const f of readdirSync(d)) {\n if (f.endsWith(ext)) return true\n }\n } catch {}\n }\n return false\n}\n\nfunction resolveModule(pkg: string, opts?: Partial<TerminalOptions>) {\n return async () => {\n const mod = await import(pkg)\n return typeof mod.resolve === \"function\"\n ? mod.resolve(opts)\n : mod[Object.keys(mod).find((k) => k.startsWith(\"create\"))!](opts)\n }\n}\n\n/** Run a backend's build/build.sh, falling back to nix if tools aren't in PATH. */\nfunction runBuildScript(pkgDir: string): void {\n const buildScript = join(pkgDir, \"build\", \"build.sh\")\n if (!existsSync(buildScript)) return\n console.log(` Building in ${pkgDir}...`)\n try {\n execSync(`bash build/build.sh`, { cwd: pkgDir, stdio: \"inherit\" })\n } catch {\n const flakeDir = join(__dirname, \"..\")\n if (existsSync(join(flakeDir, \"flake.nix\"))) {\n execSync(`nix develop ${flakeDir} --command bash build/build.sh`, { cwd: pkgDir, stdio: \"inherit\" })\n } else {\n throw new Error(`Build failed. Install dependencies or use the nix flake: nix develop`)\n }\n }\n}\n\nconst backendTypes: Record<string, BackendType> = {\n js: {\n isReady: () => true,\n build: () => {},\n resolve: async (pkg, opts) => resolveModule(pkg, opts)(),\n },\n\n wasm: {\n isReady: (pkgDir) => {\n // WASM backends distributed via npm are ready immediately (wasm bundled in package).\n // WASM backends built from source need a .wasm file.\n return hasFilesWithExt(pkgDir, \".wasm\", [\"wasm\", \"build\"]) || !existsSync(join(pkgDir, \"build\"))\n },\n build: (pkgDir) => runBuildScript(pkgDir),\n resolve: async (pkg, opts) => resolveModule(pkg, opts)(),\n },\n\n native: {\n isReady: (pkgDir) => hasFilesWithExt(pkgDir, \".node\", [\"build\", \"native\"]),\n build: (pkgDir) => runBuildScript(pkgDir),\n resolve: async (pkg, opts) => resolveModule(pkg, opts)(),\n },\n\n os: {\n isReady: () => true,\n build: () => {},\n resolve: async (pkg, opts) => resolveModule(pkg, opts)(),\n },\n}\n\n// ═══════════════════════════════════════════════════════\n// Build\n// ═══════════════════════════════════════════════════════\n\n/** Build a backend's native artifacts if not already ready. */\nexport function buildBackend(name: string): void {\n const m = manifest()\n const e = m.backends[name]\n if (!e) throw new Error(`Unknown backend: ${name}`)\n\n const type = backendTypes[e.type]\n if (!type) return\n\n const pkgDir = findPackageDir(e.package)\n if (!pkgDir) return\n\n if (!type.isReady(pkgDir)) {\n type.build(pkgDir)\n }\n}\n\n// ═══════════════════════════════════════════════════════\n// Core API\n// ═══════════════════════════════════════════════════════\n\n/**\n * Resolve a backend by name. The one function you need.\n *\n * @example\n * ```typescript\n * const b = await backend(\"ghostty\")\n * const b = await backend(\"xtermjs\", { version: \"5.4.0\" })\n * ```\n */\nexport async function backend(\n name: string,\n opts?: Partial<TerminalOptions> & { version?: string },\n): Promise<TerminalBackend> {\n const m = manifest()\n const entry = m.backends[name]\n\n if (!entry) {\n throw new Error(`Unknown backend \"${name}\". Available: ${Object.keys(m.backends).join(\", \")}`)\n }\n\n const type = backendTypes[entry.type]\n if (!type) throw new Error(`Unknown backend type \"${entry.type}\" for \"${name}\"`)\n\n // Version-pinned resolution\n if (opts?.version && opts.version !== entry.version) {\n return resolveVersioned(name, entry, type, opts.version, opts)\n }\n\n // Check if package is importable\n try {\n import.meta.resolve(entry.package)\n } catch {\n throw new Error(`Backend \"${name}\" is not installed.\\n` + `Run: bunx termless backend install ${name}`)\n }\n\n // Check if built\n const pkgDir = findPackageDir(entry.package)\n if (pkgDir && !type.isReady(pkgDir)) {\n throw new Error(`Backend \"${name}\" is installed but not built.\\n` + `Run: cd ${pkgDir} && ${getBuildHint(entry)}`)\n }\n\n return type.resolve(entry.package, opts)\n}\n\n/** Check if a backend is installed and ready. */\nexport function isReady(name: string): boolean {\n const m = manifest()\n const entry = m.backends[name]\n if (!entry) return false\n\n try {\n import.meta.resolve(entry.package)\n } catch {\n return false\n }\n\n const type = backendTypes[entry.type]\n if (!type) return false\n\n const pkgDir = findPackageDir(entry.package)\n return pkgDir ? type.isReady(pkgDir) : false\n}\n\n/** List all backend names. */\nexport function backends(): string[] {\n return Object.keys(manifest().backends)\n}\n\n/** Get entry for a backend. */\nexport function entry(name: string): BackendEntry | undefined {\n return manifest().backends[name]\n}\n\n/** Create a Terminal by backend name. */\nexport async function createTerminalByName(\n name: string,\n opts?: { cols?: number; rows?: number; scrollbackLimit?: number; version?: string },\n): Promise<Terminal> {\n const b = await backend(name, opts)\n return createTerminal({ backend: b, ...opts })\n}\n\n// ═══════════════════════════════════════════════════════\n// Version-pinned resolution\n// ═══════════════════════════════════════════════════════\n\nconst CACHE_DIR = join(process.env.XDG_CACHE_HOME ?? join(homedir(), \".cache\"), \"termless\", \"backends\")\n\nasync function resolveVersioned(\n name: string,\n entry: BackendEntry,\n type: BackendType,\n version: string,\n opts?: Partial<TerminalOptions>,\n): Promise<TerminalBackend> {\n if (entry.type === \"native\") {\n throw new Error(\n `Version-pinned resolution for native backend \"${name}\" requires nix.\\n` +\n `Run: nix develop .#${name}-${version.replace(/\\./g, \"_\")}`,\n )\n }\n\n if (!entry.upstream) {\n throw new Error(`Backend \"${name}\" has no upstream to version-pin.`)\n }\n\n const cacheDir = ensureCachedVersion(entry.upstream, version)\n\n const origNodePath = process.env.NODE_PATH\n process.env.NODE_PATH = join(cacheDir, \"node_modules\") + (origNodePath ? `:${origNodePath}` : \"\")\n\n try {\n return await type.resolve(entry.package, opts)\n } finally {\n if (origNodePath) process.env.NODE_PATH = origNodePath\n else delete process.env.NODE_PATH\n }\n}\n\n// ═══════════════════════════════════════════════════════\n// Version cache (shared by backend() and census)\n// ═══════════════════════════════════════════════════════\n\n/**\n * Install an upstream package at a specific version to the cache directory.\n * Returns the cache dir path (contains node_modules/).\n * Shared by backend() version-pinned resolution and census versioned runs.\n */\nexport function ensureCachedVersion(upstream: string, version: string): string {\n const cacheDir = join(CACHE_DIR, `${upstream.replace(/[/@]/g, \"_\")}-${version}`)\n\n if (!existsSync(join(cacheDir, \"node_modules\"))) {\n mkdirSync(cacheDir, { recursive: true })\n writeFileSync(\n join(cacheDir, \"package.json\"),\n JSON.stringify({ private: true, dependencies: { [upstream]: version } }),\n )\n execSync(\"bun install --no-save\", { cwd: cacheDir, stdio: \"pipe\" })\n }\n\n return cacheDir\n}\n\n// ═══════════════════════════════════════════════════════\n// Helpers\n// ═══════════════════════════════════════════════════════\n\nfunction findPackageDir(packageName: string): string | null {\n try {\n const resolved = fileURLToPath(import.meta.resolve(packageName))\n let dir = dirname(resolved)\n for (let i = 0; i < 10; i++) {\n if (existsSync(join(dir, \"package.json\"))) {\n try {\n const pkg = JSON.parse(readFileSync(join(dir, \"package.json\"), \"utf-8\")) as any\n if (pkg.name === packageName) return dir\n } catch {}\n }\n const parent = dirname(dir)\n if (parent === dir) break\n dir = parent\n }\n } catch {}\n return null\n}\n\nfunction getBuildHint(entry: BackendEntry): string {\n if (entry.type === \"native\") return \"cargo build --release\"\n if (entry.type === \"wasm\") return \"bash build/build.sh\"\n return \"bun install\"\n}\n\n/** Get installed version of a backend package. */\nexport function getInstalledVersion(packageName: string): string | null {\n const dir = findPackageDir(packageName)\n if (!dir) return null\n try {\n const pkg = JSON.parse(readFileSync(join(dir, \"package.json\"), \"utf-8\")) as Record<string, any>\n return pkg.version ?? null\n } catch {\n return null\n }\n}\n\n/** Detect package manager from lockfiles. */\nexport function detectPackageManager(): \"bun\" | \"npm\" | \"pnpm\" | \"yarn\" {\n const cwd = process.cwd()\n if (existsSync(join(cwd, \"bun.lockb\")) || existsSync(join(cwd, \"bun.lock\"))) return \"bun\"\n if (existsSync(join(cwd, \"pnpm-lock.yaml\"))) return \"pnpm\"\n if (existsSync(join(cwd, \"yarn.lock\"))) return \"yarn\"\n return \"npm\"\n}\n\nexport type ResolveOptions = Partial<TerminalOptions> & { version?: string }\n"],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import { s as init_backends, t as backend } from "./backends-CkvbG3js.mjs";
2
+ init_backends();
3
+ export { backend };
@@ -0,0 +1,37 @@
1
+ import { createRequire } from "node:module";
2
+ //#region \0rolldown/runtime.js
3
+ var __create = Object.create;
4
+ var __defProp = Object.defineProperty;
5
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
+ var __getOwnPropNames = Object.getOwnPropertyNames;
7
+ var __getProtoOf = Object.getPrototypeOf;
8
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esmMin = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
10
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
11
+ var __exportAll = (all, no_symbols) => {
12
+ let target = {};
13
+ for (var name in all) __defProp(target, name, {
14
+ get: all[name],
15
+ enumerable: true
16
+ });
17
+ if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
18
+ return target;
19
+ };
20
+ var __copyProps = (to, from, except, desc) => {
21
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
22
+ key = keys[i];
23
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
24
+ get: ((k) => from[k]).bind(null, key),
25
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
26
+ });
27
+ }
28
+ return to;
29
+ };
30
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
31
+ value: mod,
32
+ enumerable: true
33
+ }) : target, mod));
34
+ var __toCommonJS = (mod) => __hasOwnProp.call(mod, "module.exports") ? mod["module.exports"] : __copyProps(__defProp({}, "__esModule", { value: true }), mod);
35
+ var __require = /* @__PURE__ */ createRequire(import.meta.url);
36
+ //#endregion
37
+ export { __toCommonJS as a, __require as i, __esmMin as n, __toESM as o, __exportAll as r, __commonJSMin as t };
@@ -0,0 +1,4 @@
1
+ import "./spinner-DSByknyx.mjs";
2
+ import "./progress-bar-COPSBlT9.mjs";
3
+ import "./multi-progress-CQVB9lES.mjs";
4
+ export {};
@@ -0,0 +1,64 @@
1
+ import { createContext } from "react";
2
+ //#region packages/ag-react/src/context.ts
3
+ /**
4
+ * Context that provides access to the Term instance.
5
+ * Used by useTerm() hook to access terminal capabilities and styling.
6
+ */
7
+ const TermContext = createContext(null);
8
+ /**
9
+ * Context that provides access to the current SilveryNode.
10
+ * Used by useBoxRect() to subscribe to layout changes.
11
+ *
12
+ * Each Box component wraps its children in a NodeContext.Provider
13
+ * with its corresponding SilveryNode.
14
+ */
15
+ const NodeContext = createContext(null);
16
+ /**
17
+ * Context for stdout access.
18
+ * Used by useStdout() hook.
19
+ */
20
+ const StdoutContext = createContext(null);
21
+ /**
22
+ * Context for stderr access.
23
+ * Used by useStderr() hook.
24
+ */
25
+ const StderrContext = createContext(null);
26
+ /**
27
+ * Context that provides the typed runtime event bus.
28
+ *
29
+ * When non-null: interactive mode — useInput works, components can subscribe
30
+ * to events via rt.on() and emit via rt.emit().
31
+ *
32
+ * When null: static mode — useInput throws (by design), use useRuntime()
33
+ * for components that need to work in both modes.
34
+ */
35
+ const RuntimeContext = createContext(null);
36
+ /**
37
+ * Context that provides the cache backend to ListView.
38
+ * Set by the runtime based on rendering mode:
39
+ * - alternateScreen: false (inline) → "terminal"
40
+ * - alternateScreen: true + virtualInline → "virtual"
41
+ * - alternateScreen: true (plain fullscreen) → "retain"
42
+ *
43
+ * Default: "virtual" (safe fallback for test renderers — items unmount as expected)
44
+ */
45
+ const CacheBackendContext = createContext("virtual");
46
+ /**
47
+ * Context for the tree-based focus manager.
48
+ * Provides the FocusManager instance to useFocusable(), useFocusWithin(), and useFocusManager() hooks.
49
+ */
50
+ const FocusManagerContext = createContext(null);
51
+ /**
52
+ * Context for the capability registry (from @silvery/create composition).
53
+ *
54
+ * Provided by createApp() when a capabilityRegistry exists on the app object.
55
+ * Hooks like useSelection() use this to discover interaction features
56
+ * (e.g., SelectionFeature) without coupling to the composition layer.
57
+ *
58
+ * Returns null in simple `run()` or `render()` apps that don't use pipe() composition.
59
+ */
60
+ const CapabilityRegistryContext = createContext(null);
61
+ //#endregion
62
+ export { RuntimeContext as a, TermContext as c, NodeContext as i, CapabilityRegistryContext as n, StderrContext as o, FocusManagerContext as r, StdoutContext as s, CacheBackendContext as t };
63
+
64
+ //# sourceMappingURL=context-QreF3UHr.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-QreF3UHr.mjs","names":[],"sources":["../packages/ag-react/src/context.ts"],"sourcesContent":["/**\n * Silvery React Contexts\n *\n * Provides contexts for:\n * - TermContext: Access to Term instance (for styling/detection)\n * - NodeContext: Access to the current SilveryNode (for useBoxRect)\n * - RuntimeContext: Unified input/app controls (replaces Events/Input/Stdin/App contexts)\n * - StdoutContext: Access to stdout\n * - StderrContext: Access to stderr\n */\n\nimport type { Term } from \"@silvery/ag-term/ansi\"\nimport { createContext } from \"react\"\nimport type { FocusManager } from \"@silvery/ag/focus-manager\"\nimport type { Key } from \"@silvery/ag/keys\"\nimport type { AgNode } from \"@silvery/ag/types\"\n\n// ============================================================================\n// Term Context\n// ============================================================================\n\n/**\n * Context that provides access to the Term instance.\n * Used by useTerm() hook to access terminal capabilities and styling.\n */\nexport const TermContext = createContext<Term | null>(null)\n\n// ============================================================================\n// Node Context\n// ============================================================================\n\n/**\n * Context that provides access to the current SilveryNode.\n * Used by useBoxRect() to subscribe to layout changes.\n *\n * Each Box component wraps its children in a NodeContext.Provider\n * with its corresponding SilveryNode.\n */\nexport const NodeContext = createContext<AgNode | null>(null)\n\n// ============================================================================\n// Stdio Context\n// ============================================================================\n\nexport interface StdoutContextValue {\n /** Standard output stream */\n stdout: NodeJS.WriteStream\n /** Write to stdout */\n write: (data: string) => void\n /**\n * Notify the scheduler that lines were written to stdout externally.\n * Used by useScrollback to report lines written between renders so that\n * inline mode cursor positioning accounts for the displacement.\n */\n notifyScrollback?: (lines: number) => void\n /**\n * Reset inline cursor state in the output phase.\n * Used by useScrollback on resize to clear cursor tracking before\n * re-emitting frozen items at the new width.\n */\n resetInlineCursor?: () => void\n /**\n * Get inline cursor row relative to render region start. -1 if unknown.\n * Used by useScrollback to position frozen items at the render region start.\n */\n getInlineCursorRow?: () => number\n /**\n * Promote frozen content to scrollback via the output phase.\n * Instead of writing directly to stdout (which causes flicker),\n * this passes the content to the output phase which writes frozen content\n * + live content in a single target.write() — no blanking, no cursor desync.\n */\n promoteScrollback?: (frozenContent: string, frozenLineCount: number) => void\n}\n\n/**\n * Context for stdout access.\n * Used by useStdout() hook.\n */\nexport const StdoutContext = createContext<StdoutContextValue | null>(null)\n\nexport interface StderrContextValue {\n /** Standard error stream */\n stderr: NodeJS.WriteStream\n /** Write to stderr */\n write: (data: string) => void\n}\n\n/**\n * Context for stderr access.\n * Used by useStderr() hook.\n */\nexport const StderrContext = createContext<StderrContextValue | null>(null)\n\n// ============================================================================\n// Runtime Context (typed bidirectional event bus — TEA)\n// ============================================================================\n\n/**\n * Base events every runtime provides.\n * Apps extend this to add custom events (e.g., BoardEvents adds \"op\").\n */\nexport interface BaseRuntimeEvents {\n /** Keyboard input: [parsedInput, keyMetadata] */\n input: [input: string, key: Key]\n /** Bracketed paste: [pastedText] */\n paste: [text: string]\n /** Terminal window focus change: [isFocused] */\n focus: [focused: boolean]\n}\n\n/**\n * Extract handler function type from an event map entry.\n */\ntype EventHandler<Args extends unknown[]> = (...args: Args) => void\n\n/**\n * Typed bidirectional event bus + app lifecycle controls.\n *\n * Replaces EventsContext, InputContext, StdinContext, and AppContext with\n * a single typed interface. Components never see stdin or raw mode.\n *\n * Generic parameter E extends BaseRuntimeEvents — all runtimes provide\n * at least \"input\" and \"paste\" events. Apps can extend with custom events:\n *\n * ```tsx\n * interface BoardEvents extends BaseRuntimeEvents {\n * op: [BoardOp]\n * }\n * const rt = useRuntime<BoardEvents>()\n * rt?.on(\"input\", handler) // runtime → view\n * rt?.emit(\"op\", { type: \"cursor_down\" }) // view → runtime\n * ```\n *\n * Present in interactive mode (run/render/createApp/test renderer).\n * Absent (null) in static mode (renderStatic).\n */\nexport interface RuntimeContextValue<E extends BaseRuntimeEvents = BaseRuntimeEvents> {\n /** Subscribe to a typed event. Returns cleanup function. */\n on<K extends string & keyof E>(event: K, handler: EventHandler<E[K] extends unknown[] ? E[K] : never>): () => void\n /** Emit a typed event (view → runtime). */\n emit<K extends string & keyof E>(event: K, ...args: E[K] extends unknown[] ? E[K] : never): void\n /** Exit the application with optional error. */\n exit: (error?: Error) => void\n /** Pause rendering output (for screen switching). */\n pause?: () => void\n /** Resume rendering after pause. */\n resume?: () => void\n}\n\n/**\n * Context that provides the typed runtime event bus.\n *\n * When non-null: interactive mode — useInput works, components can subscribe\n * to events via rt.on() and emit via rt.emit().\n *\n * When null: static mode — useInput throws (by design), use useRuntime()\n * for components that need to work in both modes.\n */\nexport const RuntimeContext = createContext<RuntimeContextValue | null>(null)\n\n// ============================================================================\n// Cache Backend Context (mode-agnostic cache selection)\n// ============================================================================\n\n/**\n * Cache backend type — determines where ListView stores cached items.\n * - \"terminal\": Write to stdout as native scrollback (inline mode)\n * - \"virtual\": In-memory HistoryBuffer ring buffer (fullscreen + virtualInline)\n * - \"retain\": Cache items but keep them in the render tree (plain fullscreen\n * without virtual scrollback — the virtualizer handles windowing)\n */\nexport type CacheBackend = \"terminal\" | \"virtual\" | \"retain\"\n\n/**\n * Context that provides the cache backend to ListView.\n * Set by the runtime based on rendering mode:\n * - alternateScreen: false (inline) → \"terminal\"\n * - alternateScreen: true + virtualInline → \"virtual\"\n * - alternateScreen: true (plain fullscreen) → \"retain\"\n *\n * Default: \"virtual\" (safe fallback for test renderers — items unmount as expected)\n */\nexport const CacheBackendContext = createContext<CacheBackend>(\"virtual\")\n\n// ============================================================================\n// Focus Manager Context (tree-based focus system)\n// ============================================================================\n\n/**\n * Context for the tree-based focus manager.\n * Provides the FocusManager instance to useFocusable(), useFocusWithin(), and useFocusManager() hooks.\n */\nexport const FocusManagerContext = createContext<FocusManager | null>(null)\n\n// ============================================================================\n// Capability Registry Context\n// ============================================================================\n\n/**\n * Minimal capability lookup interface — matches CapabilityRegistry.get().\n * Defined here to avoid a dependency from ag-react → @silvery/create internals.\n */\nexport interface CapabilityLookup {\n get<T>(key: symbol): T | undefined\n}\n\n/**\n * Context for the capability registry (from @silvery/create composition).\n *\n * Provided by createApp() when a capabilityRegistry exists on the app object.\n * Hooks like useSelection() use this to discover interaction features\n * (e.g., SelectionFeature) without coupling to the composition layer.\n *\n * Returns null in simple `run()` or `render()` apps that don't use pipe() composition.\n */\nexport const CapabilityRegistryContext = createContext<CapabilityLookup | null>(null)\n"],"mappings":";;;;;;AAyBA,MAAa,cAAc,cAA2B,KAAK;;;;;;;;AAa3D,MAAa,cAAc,cAA6B,KAAK;;;;;AAyC7D,MAAa,gBAAgB,cAAyC,KAAK;;;;;AAa3E,MAAa,gBAAgB,cAAyC,KAAK;;;;;;;;;;AAmE3E,MAAa,iBAAiB,cAA0C,KAAK;;;;;;;;;;AAwB7E,MAAa,sBAAsB,cAA4B,UAAU;;;;;AAUzE,MAAa,sBAAsB,cAAmC,KAAK;;;;;;;;;;AAuB3E,MAAa,4BAA4B,cAAuC,KAAK"}
@@ -0,0 +1,28 @@
1
+ import { jt as Theme, kt as ColorPalette } from "./index-DCVL3jHo.mjs";
2
+
3
+ //#region packages/ansi/src/style/style.d.ts
4
+ /**
5
+ * Resolve a color value against a theme — the canonical token resolver.
6
+ *
7
+ * If the color starts with `$`, looks up the token in the theme.
8
+ * Supports `$primary`, `$surface-bg` (hyphens stripped), `$color0`–`$color15` (palette).
9
+ * Non-`$` strings pass through unchanged. Returns undefined if no theme or unknown token.
10
+ *
11
+ * Compatible with @silvery/theme's Theme type (or any object with string properties).
12
+ */
13
+ declare function resolveThemeColor(name: string | undefined, theme: object | undefined): string | undefined;
14
+ //#endregion
15
+ //#region packages/ansi/src/theme/derive.d.ts
16
+ interface ThemeAdjustment {
17
+ token: string;
18
+ from: string;
19
+ to: string;
20
+ against: string;
21
+ target: number;
22
+ ratioBefore: number;
23
+ ratioAfter: number;
24
+ }
25
+ declare function deriveTheme(palette: ColorPalette, mode?: "ansi16" | "truecolor", adjustments?: ThemeAdjustment[]): Theme;
26
+ //#endregion
27
+ export { deriveTheme as n, resolveThemeColor as r, ThemeAdjustment as t };
28
+ //# sourceMappingURL=derive-D7bFJdfU.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive-D7bFJdfU.d.mts","names":[],"sources":["../packages/ansi/src/style/style.ts","../packages/ansi/src/theme/derive.ts"],"mappings":";;;;;;;;;;ACkBA;;iBD4BgB,iBAAA,CAAkB,IAAA,sBAA0B,KAAA;;;UCtC3C,eAAA;EACf,KAAA;EACA,IAAA;EACA,EAAA;EACA,OAAA;EACA,MAAA;EACA,WAAA;EACA,UAAA;AAAA;AAAA,iBAGc,WAAA,CACd,OAAA,EAAS,YAAA,EACT,IAAA,2BACA,WAAA,GAAc,eAAA,KACb,KAAA"}
@@ -0,0 +1,89 @@
1
+ import { o as __toESM } from "./chunk-BSw8zbkd.mjs";
2
+ import { i as reconciler } from "./reconciler-2lp5VXK7.mjs";
3
+ import { createLogger } from "loggily";
4
+ //#region packages/ag-term/src/devtools.ts
5
+ /**
6
+ * React DevTools integration for silvery.
7
+ *
8
+ * Provides optional connection to React DevTools standalone app for
9
+ * debugging TUI component trees. Requires `react-devtools-core` to be
10
+ * installed (optional peer dependency).
11
+ *
12
+ * Usage:
13
+ * 1. Install: `bun add -d react-devtools-core`
14
+ * 2. Run devtools: `npx react-devtools`
15
+ * 3. Launch app with: `DEBUG_DEVTOOLS=1 bun run app.ts`
16
+ *
17
+ * Or call `connectDevTools()` manually from your app code.
18
+ *
19
+ * @module
20
+ */
21
+ const log = createLogger("silvery:devtools");
22
+ let connected = false;
23
+ /**
24
+ * Connect to React DevTools standalone app.
25
+ *
26
+ * This lazy-loads `react-devtools-core` so it has zero impact on
27
+ * production bundles. The connection is established via WebSocket
28
+ * to the devtools electron app (default: ws://localhost:8097).
29
+ *
30
+ * Safe to call multiple times -- subsequent calls are no-ops.
31
+ *
32
+ * @example
33
+ * ```ts
34
+ * import { connectDevTools } from '@silvery/ag-react';
35
+ * await connectDevTools();
36
+ * // Now open React DevTools standalone to inspect the component tree
37
+ * ```
38
+ */
39
+ async function connectDevTools() {
40
+ if (connected) return true;
41
+ try {
42
+ if (typeof globalThis.WebSocket === "undefined") try {
43
+ const ws = await import("./wrapper-Dqh0zi2W.mjs");
44
+ globalThis.WebSocket = ws.default ?? ws;
45
+ } catch {
46
+ log.warn?.("WebSocket polyfill (ws) not available. Install ws for DevTools support: bun add -d ws");
47
+ return false;
48
+ }
49
+ if (typeof globalThis.window === "undefined") globalThis.window = globalThis;
50
+ if (!globalThis.__REACT_DEVTOOLS_COMPONENT_FILTERS__) globalThis.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = [{
51
+ type: 1,
52
+ value: 7,
53
+ isEnabled: true
54
+ }, {
55
+ type: 2,
56
+ value: "SilveryApp",
57
+ isEnabled: true,
58
+ isValid: true
59
+ }];
60
+ const devtools = await import("./backend-CkIkIHR-.mjs").then((m) => /* @__PURE__ */ __toESM(m.default, 1));
61
+ devtools.initialize();
62
+ devtools.connectToDevTools();
63
+ reconciler.injectIntoDevTools();
64
+ connected = true;
65
+ return true;
66
+ } catch (error) {
67
+ const message = error instanceof Error ? error.message : String(error);
68
+ log.warn?.(`Failed to connect to React DevTools. Install react-devtools-core: bun add -d react-devtools-core
69
+ Error: ${message}`);
70
+ return false;
71
+ }
72
+ }
73
+ /**
74
+ * Check if DevTools are currently connected.
75
+ */
76
+ function isDevToolsConnected() {
77
+ return connected;
78
+ }
79
+ /**
80
+ * Auto-connect to DevTools if DEBUG_DEVTOOLS=1 environment variable is set.
81
+ * Called internally during render initialization.
82
+ */
83
+ async function autoConnectDevTools() {
84
+ if (process.env.DEBUG_DEVTOOLS === "1" || process.env.DEBUG_DEVTOOLS === "true") await connectDevTools();
85
+ }
86
+ //#endregion
87
+ export { connectDevTools as n, isDevToolsConnected as r, autoConnectDevTools as t };
88
+
89
+ //# sourceMappingURL=devtools-CscuKaDK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devtools-CscuKaDK.mjs","names":[],"sources":["../packages/ag-term/src/devtools.ts"],"sourcesContent":["/**\n * React DevTools integration for silvery.\n *\n * Provides optional connection to React DevTools standalone app for\n * debugging TUI component trees. Requires `react-devtools-core` to be\n * installed (optional peer dependency).\n *\n * Usage:\n * 1. Install: `bun add -d react-devtools-core`\n * 2. Run devtools: `npx react-devtools`\n * 3. Launch app with: `DEBUG_DEVTOOLS=1 bun run app.ts`\n *\n * Or call `connectDevTools()` manually from your app code.\n *\n * @module\n */\n\nimport { reconciler } from \"@silvery/ag-react/reconciler\"\nimport { createLogger } from \"loggily\"\n\nconst log = createLogger(\"silvery:devtools\")\n\nlet connected = false\n\n/**\n * Connect to React DevTools standalone app.\n *\n * This lazy-loads `react-devtools-core` so it has zero impact on\n * production bundles. The connection is established via WebSocket\n * to the devtools electron app (default: ws://localhost:8097).\n *\n * Safe to call multiple times -- subsequent calls are no-ops.\n *\n * @example\n * ```ts\n * import { connectDevTools } from '@silvery/ag-react';\n * await connectDevTools();\n * // Now open React DevTools standalone to inspect the component tree\n * ```\n */\nexport async function connectDevTools(): Promise<boolean> {\n if (connected) return true\n\n try {\n // Polyfill WebSocket for Node.js environments (required by react-devtools-core)\n if (typeof globalThis.WebSocket === \"undefined\") {\n try {\n // @ts-expect-error -- ws is an optional peer dependency\n const ws = await import(\"ws\")\n globalThis.WebSocket = ws.default ?? ws\n } catch {\n // ws not available -- devtools won't be able to connect\n log.warn?.(\"WebSocket polyfill (ws) not available. \" + \"Install ws for DevTools support: bun add -d ws\")\n return false\n }\n }\n\n // Ensure window/self exist for react-devtools-core internals\n if (typeof globalThis.window === \"undefined\") {\n // @ts-expect-error -- polyfill for devtools\n globalThis.window = globalThis\n }\n\n // Configure component filters to hide silvery internals from the DevTools tree.\n // Filter types from react-devtools-shared/src/types.js:\n // 1 = ComponentFilterElementType, value 7 = HostComponent\n // 2 = ComponentFilterDisplayName (regex on displayName)\n if (!globalThis.__REACT_DEVTOOLS_COMPONENT_FILTERS__) {\n globalThis.__REACT_DEVTOOLS_COMPONENT_FILTERS__ = [\n { type: 1, value: 7, isEnabled: true },\n { type: 2, value: \"SilveryApp\", isEnabled: true, isValid: true },\n ]\n }\n\n // @ts-expect-error -- react-devtools-core has no type declarations\n const devtools = await import(\"react-devtools-core\")\n devtools.initialize()\n devtools.connectToDevTools()\n\n // Inject renderer info so DevTools can identify silvery.\n // rendererPackageName and rendererVersion are read from the host config\n // passed to Reconciler() -- see reconciler/host-config.ts.\n reconciler.injectIntoDevTools()\n\n connected = true\n return true\n } catch (error: unknown) {\n const message = error instanceof Error ? error.message : String(error)\n log.warn?.(\n `Failed to connect to React DevTools. ` +\n `Install react-devtools-core: bun add -d react-devtools-core\\n` +\n ` Error: ${message}`,\n )\n return false\n }\n}\n\n/**\n * Check if DevTools are currently connected.\n */\nexport function isDevToolsConnected(): boolean {\n return connected\n}\n\n/**\n * Auto-connect to DevTools if DEBUG_DEVTOOLS=1 environment variable is set.\n * Called internally during render initialization.\n */\nexport async function autoConnectDevTools(): Promise<void> {\n if (process.env.DEBUG_DEVTOOLS === \"1\" || process.env.DEBUG_DEVTOOLS === \"true\") {\n await connectDevTools()\n }\n}\n\n// Global type augmentation for devtools polyfills\ndeclare global {\n var __REACT_DEVTOOLS_COMPONENT_FILTERS__: Array<{\n type: number\n value: number | string\n isEnabled: boolean\n isValid?: boolean\n }>\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,MAAM,aAAa,mBAAmB;AAE5C,IAAI,YAAY;;;;;;;;;;;;;;;;;AAkBhB,eAAsB,kBAAoC;AACxD,KAAI,UAAW,QAAO;AAEtB,KAAI;AAEF,MAAI,OAAO,WAAW,cAAc,YAClC,KAAI;GAEF,MAAM,KAAK,MAAM,OAAO;AACxB,cAAW,YAAY,GAAG,WAAW;UAC/B;AAEN,OAAI,OAAO,wFAA6F;AACxG,UAAO;;AAKX,MAAI,OAAO,WAAW,WAAW,YAE/B,YAAW,SAAS;AAOtB,MAAI,CAAC,WAAW,qCACd,YAAW,uCAAuC,CAChD;GAAE,MAAM;GAAG,OAAO;GAAG,WAAW;GAAM,EACtC;GAAE,MAAM;GAAG,OAAO;GAAc,WAAW;GAAM,SAAS;GAAM,CACjE;EAIH,MAAM,WAAW,MAAM,OAAO,0BAAA,MAAA,MAAA,wBAAA,EAAA,SAAA,EAAA,CAAA;AAC9B,WAAS,YAAY;AACrB,WAAS,mBAAmB;AAK5B,aAAW,oBAAoB;AAE/B,cAAY;AACZ,SAAO;UACA,OAAgB;EACvB,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;AACtE,MAAI,OACF;WAEc,UACf;AACD,SAAO;;;;;;AAOX,SAAgB,sBAA+B;AAC7C,QAAO;;;;;;AAOT,eAAsB,sBAAqC;AACzD,KAAI,QAAQ,IAAI,mBAAmB,OAAO,QAAQ,IAAI,mBAAmB,OACvE,OAAM,iBAAiB"}
@@ -0,0 +1,2 @@
1
+ import { t as autoConnectDevTools } from "./devtools-CscuKaDK.mjs";
2
+ export { autoConnectDevTools };
@@ -0,0 +1,110 @@
1
+ //#region packages/ag-react/src/ui/utils/eta.ts
2
+ /**
3
+ * Calculate ETA from a buffer of samples
4
+ *
5
+ * @param buffer - Array of {time, value} samples
6
+ * @param current - Current progress value
7
+ * @param total - Total target value
8
+ * @returns ETA in seconds (null if insufficient data)
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const buffer = [
13
+ * { time: 1000, value: 0 },
14
+ * { time: 2000, value: 10 },
15
+ * ];
16
+ * const eta = calculateETA(buffer, 10, 100);
17
+ * // eta = 9 (9 seconds remaining at 10 items/sec)
18
+ * ```
19
+ */
20
+ function calculateETA(buffer, current, total) {
21
+ if (buffer.length < 2) return null;
22
+ const first = buffer[0];
23
+ const last = buffer[buffer.length - 1];
24
+ const elapsed = (last.time - first.time) / 1e3;
25
+ const progress = last.value - first.value;
26
+ if (elapsed <= 0 || progress <= 0) return null;
27
+ const rate = progress / elapsed;
28
+ return (total - current) / rate;
29
+ }
30
+ /**
31
+ * Format ETA seconds as human-readable string
32
+ *
33
+ * @param eta - ETA in seconds (null for unknown)
34
+ * @returns Formatted string (e.g., "1:30", "2:15:30", "--:--", ">1d")
35
+ *
36
+ * @example
37
+ * ```ts
38
+ * formatETA(90) // "1:30"
39
+ * formatETA(3665) // "1:01:05"
40
+ * formatETA(null) // "--:--"
41
+ * formatETA(100000) // ">1d"
42
+ * ```
43
+ */
44
+ function formatETA(eta) {
45
+ if (eta === null || !isFinite(eta)) return "--:--";
46
+ if (eta > 86400) return ">1d";
47
+ const hours = Math.floor(eta / 3600);
48
+ const minutes = Math.floor(eta % 3600 / 60);
49
+ const seconds = Math.floor(eta % 60);
50
+ if (hours > 0) return `${hours}:${minutes.toString().padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`;
51
+ return `${minutes}:${seconds.toString().padStart(2, "0")}`;
52
+ }
53
+ /**
54
+ * Calculate and format ETA in one call
55
+ *
56
+ * @param buffer - Array of {time, value} samples
57
+ * @param current - Current progress value
58
+ * @param total - Total target value
59
+ * @returns Object with seconds (number|null) and formatted string
60
+ */
61
+ function getETA(buffer, current, total) {
62
+ const seconds = calculateETA(buffer, current, total);
63
+ return {
64
+ seconds,
65
+ formatted: formatETA(seconds)
66
+ };
67
+ }
68
+ /** Default buffer size for ETA smoothing */
69
+ const DEFAULT_ETA_BUFFER_SIZE = 10;
70
+ /**
71
+ * Create an ETA tracker with automatic buffer management
72
+ *
73
+ * @param bufferSize - Number of samples to keep (default: 10)
74
+ * @returns ETA tracker object
75
+ *
76
+ * @example
77
+ * ```ts
78
+ * const tracker = createETATracker();
79
+ * tracker.record(0);
80
+ * // ... later ...
81
+ * tracker.record(50);
82
+ * const eta = tracker.getETA(50, 100);
83
+ * console.log(eta.formatted); // "0:30"
84
+ * ```
85
+ */
86
+ function createETATracker(bufferSize = 10) {
87
+ const buffer = [];
88
+ return {
89
+ record(value) {
90
+ buffer.push({
91
+ time: Date.now(),
92
+ value
93
+ });
94
+ if (buffer.length > bufferSize) buffer.shift();
95
+ },
96
+ getETA(current, total) {
97
+ return getETA(buffer, current, total);
98
+ },
99
+ reset() {
100
+ buffer.length = 0;
101
+ },
102
+ getBuffer() {
103
+ return buffer;
104
+ }
105
+ };
106
+ }
107
+ //#endregion
108
+ export { getETA as a, formatETA as i, calculateETA as n, createETATracker as r, DEFAULT_ETA_BUFFER_SIZE as t };
109
+
110
+ //# sourceMappingURL=eta-DLiVPaSD.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eta-DLiVPaSD.mjs","names":[],"sources":["../packages/ag-react/src/ui/utils/eta.ts"],"sourcesContent":["/**\n * Shared ETA calculation utilities\n */\n\n/** Sample point for ETA calculation */\nexport interface ETASample {\n time: number\n value: number\n}\n\n/** ETA calculation result */\nexport interface ETAResult {\n /** Estimated seconds remaining, or null if insufficient data */\n seconds: number | null\n /** Formatted ETA string (e.g., \"1:30\", \"2:15:30\", \"--:--\") */\n formatted: string\n}\n\n/**\n * Calculate ETA from a buffer of samples\n *\n * @param buffer - Array of {time, value} samples\n * @param current - Current progress value\n * @param total - Total target value\n * @returns ETA in seconds (null if insufficient data)\n *\n * @example\n * ```ts\n * const buffer = [\n * { time: 1000, value: 0 },\n * { time: 2000, value: 10 },\n * ];\n * const eta = calculateETA(buffer, 10, 100);\n * // eta = 9 (9 seconds remaining at 10 items/sec)\n * ```\n */\nexport function calculateETA(buffer: ETASample[], current: number, total: number): number | null {\n if (buffer.length < 2) {\n return null\n }\n\n const first = buffer[0]!\n const last = buffer[buffer.length - 1]!\n\n const elapsed = (last.time - first.time) / 1000 // seconds\n const progress = last.value - first.value\n\n if (elapsed <= 0 || progress <= 0) {\n return null\n }\n\n const rate = progress / elapsed // items per second\n const remaining = total - current\n\n return remaining / rate\n}\n\n/**\n * Format ETA seconds as human-readable string\n *\n * @param eta - ETA in seconds (null for unknown)\n * @returns Formatted string (e.g., \"1:30\", \"2:15:30\", \"--:--\", \">1d\")\n *\n * @example\n * ```ts\n * formatETA(90) // \"1:30\"\n * formatETA(3665) // \"1:01:05\"\n * formatETA(null) // \"--:--\"\n * formatETA(100000) // \">1d\"\n * ```\n */\nexport function formatETA(eta: number | null): string {\n if (eta === null || !isFinite(eta)) {\n return \"--:--\"\n }\n\n if (eta > 86400) {\n // > 24 hours\n return \">1d\"\n }\n\n const hours = Math.floor(eta / 3600)\n const minutes = Math.floor((eta % 3600) / 60)\n const seconds = Math.floor(eta % 60)\n\n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, \"0\")}:${seconds.toString().padStart(2, \"0\")}`\n }\n\n return `${minutes}:${seconds.toString().padStart(2, \"0\")}`\n}\n\n/**\n * Calculate and format ETA in one call\n *\n * @param buffer - Array of {time, value} samples\n * @param current - Current progress value\n * @param total - Total target value\n * @returns Object with seconds (number|null) and formatted string\n */\nexport function getETA(buffer: ETASample[], current: number, total: number): ETAResult {\n const seconds = calculateETA(buffer, current, total)\n return {\n seconds,\n formatted: formatETA(seconds),\n }\n}\n\n/** Default buffer size for ETA smoothing */\nexport const DEFAULT_ETA_BUFFER_SIZE = 10\n\n/**\n * Create an ETA tracker with automatic buffer management\n *\n * @param bufferSize - Number of samples to keep (default: 10)\n * @returns ETA tracker object\n *\n * @example\n * ```ts\n * const tracker = createETATracker();\n * tracker.record(0);\n * // ... later ...\n * tracker.record(50);\n * const eta = tracker.getETA(50, 100);\n * console.log(eta.formatted); // \"0:30\"\n * ```\n */\nexport function createETATracker(bufferSize = DEFAULT_ETA_BUFFER_SIZE) {\n const buffer: ETASample[] = []\n\n return {\n /** Record a new sample */\n record(value: number): void {\n buffer.push({ time: Date.now(), value })\n if (buffer.length > bufferSize) {\n buffer.shift()\n }\n },\n\n /** Get current ETA */\n getETA(current: number, total: number): ETAResult {\n return getETA(buffer, current, total)\n },\n\n /** Reset the buffer */\n reset(): void {\n buffer.length = 0\n },\n\n /** Get buffer for external use */\n getBuffer(): readonly ETASample[] {\n return buffer\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAoCA,SAAgB,aAAa,QAAqB,SAAiB,OAA8B;AAC/F,KAAI,OAAO,SAAS,EAClB,QAAO;CAGT,MAAM,QAAQ,OAAO;CACrB,MAAM,OAAO,OAAO,OAAO,SAAS;CAEpC,MAAM,WAAW,KAAK,OAAO,MAAM,QAAQ;CAC3C,MAAM,WAAW,KAAK,QAAQ,MAAM;AAEpC,KAAI,WAAW,KAAK,YAAY,EAC9B,QAAO;CAGT,MAAM,OAAO,WAAW;AAGxB,SAFkB,QAAQ,WAEP;;;;;;;;;;;;;;;;AAiBrB,SAAgB,UAAU,KAA4B;AACpD,KAAI,QAAQ,QAAQ,CAAC,SAAS,IAAI,CAChC,QAAO;AAGT,KAAI,MAAM,MAER,QAAO;CAGT,MAAM,QAAQ,KAAK,MAAM,MAAM,KAAK;CACpC,MAAM,UAAU,KAAK,MAAO,MAAM,OAAQ,GAAG;CAC7C,MAAM,UAAU,KAAK,MAAM,MAAM,GAAG;AAEpC,KAAI,QAAQ,EACV,QAAO,GAAG,MAAM,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI;AAG/F,QAAO,GAAG,QAAQ,GAAG,QAAQ,UAAU,CAAC,SAAS,GAAG,IAAI;;;;;;;;;;AAW1D,SAAgB,OAAO,QAAqB,SAAiB,OAA0B;CACrF,MAAM,UAAU,aAAa,QAAQ,SAAS,MAAM;AACpD,QAAO;EACL;EACA,WAAW,UAAU,QAAQ;EAC9B;;;AAIH,MAAa,0BAA0B;;;;;;;;;;;;;;;;;AAkBvC,SAAgB,iBAAiB,aAAA,IAAsC;CACrE,MAAM,SAAsB,EAAE;AAE9B,QAAO;EAEL,OAAO,OAAqB;AAC1B,UAAO,KAAK;IAAE,MAAM,KAAK,KAAK;IAAE;IAAO,CAAC;AACxC,OAAI,OAAO,SAAS,WAClB,QAAO,OAAO;;EAKlB,OAAO,SAAiB,OAA0B;AAChD,UAAO,OAAO,QAAQ,SAAS,MAAM;;EAIvC,QAAc;AACZ,UAAO,SAAS;;EAIlB,YAAkC;AAChC,UAAO;;EAEV"}