<!-- 04_VISUAL/xwui/xwui-lib/xwui-lib-super/src/text/XWUITextStream/XWUITextStream.md -->

# XWUITextStream

Text that appears word by word, grapheme by grapheme or sentence by sentence with a caret. The host paces it (a live answer arriving over SSE) or it paces itself (a demo line). The complete text is always in the DOM: what is not revealed yet keeps its box with no ink, so assistive technology and crawlers read the whole text and nothing below moves. Typed spans (a person, a date) colour when complete, citation markers follow their offset, and one live-region announcement fires at completion, never per word.

Self pacing runs on the shared basic playback controller (`@exonware/xwui-lib-basic/_shared/playback`): it starts the first time it is seen, pauses off screen and in a hidden tab, shows everything at once under reduced motion, does not autoplay on a coarse pointer, and offers a Pause control when the motion lasts over five seconds or loops (WCAG 2.2.2).

## Basic Usage

```example
file: examples/BasicUsage.ts
html: examples/BasicUsage.html
title: Basic Usage
description: A host-paced answer: the host appends chunks as they arrive and finishes the stream.
```

## Self-paced hero line

```example
file: examples/SelfPacedHero.ts
html: examples/SelfPacedHero.html
title: Self-paced hero line
description: A demo line that types itself on the shared playback clock, rests, and starts again.
```

## Typed entity echo

```example
file: examples/EntityEcho.ts
html: examples/EntityEcho.html
title: Typed entity echo
description: Person and date runs colour when complete, with a spoken kind prefix.
```

## Data

| Field | Meaning |
| --- | --- |
| `text` | Everything known so far. Host pacing appends to it. |
| `revealed` | Host pacing: units revealed. Unset: all of `text`. |
| `complete` | Host pacing: the stream finished. Unset: finished once everything is revealed. |
| `spans[]` | `{ start, end, kind }`, UTF-16 offsets, `end` exclusive. Overlaps are dropped. |
| `citations[]` | `{ id, at, label, title?, href? }`; the marker appears once the text up to `at` is revealed. |

## Options

| Option | Default | What it does |
| --- | --- | --- |
| `unit` | `'word'` | `'word'` (Arabic letters join, so words for Arabic), `'char'` (graphemes), `'sentence'`. |
| `pacing` | `'host'` | `'host'` or `'self'`. |
| `unitsPerSecond` | `6` | Self pacing speed. |
| `loop` | play once | `{ holdMs }`: rest at the end, then again. The announcement is made once, not per loop. |
| `autoplay` | `'on-view'` | Self pacing start; never under reduced motion or on a coarse pointer. |
| `caret` | `true` | Caret while streaming. |
| `kinds` | none | `{ id, label, hue }`; `hue` is a token NAME (`violet` reads `var(--xwui-hue-violet)`). |
| `spansWhen` | `'complete'` | Colour spans at completion, or as soon as each is `'revealed'`. |
| `announce`, `politeness` | `'on-complete'`, `'polite'` | The completion announcement and its politeness. |
| `dir` | `'auto'` | Text direction. |
| `reserveSpace` | `true` | Keep the box of the text still to come. `false` hides it visually (still read). |
| `showControl` | `'auto'` | Pause / Play for self pacing: over 5 s or looping, `true` always, `false` never. |
| `label` | none | Accessible name; makes the root a labelled group. |

## Methods and events

`append(chunk)`, `setRevealed(n)`, `finish()`, `play()`, `pause()`, `toggle()`, `restart()`, `stop()`, `getStatus()`. Events: `onProgress(shown, total)` when the revealed units change (never per frame), `onComplete(total)`, `onStop(shown, total)` (the host aborts its request), `onCitation(id, href)`.

The fifth constructor argument is the playback seam, `{ clock, environment }` from `_shared/playback` (a manual clock and a fake page in tests).

## Accessibility

- The visible text and the readable text are the same nodes: pending text has no ink but stays in the accessibility tree.
- The caret is `aria-hidden`. The live region is separate (`role=status`, or `alert` when assertive) and is filled once, at completion, only after a real stream; a static text or a reduced-motion page announces nothing.
- Spans are `<mark>` with a visually hidden kind prefix ("Person: ") and a `<bdi>` around the run; the active colour also has an underline.
- Citation markers are real buttons named "Source 1: Board export", hidden (and out of the tab order) until revealed.
- The playback control is a real button named Pause, Play or Replay; 48 px on a coarse pointer.

## RTL

No physical property; `dir="auto"` by default, so an Arabic answer in an English page and an English answer in an Arabic page both read correctly, and the caret follows the inline end.

## Locale keys

`xwui.text_stream.pause`, `.play`, `.replay`, `.citation` ("Source {label}: {title}"), `.kind_prefix` ("{kind}: "). English fallbacks are built in.

```api
```
