9fe6d7cc44
Rewrites Box/Text/Spacer/Static/Newline from h()/render functions to Vue <script setup> template SFCs (Transform stays a render fn — it inspects its own child vnodes), with vue-tsc-verified consumer types (template + JSX fixtures), provide/inject text context, the always-validate Text divergence (color + backgroundColor), and three renderer fixes the SFCs surfaced (static anchor skip, transform line-index Ink-parity, useBoxMetrics subtree drill). Integrates the five main commits landed after the branch point: #163 public-API audit, generic Static scoped-slot typing, foreground color validation, useWindowSize/divergence docs. Squashed from the SFC sub-commits + the two main-integration merges to keep a linear, rebaseable history. See PR #165 for the full breakdown. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
55 lines
1.7 KiB
TypeScript
55 lines
1.7 KiB
TypeScript
import { defineComponent } from "vue";
|
|
import { expect, test } from "vite-plus/test";
|
|
import { render } from "@vue-tui/testing";
|
|
import { Box, Text, Newline } from "@vue-tui/runtime";
|
|
|
|
test("Newline works standalone (outside Text) as a yoga carrier", async () => {
|
|
// In Ink, Newline renders as ink-text (yoga carrier) so it works
|
|
// outside a Text context as a standalone line break.
|
|
const { lastFrame } = await render(
|
|
defineComponent(() => () => (
|
|
<Box flexDirection="column">
|
|
<Newline />
|
|
<Text>hi</Text>
|
|
</Box>
|
|
)),
|
|
{ columns: 100 },
|
|
);
|
|
// Newline should occupy a line before "hi"
|
|
const frame = lastFrame({ trimLines: true })!;
|
|
const lines = frame.split("\n");
|
|
expect(lines.length).toBeGreaterThanOrEqual(2);
|
|
expect(lines.at(-1)).toBe("hi");
|
|
});
|
|
|
|
test("Newline count=2 adds two blank lines standalone", async () => {
|
|
const { lastFrame } = await render(
|
|
defineComponent(() => () => (
|
|
<Box flexDirection="column">
|
|
<Text>above</Text>
|
|
<Newline count={2} />
|
|
<Text>below</Text>
|
|
</Box>
|
|
)),
|
|
{ columns: 100 },
|
|
);
|
|
const frame = lastFrame({ trimLines: true })!;
|
|
expect(frame).toContain("above");
|
|
expect(frame).toContain("below");
|
|
const lines = frame.split("\n");
|
|
// "above", 2 blank lines, "below" = at least 4 lines
|
|
expect(lines.length).toBeGreaterThanOrEqual(4);
|
|
});
|
|
|
|
test("Newline inside Text renders inline (virtual-text), not a standalone line", async () => {
|
|
const { lastFrame } = await render(
|
|
defineComponent(() => () => (
|
|
<Text>
|
|
a<Newline />b
|
|
</Text>
|
|
)),
|
|
{ columns: 100 },
|
|
);
|
|
expect(lastFrame()!.split("\n")).toEqual(["a", "b"]);
|
|
});
|