A comprehensive, production-ready PDF viewer library built with React and TypeScript that supports multiple PDFs, annotations, highlighting, and advanced navigation features.
Core Features:
- Multiple PDF document support with dropdown selection
- Page-by-page navigation with thumbnails
- Zoom in/out functionality (25% to 300%)
- Download individual pages as PNG files
- Drawing annotations (pen and highlighter tools)
- Text highlighting based on bounding box coordinates
- Undo/redo functionality for annotations
- Keyboard shortcuts for navigation and controls
Design Elements:
- Clean, modern interface with intuitive controls
- Responsive design that works on all screen sizes
- Smooth animations and hover effects
- Professional color scheme with proper contrast
- Accessible keyboard navigation
- Context-aware tooltips and status information
import { PDFViewer } from './components/PDFViewer/PDFViewer';
import { PDFDocument, BoundingBox } from './types/pdf';
const documentData: PDFDocument = {
files: ["Document1.pdf", "Document2.pdf"],
presigned_urls: {
"Document1.pdf": {
"1": "https://example.com/doc1-page1.png",
"2": "https://example.com/doc1-page2.png"
},
"Document2.pdf": {
"1": "https://example.com/doc2-page1.png"
}
}
};
const boundingBoxes: BoundingBox[] = [
{
supporting_sentence_in_document: "Important text to highlight",
document_name: "Document1.pdf",
section_name: "Section 1",
page_number: "1",
bbox: [[[0.1, 0.1, 0.9, 0.1, 0.9, 0.2, 0.1, 0.2]]]
}
];
function App() {
return (
<PDFViewer
documentData={documentData}
boundingBoxes={boundingBoxes}
onDocumentChange={(doc) => console.log('Document changed:', doc)}
onPageChange={(page) => console.log('Page changed:', page)}
onAnnotationAdd={(annotation) => console.log('Annotation added:', annotation)}
/>
);
}
import { usePDFViewer } from './hooks/usePDFViewer';
function PDFViewerContainer() {
const {
documentData,
boundingBoxes,
annotations,
loadDocument,
loadBoundingBoxes,
addAnnotation,
exportAnnotations
} = usePDFViewer();
const handleLoadDocument = () => {
loadDocument(myDocumentData);
loadBoundingBoxes(myBoundingBoxes);
};
const handleExportAnnotations = () => {
const annotationData = exportAnnotations();
// Save or process annotation data
};
return (
<div>
<button onClick={handleLoadDocument}>Load Document</button>
<button onClick={handleExportAnnotations}>Export Annotations</button>
{documentData && (
<PDFViewer
documentData={documentData}
boundingBoxes={boundingBoxes}
onAnnotationAdd={addAnnotation}
/>
)}
</div>
);
}
Prop | Type | Required | Description |
---|---|---|---|
documentData |
PDFDocument |
Yes | Object containing PDF files and their page URLs |
boundingBoxes |
BoundingBox[] |
No | Array of bounding box coordinates for highlighting |
onDocumentChange |
(documentName: string) => void |
No | Callback when document is changed |
onPageChange |
(pageNumber: number) => void |
No | Callback when page is changed |
onAnnotationAdd |
(annotation: Annotation) => void |
No | Callback when annotation is added |
className |
string |
No | Additional CSS classes |
interface PDFDocument {
files: string[];
presigned_urls: Record<string, Record<string, string>>;
}
interface BoundingBox {
supporting_sentence_in_document: string;
document_name: string;
section_name: string;
page_number: string;
bbox: number[][][];
}
interface Annotation {
id: string;
type: 'pen' | 'highlighter';
points: AnnotationPoint[];
color: string;
thickness: number;
pageNumber: number;
}
- Arrow Left/Right: Navigate between pages
- Ctrl/Cmd + Plus/Minus: Zoom in/out
- Ctrl/Cmd + Z: Undo annotation
- Ctrl/Cmd + Y or Ctrl/Cmd + Shift + Z: Redo annotation
- Escape: Exit annotation mode
The library uses Tailwind CSS for styling and can be easily customized by modifying the component classes or extending the design system.
// Modify annotation colors
const customAnnotation = {
...annotation,
color: '#FF5733', // Custom color
thickness: 5 // Custom thickness
};
You can replace the default toolbar by creating your own component that uses the same event handlers:
<CustomToolbar
onFileChange={handleFileChange}
onPageChange={handlePageChange}
onZoomIn={handleZoomIn}
// ... other handlers
/>
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
- Images are loaded on-demand for better performance
- Annotations are rendered using HTML5 Canvas for smooth drawing
- Zoom operations are optimized with requestAnimationFrame
- Memory usage is optimized by cleaning up unused canvases
This library is designed to be modular and extensible. Key areas for contribution:
- Additional annotation tools (shapes, text, etc.)
- Export formats (PDF with annotations, etc.)
- Thumbnail navigation panel
- Search functionality
- Accessibility improvements
MIT License - see LICENSE file for details.