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

@markitjs/react

v1.0.4

Published

React bindings for @markitjs/core text highlighting engine

Downloads

1

Readme

@markitjs/react

React bindings for the @markitjs/core text highlighting engine. Provides a useHighlight hook and a declarative Highlighter component.

Install

npm install @markitjs/react
# or
bun add @markitjs/react
# or
pnpm add @markitjs/react
# or (Yarn — include @markitjs/core explicitly)
yarn add @markitjs/react @markitjs/core

Peer dependencies: React 18+ or 19+, and @markitjs/core (installed automatically by npm 7+, pnpm, and bun; with Yarn, add @markitjs/core explicitly: yarn add @markitjs/react @markitjs/core).

Quick Start

Hook

Next.js App Router: Add "use client" at the top of any file that uses the hook or <Highlighter>.

import { useHighlight } from '@markitjs/react';

function SearchResults({ query }: { query: string }) {
  const ref = useHighlight(query, { caseSensitive: false });

  return (
    <div ref={ref}>
      <p>Content to search and highlight.</p>
    </div>
  );
}

Component

import { Highlighter } from '@markitjs/react';

function App() {
  return (
    <Highlighter term="react" accuracy="exactly">
      <article>
        <p>React is a JavaScript library for building user interfaces.</p>
      </article>
    </Highlighter>
  );
}

API

useHighlight(term, options?)

Returns a ref to attach to the container element.

const ref = useHighlight<HTMLDivElement>(term, {
  // All @markitjs/core options, plus:
  plugins: [], // MarkitPlugin[]
  timing: 'effect', // 'effect' (default) | 'layout'
  contentKey: value, // optional: re-run when content identity changes
});

| Option | Type | Description | | ------------ | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | timing | 'effect' \| 'layout' | 'effect' runs after paint (SSR-safe). 'layout' runs before paint — use with the DOM renderer to avoid a flash of unhighlighted content. | | plugins | MarkitPlugin[] | Plugins to register with the core instance. | | contentKey | Key \| Key[] | When content is dynamic, pass value(s) that change with content so the effect re-runs and re-applies. |

All other options are passed through to @markitjs/core's mark() method. For dynamic content (e.g. state or props), pass contentKey so highlights re-apply when content changes and avoid garbled text. See Framework lifecycles for how the React highlight cycle works.

Highlighter

Declarative component that wraps children and highlights matching text.

<Highlighter
  term="search" // string | string[]
  as="div" // Container element tag (default: 'div')
  className="my-class" // Container CSS class
  style={{ padding: 16 }} // Container inline styles
  contentKey={contentId} // optional: for dynamic content
  caseSensitive={false} // Any @markitjs/core option
  renderer="auto"
/>

Safety

The bindings are designed to be safe across React's rendering model:

| Concern | How it's handled | | ------------------------- | --------------------------------------------------------- | | StrictMode | Cleanup runs before re-invocation; unmark is idempotent | | Concurrent rendering | Effects only run on committed renders | | Next.js SSR/hydration | useEffect doesn't run on the server or during hydration | | Re-renders | Options are shallow-compared; no work if nothing changed | | Unmount | destroy() is called in the effect cleanup |

Performance

  • Term: A string term is already stable (same value = no extra work). When term is an array, the hook compares by contents, not reference: passing a new array with the same items (e.g. [word1, word2] every render) will not re-run the effect. Optionally use useMemo for the array if you want to avoid that internal comparison.
  • Options: Pass a stable options object (e.g. useMemo(() => ({ ... }), [deps]) or a constant) so the effect does not re-run when nothing actually changed. Options are shallow-compared; a new object reference every render may trigger re-runs even when values are the same.

Next.js Usage

The Highlighter component includes a 'use client' directive. Use it inside Client Components:

// app/search/results.tsx
'use client';

import { Highlighter } from '@markitjs/react';

export function Results({ query, html }: { query: string; html: string }) {
  return (
    <Highlighter term={query} renderer="auto">
      <div dangerouslySetInnerHTML={{ __html: html }} />
    </Highlighter>
  );
}

Server Components can render the content; the Highlighter applies highlights client-side after hydration.

Batched Rendering

For large content areas, enable batched rendering to keep the UI responsive:

const ref = useHighlight(query, {
  batchSize: 500,
  done: (count) => setMatchCount(count),
});

CSS Highlight API Styling

When using the default auto renderer on supported browsers, add this CSS:

::highlight(markit-highlight) {
  background-color: #fef08a;
  color: inherit;
}

License

MIT