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

@salina-app/pdf-viewer-react

v3.0.6

Published

React wrapper for Salina PDF Viewer

Readme

@salina-app/pdf-viewer-react

React components and hooks for the Salina PDF Viewer library.

Features

  • ⚛️ React Integration: Native React components and hooks
  • 🎯 TypeScript Support: Full TypeScript integration with proper types
  • 🪝 Custom Hooks: Easy-to-use hooks for PDF viewing, search, and highlighting
  • 🎨 Customizable: Flexible component system with extensive customization
  • 📱 Responsive: Mobile-friendly components
  • 🚀 Performance: Optimized for React applications

Troubleshooting

Common Issues

Error: "Cannot read properties of undefined (reading 'current')"

This error occurs when the PDFViewerToolbar component is used without a properly initialized viewerRef.

✅ Correct Usage:

import {
  SalinaPDFViewer,
  PDFViewerToolbar,
} from "@salina-app/pdf-viewer-react";

function MyPDFApp() {
  const viewerRef = useRef<SalinaPDFViewerRef>(null);

  return (
    <>
      <PDFViewerToolbar
        viewerRef={viewerRef} // ← Required!
        currentPage={1}
        totalPages={10}
        scale={1.0}
      />
      <SalinaPDFViewer
        ref={viewerRef} // ← Connect the ref
        file="/document.pdf"
      />
    </>
  );
}

❌ Common Mistakes:

// Missing viewerRef prop
<PDFViewerToolbar currentPage={1} totalPages={10} />;

// Using undefined ref
const viewerRef = null; // ← This will cause errors
<PDFViewerToolbar viewerRef={viewerRef} />;

🔧 Quick Fix: If you're getting this error, make sure:

  1. You import and create a ref: const viewerRef = useRef<SalinaPDFViewerRef>(null)
  2. Pass it to both components: viewerRef={viewerRef}
  3. The SalinaPDFViewer component is mounted when using the toolbar

Installation

npm install @salina-app/pdf-viewer-react @salina-app/pdf-viewer-core

Peer Dependencies

npm install react react-dom pdfjs-dist@^5.3.0

Quick Start

import React from "react";
import { SalinaPDFViewer } from "@salina-app/pdf-viewer-react";

function App() {
  return (
    <div style={{ height: "100vh" }}>
      <SalinaPDFViewer
        url="/sample.pdf"
        enableSearch
        enableHighlighting
        onDocumentLoad={(doc) => console.log("Loaded:", doc.numPages)}
      />
    </div>
  );
}

export default App;

Components

SalinaPDFViewer

The main PDF viewer component.

import { SalinaPDFViewer } from "@salina-app/pdf-viewer-react";

<SalinaPDFViewer
  url="/document.pdf"
  width="100%"
  height="600px"
  zoom={1.0}
  enableSearch={true}
  enableHighlighting={true}
  theme="light"
  onDocumentLoad={(doc) => console.log("Document loaded")}
  onSearchResult={(results) => console.log("Search results:", results)}
  onHighlightAdded={(highlight) => console.log("Highlight added")}
/>;

Props

interface SalinaPDFViewerProps {
  url?: string;
  width?: string | number;
  height?: string | number;
  zoom?: number;
  enableSearch?: boolean;
  enableHighlighting?: boolean;
  theme?: "light" | "dark";
  className?: string;
  style?: React.CSSProperties;

  // Event handlers
  onDocumentLoad?: (document: PDFDocument) => void;
  onSearchResult?: (results: SearchResult[]) => void;
  onHighlightAdded?: (highlight: HighlightAnnotation) => void;
  onHighlightRemoved?: (highlightId: string) => void;
  onPageChange?: (pageNumber: number) => void;
  onZoomChange?: (zoom: number) => void;
}

PDFViewerToolbar

A customizable toolbar component for PDF controls.

import { PDFViewerToolbar } from "@salina-app/pdf-viewer-react";

<PDFViewerToolbar
  onZoomIn={() => viewer.zoomIn()}
  onZoomOut={() => viewer.zoomOut()}
  onSearch={(query) => viewer.search(query)}
  showSearch={true}
  showZoom={true}
  showPageNavigation={true}
/>;

Hooks

usePDFViewer

A hook for programmatic control of the PDF viewer.

import { usePDFViewer } from "@salina-app/pdf-viewer-react";

function MyComponent() {
  const {
    viewer,
    isLoaded,
    currentPage,
    totalPages,
    zoom,
    searchResults,
    highlights,
    load,
    search,
    addHighlight,
    removeHighlight,
    zoomIn,
    zoomOut,
    goToPage,
  } = usePDFViewer();

  const handleLoadDocument = () => {
    load("/new-document.pdf");
  };

  const handleSearch = () => {
    search("important text");
  };

  return (
    <div>
      <button onClick={handleLoadDocument}>Load Document</button>
      <button onClick={handleSearch}>Search</button>
      <p>
        Page {currentPage} of {totalPages}
      </p>
      <p>Search Results: {searchResults.length}</p>
    </div>
  );
}

useHighlights

A hook for managing highlights.

import { useHighlights } from "@salina-app/pdf-viewer-react";

function HighlightManager() {
  const {
    highlights,
    addHighlight,
    removeHighlight,
    updateHighlight,
    clearHighlights,
  } = useHighlights();

  const handleAddHighlight = () => {
    addHighlight({
      pageNumber: 1,
      bounds: { x: 100, y: 200, width: 150, height: 20 },
      color: "#ffff00",
      note: "Important section",
    });
  };

  return (
    <div>
      <button onClick={handleAddHighlight}>Add Highlight</button>
      <p>Total Highlights: {highlights.length}</p>
      {highlights.map((highlight) => (
        <div key={highlight.id}>
          <span>{highlight.note}</span>
          <button onClick={() => removeHighlight(highlight.id)}>Remove</button>
        </div>
      ))}
    </div>
  );
}

usePDFSearch

A hook for advanced search functionality.

import { usePDFSearch } from "@salina-app/pdf-viewer-react";

function SearchComponent() {
  const {
    query,
    results,
    currentResult,
    isSearching,
    search,
    clearSearch,
    nextResult,
    previousResult,
  } = usePDFSearch();

  return (
    <div>
      <input
        value={query}
        onChange={(e) => search(e.target.value)}
        placeholder="Search in document..."
      />
      {isSearching && <span>Searching...</span>}
      {results.length > 0 && (
        <div>
          <span>
            {currentResult + 1} of {results.length}
          </span>
          <button onClick={previousResult}>Previous</button>
          <button onClick={nextResult}>Next</button>
        </div>
      )}
    </div>
  );
}

Advanced Usage

Custom Viewer with Toolbar

import React, { useRef } from "react";
import {
  SalinaPDFViewer,
  PDFViewerToolbar,
  usePDFViewer,
} from "@salina-app/pdf-viewer-react";

function CustomPDFViewer({ url }: { url: string }) {
  const viewerRef = useRef(null);
  const { viewer, isLoaded, currentPage, totalPages } = usePDFViewer();

  return (
    <div className="pdf-viewer-container">
      <PDFViewerToolbar
        onZoomIn={() => viewer?.zoomIn()}
        onZoomOut={() => viewer?.zoomOut()}
        onSearch={(query) => viewer?.search(query)}
        currentPage={currentPage}
        totalPages={totalPages}
      />
      <SalinaPDFViewer
        ref={viewerRef}
        url={url}
        enableSearch
        enableHighlighting
        onDocumentLoad={(doc) => console.log("Loaded:", doc.numPages)}
      />
    </div>
  );
}

Highlight Management

import React, { useState } from "react";
import { SalinaPDFViewer, useHighlights } from "@salina-app/pdf-viewer-react";

function PDFWithHighlights() {
  const { highlights, addHighlight, removeHighlight } = useHighlights();
  const [selectedColor, setSelectedColor] = useState("#ffff00");

  const handleTextSelect = (selection: TextSelection) => {
    addHighlight({
      pageNumber: selection.pageNumber,
      bounds: selection.bounds,
      color: selectedColor,
      note: "User highlight",
    });
  };

  return (
    <div>
      <div className="highlight-controls">
        <label>Highlight Color:</label>
        <input
          type="color"
          value={selectedColor}
          onChange={(e) => setSelectedColor(e.target.value)}
        />
      </div>
      <SalinaPDFViewer
        url="/document.pdf"
        enableHighlighting
        onTextSelect={handleTextSelect}
      />
      <div className="highlights-sidebar">
        {highlights.map((highlight) => (
          <div key={highlight.id} className="highlight-item">
            <div
              className="highlight-color"
              style={{ backgroundColor: highlight.color }}
            />
            <span>{highlight.note}</span>
            <button onClick={() => removeHighlight(highlight.id)}>×</button>
          </div>
        ))}
      </div>
    </div>
  );
}

Styling

The React components inherit styles from the core library. Import the styles in your app:

import "@salina-app/pdf-viewer-core/styles";

Custom CSS

.salina-pdf-viewer {
  border: 1px solid #ddd;
  border-radius: 8px;
}

.salina-pdf-toolbar {
  background: #f8f9fa;
  padding: 8px;
  border-bottom: 1px solid #ddd;
}

TypeScript Support

Full TypeScript support with comprehensive type definitions:

import {
  SalinaPDFViewer,
  PDFViewerToolbar,
  usePDFViewer,
  useHighlights,
  usePDFSearch,
  type PDFViewerProps,
  type HighlightAnnotation,
  type SearchResult,
} from "@salina-app/pdf-viewer-react";

Requirements

  • React 16.8+ (hooks support)
  • TypeScript 4.0+ (optional but recommended)

License

MIT

Support