pdf-preview.tsx
Overview
The pdf-preview.tsx file defines a React functional component named PdfPreview designed to render and interact with PDF documents within a web application. It leverages the third-party library react-pdf-highlighter to provide PDF rendering, text and area highlighting, and interactive popups for annotations.
This component enables users to view a PDF file loaded from a URL, display existing highlights on the document, and visualize comments associated with those highlights. It also reports the dimensions of the first PDF page to the parent component for layout or other purposes.
Key features:
Loads PDF asynchronously, showing a loading spinner during fetch.
Handles errors gracefully by displaying an error message when PDF loading fails.
Supports both text and area highlights, with custom popup comments.
Enables area selection via holding the
Altkey.Memoized for performance optimization to avoid unnecessary re-renders.
Detailed Explanation
Imports and Dependencies
React Hooks:
memo,useEffect,useRefreact-pdf-highlighter components:
PdfLoader: Loads the PDF document asynchronously.PdfHighlighter: Renders the PDF and manages highlights.Highlight,AreaHighlight: Components for displaying highlights.Popup: For showing popups on highlights.IHighlight: Interface/type for highlight objects.
Custom hooks and components:
useCatchDocumentError: Hook to catch and manage PDF loading errors.Spin: UI spinner for loading state.FileError: UI to display error messages.
Styling imported from
'./index.less'.
Interface: IProps
export interface IProps {
highlights: IHighlight[];
setWidthAndHeight: (width: number, height: number) => void;
url: string;
}
Purpose: Defines props for the PdfPreview component.
Prop | Type | Description |
|---|---|---|
|
| Array of highlight objects to render on the PDF. |
|
| Callback to report PDF page dimensions. |
|
| URL of the PDF document to load and display. |
Component: HighlightPopup
const HighlightPopup = ({
comment,
}: {
comment: { text: string; emoji: string };
}) =>
comment.text ? (
<div className="Highlight__popup">
{comment.emoji} {comment.text}
</div>
) : null;
Purpose: Renders a small popup containing a comment associated with a highlight.
Parameters:
comment: Object containingtextandemojistrings.
Returns: JSX element showing emoji and text if text exists; otherwise, returns
null.Usage: Used as content inside the
Popupcomponent to display highlight comments interactively.
Main Component: PdfPreview
const PdfPreview = ({ highlights: state, setWidthAndHeight, url }: IProps) => {
...
};
Purpose: Loads and displays a PDF document with interactive highlights and popups.
Internal Variables and Hooks
ref: A React ref to store a function that scrolls to a highlight.error: Catches errors during PDF loading viauseCatchDocumentError(url).
Important Methods
resetHash: Empty placeholder function called on scroll; presumably for hash or URL reset.
Effects
useEffectwatches thestate(highlights array). If there are highlights, it uses thereffunction to scroll to the first highlight automatically on highlight updates.
Render Logic
Wraps the content in a styled div container for layout and styling.
Uses
PdfLoaderto asynchronously load the PDF from the providedurl.Shows a centered
Spinloader before load.Shows
FileErrorcomponent if loading fails.Specifies the worker source for PDF.js.
Once loaded, gets the first page to determine dimensions:
Calls
setWidthAndHeightwith page width and height.
Renders
PdfHighlighterwith the following features:enableAreaSelection: Enables area selection only whenAltkey is pressed.scrollRef: Captures the scrolling function toref.current.highlightTransform: Custom rendering logic for highlights:Differentiates between text and area highlights.
Wraps the highlight in a
Popupcomponent displaying theHighlightPopup.Uses
HighlightorAreaHighlightcomponents accordingly.
Passes down the
highlightsstate to display.
Parameters and Return Values
Element | Parameters | Return Value | Notes/Usage |
|---|---|---|---|
|
| React element | Renders the PDF viewer with highlights and popups. |
|
| JSX element or | Displays a small comment popup for highlights. |
|
| JSX element (Popup with Highlight) | Custom highlight rendering function passed to PdfHighlighter. |
Usage Example
import PdfPreview, { IHighlight } from './pdf-preview';
const highlights: IHighlight[] = [
{
content: { text: 'Example highlight' },
position: { boundingRect: { x1: 0, y1: 0, x2: 10, y2: 10 }, rects: [], pageNumber: 1 },
comment: { text: 'Important note', emoji: '💡' },
id: '1',
},
// more highlights...
];
const MyPdfContainer = () => {
const [pdfWidth, setPdfWidth] = useState(0);
const [pdfHeight, setPdfHeight] = useState(0);
return (
<PdfPreview
highlights={highlights}
url="https://example.com/sample.pdf"
setWidthAndHeight={(width, height) => {
setPdfWidth(width);
setPdfHeight(height);
}}
/>
);
};
Important Implementation Details
Highlight Differentiation:
The component distinguishes between text highlights and area/image highlights by checking ifhighlight.content.imageexists. This affects which subcomponent (HighlightorAreaHighlight) is used.Popup Handling:
Highlights are wrapped in aPopupthat shows comments on mouse hover, improving usability by providing inline annotation visibility.Area Selection Activation:
Users can select areas to highlight only when holding theAltkey, preventing accidental area selections.Performance Optimization:
The component is wrapped withReact.memo, which prevents unnecessary re-renders when props have not changed.Error Handling:
Uses a custom hookuseCatchDocumentErrorto detect loading errors and displays a user-friendly message viaFileError.Dimension Reporting:
The first page's dimensions are retrieved asynchronously and passed upward viasetWidthAndHeight. This allows parent components to adjust layouts or overlays accordingly.
Interaction with Other Parts of the System
Custom Hooks:
useCatchDocumentError: Manages error states for document loading.
UI Components:
Spin: Loading spinner displayed during PDF fetching.FileError: Error message display component when PDF fails to load.
Styling:
Uses CSS modules imported from
index.lessto style the container and popups.
PDF Highlighting Library:
Relies heavily on
react-pdf-highlighterfor PDF rendering, highlighting, and popup behavior.
Parent Component:
Receives PDF page dimensions through
setWidthAndHeightcallback, which likely influences layout or interactive overlays elsewhere.
Mermaid Component Diagram
componentDiagram
component PdfPreview {
+highlights: IHighlight[]
+setWidthAndHeight(width: number, height: number)
+url: string
-- Internal --
+ref: React.Ref<(highlight: IHighlight) => void>
+error: string | null
+resetHash(): void
+useEffect() // scrolls to first highlight on update
}
component PdfLoader {
+url: string
+beforeLoad: JSX.Element
+workerSrc: string
+errorMessage: JSX.Element
+children: (pdfDocument) => JSX.Element
}
component PdfHighlighter {
+pdfDocument: any
+enableAreaSelection(event): boolean
+onScrollChange(): void
+scrollRef(scrollTo): void
+onSelectionFinished(): void
+highlightTransform(...)
+highlights: IHighlight[]
}
component HighlightPopup {
+comment: { text: string; emoji: string }
}
component Highlight
component AreaHighlight
component Popup
PdfPreview --> PdfLoader : loads PDF
PdfLoader --> PdfHighlighter : renders PDF and highlights
PdfHighlighter --> Popup : wraps highlights with popups
Popup --> HighlightPopup : renders comment content
Popup --> Highlight : for text highlights
Popup --> AreaHighlight : for area/image highlights
Summary
The pdf-preview.tsx file provides a highly reusable and interactive PDF viewer component with annotation capabilities. By integrating with react-pdf-highlighter, it supports complex highlighting features while maintaining responsiveness and error handling. Its design allows easy integration into larger applications requiring document preview and annotation functionality.