feat(runtime): re-export Ink-aligned named prop/data types (BoxProps, …) (#70)
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>
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
// Type-level guarantees for the public *named* type surface.
|
||||
//
|
||||
// vue-tui tracks Ink, and Ink re-exports its component prop types and a couple of
|
||||
// framework-neutral data shapes under stable names. These names (BoxProps, TextProps,
|
||||
// …, WindowSize, CursorPosition) have nothing to do with React vs Vue — a <Box> has
|
||||
// props in Vue exactly as in React — so vue-tui re-exports them too, letting consumers
|
||||
// name a component's props the same way they would in Ink. See
|
||||
// `.agents/docs/ink-divergences.md` ("Named type / prop re-exports").
|
||||
//
|
||||
// These assertions are erased at runtime; the real gate is `tsc --noEmit` (the package's
|
||||
// `check:type` script). This file is named `*.test-d.ts` on purpose so vitest does NOT
|
||||
// pick it up as a runtime test (its include is `*.test.ts`), while tsc still checks it.
|
||||
import { expectTypeOf } from "vite-plus/test";
|
||||
import type {
|
||||
BoxProps,
|
||||
TextProps,
|
||||
StaticProps,
|
||||
TransformProps,
|
||||
NewlineProps,
|
||||
WindowSize,
|
||||
CursorPosition,
|
||||
} from "@vue-tui/runtime";
|
||||
|
||||
// Prop types carry their component's real, declared props.
|
||||
expectTypeOf<BoxProps["flexDirection"]>().toEqualTypeOf<
|
||||
"row" | "row-reverse" | "column" | "column-reverse" | undefined
|
||||
>();
|
||||
expectTypeOf<BoxProps["gap"]>().toEqualTypeOf<number | undefined>();
|
||||
expectTypeOf<TextProps["bold"]>().toEqualTypeOf<boolean | undefined>();
|
||||
expectTypeOf<StaticProps["items"]>().toEqualTypeOf<unknown[]>();
|
||||
expectTypeOf<TransformProps["transform"]>().toEqualTypeOf<
|
||||
(line: string, lineIndex: number) => string
|
||||
>();
|
||||
expectTypeOf<NewlineProps["count"]>().toEqualTypeOf<number | undefined>();
|
||||
|
||||
// Framework-neutral data shapes, mirrored from Ink exactly.
|
||||
expectTypeOf<WindowSize>().toEqualTypeOf<{ readonly columns: number; readonly rows: number }>();
|
||||
expectTypeOf<CursorPosition>().toEqualTypeOf<{ x: number; y: number }>();
|
||||
Reference in New Issue
Block a user