New features
- You can highlight multiple keywords programatically:
import { searchPlugin } from '@react-pdf-viewer/search';
const searchPluginInstance = searchPlugin();
const { highlight } = searchPluginInstance;
<button onClick={() => highlight(['document', 'PDF']) }>
Highlight: document, PDF
</button>
It's also possible to clear the highlights:
const { clearHighlights } = searchPluginInstance;
- It's possible to add custom styles for highlighted area based on the keyword:
const searchPluginInstance = searchPlugin({
onHighlightKeyword: (props: OnHighlightKeyword) => {
if (props.keyword.source === 'document') {
props.highlightEle.style.outline = '2px dashed blue';
props.highlightEle.style.backgroundColor = 'rgba(0, 0, 0, .1)';
}
},
});
- The Zoom plugin exposes the
zoomTo
function:
const { zoomTo } = zoomPluginInstance;
// Zoom to a given level
zoomTo(1.5);
zoomTo(SpecialZoomLevel.PageFit);
- The Page Navigation plugin provides the
jumpToPage
function:
const { jumpToPage } = pageNavigationPluginInstance;
// Jump to the third page
jumpToPage(2);
- It's possible to retrieve the instances of Attachment, Bookmark, Thumbnail, Toolbar plugins from the Default Layout plugin instance.
const defaultLayoutPluginInstance = defaultLayoutPlugin();
const {
attachmentPluginInstance,
bookmarkPluginInstance,
thumbnailPluginInstance,
toolbarPluginInstance,
} = defaultLayoutPluginInstance;
Similarity, the Toolbar plugin instance provides the accesses to the instance of other plugins that build the toolbar:
const toolbarPluginInstance = toolbarPlugin();
const {
dropPluginInstance,
fullScreenPluginInstance,
getFilePluginInstance,
openPluginInstance,
pageNavigationPluginInstance,
printPluginInstance,
propertiesPluginInstance,
rotatePluginInstance,
scrollModePluginInstance,
searchPluginInstance,
selectionModePluginInstance,
zoomPluginInstance,
} = toolbarPluginInstance;
Improvements
- Support Next.js integration
- Fix a warning in the Console when using with Next.js
Bug fixes
- The Search plugin can find text that belongs to multiple
span
elements
Breaking changes
- The
Observer
component is removed from the@react-pdf-viewer/core
package
Improvements
- Lazy load the document. The PDF document will be loaded if the viewer container is visible in the viewport.
Bug fixes
Fix a bug that could happen when we load multiple documents by changing fileUrl
.
In that case, you may see the error message
Worker was destroyed
Cannot read property 'sendWithPromise' of null
This version also fixes a potential memory leaks reported by React DevTools when we try to load new document even if the current document isn't rendered completely.
Improvements
full-screen
plugin provides new callbacks that are triggered after entering and exiting the full screen mode
import { SpecialZoomLevel } from '@react-pdf-viewer/core';
import { fullScreenPlugin } from '@react-pdf-viewer/full-screen';
const fullScreenPluginInstance = fullScreenPlugin({
// Zoom to fit the screen after entering and exiting the full screen mode
onEnterFullScreen: (zoom) => {
zoom(SpecialZoomLevel.PageFit);
},
onExitFullScreen: (zoom) => {
zoom(SpecialZoomLevel.PageFit);
},
});
Bug fixes
- The style files are missing in the
highlight
plugin - Render highlight annotations formed by quadrilaterals
- The popup annotations aren't shown if they are children of highlight annotations
- Clicking a destination (bookmark, for example) with name of
FitH
orFitBH
throws an exception
New features
- New
highlight
plugin provides the ability of selecting and adding notes for text in the document - The
default-layout
plugin allows to customize the tabs:
// `defaultTabs` is the list of default tabs which lists thumbnails, bookmarks and attachments respetively
const defaultLayoutPluginInstance = defaultLayoutPlugin({
sidebarTabs: defaultTabs => { ... }
});
We also can activate a given tab:
const { activateTab } = defaultLayoutPluginInstance;
// Activate a tab
// activateTab(index);
Breaking changes
- The
getPagesRef
method in plugins are changed togetPagesContainer
:
// Before
interface PluginFunctions {
getPagesRef(): React.RefObject<HTMLDivElement>;
}
// After
interface PluginFunctions {
getPagesContainer(): HTMLElement;
}
- The
authorization
option is removed. You can use newwithCredentials
option:
// Before v2.3.0
<Viewer
fileUrl={...}
authorization='Bearer ...'
/>
// From v2.3.0
<Viewer
fileUrl={...}
withCredentials={true}
httpHeaders={{
'Authorization': 'Bearer ...',
}}
/>
Improvements
- Keep the current page and scroll position after zooming the document
- Pre-render a few of previous and next pages of the current page, so users see the page instantly when scrolling
New features
- Support loading PDF from a protected resource with new
authorization
option.
import { Viewer } from '@react-pdf-viewer/core';
<Viewer
fileUrl={...}
authorization='Bearer ...'
/>
If you want to use another authorization servers or send more additional authentication headers, then use the new httpHeaders
option, for example:
import { Viewer } from '@react-pdf-viewer/core';
<Viewer
fileUrl={...}
authorization='...'
httpHeaders={{
key: value,
}}
/>
- It's possible to customize the search control with the new
Search
component:
import { RenderSearchProps, Search } from '@react-pdf-viewer/search';
<Search>
{
(renderSearchProps: RenderSearchProps) => (
// Your custom search control
)
}
</Search>
The parameter renderSearchProps
provides the properties and methods to build up a custom search control:
Property | Type | Description |
---|---|---|
clearKeyword |
Function |
Clear the keyword |
changeMatchCase |
Function |
The result has to match case with the keyword |
changeWholeWords |
Function |
The result has to match the whole keyword |
currentMatch |
number |
The index of current match |
jumpToNextMatch |
Function |
Jump to the next match |
jumpToPreviousMatch |
Function |
Jump to the previous match |
keyword |
string |
The current keyword |
matchCase |
boolean |
true if the result matches case with the keyword |
wholeWords |
boolean |
true if the result matches the whole keyword |
search |
Function |
Perform the search with current keyword and matchCase , wholeWords conditions |
setKeyword |
Function |
Set the current keyword |
Improvements
- A current match search has a custom class
rpv-search-text-highlight-current
. So you can customize the current match by adding CSS properties for the class. - Avoid the black flickering when clicking a bookmark
- Support both React v16 and v17
Bug fixes
- The print plugin doesn't work with default-layout plugin
- In some cases, there is an extra blank page when printing
- Clicking bookmark doesn't jump to correct page in horizontal scroll mode
- Jumping between search match doesn't work properly in horizontal scroll mode
Breaking changes
- The
onCanvasLayerRender
option is removed. Instead, use theonCanvasLayerRender
option in your plugin. - The
TextLayerRenderStatus
enum is renamed toLayerRenderStatus
.
New features
- Add
onAnnotationLayerRender
hook for plugin. We can perform custom action after annotations are rendered. The following sample code creates a plugin that finds all annotation links, and add thetarget="_blank"
attribute to the links:
import { AnnotationType, Plugin, PluginOnAnnotationLayerRender } from '@react-pdf-viewer/core';
const customPlugin = (): Plugin => {
const onRenderAnnotations = (e: PluginOnAnnotationLayerRender) => {
// Find all `Link` annotation
e.annotations
.filter(annotation => annotation.annotationType === AnnotationType.Link)
.forEach(annotation => {
if (annotation.url) {
// Find the `a` element represents the link
[...e.container.querySelectorAll('.rpv-core-annotation-link a')].forEach(linkEle => {
linkEle.setAttribute('target', '_blank');
});
}
});
};
return {
onAnnotationLayerRender: onRenderAnnotations,
};
};
- The search plugin allows to set multiple keywords to be highlighted initially
// Use the search plugin
import { searchPlugin } from '@react-pdf-viewer/search';
const searchPluginInstance = searchPlugin({
keyword: ['document', 'PDF'],
});
// Use with default-layout plugin
import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
const defaultLayoutPluginInstance = defaultLayoutPlugin({
toolbarPlugin: {
searchPlugin: {
keyword: ['document', 'PDF'],
},
},
});
Improvements
- Optimize the search plugin that doesn't perform unhighligting and highlighting many times after texts are rendered
Bug fixes
- Clicking Previous match or Next match button throws an error if the keyword is empty
- Fix the incorrect path of styles
Upgrade from 2.0.1 to 2.1.0
We have to update the path of styles which are placed in the lib
directory. For example:
// Old version
import '@react-pdf-viewer/core/styles/index.css';
// New version
import '@react-pdf-viewer/core/lib/styles/index.css';
This version rewrites the entire viewer with the plugin architecture. The main viewer component Viewer
is very lightweight,
and everything else is powered by plugins.
The basic setup looks like following:
// Import plugin
import { toolbarPlugin } from '@react-pdf-viewer/toolbar';
// Import styles
import '@react-pdf-viewer/toolbar/lib/styles/index.css';
// Create the plugin instance
const toolbarPluginInstance = toolbarPlugin(...);
// Register plugins
<Viewer
plugins={[
// Array of plugins
toolbarPlugin,
...
]}
/>
New features
Viewer
supports to use a custom loader instead of the default<Spinner>
:
import { ProgressBar, Viewer } from '@react-pdf-viewer/core';
<Viewer
renderLoader={(percentages: number) => (
// You can use your own progress bar component
<div style={{ width: '240px' }}>
<ProgressBar progress={Math.round(percentages)} />
</div>
)}
/>
- Customizable name of download file with the get-file plugin:
const getFilePluginInstance = getFilePlugin({
fileNameGenerator: (file: OpenFile) => {
// `file.name` is the URL of opened file
const fileName = file.name.substring(file.name.lastIndexOf('/') + 1);
return `a-copy-of-${fileName}`;
},
});
- New Locale Switcher plugin for switching between different locales
- Provide the ability of setting the scroll mode via the Scroll Mode plugin.
Bug fixes
- The
onPageChange
could be invoked several times when clicking an outline item
Breaking changes
- The
keyword
option is removed. Use thekeyword
option provided by the search plugin. - The
layout
option is removed - The
render
option is removed - The
selectionMode
option is removed. Use theselectionMode
option provided by the selection-mode plugin. - The
onTextLayerRender
option is removed. Instead, use theonTextLayerRender
option in your plugin.
Upgrade from 1.7.0 to 2.0.0
Uninstall the old packages:
npm uninstall pdfjs-dist
npm uninstall @phuocng/react-pdf-viewer
Install the new packages:
npm install pdfjs-dist@2.5.207
npm install @react-pdf-viewer/core@2.0.1
Replace the old `Worker` with new one:
// Remove the old Worker
import { Worker } from '@phuocng/react-pdf-viewer';
// Use the new Worker
import { Worker } from '@react-pdf-viewer/core';
Use the new Viewer
:
- First, you might need to install the Default Layout plugin:
npm install @react-pdf-viewer/default-layout@2.0.0
- Replace the old
Viewer
with new one:
// Old Viewer
import Viewer from '@phuocng/react-pdf-viewer';
// New Viewer
import { Viewer } from '@react-pdf-viewer/core';
// Plugins
import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
// Import styles
import '@react-pdf-viewer/core/lib/styles/index.css';
import '@react-pdf-viewer/default-layout/lib/styles/index.css';
// Create new plugin instance
const defaultLayoutPluginInstance = defaultLayoutPlugin();
// Your render function
<Viewer
fileUrl='/path/to/document.pdf'
plugins={[
// Register plugins
defaultLayoutPluginInstance,
...
]}
/>
New features
- Add
onPageChange
callback that is invoked when user changes page:
import Viewer, { PageChangeEvent } from '@phuocng/react-pdf-viewer';
const handlePageChange = (e: PageChangeEvent) => {
console.log(`Changed to page: ${e.currentPage}`)
};
<Viewer
fileUrl='/path/to/document.pdf'
onPageChange={handlePageChange}
/>
- Add
onCanvasLayerRender
event that is invoked when the canvas layer is rendered completely.
import Viewer, { CanvasLayerRenderEvent } from '@phuocng/react-pdf-viewer';
const onCanvasLayerRender = (e: CanvasLayerRenderEvent) => {
// `e.ele` is the canvas element
const canvas = e.ele;
// Do something with the canvas element
};
<Viewer
fileUrl='/path/to/document.pdf'
onCanvasLayerRender={onCanvasLayerRender}
/>
- Add
onTextLayerRender
event that is invoked when the text layer is ready.
import Viewer, { TextLayerRenderEvent } from '@phuocng/react-pdf-viewer';
const onTextLayerRender = (e: TextLayerRenderEvent) => {
// For example, we can find all text elements that look like a link,
// and replace it with `a` elements
};
<Viewer
fileUrl='/path/to/document.pdf'
onTextLayerRender={onTextLayerRender}
/>
- Support non-latin characters via the
characterMap
option
import Viewer, { CharacterMap } from '@phuocng/react-pdf-viewer';
const characterMap: CharacterMap = {
isCompressed: true,
url: 'https://unpkg.com/pdfjs-dist@2.4.456/cmaps/',
};
<Viewer
characterMap={characterMap}
fileUrl='/path/to/document.pdf'
/>
Bug fixes
- The viewer doesn't jump to the destination or searching result exactly
Breaking changes
The parameters of onDocumentLoad
and onZoom
are changed as following:
v1.6.0 | v1.7.0 |
---|---|
onDocumentLoad(doc) |
onDocumentLoad({ doc }) |
onZoom(doc, scale) |
onZoom({ doc, scale }) |
New features
-
The annotation layer is rewritten. Support the following type of annotations:
- Caret
- Circle
- File attachment
- Free text
- Highlight
- Ink
- Line
- Link
- Polygon
- Polyline
- Popup
- Square
- Squiggly
- Stamp
- StrikeOut
- Text
- Underline
-
The link annotation supports named actions which allow to jump to the first, last, next or previous pages
-
Customize error renderer.
const renderError = (error: LoadError) => {
let message = '';
switch (error.name) {
case 'InvalidPDFException':
message = 'The document is invalid or corrupted';
break;
case 'MissingPDFException':
message = 'The document is missing';
break;
case 'UnexpectedResponseException':
message = 'Unexpected server response';
break;
default:
message = 'Cannot load the document';
break;
}
return (<div>{message}</div>);
};
<Viewer
fileUrl={fileUrl}
renderError={renderError}
/>
Improvements
- Allow to control the
fileUrl
option - Bookmarks support external links
- Support external links
Bug fixes
- The canvas layer is blurry
- The tooltip, popover positions are not correct in some cases
- The drag zone isn't visible if the main area is scrolled
- The document rotated initially isn't displayed properly
New features
- Highlight given keyword in the first render
<Viewer
fileUrl='/path/to/document.pdf'
// The `keyword` option can be a string or a regular expression
// keyword='PDF Library'
keyword={new RegExp('pdf document', 'i')}
/>
- Add new SVG layer which can be used to replace the canvas layer
const renderPage = (props: RenderPageProps) => {
return (
<>
{props.svgLayer.children}
{props.textLayer.children}
{props.annotationLayer.children}
</>
);
};
<Viewer
fileUrl='/path/to/document.pdf'
renderPage={renderPage}
/>
- Customize page renderer. The following code adds a simple Draft watermark at the center of every page:
const renderPage: RenderPage = (props: RenderPageProps) => (
<>
{props.canvasLayer.children}
<div
style={{
alignItems: 'center',
display: 'flex',
height: '100%',
justifyContent: 'center',
left: 0,
position: 'absolute',
top: 0,
width: '100%',
}
}>
<div
style={{
color: 'rgba(0, 0, 0, 0.2)',
fontSize: `${8 * props.scale}rem`,
fontWeight: 'bold',
textTransform: 'uppercase',
transform: 'rotate(-45deg)',
userSelect: 'none',
}}
>
Draft
</div>
</div>
{props.annotationLayer.children}
{props.textLayer.children}
</>
);
<Viewer
fileUrl='/path/to/document.pdf'
renderPage={renderPage}
/>
Improvement
- The default scale can be a special zoom level. For example, we can fit page in the container initially:
<Viewer
fileUrl='/path/to/document.pdf'
defaultScale={SpecialZoomLevel.PageFit}
/>
- The
fileUrl
option can beUint8Array
:
<Viewer
fileUrl={new Uint8Array([...])}
/>
- Add styles for error message
New features
- Add new optional parameter indicating the page that will be displayed initially
<Viewer
// The page is zero-based index
// We will display the third page initially
initialPage={2}
/>
- Add new optional parameter to define the prefix of CSS classes
<Viewer
prefixClass='viewer'
/>
- Add new
render
parameter that includes many functions that could be called from outside of the component:
import Viewer, { RenderViewerProps, ScrollMode, SpecialZoomLevel, SelectionMode } from '@phuocng/react-pdf-viewer';
const render = (props: RenderViewerProps) => {
return (
<div>
<div style={{ height: '500px' }}>
{props.viewer}
</div>
<button onClick={() => props.jumpToPage(props.doc.numPages - 1)}>Jump to last page</button>
<button onClick={() => props.rotate(90)}>Rotate +90 degrees</button>
<button onClick={() => props.zoom(0.5)}>Zoom to 50%</button>
<button onClick={() => props.zoom(SpecialZoomLevel.ActualSize)}>Zoom to actual size</button>
<button onClick={() => props.changeScrollMode(ScrollMode.Wrapped)}>Switch to wrapped scrolling</button>
<button onClick={() => props.changeSelectionMode(SelectionMode.Hand)}>Switch to hand tool</button>
<button onClick={() => props.print()}>Print</button>
<button onClick={() => props.download()}>Download</button>
</div>
);
};
<Viewer
fileUrl='/path/to/document.pdf'
render={render}
/>
Improvement
- All styles are moved to external CSS files. It's possible for us to override components' styles.
Bug fixes
- Can't scroll and print on IE 11
- Printing doesn't look good if the page size isn't set
- Blank page when print the current web page
New features
Expose all the buttons from the more actions popover to the toolbar.
ToolbarSlot
now includes
goToFirstPageButton
: the button to go to the first pagegoToLastPageButton
: go to the last pagerotateClockwiseButton
: rotate the documentrotateCounterclockwiseButton
: rotate counterclockwise the documenttextSelectionButton
: switch to the text selection modehandToolButton
: switch to the hand tool modeverticalScrollingButton
: scroll the document verticallyhorizontalScrollingButton
: scroll the document horizontallywrappedScrollingButton
: display pages as a griddocumentPropertiesButton
: show the document properties
Improvement
- Make the spinner thiner
- Add minified CSS files
Bug fixes
- Tooltip for the left/right buttons don't look good in full width mode
- The view now takes full height by default. It fixes the issue that users can't navigate between pages from the toolbar in some cases
New features
- Provide the ability of printing document
- Add new
selectionMode
option indicates the selection mode:
import Viewer, { SelectionMode } from '@phuocng/react-pdf-viewer';
<Viewer
fileUrl='/path/to/document.pdf'
// By default, it will be SelectionMode.Text
selectionMode={SelectionMode.Hand}
/>
- Add
onDocumentLoad
callback that uis invoked when the document is loaded completely
import Viewer, { PdfJs } from '@phuocng/react-pdf-viewer';
const documentLoad = (doc: PdfJs.PdfDocument) => {
console.log(`Document is loaded: ${doc.numPages}`)
};
<Viewer
fileUrl='/path/to/document.pdf'
onDocumentLoad={documentLoad}
/>
- Add
onZoom
callback that is invoked when zooming in/out the document
import Viewer, { PdfJs } from '@phuocng/react-pdf-viewer';
const zoom = (doc: PdfJs.PdfDocument, scale: number) => {
console.log(`Zoom document to ${scale}`);
};
<Viewer
fileUrl='/path/to/document.pdf'
onZoom={zoom}
/>
New features
- Add new, optional
defaultScale
parameter that indicates the default zoom level:
<Viewer defaultScale={1.5} ... />
Improvement
- The document should fit best in the container initially
Improvement
- Support SSR
Bug fixes
- Cannot re-export a type when --isolatedModules is set to true
- The CSS files are missing in es6 package
First release