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

@nicklasastorian/react-pdf-annotator

v1.2.7

Published

Extended Set of React components for PDF annotation

Readme

react-pdf-highlighter

Set of React components for PDF annotation.

Note: This is a fork of agentcooper/react-pdf-highlighter with significant UX improvements.

Features

  • Built on top of PDF.js
  • Text and image highlights
  • Popover text for highlights
  • Scroll to highlights

Fork Improvements

This fork includes the following enhancements:

Highlight Interaction

  • Hover-based action bar: Shows on hover with 200ms delay (prevents flickering), instead of right-click
  • Smooth hover transitions: 150ms grace period allows mouse to move from highlight to action bar
  • Click protection: Clicking action bar buttons no longer dismisses the popup

Selection Flow

  • Mouseup-based selection: Toolbar appears only after releasing mouse, not while dragging
  • Morphing toolbar: After saving, toolbar transitions from "save mode" to "edit mode"
  • No double-yellow: Browser selection is cleared on save to prevent color stacking

Positioning

  • Centered popups: Action bars are horizontally centered above highlights
  • Smart clamping: Popups stay within page bounds while maintaining optimal position

Visual

  • Better highlight color: More vibrant yellow (rgba(255, 212, 0, 0.4))
  • Hover feedback: Highlights brighten slightly on hover

New Props

| Prop | Description | |------|-------------| | renderPopup | Simpler alternative to highlightTransform for hover action bars | | onTextLayerReady | Callback when a page's text layer is rendered | | onDocumentReady | Callback when document is ready | | forceRenderOnLoad | Force re-render highlights when all pages loaded | | onHighlightHover | Callback when a highlight is hovered | | onHighlightBlur | Callback when a highlight loses hover | | disallowOverlappingHighlights | Prevent creating overlapping text highlights on the same line | | onOverlap | Callback fired when a selection overlaps an existing highlight |

Install

npm install react-pdf-highlighter

Importing CSS

import "react-pdf-highlighter/dist/style.css";

Example

npm install
npm start

The example demonstrates:

  • Slide-over panel pattern
  • Zoom controls (Ctrl+scroll or buttons)
  • Morphing toolbar (save → edit)
  • Comment dialog modal
  • In-memory highlight persistence

Basic Usage

import { PdfHighlighter, PdfLoader } from "react-pdf-highlighter";
import "react-pdf-highlighter/dist/style.css";

<PdfLoader url={pdfUrl} beforeLoad={<Spinner />}>
  {(pdfDocument) => (
    <PdfHighlighter
      pdfDocument={pdfDocument}
      enableAreaSelection={(event) => event.altKey}
      onScrollChange={() => {}}
      scrollRef={(scrollTo) => { /* store scrollTo */ }}
      onSelectionFinished={(position, content, hideTipAndSelection, transformSelection) => (
        <MySelectionToolbar
          onSave={() => {
            saveHighlight({ position, content });
            hideTipAndSelection();
          }}
        />
      )}
      renderPopup={(highlight) => (
        <MyActionBar highlight={highlight} />
      )}
      highlights={highlights}
    />
  )}
</PdfLoader>

useHighlights Helper

useHighlights is an optional convenience hook for managing highlight state while keeping your data source external (React Query, Redux, etc.).

import { useState } from "react";
import { useHighlights } from "react-pdf-highlighter";

const [highlights, setHighlights] = useState<IHighlight[]>([]);
const {
  addHighlight,
  updateHighlight,
  deleteHighlight,
  saveComment,
} = useHighlights({
  highlights,
  setHighlights,
});

This pattern lets you merge/split your own persistence models in setHighlights and rehydrate via async fetches.

useZoom Helper

useZoom provides a small controller for zooming the PDF viewer (buttons + ctrl/cmd + wheel).

import { useRef } from "react";
import { useZoom } from "react-pdf-highlighter";

const containerRef = useRef<HTMLDivElement | null>(null);
const { pdfScaleValue, zoomLabel, zoomIn, zoomOut, fitWidth } = useZoom(
  containerRef,
  true,
);

How It Works (Library)

High-level flow

  • PdfLoader loads a PDFDocumentProxy using PDF.js and hands it to your render prop.
  • PdfHighlighter owns a PDF.js PDFViewer, attaches selection/scroll listeners, and renders highlights into a per-page overlay layer.
  • Text selections call onSelectionFinished with a ScaledPosition and text content; area selections are handled by MouseSelection and yield image content.
  • Highlights are rendered via highlightTransform (custom) or the default transform, which chooses Highlight for text or AreaHighlight for images and can show a popup via renderPopup.

Data model and coordinates

  • ScaledPosition is stored in PDF/viewport-independent units (optionally usePdfCoordinates).
  • Position is viewport pixels used for rendering. scaledToViewport and viewportToScaled live in src/lib/coordinates.ts.
  • IHighlight is the base interface for highlight objects; HighlightHooks exposes onCreate, onUpdate, and onDelete.

Project layout (library)

  • src/index.ts is the public entry point; it re-exports components, types, and the global CSS.
  • src/components/ contains PdfHighlighter, PdfLoader, and the overlay UI (Highlight, AreaHighlight, TipContainer).
  • src/lib/ contains PDF.js DOM helpers, coordinate conversions, and geometry utilities.
  • src/style/ holds CSS modules plus index.css which imports the PDF.js viewer styles.

Build outputs

  • Vite builds the package and emits JS + CSS into dist/.
  • Types are emitted via vite-plugin-dts and exposed at dist/index.d.ts.
  • The published package exposes dist/style.css for styling.

API Reference

See ./example/src/App.tsx for a complete implementation example.

API Improvement Ideas (Future)

These are optional, backward-compatible ideas that could simplify usage and improve extensibility:

  • Decouple UI from selection: make onSelectionFinished return data/payload, with an optional renderSelection for UI.
  • Consolidate highlight types: collapse HighlightPayload/HighlightBase/IHighlight into a clearer, generic model (typed meta).
  • Unified PDF.js options: accept a single pdfjsOptions object (worker/cMap/viewer) to reduce prop surface area.
  • Public coordinate helpers: export scaledToViewport/viewportToScaled from the public API for consumers.

License

MIT