Skip to content

frank1003A/use-pretext

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

5 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-pretext-hooks

npm: react-pretext-hooks

Pretext is the engine; this is a small React wrapper

Pretext by Chen Lou is the library worth knowing about: canvas-backed text measurement, line breaking, and layout that keeps the expensive work off the DOM, with typography that stays faithful to how browsers render text.

react-pretext-hooks brings @chenglou/pretext into React with a few hooks (prepare / layout memoization, ResizeObserver where it helps) and a small <MeasuredText> component. Capabilities and design live in the Pretext repo, this is just convenience wiring.

Install

npm install react-pretext-hooks @chenglou/pretext react

@chenglou/pretext and react (>=18) are peer dependencies.

API

useTextLayout(text, font, width, lineHeight, options?)

All-in-one hook. Returns { height, lineCount }.

import { useTextLayout } from "react-pretext-hooks";

function MyComponent() {
  const { height, lineCount } = useTextLayout(
    "Hello world, this is a long paragraph…",
    "16px/1.5 Inter",
    300,
    24,
  );

  return <div style={{ height }}></div>;
}

usePrepared(text, font, options?)

Returns the raw PreparedText handle for power users who want to call layout() manually at multiple widths.

import { usePrepared } from "react-pretext-hooks";
import { layout } from "@chenglou/pretext";

function MyComponent({ widths }: { widths: number[] }) {
  const prepared = usePrepared("Some text", "16px Inter");

  const layouts = widths.map((w) => layout(prepared, w, 24));
  // …
}

useAutoLayout(text, font, lineHeight, ref, options?)

ResizeObserver-aware hook. Attach it to a container ref and it recomputes layout automatically when the container resizes.

import { useRef } from "react";
import { useAutoLayout } from "react-pretext-hooks";

function AutoBox() {
  const ref = useRef<HTMLDivElement>(null);
  const { height, lineCount, width } = useAutoLayout(
    "Resizable text…",
    "16px Inter",
    24,
    ref,
  );

  return (
    <div ref={ref} style={{ height }}>
      Resizable text…
    </div>
  );
}

<MeasuredText>

Component wrapper around useAutoLayout. Renders a container whose height is driven by the measured text layout.

import { MeasuredText } from "react-pretext-hooks";

<MeasuredText text="Hello world" font="16px Inter" lineHeight={24}>
  <p>Hello world</p>
</MeasuredText>;

Props:

Prop Type Description
text string The text to measure.
font string CSS font shorthand (e.g. "16px Inter").
lineHeight number Line height in pixels.
options PrepareOptions Optional whiteSpace / wordBreak overrides.
children ReactNode Rendered inside the container (defaults to text).
className string Class name for the wrapper element.
style CSSProperties Additional inline styles.
as keyof JSX.IntrinsicElements HTML tag to render (default "div").

The component also sets data-measured-height, data-measured-lines, and data-measured-width attributes on the wrapper element.

PrepareOptions

interface PrepareOptions {
  whiteSpace?: "normal" | "pre-wrap";
  wordBreak?: "normal" | "keep-all";
}

How it works

@chenglou/pretext splits text measurement into two phases:

  1. prepare() — the expensive step. Segments text and measures each segment via an offscreen canvas. This is memoized by the hooks so it only runs when text or font change.
  2. layout() — pure arithmetic (~0.0002 ms). Computes height and line count from the prepared data for a given width. This runs on every resize or parameter change with negligible cost.

License

MIT

About

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors