Files
vue-tui/packages/runtime-tests/integration/components
Yunfei He eaf333a5ea fix(runtime): unmount written <Static> items to match Ink (G01) (#34)
* fix(runtime): unmount written <Static> items to match Ink (G01)

Ink's <Static> renders `items.slice(index)` and advances `index` to
`items.length` in a post-commit `useLayoutEffect`, so once an item has been
painted it is removed from the tree and its component unmounts. vue-tui kept
every Static item mounted forever: the component always mapped the full
`props.items`, and write-once was enforced only at flush time via a positional
`writtenCount` slice — the item components never tore down.

Now the <Static> component owns a `cursor` (Ink's `index`) and renders only
`items.slice(cursor)`. The renderer advances the cursor AFTER a commit has
painted the fresh items, via an `onWritten` callback registered on the host
static node — the vue-tui analogue of Ink's post-commit layout effect. This
ordering guarantees items are written before they are sliced out and unmounted,
so no item is ever lost or re-painted.

Write-once bookkeeping moved from a positional `writtenCount` to a
`writtenNodes` Set keyed by host-node identity. A single logical item expands to
several host nodes (the <Text>/<Box> plus empty text-leaf fragment anchors Vue
inserts), so a positional count mis-sliced once the cursor advanced; identity
tracking is anchor-agnostic. The shared `paintStaticNode` helper paints children
not yet in the set, records them, prunes unmounted entries, then fires
`onWritten`; render.ts, render-to-string.ts and flushStatic all use it.

Make the cursor mirror Ink fully so it can DECREASE, not just increase.
`onWritten` now SETS the cursor to items.length (was max-with-current), and a
length watch lowers it on shrink — needed because a shrink that leaves the
already-sliced children empty produces no host mutation, hence no commit/
onWritten to re-sync. Without this, [A,B] (cursor→2) → [A] → [A,C] sliced(2)=[]
and silently dropped C. paintStaticNode now always prunes and calls onWritten
(even on empty commits), painting only when there are fresh children.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore(parity): ledger — G01 pr-open, reconcile G12 merged

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-05-30 01:01:08 +08:00
..