@pretextui/react
v0.3.1
Published
React components powered by [Pretext](https://github.com/chenglou/pretext) — virtual scrolling, auto-resize textareas, and text measurement without DOM reflow.
Readme
PretextUI
React components powered by Pretext — virtual scrolling, auto-resize textareas, and text measurement without DOM reflow.
Install
npm install @pretextui/core @pretextui/react @chenglou/pretextQuick Examples
VirtualTextList — virtual scroll 10,000 chat messages:
import { VirtualTextList } from "@pretextui/react";
<VirtualTextList
items={messages}
renderItem={(item) => <div className="bubble">{item.text}</div>}
defaultFont="16px Inter"
lineHeight={22}
height={600}
padding={16}
scrollToIndex={5000}
/>;Width is measured automatically. Padding is subtracted from measurements internally.
AutoTextarea — grows with content:
import { AutoTextarea } from "@pretextui/react";
<AutoTextarea
font="16px Inter"
lineHeight={24}
minRows={1}
maxRows={10}
padding={16}
/>;BalancedText — minimize ragged-right in headlines:
import { BalancedText } from "@pretextui/react";
<BalancedText font="20px Inter" lineHeight={28} maxWidth={400}>
The quick brown fox jumps over the lazy dog
</BalancedText>;useTextMeasure — raw measurement hook:
import { useTextMeasure } from "@pretextui/react";
const measurement = useTextMeasure(text, "16px Inter", 400, 24);
// returns { height, lineCount } or null while fonts loaduseRichTextMeasure — measure mixed-font inline text:
import { useRichTextMeasure } from "@pretextui/react";
const items = [
{ text: "Hello ", font: "700 16px Inter" },
{ text: "world", font: "16px Inter" },
];
const measurement = useRichTextMeasure(items, 400, 24);
// returns { height, lineCount } or null while fonts loadAPI Reference
| Export | Package | Description |
| -------------------- | ------- | -------------------------------------------------------------------------- |
| VirtualTextList | react | Virtualized list for variable-height text. Auto-measures container width. |
| AutoTextarea | react | Textarea that auto-resizes with arithmetic height computation. |
| BalancedText | react | Text block that minimizes ragged-right by computing optimal width. |
| useTextMeasure | react | Hook returning text height and line count. Returns null during SSR. |
| useTextOverflow | react | Hook detecting overflow and computing truncation index. |
| useShrinkWrap | react | Hook finding the minimum width that preserves line count. |
| measureText | core | Synchronous text height and line count measurement. |
| measureTextLines | core | Measurement with per-line text content and widths. |
| findShrinkWidth | core | Binary search for the tightest width preserving line count. Padding-aware. |
| checkOverflow | core | Check whether text overflows and find truncation point. |
| createMeasureCache | core | Memoized measurement cache. |
| checkFont | core | Check if a font string matches a loaded font. |
| useRichTextMeasure | react | Hook measuring mixed-font inline text. Returns null during SSR. |
| measureRichText | core | Measure inline-flow rich text height and line count. |
| measureRichTextLines | core | Rich text measurement with per-line fragments and item indices. |
| findRichShrinkWidth | core | Binary search for tightest width preserving rich text line count. |
Gotchas
Font must be loaded before measurement. Measurements run after document.fonts.ready, but if a custom font never loads, results use a fallback. In development, PretextUI warns via console.warn when a font isn't ready.
Font string format. The font prop must be a valid CSS font shorthand: '16px Inter', '700 14px Arial'. The family name must exactly match a loaded @font-face or system font.
Width is auto-measured. VirtualTextList measures its own container width via ResizeObserver. Pass an explicit width prop only to override. Items render after the first width measurement.
Padding. Pass padding={16} (symmetric) or padding={{ left: 12, right: 20 }} (asymmetric) so measurements account for container padding. Without this, text heights will be computed at the wrong width.
SSR safe. All hooks return null during server-side rendering. Components render without computed dimensions on the server and hydrate correctly on the client.
How It Works
Pretext computes text height through pure arithmetic — no DOM measurement, no layout reflow. PretextUI wraps this into React components that handle font loading, caching, container measurement, and lifecycle automatically.
Performance
| Scenario | Traditional (DOM) | PretextUI | | -------------------- | -------------------------- | ------------------------------ | | 10,000 item heights | ~500ms (reflow) | ~19ms prepare + ~0.09ms layout | | Textarea keystroke | 1–5ms (hidden element) | ~0.001ms (arithmetic) | | Scroll to item #5000 | Wrong position (estimated) | Pixel-perfect (exact) |
prepare() runs once per unique text. layout() is the hot path.
Changelog
See CHANGELOG.md.
License
MIT
