feat(components): add ScrollBox component (#237)
* feat(runtime): add ScrollBox component * refactor(components): move ScrollBox into components package * feat(runtime): add mouse input composable * refactor(components): delegate ScrollBox mouse input * docs: describe mouse input composable * fix(runtime): consume unsupported SGR mouse input * fix(components): gate ScrollBox input on raw mode support * fix(runtime): require escape prefix for SGR mouse input * refactor(components): rename ScrollBox input props to wheel/keyboard Follow the components boolean-prop convention (bare noun, default false): enableMouse/enableKeyboard/isActive -> wheel/keyboard, both opt-in. Mouse- wheel is off by default because enabling terminal mouse tracking suppresses the terminal's native text selection window-wide. Record the convention in components-design-principles.md. * refactor(components): rename ScrollBox linesPerWheel + input tests - Rename the wheel-step prop wheelLines -> linesPerWheel. - Drop Home/End keyboard scroll for now — keyboard is PageUp/PageDown only. - Add tests: keyboard paging, and SGR mouse-mode disable on signal-exit (fs.writeSync path, mirroring the bracketed-paste test). * feat(examples): add ScrollBox streaming demo A streaming-log demo of <ScrollBox wheel keyboard>: new lines arrive on a timer and stick to the bottom until you scroll up (wheel / PageUp / PageDown), then hold position while output keeps arriving. Press q to quit. --------- Co-authored-by: Yunfei He <i.heyunfei@gmail.com>
This commit is contained in:
@@ -129,27 +129,29 @@ createApp(App).mount();
|
||||
|
||||
The [`@vue-tui/components`](./packages/components) package adds higher-level components composed from the runtime primitives — published separately from the core.
|
||||
|
||||
| Component | Description |
|
||||
| ------------------------------------ | ------------------------------------------------------------------------------------------ |
|
||||
| [`<Spinner>`](./packages/components) | Animated loading spinner — built-in `dots`/`line` presets or custom frames, optional label |
|
||||
| Component | Description |
|
||||
| -------------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| [`<ScrollBox>`](./packages/components) | Bounded scroll viewport with mouse-wheel scrolling and sticky-bottom behavior |
|
||||
| [`<Spinner>`](./packages/components) | Animated loading spinner — built-in `dots`/`line` presets or custom frames, optional label |
|
||||
|
||||
## Composables (Hooks)
|
||||
|
||||
| Composable | Description |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `useInput(handler, opts?)` | Handle keyboard input — receives `(input, key)` with modifier and arrow key detection |
|
||||
| `usePaste(handler, opts?)` | Handle bracketed paste — receives the pasted `text` as a single event |
|
||||
| `useFocus(opts?)` | Component-level focus — returns `{ isFocused, focus }` |
|
||||
| `useFocusManager()` | App-level focus control — `focusNext()`, `focusPrevious()`, `focus(id)` |
|
||||
| `useApp()` | App lifecycle — `{ exit(error?), waitUntilRenderFlush() }` |
|
||||
| `useWindowSize()` | Reactive terminal dimensions — `{ columns, rows }` |
|
||||
| `useStdin()` | Access stdin stream and raw mode control |
|
||||
| `useStdout()` | Write directly to stdout |
|
||||
| `useStderr()` | Write directly to stderr |
|
||||
| `useBoxMetrics(ref)` | Measure a `<Box>` via a template ref — reactive `{ width, height, left, top, hasMeasured }` (or `measureElement(el)` for a one-off `{ width, height }` read) |
|
||||
| `useCursor()` | Control the terminal cursor — `setCursorPosition(pos)` in output coordinates |
|
||||
| `useIsScreenReaderEnabled()` | Whether a screen reader is active — returns a boolean for adapting accessible output |
|
||||
| `useAnimation(opts?)` | Frame-based animation driver — reactive `{ frame, time, delta }` + `reset()` |
|
||||
| Composable | Description |
|
||||
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `useInput(handler, opts?)` | Handle keyboard input — receives `(input, key)` with modifier and arrow key detection |
|
||||
| `useMouseInput(handler, opts?)` | Handle terminal mouse input — currently SGR wheel events with ref-counted mouse-mode ownership |
|
||||
| `usePaste(handler, opts?)` | Handle bracketed paste — receives the pasted `text` as a single event |
|
||||
| `useFocus(opts?)` | Component-level focus — returns `{ isFocused, focus }` |
|
||||
| `useFocusManager()` | App-level focus control — `focusNext()`, `focusPrevious()`, `focus(id)` |
|
||||
| `useApp()` | App lifecycle — `{ exit(error?), waitUntilRenderFlush() }` |
|
||||
| `useWindowSize()` | Reactive terminal dimensions — `{ columns, rows }` |
|
||||
| `useStdin()` | Access stdin stream and raw mode control |
|
||||
| `useStdout()` | Write directly to stdout |
|
||||
| `useStderr()` | Write directly to stderr |
|
||||
| `useBoxMetrics(ref)` | Measure a `<Box>` via a template ref — reactive `{ width, height, left, top, hasMeasured }` (or `measureElement(el)` for a one-off `{ width, height }` read) |
|
||||
| `useCursor()` | Control the terminal cursor — `setCursorPosition(pos)` in output coordinates |
|
||||
| `useIsScreenReaderEnabled()` | Whether a screen reader is active — returns a boolean for adapting accessible output |
|
||||
| `useAnimation(opts?)` | Frame-based animation driver — reactive `{ frame, time, delta }` + `reset()` |
|
||||
|
||||
## Testing
|
||||
|
||||
|
||||
Reference in New Issue
Block a user