feat: implement overflow clipping in paint pipeline

Port Ink's clip/unclip approach to vue-tui's paint output. When a box
has overflow="hidden", content painted by its children that falls
outside the box's content area (inside borders) is clipped.

Implementation:
- Add ClipRect, clip(), and unclip() to the Output class
- Maintain a clip stack; active clip is applied to each write op
- Horizontal clipping uses slice-ansi for correct ANSI handling
- Vertical clipping slices the lines array
- Store "overflow" in STYLE_PROPS so it's available in node.props for
  the paint pass

Also adds explicit flexDirection="row" to two overflow tests where
multiple child boxes should lay out side-by-side (Ink defaults to row,
vue-tui defaults to yoga's column).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Yunfei He
2026-05-25 22:47:10 +08:00
parent 07a851ce2a
commit da7c843d44
3 changed files with 118 additions and 8 deletions
@@ -70,7 +70,7 @@ test("overflow - multiple boxes inside overflow container", async () => {
const { lastFrame } = await render(
defineComponent(() => () => (
<Box paddingBottom={1}>
<Box width={4} height={1} overflow="hidden">
<Box width={4} height={1} overflow="hidden" flexDirection="row">
<Box width={2} height={2} flexShrink={0}>
<Text>TL{"\n"}BL</Text>
</Box>
@@ -89,7 +89,7 @@ test("overflow - multiple boxes inside overflow container with border", async ()
const { lastFrame } = await render(
defineComponent(() => () => (
<Box paddingBottom={1}>
<Box width={6} height={3} overflow="hidden" borderStyle="round">
<Box width={6} height={3} overflow="hidden" borderStyle="round" flexDirection="row">
<Box width={2} height={2} flexShrink={0}>
<Text>TL{"\n"}BL</Text>
</Box>