Ink has no reset branch for these two props (every other flex prop does),
so explicit `={undefined}` leaves a stale value. vue-tui resets to the
row/nowrap default. Why: the render is a function of the current props —
absent a special contract, dropping/changing a prop changes the output;
Ink keeping a previous render's value is the anomaly. KEEP.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#69 added `useAppContext()` as a Vue-native rename of Ink's `useApp()`,
qualified to avoid reading as the Vue application instance. On reflection the
"Context" suffix borrowed the name of an internal grab-bag context and slightly
mislabels the hook — it returns app lifecycle controls, not that context. The
collision worry doesn't hold up: Vue has no `useApp()`, the returned
`{ exit, waitUntilRenderFlush }` is clearly not the Vue app instance, and "App"
in vue-tui already means the `TuiApp` from `createApp()`.
Rename to `useApp()` for full Ink fidelity (same name + same shape), and drop
the now-defunct "App composable" entry from ink-divergences.md — it ceases to
be a divergence.
Internal context cleanup (the grab-bag `AppContext` + the `StdinContext`
duplication) is intentionally out of scope here, tracked separately.
BREAKING CHANGE: `useAppContext()` is renamed to `useApp()`. Replace
`const { exit } = useAppContext()` with `const { exit } = useApp()`.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The "Accessibility props — AriaRole / AriaState" entry claimed "Ink: no
equivalent" and filed aria/screen-reader support under additive features. That
is incorrect: Ink has full accessibility support at this doc's own baseline
(v7.0.4, commit 40b3a75) — aria-label/aria-hidden/aria-role/aria-state on
Box/Text, useIsScreenReaderEnabled, and screen-reader linearization in
render-node-to-output. vue-tui's implementation is a faithful port of it; the
parity commits G03–G59 align the linearization with Ink (e.g. G22's parent-role
dedup matches Ink's `role !== parentRole`).
Accessibility is parity-by-default, so it does not belong in a doc that records
only intentional divergences. Remove the entry; the feature itself is unchanged.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ink's `useApp()` returns `{ exit, waitUntilRenderFlush }`. vue-tui previously
exposed only `exit()` via `useExit()` and kept `waitUntilRenderFlush` on the
`TuiApp` handle alone. Align the public surface with Ink: add `useAppContext()`
returning the same pair, and remove `useExit()`.
- thread `waitUntilRenderFlush` into the injected `AppContext` via a hoisted
impl shared by the `TuiApp` handle and the composable, so both resolve
identically
- add `useAppContext()`; delete `useExit()`; migrate all call sites, PTY
fixtures, examples, READMEs and the public-API surface test
- port Ink's two "useApp waitUntilRenderFlush" tests; Ink's third relies on
React concurrent mode (N/A in Vue)
- rewrite the ink-divergences entry: this is now a *naming* divergence
(`useAppContext` vs `useApp`, mirroring `createApp` vs `render`), not a
surface one — and fix the prior wrong claim that Ink's `useApp` returns
stdin/stdout/stderr
The name is qualified (`useAppContext`, not `useApp`) so it doesn't read as the
Vue application instance (`createApp`/`app.mount`) — the same Vue-native naming
choice vue-tui already makes with `createApp()` vs Ink's `render()`.
BREAKING CHANGE: `useExit()` is removed. Replace `const exit = useExit()` with
`const { exit } = useAppContext()`.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
vue-tui withheld Ink's named prop types (BoxProps, TextProps, StaticProps,
TransformProps, NewlineProps) and the WindowSize/CursorPosition data shapes
under a blanket "avoid React-shaped type names" rule. That rule over-reached:
a <Box> has props in Vue exactly as in React, so those names carry no
React-vs-Vue content — there's no reason to rename them. Re-export them under
Ink's names so a consumer can name a component's props the same way as in Ink.
- Derive each XProps from the component's runtime `props` object via Vue's
`ExtractPublicPropTypes`, so the public type can never drift from the real
props. Pin `required: true as const` on Static.items / Transform.transform:
a standalone `const` widens `true`→`boolean`, which would otherwise drop them
from the required keys — in both the exported type AND the component's own
`setup(props)` typing.
- Add `WindowSize { columns, rows }` and `CursorPosition { x, y }`, anchored to
their real usage in useTerminalSize / useCursor. (The composables still return
reactive refs of these — the data shape matches Ink; the ref wrapper is the
framework difference.)
- Keep the genuinely-divergent names as-is: DOMElement→TuiNode (real
DOM-emulation vs host-node difference), RenderOptions/Instance→MountOptions/
TuiApp (downstream of createApp()), App/Stdin/Stdout/StderrProps = N/A. Rewrite
the ink-divergences doc to record what's now aligned vs still divergent.
- Add a tsc-checked type-level test (public-types.test-d.ts) asserting the
exported shapes; it is excluded from vitest's runtime run by naming.
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Ink keeps its `measure-text` module internal and never re-exports it. vue-tui
exported `measureText` / `measureTextNatural` from the public index under the
mistaken belief — stated verbatim in commit 0e7d775's own message — that doing
so "matched Ink's public API". It does not; Ink keeps that module internal. A
later design doc then rationalized the leak post-hoc as an intentional
divergence. It was neither intentional nor a divergence — it was a mistake.
Align with Ink:
- Drop both from the public index. `measureTextNatural` stays as an internal
helper (yoga.ts uses it). `measureText` had zero production callers (yoga uses
`wrapText` + `measureTextNatural`, never `measureText`) and is removed.
- Integration tests that used `measureText(stripAnsi(x), 9999).width` as a
line-width helper now use `stringWidth(stripAnsi(x))` directly.
- public-api.test.ts gains a regression test asserting neither is exported.
- Remove the now-obsolete entry from .agents/docs/ink-divergences.md.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: remove Ink-parity design docs (.agents/docs), keep the code
Removes the Ink-parity loop documentation — ink-parity-loop.md, ink-parity.md,
and the parity-ledger.md — and drops the now-dangling 'Current docs:' list from
AGENTS.md's Context Engineering section (the convention itself is kept). All the
merged parity CODE fixes remain on main; only the documentation/ledger artifacts
are cleared, to re-orchestrate the documentation with a different approach.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* docs: add focused Ink intentional-divergences design doc
Replaces the removed sprawling parity docs with one focused doc that records
ONLY where vue-tui deliberately differs from Ink (API surface, additive
features, unavoidable Vue-vs-React semantics, N/A React concepts, framework
idioms) — leaving placeholders for the maintainer to supplement.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>