codev / docs /ink-ui /overview.md
chenbhao's picture
chore: rename VersperClaw to Codev, update org to chenbhao
96f34e3
|
Raw
History Blame Contribute Delete
25.4 kB

Ink 终端 UI 框架

概述

Codev 的 Ink 是基于 vadimdemedes/ink v6 的深度定制分叉(fork)。Ink 使用 React 组件模型渲染终端用户界面。它将 React 的虚拟 DOM 映射到终端字符网格,支持 Yoga Flexbox 布局、样式继承、事件处理、文本选择、搜索高亮等丰富的交互能力。

与上游相比,Codev 的 Ink 新增/修改了以下核心能力:自定义 DOM 节点树、压缩屏幕缓冲区(Int32Array)、基于 Yoga WASM 的布局引擎、Kitty 键盘协议支持、SGR 鼠标跟踪、文本选择模式、搜索高亮、双向文本处理、scrollable 容器、声明式光标位置等。


核心架构

Ink 的渲染管线分为以下几个层次:

React 组件树
    │
    ▼
React Reconciler (自定义 Fiber 协调器)
    │
    ▼
DOM 节点树 (ink-root, ink-box, ink-text, ...)
    │
    ▼
Yoga 布局引擎 (WASM Flexbox)
    │
    ▼
Renderer → Output (screen buffer)
    │
    ▼
LogUpdate (差异比较)
    │
    ▼
Patch[] → ANSI 序列 → stdout

Ink 主类

文件:src/ink/ink.tsx

Ink 类(约 1723 行)管理整个渲染生命周期:

  • 构造函数:设置 LogUpdate、节流渲染调度器(scheduleRender,使用 FRAME_INTERVAL_MS=16ms)、FocusManager、Yoga onComputeLayout 回调、React reconciler 容器
  • **onRender()**:核心帧循环,每个渲染周期执行以下步骤:
    1. 调用 createRenderer 执行 DOM → Yoga 布局 → 屏幕缓冲区的渲染
    2. 处理选择滚动追踪
    3. 应用选择/搜索覆盖层
    4. 全损坏回退(full-damage backstop)
    5. 计算差异(diff)
    6. 缓冲池交换
    7. 补丁优化与序列化
    8. 光标定位(原生光标或声明式光标)
    9. 写入 stdout
  • 选择管理startSelection, extendSelection, wordSelect, lineSelect, dragScrollCapture, shiftSelection
  • stdin 挂起/恢复:用于外部编辑器集成
  • 控制台/stderr 补丁:拦截 console.log 等输出重定向
  • drainStdin:清理时清空 stdin 缓冲区

React Reconciler(协调器)

文件:src/ink/reconciler.ts

使用 react-reconciler 包创建自定义 Fiber 协调器,将 React 组件映射到 Ink 的 DOM 节点。

关键宿主配置

钩子 说明
createInstance 创建 DOMElementink-box, ink-text 等),在 <Text> 内部嵌套时将 ink-text 转换为 ink-virtual-text
createTextInstance 创建 TextNode,要求必须在 <Text> 内使用
commitUpdate React 19 使用新旧 props 直接比较,调用 setStyle, setAttribute, setTextStyles, setEventHandler
commitTextUpdate 更新文本节点
appendChild / insertBefore / removeChild DOM 树操作,同步更新 Yoga 节点树
resetAfterCommit 提交后触发 onComputeLayout(Yoga 布局)和 onRender(渲染帧)
hideInstance / unhideInstance 设置/取消 Yoga display: none

调试工具

  • getOwnerChain():从 React Fiber _debugOwner 提取组件名链,用于识别重绘来源
  • CLAUDE_CODE_DEBUG_REPAINTS 环境变量:启用后记录组件树归属
  • CLAUDE_CODE_COMMIT_LOG:记录提交/渲染性能日志

DOM 节点树

文件:src/ink/dom.ts

自定义 DOM 树,与浏览器 DOM 不同,专为终端渲染优化。

节点类型

节点名 说明
ink-root 根节点,持有 FocusManager
ink-box 容器(类似 <div>),有 Yoga 节点
ink-text 文本容器,有测量函数
ink-virtual-text <Text> 内嵌套的文本,无 Yoga 节点
ink-link 超链接,无 Yoga 节点
ink-progress 进度条,无 Yoga 节点
ink-raw-ansi 预渲染 ANSI 字符串,固定尺寸测量
#text 文本叶子节点

DOM 操作

  • createNode() / createTextNode() —— 创建节点
  • appendChildNode() / insertBeforeNode() / removeChildNode() —— DOM 树操作,同步更新 Yoga 节点
  • setStyle() / setAttribute() / setTextStyles() —— 属性更新,含脏检测(shallow equal 跳过未变更的渲染)
  • markDirty() —— 标记节点及其所有祖先为脏
  • scheduleRenderFrom() —— 从指定节点触发渲染(用于非 React 触发的 DOM 变更)

脏标记(Dirty Flag):每个 DOMElementdirty 属性(boolean),markDirty() 从当前节点向上遍历直到根节点。渲染完成后清除。这允许增量重绘 —— 只有脏子树被重新布局和渲染。

Screen(屏幕缓冲区)

文件:src/ink/screen.ts

Screen 是终端渲染的核心数据结构,使用压缩的 Int32Array 存储每个单元格,避免为每个单元格分配对象(200x120 屏幕可避免分配 24000 个对象)。

单元格存储布局: 每个单元格占用 2 个 Int32(共 8 字节):

  • word0:字符 ID(索引到 CharPool,32 位)
  • word1styleId[31:17] | hyperlinkId[16:2] | width[1:0]

池化系统

说明
CharPool 字符字符串池,共享跨所有屏幕。ASCII 字符使用 Int32Array 快速查找;非 ASCII 使用 Map。索引 0 固定为空格,索引 1 为 spacer 空字符串。
StylePool ANSI 样式池,位 0 标识样式是否在空格上可见(背景色、反色、下划线等)。提供 transition(fromId, toId) 方法生成缓存的 ANSI 过渡字符串。withInverse()withCurrentMatch()withSelectionBg() 用于选择/搜索覆盖层。
HyperlinkPool OSC 8 超链接池,索引 0 表示无链接。

单元格宽度枚举(CellWidth

名称 说明
0 Narrow 单宽字符
1 Wide 宽字符(CJK、emoji),占用两列
2 SpacerTail 宽字符的第二列占位符
3 SpacerHead 软换行时在行尾标记宽字符延续

关键函数

  • createScreen() —— 创建屏幕,8 字节/单元格的 ArrayBuffer
  • resetScreen() —— 重用屏幕,使用 BigInt64Array.fill() 快速清空
  • setCellAt() —— 写入单元格,自动创建宽字符的 SpacerTail
  • setCellStyleId() —— 仅更新样式 ID,用于选择/搜索覆盖层
  • cellAt() / cellAtIndex() —— 读取单元格
  • diff() / diffEach() —— 比较两个屏幕,使用 findNextDiff() 快速跳过相同区域
  • blitRegion() —— 批量复制矩形区域(TypedArray.set()
  • clearRegion() —— 快速清空矩形区域
  • shiftRows() —— 行位移(copyWithin),用于 DECSTBM 滚动优化
  • markNoSelectRegion() —— 标记选择排除区域
  • migrateScreenPools() —— 跨代池重置时重新 intern

Output(输出缓冲)

文件:src/ink/output.ts

收集渲染操作(Operations),在 get() 中统一应用到 Screen 缓冲区。

操作类型

类型 说明
write 写入 ANSI 文本到指定位置
blit 复制源屏幕的矩形区域
clear 清空矩形区域
clip / unclip 裁剪区域(嵌套 overflow:hidden
shift 行位移
noSelect 标记选择排除区域(最后应用)

字符缓存charCache): 每行文本经过 tokenize(ANSI 解析)、grapheme 聚类、双向文本重排、样式 ID + 超链接预计算后缓存。大多数行在帧间不变,缓存命中后只需读取属性并调用 setCellAt()

**writeLineToScreen()**: 核心写入函数,处理:

  • C0 控制字符(tab → 空格展开,ESC → CSI/single-char 序列跳过)
  • 零宽字符(组合标记等)静默跳过
  • 宽字符在行尾时放置 SpacerHead
  • 写时损坏区域追踪(screen.damage

LogUpdate(差异比较与补丁生成)

文件:src/ink/log-update.ts

比较前一帧和当前帧的 Screen 缓冲区,生成最小补丁序列(Diff = Patch[])。

补丁类型

类型 说明
stdout 原始 ANSI 字符串输出
clear 清空 N 行
clearTerminal 完全清屏(全损坏,引发闪烁)
cursorHide / cursorShow 光标显隐
cursorMove 光标相对移动
cursorTo 光标绝对定位到列
carriageReturn CR
hyperlink OSC 8 超链接
styleStr 预序列化的 ANSI 样式过渡字符串

DECSTBM 滚动优化: 当 ScrollBox 的 scrollTop 变化时,使用硬件滚动(CSI top;bottom r + CSI n S/T)替代重写整个滚动区域,大幅减少输出字节。

全损坏重置fullResetSequence_CAUSES_FLICKER): 在以下情况触发终端完全清屏:

  • 终端尺寸变化(resize)
  • 内容高度超出视口后又缩小到视口内
  • 需要更新的行在滚动缓冲区中(不可达)
  • 这些重置会引发可见的闪烁

VirtualScreen: 内部辅助类,追踪虚拟光标位置和差异补丁列表,支持事务性操作(txn())批量提交补丁。

Frame(帧结构)

文件:src/ink/frame.ts

type Frame = {
  screen: Screen          // 屏幕缓冲区
  viewport: Size           // 视口尺寸
  cursor: Cursor           // 光标状态
  scrollHint?: ScrollHint  // DECSTBM 滚动提示
  scrollDrainPending?: boolean  // 是否需要继续帧
}

辅助函数:

  • shouldClearScreen() —— 判断是否需要清屏(resize 或 offscreen)
  • emptyFrame() —— 创建空帧

布局引擎(Yoga)

文件:src/ink/layout/ 目录

使用 Yoga 的 WASM 实现进行 Flexbox 布局计算。

在渲染管线中的位置

  1. React commit 后,resetAfterCommit 调用 rootNode.onComputeLayout()
  2. ink.tsx 中的 onComputeLayout 调用 root.yogaNode.calculateLayout()
  3. Yoga 执行完整的 Flexbox 布局计算(含 measureFunc 回调用于文本测量)
  4. Renderer 读取 getComputedWidth/Height/Top/Left 获取布局结果

布局节点:文件 src/ink/layout/node.ts,定义 LayoutNode 接口和所有布局常量(LayoutEdge, LayoutDisplay, LayoutFlexDirection, LayoutJustify, LayoutAlign, LayoutOverflow, LayoutPositionType, LayoutWrap, LayoutGutter)。

布局引擎:文件 src/ink/layout/engine.ts,创建和管理 Yoga WASM 实例。提供 createLayoutNode()getYogaCounters() 等函数。

测量函数

  • ink-textmeasureTextNode() —— 处理文本换行、tab 展开、bi-di 重排
  • ink-raw-ansimeasureRawAnsiNode() —— 使用预设的 rawWidth/rawHeight

样式系统

文件:src/ink/styles.ts

样式类型定义(Styles)涵盖所有 CSS Flexbox 属性:

布局display, position, overflow, flexDirection, flexWrap, flexGrow, flexShrink, flexBasis, alignItems, alignSelf, justifyContent

尺寸width, height, minWidth, maxWidth, minHeight, maxHeight(支持数值和百分比字符串)

间距margin, padding, gap(含 X/Y 方向缩写)

边框borderStyle(圆角/单线/双线等), borderColor, borderTop/Right/Bottom/Left(控制各边显隐)

文本textWrap(8 种模式:wrap, wrap-trim, end, middle, truncate-end, truncate, truncate-middle, truncate-start

其他backgroundColor, opaque, noSelect(选择排除), borderText(边框内文本)

applyStyles() 函数将 Styles 对象映射到 Yoga 节点属性。每个样式类别有独立的函数(applyPositionStyles, applyOverflowStyles, applyFlexStyles 等)。

TextStyles

文件:src/ink/styles.ts

type TextStyles = {
  color?, backgroundColor?  // 颜色
  dim?, bold?, italic?       // 字体样式
  underline?, strikethrough? // 装饰
  inverse?                   // 反色
}

TextStyles<Text> 组件中声明,通过 ink-text 节点的 textStyles 属性传递。渲染时由 render-node-to-output.tsbuildTextStyles() 转换为 ANSI SGR 序列。


事件系统

键盘事件

Kitty 键盘协议:在 raw mode 中启用 CSI u 扩展键编码(ENABLE_KITTY_KEYBOARD + ENABLE_MODIFY_OTHER_KEYS),使 Ctrl+Shift+字母 与 Ctrl+字母 可区分。终端识别通过在 XTVERSION 查询后设置。

输入解析:文件 src/ink/parse-keypress.ts,状态机解析 stdin 的原始字节流。支持:

  • 普通字符(UTF-8)
  • CSI 序列(方向键、功能键等)
  • Kitty CSI u 序列(带修饰键编码)
  • SGR 鼠标编码(<row;col;button M/m)
  • DEC 私有模式响应(DCS 序列)
  • OSC 序列(操作系统命令)
  • 粘贴模式(IN_PASTE 状态)

App 组件中的处理(文件 src/ink/components/App.tsx):

  • handleReadable() —— stdin readable 事件回调
  • processInput() —— 调用 parseMultipleKeypresses() 解析多按键
  • processKeysInBatch() —— 在 reconciler.discreteUpdates 中批量处理按键,避免"最大更新深度超出"错误
  • 处理 Ctrl+C(退出)、Ctrl+Z(挂起)、终端焦点事件(DECSET 1004)

鼠标事件

通过 DECSET 1003(SGR 鼠标跟踪)启用/禁用。

processKeysInBatch 中的鼠标处理handleMouseEvent()):

  • press:开始选择、多击检测(双击选中单词、三击选中行)
  • drag:扩展选择(字符/单词/行模式)
  • release:结束选择
  • no-button motion(模式 1003):悬停事件分发(onMouseEnter/onMouseLeave
  • 超链接:单点击时延迟打开,双击取消

handleMouseEvent() 中的选择逻辑

  • startSelection() / finishSelection() / hasSelection()
  • 多击跟踪:clickCount 在 500ms 内递增,支持双击单词选择和三击行选择
  • lastPressHadAlt:记录 Alt 修饰键,用于终端判定

焦点管理

文件:src/ink/focus.ts

FocusManager 存储在每个根节点,类似于浏览器 document.activeElement

功能

  • focus(node) / blur() —— 获取/失去焦点
  • handleNodeRemoved() —— 节点移除时自动恢复焦点到栈中上一个
  • handleAutoFocus() —— 自动聚焦(autoFocus prop)
  • handleClickFocus() —— 点击聚焦(tabIndex prop)
  • focusNext() / focusPrevious() —— Tab / Shift+Tab 导航

焦点栈:最多 32 层,用于节点移除后的焦点恢复。

事件分发:事件系统使用 Dispatcher 类(src/ink/events/dispatcher.ts)处理捕获(Capture)和冒泡(Bubble)阶段。EVENT_HANDLER_PROPS 集合定义哪些 props 是事件处理器(onClick, onKeyDown 等)。


组件库

文件:src/ink/components/

组件 文件 说明
App App.tsx 根组件,管理 stdin/stdout、raw mode、光标、挂起/恢复、事件分发、多击选择
Box Box.tsx 布局容器(类似 <div>),支持完整 Flexbox 样式和事件处理器(onClick, onKeyDown, onMouseEnter, onMouseLeave, onFocus, onBlur)
Text Text.tsx 文本组件,支持颜色(color, backgroundColor)、加粗(bold)、斜体(italic)、下划线(underline)、删除线(strikethrough)、反色(inverse)、换行模式(wrap)
Button Button.tsx 按钮组件(继承 Box 的点击能力)
Link Link.tsx 超链接(使用 OSC 8 协议),终端不支持时回退到纯文本
Spacer Spacer.tsx 弹性空间填充(flexGrow: 1
Newline Newline.tsx 插入空白行
ScrollBox ScrollBox.tsx 滚动容器(overflow: scroll),支持 scrollTo(), scrollToElement() 和粘性滚动
AlternateScreen AlternateScreen.tsx 替代屏幕(alt-screen)管理
RawAnsi RawAnsi.tsx 原始 ANSI 字符串渲染(预计算的宽度和高度)
NoSelect NoSelect.tsx 选择排除区域(如行号、diff 标记)
Ansi (在 ink.ts 中 re-export) ANSI 文本渲染
ErrorOverview ErrorOverview.tsx 错误概览组件

Context 提供者

Context 文件 提供内容
AppContext AppContext.ts exit() 退出函数
StdinContext StdinContext.ts stdin, setRawMode, internal_eventEmitter, internal_querier
TerminalSizeContext TerminalSizeContext.tsx columns, rows 终端尺寸
TerminalFocusContext TerminalFocusContext.tsx isTerminalFocused 终端焦点状态
ClockContext ClockContext.tsx 时钟/定时器(根据焦点状态调整间隔)
CursorDeclarationContext CursorDeclarationContext.ts 声明式光标位置

Hooks

文件:src/ink/hooks/

Hook 文件 说明
useInput use-input.ts 处理用户键盘输入(useLayoutEffect 同步启用 raw mode),注册 input 事件监听器
useStdin use-stdin.ts 访问 stdin/setRawMode/EventEmitter
useApp use-app.ts 访问 exit() 函数
useAnimationFrame use-animation-frame.ts 动画帧钩子(使用 FRAME_INTERVAL_MS=16ms 节流渲染)
useInterval use-interval.ts 定时器(终端失焦时可选减速)
useSelection use-selection.ts 文本选择状态管理(anchor, focus, word/line 模式)
useSearchHighlight use-search-highlight.ts 搜索高亮状态(匹配位置、当前匹配导航)
useDeclaredCursor use-declared-cursor.ts 声明式光标位置(用于 IME 输入和屏幕阅读器)
useTabStatus use-tab-status.ts Tab 状态管理
useTerminalFocus use-terminal-focus.ts 终端焦点变化监听
useTerminalTitle use-terminal-title.ts 终端标题设置
useTerminalViewport use-terminal-viewport.ts 终端视口信息

文本选择

文件:src/ink/selection.ts

SelectionState 管理全屏模式下的文本选择:

  • anchor:选择起点(鼠标按下处)
  • focus:选择终点(鼠标拖动处)
  • anchorSpan:多击(双击/三击)时初始单词/行的范围
  • scrolledOffAbove/Below:选择过程中滚动出视口的文本
  • softWrap 标记:跟踪软换行位置

选择操作

  • startSelection() / updateSelection() / finishSelection()
  • extendSelection() —— 字符/单词/行模式扩展
  • getSelectedText() —— 获取选中文本(拼接跨行的选择,含滚动出视口的文本)
  • applySelectionOverlay() —— 在屏幕覆盖层中高亮选中区域

搜索高亮

文件:src/ink/render-to-screen.tssrc/ink/components/App.tsx

搜索高亮系统分为两个层次:

  1. renderToScreen() —— 在独立屏幕缓冲区中渲染单个消息,扫描查询字符串的位置
  2. applySearchHighlight() / applyPositionedHighlight() —— 将搜索匹配覆盖层应用到实际屏幕

匹配视觉风格

  • 普通匹配:反色(SGR 7,白色底,从主题继承)
  • 当前匹配(用户导航到的位置):黄色背景(通过黄色前景 + 反色实现)+ 加粗 + 下划线

渲染管线完整流程

从 React 组件到终端输出的完整流程:

1. React 更新 (setState / 新 props)
    │
2. Reconciler commit (resetAfterCommit)
    ├── onComputeLayout: Yoga calculateLayout()
    └── onRender: scheduleRender (节流, 16ms)
    │
3. createRenderer → renderNodeToOutput
    ├── 递归遍历 DOM 树
    ├── 应用 scrollTop 偏移
    ├── 写操作 -> Output buffer
    └── blit 操作 -> Output buffer
    │
4. Output.get()
    ├── 应用所有操作到 Screen
    ├── 处理裁剪区域
    ├── 处理 absolute 清除
    └── 更新 softWrap 标记
    │
5. LogUpdate.render()
    ├── 检查是否要全损坏重置
    ├── DECSTBM 滚动优化
    ├── diffEach 比较前后帧
    ├── 处理增长/收缩
    └── 生成 Patch[]
    │
6. optimize() — 补丁合并与去重
    │
7. writeDiffToTerminal() — 补丁序列化为 ANSI → stdout
    │
8. 屏幕选择/搜索覆盖层更新
    │
9. 光标定位
    └── 下一帧

特殊功能

双缓冲(Double Buffering)

使用前后帧(frontFrame / backFrame)实现双缓冲:

  • backFrame.screen 是当前渲染目标
  • frontFrame.screen 是前一帧的屏幕,用于差异比较和 blit
  • 渲染帧切换后进行缓冲池交换(swapFrames()

屏幕伤害追踪(Damage Tracking)

每个 Screen 有一个 damage 矩形区域,记录自上次重置以来发生写操作的区域。diffEach() 只扫描损伤区域,避免遍历整个屏幕。

双向文本(BiDi)

文件:src/ink/bidi.ts

使用 Unicode Bidirectional Algorithm 对文本行进行重排。在 writeLineToScreen() 中,每行文本在 tokenize 和 grapheme 聚类后执行 reorderBidi()

ANSI 解析与 Grapheme 聚类

使用 @alcalzone/ansi-tokenize 解析 ANSI 序列,然后通过 Intl.Segmenter 进行 grapheme 聚类(支持家族 emoji 等多码点字符)。结果缓存到 charCache,帧间重用。

终端查询(Terminal Querier)

文件:src/ink/terminal-querier.ts

TerminalQuerier 通过 DEC 请求序列(如 DA1、XTVERSION、DECRPM)与终端通信。它维护一个待处理请求的 Promise 队列,在收到终端响应时解析相应的 Promise。

DEC 私有模式

文件:src/ink/termio/dec.ts

管理 DEC 私有模式:

  • 鼠标跟踪:ENABLE_MOUSE_TRACKING(SGR, 1003) / DISABLE_MOUSE_TRACKING
  • 光标显隐:HIDE_CURSOR / SHOW_CURSOR
  • 焦点报告:EFE / DFE(DECSET 1004)
  • 滚轮支持:通过 DECRPM 查询终端能力

Kitty 键盘协议

文件:src/ink/termio/ansi.tssrc/ink/termio/csi.ts

通过 CSI >1u(Kitty 协议)和 CSI >4;2m(xterm modifyOtherKeys)启用扩展键盘报告,使修饰键组合(Ctrl+Shift+A 等)可区分。

替代屏幕(Alt Screen)

<AlternateScreen> 组件管理终端的替代屏幕缓冲区。启用时:

  • 内容始终恰好占满终端行数
  • 光标隐藏
  • 启用 DECSET 1000/1002/1003 鼠标跟踪
  • 支持 DECSTBM 滚动优化
  • 退出时恢复主屏幕内容

声明式光标(Declared Cursor)

useDeclaredCursor 钩子和 CursorDeclarationContext 允许组件声明当前光标位置(如输入框),使 Ink 在每一帧后将终端光标放置在该位置,支持 IME 输入和屏幕阅读器。

滚动容器(ScrollBox)

<ScrollBox> 组件(overflow: scroll)实现:

  • scrollTop:可编程滚动位置
  • pendingScrollDelta:累积的滚动增量(限制 SCROLL_MAX_PER_FRAME 行/帧,防止大幅跳动)
  • stickyScroll:粘性滚动(内容增长时自动保持在底部)
  • scrollTo(y) / scrollToElement(el, offset):可编程滚动
  • scrollHeight / scrollViewportHeight:滚动信息查询
  • scrollClampMin / scrollClampMax:虚拟滚动边界保护
  • 渲染时通过 output.shift() 实现 DECSTBM 硬件滚动

选择排除(NoSelect)

<NoSelect> 组件标记区域为选择排除:

  • noSelect 模式:仅排除该盒子的精确区域
  • from-left-edge 模式:从第 0 列到盒子右边缘的整行区域
  • screen.noSelect 位图每帧重置,blitRegion 复制时连带复制

调试与性能分析

  • CLAUDE_CODE_DEBUG_REPAINTS:追踪重绘来源组件
  • CLAUDE_CODE_COMMIT_LOG:记录提交/渲染时间日志
  • YOGA 计数器:getYogaCounters() 报告每个框架的节点访问、测量、缓存命中
  • FRAME_INTERVAL_MS = 16:60fps 帧率
  • Blit/Write 比率日志:高频写入(而非 blit)时发出警告

文件索引

按功能类别整理的核心文件:

类别 文件
主入口 src/ink.ts, src/ink/ink.tsx
DOM src/ink/dom.ts
Reconciler src/ink/reconciler.ts
Renderer src/ink/renderer.ts, src/ink/render-node-to-output.ts
Screen src/ink/screen.ts
Output src/ink/output.ts
LogUpdate src/ink/log-update.ts
Frame src/ink/frame.ts
Styles src/ink/styles.ts
Focus src/ink/focus.ts
Selection src/ink/selection.ts
Layout src/ink/layout/engine.ts, node.ts
Event Dispatcher src/ink/events/dispatcher.ts
Event Handlers src/ink/events/event-handlers.ts
Components src/ink/components/ (App, Box, Text, Button, Link, Spacer, Newline, ScrollBox, AlternateScreen, RawAnsi, NoSelect, ErrorOverview)
Hooks src/ink/hooks/ (use-input, use-stdin, use-app, use-animation-frame, use-interval, use-selection, use-search-highlight, use-declared-cursor, use-tab-status, use-terminal-focus, use-terminal-title, use-terminal-viewport)
Termio src/ink/termio/ansi.ts, csi.ts, dec.ts, osc.ts
Bidi src/ink/bidi.ts
Constants src/ink/constants.ts
Contexts src/ink/components/AppContext.ts, StdinContext.ts, TerminalSizeContext.tsx, TerminalFocusContext.tsx, ClockContext.tsx, CursorDeclarationContext.ts