npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@semantic-wrap/react

v0.4.0

Published

Headless React integration for model-driven line breaking.

Readme

@semantic-wrap/react

English | 한국어

@semantic-wrap/react measures the rendered font, width, and native wrapping of a DOM element. It passes that data to Core and renders the selected calculated layout as <br> elements.

Installation

npm install @semantic-wrap/core @semantic-wrap/react @semantic-wrap/en react react-dom

React and React DOM 19 or later are required as peer dependencies. This package is ESM-only.

SemanticWrap

import { enTitleModel } from "@semantic-wrap/en";
import { SemanticWrap } from "@semantic-wrap/react";

export function Title({ children }: { children: string }) {
  return (
    <SemanticWrap model={enTitleModel}>
      <h1 className="title">{children}</h1>
    </SemanticWrap>
  );
}

SemanticWrap preserves its child element and adds no wrapper. Pass exactly one plain-text React element that forwards its ref to an actual HTMLElement.

Display and update scheduling

| Option | Default | Alternative | | --- | --- | --- | | initial | "resolved": hide until the first exact selection | "native": show source, then automatically calculate cooperatively | | resize | "immediate": synchronous calculation and application | "settled": cooperative calculation and stable-width application |

All four combinations preserve the same exact selection and native comparison.

<SemanticWrap initial="native" resize="settled" model={enTitleModel}>
  <p>{text}</p>
</SemanticWrap>

Native-first allows a source frame before starting work, without requiring a resize. Its initial result is applied when ready, without an extra stability wait. If width changes during startup, obsolete work is cancelled and the selected resize policy applies. Settled updates keep source text visible, calculate in approximately 4 ms slices, and apply only the latest result after about 100 ms of stable width and completed calculation. Immediate updates do not introduce this wait.

Text changes restart the first-display policy. Font/style changes use the update policy. At unchanged text and measurement conditions, new model/strategy references keep the displayed result while revalidating; only changed results are published. This includes candidate metadata and diagnostics, not just break offsets. Changing options or unmounting cancels pending work. Resolved-first SSR keeps source text in HTML with zero opacity; native-first SSR is visible and hydration starts automatic calculation. No additional DOM wrapper is introduced.

Migration from mode

mode and SemanticWrapMode are deprecated, but supported:

  • mode="precise" maps to initial="resolved" resize="immediate".
  • mode="progressive" retains its original behavior: native source until the first viewport/element resize, then synchronous updates. It is not an alias for the new automatic initial="native".
  • Mixing mode with either new option is rejected by TypeScript and at runtime.
  • The interim cooperative-precise behavior in commit 57f73fd requires explicit resize="settled"; the default restores the earlier immediate behavior.

Exact segment widths are reused across container widths, with at most 65,536 offset-keyed entries per plan/metric identity. Typography changes and unmount invalidate the cache. The 4 ms work budget is cooperative, not a hard deadline: individual browser operations and custom synchronous predictors/calculators/selectors cannot be interrupted. Calculators can provide a synchronous steps iterator. Completion can take longer than 100 ms. Stable model/strategy references avoid redundant calculation, but memoization is not required for correctness. Callbacks must remain deterministic for the same inputs.

Chakra UI

import { Text } from "@chakra-ui/react";
import { enTitleModel } from "@semantic-wrap/en";
import { SemanticWrap } from "@semantic-wrap/react";

<SemanticWrap model={enTitleModel}>
  <Text textStyle="heading2">{title}</Text>
</SemanticWrap>

Tailwind CSS

import { createLineBreakStrategy, greedy } from "@semantic-wrap/core";
import { enTitleModel } from "@semantic-wrap/en";
import { SemanticWrap } from "@semantic-wrap/react";

const greedyStrategy = createLineBreakStrategy({ calculate: greedy() });

<SemanticWrap model={enTitleModel} strategy={greedyStrategy}>
  <h2 className="text-3xl font-bold leading-tight">{title}</h2>
</SemanticWrap>

The default global search batches exact DOM text measurements automatically, using a bounded pool of reusable hidden elements. It keeps the existing candidate space and selection rules; no configuration is required. Probes are released on invalidation and unmount.

Faster local search for long text

import { createLineBreakStrategy, nearbyLayouts } from "@semantic-wrap/core";

const nearbyStrategy = createLineBreakStrategy({ calculate: nearbyLayouts() });

<SemanticWrap model={enTitleModel} strategy={nearbyStrategy}>
  <p>{longText}</p>
</SemanticWrap>

React supplies the measured native breaks automatically. This opt-in calculator searches near native line endings using exact substring measurements. It can substantially reduce work on long text, but can miss improvements found by the default global search; it is not a guarantee of identical wrapping or smooth 60fps resizing. The default remains optimalLayouts(). The same strategy works with useSemanticWrap.

useSemanticWrap

Use the hook when your application needs to render or inspect the selected layout itself. Measurement uses the target element's computed text style. If nested markup uses different typography, use Core with a matching custom measureText function.

const { ref, selection, diagnostics } = useSemanticWrap({
  text: title,
  model: enTitleModel,
  diagnostics: true,
  initial: "native",
  resize: "settled",
});

The hook returns a measurement ref, the selected layout, and optional diagnostics. It does not change the target element's children or CSS. The same initial/resize options control its scheduling, not visibility. Selection and diagnostics are null during pending initial or geometry/text work; render source text then. Reference-only revalidation retains the previous result. Hiding the initial content, if desired, is caller-owned.

License

Apache-2.0.