
Product
Introducing Scala and Kotlin Support in Socket
Socket now supports Scala and Kotlin, bringing AI-powered threat detection to JVM projects with easy manifest generation and fast, accurate scans.
@salina-app/pdf-viewer-react
Advanced tools
React components and hooks for the Salina PDF Viewer library.
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:
const viewerRef = useRef<SalinaPDFViewerRef>(null)
viewerRef={viewerRef}
SalinaPDFViewer
component is mounted when using the toolbarnpm install @salina-app/pdf-viewer-react @salina-app/pdf-viewer-core
npm install react react-dom pdfjs-dist@^5.3.0
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;
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")}
/>;
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;
}
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}
/>;
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>
);
}
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>
);
}
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>
);
}
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>
);
}
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>
);
}
The React components inherit styles from the core library. Import the styles in your app:
import "@salina-app/pdf-viewer-core/styles";
.salina-pdf-viewer {
border: 1px solid #ddd;
border-radius: 8px;
}
.salina-pdf-toolbar {
background: #f8f9fa;
padding: 8px;
border-bottom: 1px solid #ddd;
}
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";
MIT
FAQs
React wrapper for Salina PDF Viewer
The npm package @salina-app/pdf-viewer-react receives a total of 607 weekly downloads. As such, @salina-app/pdf-viewer-react popularity was classified as not popular.
We found that @salina-app/pdf-viewer-react demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Product
Socket now supports Scala and Kotlin, bringing AI-powered threat detection to JVM projects with easy manifest generation and fast, accurate scans.
Application Security
/Security News
Socket CEO Feross Aboukhadijeh and a16z partner Joel de la Garza discuss vibe coding, AI-driven software development, and how the rise of LLMs, despite their risks, still points toward a more secure and innovative future.
Research
/Security News
Threat actors hijacked Toptal’s GitHub org, publishing npm packages with malicious payloads that steal tokens and attempt to wipe victim systems.