Function | Destination |
---|---|
`jumpToNextDestination` | Jump to the next destination |
`jumpToPreviousDestination` | Jump to the previous destination |
`Viewer`
component adds a new property to disable smooth scroll:<Viewer enableSmoothScroll={false} />
import type { SetRenderRange, VisiblePagesRange } from '@react-pdf-viewer/core';const setRenderRange: SetRenderRange = React.useCallback((visiblePagesRange: VisiblePagesRange) => {return {startPage: visiblePagesRange.startPage - 10,endPage: visiblePagesRange.endPage + 10,};}, []);// Another usage: render the first 20 pages initiallyconst setRenderRange: SetRenderRange = React.useCallback((visiblePagesRange: VisiblePagesRange) => {return {startPage: visiblePagesRange.endPage <= 20 ? 0 : visiblePagesRange.startPage - 5,endPage:visiblePagesRange.startPage <= 20? Math.max(20, visiblePagesRange.endPage + 5): visiblePagesRange.endPage + 5,};}, []);<Viewer setRenderRange={setRenderRange} />;
`Cover`
component adds new `width`
property:const { Cover } = thumbnailPluginInstance;// Render the cover of second page<Cover getPageIndex={() => 1} width={300} />;
Shortcut | Operating System | Action |
---|---|---|
`Command` + `ArrowLeft` | macOS | Jump to the previous bookmark destination |
`Alt` + `ArrowLeft` | Windows | Same as above |
`Command` + `ArrowRight` | macOS | Jump to next bookmark destination |
`Alt` + `ArrowRight` | Windows | Same as above |
`Viewer`
component scrolls to the `initialPage`
page automatically after resizing the container or browser`jumpToDestination`
function now has only a single property. You don't have to change anything if your application doesn't have any custom plugin using the `jumpToDestination`
function.// Beforeimport type { DestinationOffsetFromViewport } from '@react-pdf-viewer/core';import { SpecialZoomLevel } from '@react-pdf-viewer/core';jumpToDestination(pageIndex: number,bottomOffset: number | DestinationOffsetFromViewport,leftOffset: number | DestinationOffsetFromViewport,scaleTo?: number | SpecialZoomLevel);// Afterimport type { Destination } from '@react-pdf-viewer/core';jumpToDestination(destination: Destination);
`pagesContainerRef`
to `RenderViewer`
, so the plugin can access the pages container more easily`Viewer`
component adds new property to customize the view of a protected document:import { RenderProtectedViewProps, Viewer } from '@react-pdf-viewer/core';const ProtectedView: React.FC<RenderProtectedViewProps> = ({ passwordStatus, verifyPassword }) => {...};<Viewer renderProtectedView={renderProps => <ProtectedView {...renderProps} />} />
import { pageNavigationPlugin } from '@react-pdf-viewer/page-navigation';const pageNavigationPluginInstance = pageNavigationPlugin();const { jumpToNextPage, jumpToPreviousPage } = pageNavigationPluginInstance;
`Thumbnails`
component provides new property to display the thumbnails in the given direction:import { ThumbnailDirection } from '@react-pdf-viewer/thumbnail';// Display thumbnails horizontally<Thumbnails thumbnailDirection={ThumbnailDirection.Horizontal} />// Display thumbnails vertically<Thumbnails thumbnailDirection={ThumbnailDirection.Vertical} />
Shortcut | Operating System | Action |
---|---|---|
`Command` + `ArrowLeft` | macOS | Jump to previous clicked link annotation |
`Alt` + `ArrowLeft` | Windows | Same as above |
`initialPage`
) option`tranformSize`
property is changed to `transformSize`
import { ScrollMode, Viewer } from '@react-pdf-viewer/core';<Viewer scrollMode={ScrollMode.Page} />;
import { ViewMode, Viewer } from '@react-pdf-viewer/core';<Viewer viewMode={ViewMode.DualPage} />;
Mode | Description |
---|---|
`ViewMode.SinglePage` | The default mode. View single page continuously |
`ViewMode.DualPage` | View two pages each time |
`ViewMode.DualPageWithCover` | View two pages each time. The first page is displayed as a cover |
`scrollMode`
and `viewMode`
options. The following screenshot demonstrates how to apply the dual page viewmode and page scroll mode.`PluginFunctions`
provides new `jumpToPreviousPage`
and `jumpToNextPage`
to jump to the previous and next pages`DualPageCoverViewModeIcon`
, `DualPageViewModeIcon`
and `PageScrollingIcon`
icons`pageLayout`
option to customize the layout of each page.
The following code adds margin between pages, and center the page in its container:import { type PageLayout, Viewer } from '@react-pdf-viewer/core';const pageLayout: PageLayout = {buildPageStyles: () => ({alignItems: 'center',display: 'flex',justifyContent: 'center',}),tranformSize: ({ size }) => ({ height: size.height + 30, width: size.width + 30 }),};<Viewer pageLayout={pageLayout} />;
`initialPage`
option`pageHeight`
and `pageWidth`
properties in `RenderViewer`
are replaced with the `pageSizes`
property that are the sizes of pages.
You don't have to do anything if you don't develope your own plugin using those properties.`initialRotation`
parameter:<Viewer initialRotation={90} />
const highlightPluginInstance = highlightPlugin();const { switchTrigger } = highlightPluginInstance;// Switch to NoneswitchTrigger(Trigger.None);// Switch to Selection modeswitchTrigger(Trigger.TextSelection);
`title`
and `aria-label`
attributes for link annotations without using the Bookmark plugin`RenderBookmarkItemProps`
props includes new `path`
property that indicates the path from each bookmark item to the root`SelectionData`
provides more information about the selected text including:Property | Type | Description |
---|---|---|
`selectedText` | `string` | The selected text |
`divTexts` | `DivText[]` | List of text items contain the selected text |
`DivText`
item consists ofProperty | Type | Description |
---|---|---|
`divIndex` | `number` | The zero-based text element rendered by the text layer |
`pageIndex` | `number` | The zero-based page index |
`textContent` | `string` | The text content of text element |
`keyword`
option:const searchPluginInstance = searchPlugin({keyword: '...',});
`RenderSearchProps`
adds new `isDocumentLoaded`
property that indicates if the document is loaded.
You can use it to perform searching for a keyword in a sidebar:import type { Match, RenderSearchProps } from '@react-pdf-viewer/search';const SearchSidebarInner: React.FC<{renderSearchProps: RenderSearchProps}> = ({ renderSearchProps }) => {const [matches, setMatches] = React.useState<Match[]>([]);const { isDocumentLoaded, keyword, search } = renderSearchProps;React.useEffect(() => {if (isDocumentLoaded && keyword) {search().then((matches) => {setMatches(matches);});}}, [isDocumentLoaded]);return (// Display matches ...);};
`Viewer`
is rendered inside ShadowDOM`contents`
and `title`
properties of annotations with corresponding objects`Cover`
component doesn't rotate the corresponding rotated page`jumpToHighlightArea`
function does not work properly with some documents`startPageIndex`
and `endPageIndex`
properties of `SelectionData`
aren't correct`SelectionData`
data.
The `SelectionData`
property in `RenderHighlightContentProps`
and `RenderHighlightTargetProps`
turn to optional properties.interface RenderHighlightContentProps {selectionData?: SelectionData;}interface RenderHighlightTargetProps {selectionData?: SelectionData;}
if (renderHighlightContentProps.selectionData) {// Do something ...}if (renderHighlightTargetProps.selectionData) {// Do something ...}
`renderBookmarkItem`
properly:<Bookmark renderBookmarkItem={renderBookmarkItem} />
`toggleTab`
function to toggle a given tab in the sidebar:const defaultLayoutPluginInstance = defaultLayoutPlugin();const { toggleTab } = defaultLayoutPluginInstance;// Toggle the second tabtoggleTab(1);
`Command`
+ `ArrowUp`
(on macOS) or `Ctrl`
+ `ArrowUp`
(on Windows) will bring users to the previous clicked link annotation.
You can disable that shortcuts via the `enableShortcuts`
option:// Use the standalone page navigation pluginconst pageNavigationPluginInstance = pageNavigationPlugin({enableShortcuts: false,});// Use the default layout pluginconst defaultLayoutPluginInstance = defaultLayoutPlugin({toolbarPlugin: {pageNavigationPlugin: {enableShortcuts: false,},},});
`CharacterMap`
type isn't available`onPageChange`
callback does not trigger if the current page equals to the initial page`setPages`
option. It is a function that takes the current document and returns the list of zero-based indexes of pages you want to print.import type { PdfJs } from '@react-pdf-viewer/core';import { printPlugin } from '@react-pdf-viewer/print';const printPluginInstance = printPlugin({setPages: (doc: PdfJs.PdfDocument) => number[],});
// Only print the even pagesconst printPluginInstance = printPlugin({setPages: (doc) =>Array(doc.numPages).fill(0).map((_, i) => i).filter((i) => (i + 1) % 2 === 0),});// Only print the odd pagesconst printPluginInstance = printPlugin({setPages: (doc) =>Array(doc.numPages).fill(0).map((_, i) => i).filter((i) => (i + 1) % 2 === 1),});
const defaultLayoutPluginInstance = defaultLayoutPlugin({toolbarPlugin: {printPlugin: {setPages: ...,},},});
import {getAllPagesNumbers,getCustomPagesNumbers,getEvenPagesNumbers,getOddPagesNumbers,} from '@react-pdf-viewer/print';const printPluginInstance = printPlugin({setPages: getEvenPagesNumbers,});
Function | Description |
---|---|
`getAllPagesNumbers` | Returns all pages numbers of the document |
`getCustomPagesNumbers` | Returns the custom page numbers. The input is a string consisting of given pages or ranges of pages. For example: |
1, 2, 3 | |
1-3 | |
1-3, 5, 8-11 | |
`getEvenPagesNumbers` | Returns even pages numbers |
`getOddPagesNumbers` | Returns odd pages numbers |
import { getEvenPagesNumbers } from '@react-pdf-viewer/print';const printPluginInstance = printPlugin();const { setPages } = printPluginInstance;// Show UI for users to choose pagesconst handleChooseEvenPages = () => setPages(getEvenPagesNumbers);<label><input type="radio" onChange={handleChooseEvenPages} /> Print even pages</label>;
`print`
function:import { printPlugin } from '@react-pdf-viewer/print';const printPluginInstance = printPlugin();const { print } = printPluginInstance;
`print`
function is also available if you use the default layout plugin:import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';const defaultLayoutPluginInstance = defaultLayoutPlugin();const { print } = defaultLayoutPluginInstance.toolbarPluginInstance.printPluginInstance;
const printPluginInstance = printPlugin({renderProgressBar: (numLoadedPages: number, numPages: number, onCancel: () => void) => (// Render the progress bar),});
import { DownloadIcon } from '@react-pdf-viewer/get-file';import { OpenFileIcon } from '@react-pdf-viewer/open';
const searchPluginInstance = searchPlugin({renderHighlights: (renderProps: RenderHighlightsProps) => (// Your custom highlighted elements),});
Shortcut | Action |
---|---|
`PageUp` or `Alt` + `ArrowUp` | Go to the previous page |
`PageDown` or `Alt` + `ArrowDown` | Go to the next page |
// Use the standalone page navigation pluginconst pageNavigationPluginInstance = pageNavigationPlugin({enableShortcuts: false,});// Use the default layout pluginconst defaultLayoutPluginInstance = defaultLayoutPlugin({toolbarPlugin: {pageNavigationPlugin: {enableShortcuts: false,},},});
`setInitialTabFromPageMode`
function returns a `Promise`
which resolves an invalid tab indeximport { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';const defaultLayoutPluginInstance = defaultLayoutPlugin({// The `Bookmark` tab is active initiallysetInitialTab: () => Promise.resolve(1),});
`setInitialTabFromPageMode`
function:import { defaultLayoutPlugin, setInitialTabFromPageMode } from '@react-pdf-viewer/default-layout';const defaultLayoutPluginInstance = defaultLayoutPlugin({setInitialTab: setInitialTabFromPageMode,});
`Enter`
automatically jumps to the next match when being focused on the keyword field`renderPageLayer`
method`initialPage`
option doesn't workconst thumbnailPluginInstance = thumbnailPlugin({thumbnailWidth: 150,});// Use with the default layout pluginconst defaultLayoutPluginInstance = defaultLayoutPlugin({thumbnailPlugin: {thumbnailWidth: 150,},});
<React.StrictMode><Worker workerUrl="..."><Viewer fileUrl="..." /></Worker></React.StrictMode>
`Bookmarks`
component provides new property that can be used to set a bookmark expanded or collapsed initially.
This example expands bookmarks whose depth are zero:const setBookmarkExpanded = ({ bookmark, depth, doc, index }) => {// `bookmark` is the bookmark data structure// `depth` is the current depth// `doc` is the current document// `index` is the zero-based index of bookmark relative to its parentreturn depth === 0;};<Bookmarks isBookmarkExpanded={setBookmarkExpanded} />;
// Expand bookmarks initiallyconst setBookmarkExpanded = ({ bookmark, depth, doc, index }) => true;// Collapse bookmarks initiallyconst setBookmarkExpanded = ({ bookmark, depth, doc, index }) => false;
`NumberOfPages`
component that displays the total number of pages`NumberOfPages`
provides the ability of customizing the number of pages`Popover`
component has new prop `lockScroll`
which indicates whether the `body`
element is scrollable or not. By default, it takes the `true`
value`Viewer`
component adds new `onRotate`
callback that is invoked when users rotate the document:<VieweronRotate={({ direction, doc, rotation }) => {// `direction` is the rotate direction// `doc` is the current document// `rotation` is the latest rotation value}}/>
const renderThumbnailItem = (props: RenderThumbnailItemProps) => (<MinimalButton onClick={() => props.onRotatePage(RotateDirection.Forward)}><RotateForwardIcon /></MinimalButton><MinimalButton onClick={() => props.onRotatePage(RotateDirection.Backward)}><RotateBackwardIcon /></MinimalButton>);const thumbnailPluginInstance = thumbnailPlugin();const { Thumbnails } = thumbnailPluginInstance;<Thumbnails renderThumbnailItem={renderThumbnailItem} />
`renderPage`
:const renderPage: RenderPage = (props: RenderPageProps) => (<>{props.canvasLayer.children}<div><MinimalButton onClick={() => props.onRotatePage(RotateDirection.Forward)}><RotateForwardIcon /></MinimalButton><MinimalButton onClick={() => props.onRotatePage(RotateDirection.Backward)}><RotateBackwardIcon /></MinimalButton></div>{props.annotationLayer.children}{props.textLayer.children}</>);<Viewer renderPage={renderPage} />;
`RotatePage`
component in case you want to rotate a particular page from outside:const rotatePluginInstance = rotatePlugin();const { RotatePage } = rotatePluginInstance;<RotatePage>{(props) => <PrimaryButton onClick={() => props.onRotatePage(0, RotateDirection.Forward)}>Rotate the first page forward</PrimaryButton>}</RotatePage><RotatePage>{(props) => <PrimaryButton onClick={() => props.onRotatePage(0, RotateDirection.Backward)}>Rotate the first page backward</PrimaryButton>}</RotatePage>
`onRotatePage`
event is triggered when a page is rotated:<VieweronRotatePage={({ direction, doc, pageIndex, rotation }) => {// `direction` is the rotate direction// `doc` is the current document// `pageIndex` is the zero-based page index// `rotation` is the latest rotation value}}/>
`Ctrl + F`
, or `Cmd + F`
on macOS) when the mouse is inside the viewer container`unsafeUrl`
property`RotateDirection`
provided by the `@react-pdf-viewer/rotate`
package now belongs to the `@react-pdf-viewer/core`
package:// v3.1.2 and previous versionsimport { RotateDirection } from '@react-pdf-viewer/rotate';// From v3.2.0import { RotateDirection } from '@react-pdf-viewer/core';
`rotate`
function used in the plugins changes the parameter type:// v3.1.2 and previous versionsrotate(90);rotate(-90);// From v3.2.0rotate(RotateDirection.Forward);rotate(RotateDirection.Backward);
`clearHighlights`
and `clearKeyword()`
functions provided by the search plugin should remove all highlights when the keyword is empty`jumpToMatch()`
function provided by the search plugin does not properly highlight keyword when the page is not in the virtual list`ScrollModePluginProps`
type isn't defined in the type definitions of the toolbar plugin`onPageChange()`
should fire after `onDocumentLoad()`
`testId`
property to `Spinner`
`Viewer`
component provides new `scrollMode`
option:import { ScrollMode, Viewer } from '@react-pdf-viewer/core';<Viewer scrollMode={ScrollMode.Horizontal} />;
`switchScrollMode`
method to switch the scroll mode programatically`Viewer`
component now works on mobile.`Viewer`
component to crash if we zoom the document to a big enough level. This version fixes these kinds of issues. There is no crash on mobile anymore!`div`
element. The element isn't rendered by default, and will be rendered when the corresponding page is visible in the viewport.
However, this optimization is not enough for a document that has a big number of pages.`Viewer`
component only renders a given range of pages including the visible pages and some pages that are before and after them.
For example, if users see pages 5-8 in the screen, we will render the pages 3-10 ony. The range will be changed when users scroll up or down, and then the corresponding pages are rendered accordingly.`Spinner`
is used when using the `renderLoader`
option`onPageChange`
event fires more than once`renderThumbnailItem`
option doesn't work with dynamic document`getPageElement`
function. The method is removed because the pages are rendered dynamically`ScrollMode`
provided by the `@react-pdf-viewer/scroll-mode`
package now belongs to the `@react-pdf-viewer/core`
package:// v3.0.0 and previous versionsimport { ScrollMode } from '@react-pdf-viewer/scroll-mode';// From v3.1.0import { ScrollMode } from '@react-pdf-viewer/core';
`scrollModePlugin`
plugin now belongs to the `Viewer`
component:// v3.0.0 and previous versionsimport { scrollModePlugin, ScrollMode } from '@react-pdf-viewer/scroll-mode';const scrollModePluginInstance = scrollModePlugin({scrollMode: ScrollMode.Horizontal,});// From v3.1.0import { ScrollMode } from '@react-pdf-viewer/core';<Viewer scrollMode={ScrollMode.Horizontal} />;
`@react-pdf-viewer/scroll-mode`
package:// v3.0.0 and previous versionsimport '@react-pdf-viewer/scroll-mode/lib/styles/index.css';// From v3.1.0// Remove the import above
`markRendered`
method to mark the page rendered completely.
Hence the next page in the queue will be rendered.// v3.0.0 and previous versionsimport type { RenderPageProps } from '@react-pdf-viewer/core';const CustomPageRender: React.FC<{renderPageProps: RenderPageProps;}> = ({ renderPageProps }) => {return (<>{/* Use the canvas and/or text layers */}{renderPageProps.canvasLayer.children}{renderPageProps.textLayer.children}{/* Your custom components on page ... */}</>);};<Viewer renderPage={(props) => <CustomPageRender renderPageProps={props} />} />;// From v3.1.0const CustomPageRender: React.FC<{renderPageProps: RenderPageProps;}> = ({ renderPageProps }) => {React.useEffect(() => {if (renderPageProps.canvasLayerRendered && renderPageProps.textLayerRendered) {renderPageProps.markRendered(renderPageProps.pageIndex);}}, [renderPageProps.canvasLayerRendered, renderPageProps.textLayerRendered]);return (<>{/* Use the canvas and/or text layers */}{renderPageProps.canvasLayer.children}{renderPageProps.textLayer.children}{/* Your custom components on page ... */}</>);};<Viewer renderPage={(props) => <CustomPageRender renderPageProps={props} />} />;
`testId`
property to `MenuItem`
, `MinimalButton`
, `PrimaryButton`
const fullScreenPluginInstance = fullScreenPlugin({renderExitFullScreenButton: (props) => (<divstyle={{bottom: '1rem',position: 'fixed',right: '1rem',}}><button onClick={props.onClick}>Exit full screen</button></div>),});
const fullScreenPluginInstance = fullScreenPlugin({// `pagesContainer` is the pages containergetFullScreenTarget: (pagesContainer) => pagesContainer.closest('[data-testid="default-layout__body"]'),}),
`renderSpinner`
property that can be used to replace the default `Spinner`
component. This example displays custom loading indicators when loading the cover or thumbnail of a page:const thumbnailPluginInstance = thumbnailPlugin({renderSpinner: () => <div className="square-spinner" />,});
`Thumbnails`
component adds new `renderThumbnailItem`
property that is used to customize the thumbnail renderer:const renderThumbnailItem = (props: RenderThumbnailItemProps) => (<divkey={props.pageIndex}onClick={props.onJumpToPage}style={{backgroundColor: props.pageIndex === props.currentPage ? 'rgba(0, 0, 0, 0.3)' : '#fff',cursor: 'pointer',padding: '0.5rem',}}>{props.renderPageThumbnail}</div>);const thumbnailPluginInstance = thumbnailPlugin();const { Thumbnails } = thumbnailPluginInstance;<Thumbnails renderThumbnailItem={renderThumbnailItem} />;
`data-testid`
attribute to buttons in the toolbar`Cover`
component uses the image instead of canvas tag`Cover`
component position isn't correct`<NumberOfPages />`
isn't correct when using the `renderToolbar`
`React has detected a change in the order of Hooks`
when switching documents`Button`
component has new `testId`
property that is identical with the `data-testid`
attributeconst scrollModePluginInstance = scrollModePlugin();const { switchScrollMode } = scrollModePluginInstance;// Switch to the wrapped modeswitchScrollMode(ScrollMode.Wrapped);
const defaultLayoutPluginInstance = defaultLayoutPlugin({toolbarPlugin: {fullScreenPlugin: {onEnterFullScreen: (zoom) => {zoom(SpecialZoomLevel.PageFit);defaultLayoutPluginInstance.toolbarPluginInstance.scrollModePluginInstance.switchScrollMode(ScrollMode.Wrapped);},onExitFullScreen: (zoom) => {zoom(SpecialZoomLevel.PageWidth);defaultLayoutPluginInstance.toolbarPluginInstance.scrollModePluginInstance.switchScrollMode(ScrollMode.Horizontal);},},},});
const defaultLayoutPluginInstance = defaultLayoutPlugin({sidebarTabs: () => [],});
`(`
, `)`
, `[`
, `]`
, `*`
in the keyword`selectedText`
prop of `RenderHighlightContentProps`
isn't correct`Zoom`
and `ZoomPopover`
components provided by the zoom plugin add new option to customize the zoom levels<Zoom levels={[0.5, 1, 2, 3, 4]} /><ZoomPopover levels={[0.5, 1, 2, 3, 4]} />
`trigger`
option for the highlight plugin:import { Trigger } from '@react-pdf-viewer/highlight';const highlightPluginInstance = highlightPlugin({trigger: Trigger.None,});
`trigger`
option:Value | Description |
---|---|
`Trigger.TextSelection` | Show the target after users select text. It is the default value |
`Trigger.None` | Doesn't trigger the highlight. It is often used to render the highlight areas |
`CurrentPageLabel`
component provided by the Page Navigation plugin includes new `pageLabel`
property.
It is useful if the page has a label that isn't the same as its page number:const { CurrentPageLabel } = pageNavigationPluginInstance;<CurrentPageLabel>{(props) => (<>{props.currentPage + 1}{props.pageLabel === `${props.currentPage + 1}` ? '' : ` (${props.pageLabel})`} of {props.numberOfPages}</>)}</CurrentPageLabel>;
const thumbnailPluginInstance = thumbnailPlugin({renderCurrentPageLabel: (props) => (<>{props.pageIndex + 1}{props.pageLabel !== `${props.pageIndex + 1}` && `(${props.pageLabel})`}</>),});const { Thumbnails } = thumbnailPluginInstance;<Thumbnails />;
`renderDefaultToolbar`
function to create a custom toolbar from the default toolbar easily.
The following sample code prepends `of`
to the `NumberOfPages`
component:import type { ToolbarSlot, TransformToolbarSlot } from '@react-pdf-viewer/toolbar';const { renderDefaultToolbar, Toolbar } = toolbarPluginInstance;const transform: TransformToolbarSlot = (slot: ToolbarSlot) => {const { NumberOfPages } = slot;return Object.assign({}, slot, {NumberOfPages: () => (<>of <NumberOfPages /></>),});};// Render the toolbar<Toolbar>{renderDefaultToolbar(transform)}</Toolbar>;
`Viewer`
component only renders the pages which are visible in the screen. For an invisible page, users will see a spinner. However, the animation used in the `Spinner`
component can slow down the app if the document has a big number of pages.`Spinner`
component when it's visible only.`core`
package provides new `Splitter`
component`Cover`
component that shows the thumbnail of a particular page:const { thumbnailPluginInstance } = thumbnailPlugin();const { Cover } = thumbnailPluginInstance;// Thumbnail of the first page<Cover getPageIndex={_ => 0} />// Thumbnail of the last page<Cover getPageIndex={props => props.numPages - 1} />
`onDocumentAskPassword`
event that is triggered when a protected document requires a password to open:const handleAskPassword = (e: DocumentAskPasswordEvent) => {// ...};<Viewer onDocumentAskPassword={handleAskPassword} />;
`Enter`
to submit the password when opening a protected documentShortcut | Supported plugin | Action |
---|---|---|
`ctrl` + `cmd` + `F` or `F11` | Full screen | Enter the full screen mode |
`cmd` + `O` | Open | Open a document |
`cmd` + `F` | Search | Open the search popover |
// Use the standalone open pluginconst openPluginInstance = openPlugin({enableShortcuts: false,});// Use the default layout pluginconst defaultLayoutPluginInstance = defaultLayoutPlugin({toolbarPlugin: {openPlugin: {enableShortcuts: false,},},});
import { TextDirection, Viewer } from '@react-pdf-viewer/core';<Viewertheme={{direction: TextDirection.RightToLeft,}}/>;
`RenderViewer`
type includes the theme context`setTargetPages`
which sets the pages that you want to search in.import { searchPlugin } from '@react-pdf-viewer/search';const searchPluginInstance = searchPlugin();const { setTargetPages } = searchPluginInstance;// Only search in even pagessetTargetPages((targetPage) => targetPage.pageIndex % 2 === 0);// Only search in the page 4setTargetPages((targetPage) => targetPage.pageIndex === 3);
`Viewer`
component`onDocumentLoad`
event and plugins' `PluginOnDocumentLoad`
callback provide access to the current opened file which contains the `data`
and `name`
properties:const handleDocumentLoad = (e: DocumentLoadEvent) => {console.log(e.file.name, e.file.data);};<Viewer onDocumentLoad={handleDocumentLoad} />;
`activateTab()`
method provided by the default layout plugin shouldn't toggle the tab`LocalePopover`
component doesn't update the localization`SpecialZoomLevel.PageWidth`
Component | Press key | Action |
---|---|---|
`Menu` | `End` | Focus on the last menu item |
`Home` | Focus on the first menu item |
`onSwitchTheme`
option that allows to track if users switch theme. The following snippet demonstrates an example that the current theme is stored in the local storage, and is loaded back in the next user's visit:const handleSwitchTheme = (theme: string) => {localStorage.setItem('theme', theme);};const theme = localStorage.getItem('theme') || 'light';<Viewer theme={theme} onSwitchTheme={handleSwitchTheme} />;
`jumpToMatch`
function which jumps to the given match`highlight`
function now returns a `Promise`
that holds the results. Each result also contains the matching text`core`
package provides `isMac`
function`Icon`
, `Menu`
, `MenuDivider`
, `MenuItem`
, `MinimalButton`
, `Modal`
, `Popover`
, `TextBox`
, `Tooltip`
components`aria-keyshortcuts`
attributesComponent | Press key | Action |
---|---|---|
`Attachments` | `ArrowDown` | Focus on the next attachment |
`ArrowUp` | Focus on the previous attachment | |
`End` | Focus on the last attachment | |
`Enter` | Download the current focused attachment | |
`Home` | Focus on the first attachment | |
`Bookmark` | `ArrowDown` | Focus on the next bookmark |
`ArrowLeft` | Collapse the current bookmark | |
`ArrowRight` | Expand the current bookmark | |
`ArrowUp` | Focus on the previous bookmark | |
`End` | Focus on the last bookmark | |
`Enter` | Click the current focused bookmark | |
`Home` | Focus on the first bookmark | |
`Space` | Click the current focused bookmark | |
`Menu` | `ArrowDown` | Focus on the next menu item |
`ArrowUp` | Focus on the previous menu item | |
`Enter` | Click the current focused item | |
`Thumbnails` | `ArrowDown` | Focus on the thumbnail of next page |
`ArrowUp` | Focus on the thumbnail of the previous page | |
`Enter` | Jump to the associate page | |
`Tooltip` | `Escape` | Close |
`Tab` | Show when being focused | |
Close when being blured |
`Spinner`
component adds new `size`
property`br`
elements generated by the recent versions of pdf.js before rendering the text layer`keyCode`
usages because it's deprecated`:root`
, so we can use components (`Button`
, `Menu`
, `Tooltip`
, etc.) outside of the `Viewer`
`DownloadIcon`
, `ExitFullScreenIcon`
, `FullScreenIcon`
and `OpenFileIcon`
icons`rpv-PACKAGE__COMPONENT`
, `rpv-PACKAGE__COMPONENT--STATE`
. For example:/* Old version */.rpv-search-highlight {...;}.rpv-search-highlight-current {...;}/* From v2.6.0 */.rpv-search__highlight {...;}.rpv-search__highlight--current {...;}
`TextBox`
component`theme`
option:<Viewer theme="bootstrap" />
`rpv-core__viewer--bootstrap`
. You can set the value for CSS variables which are provided by plugins:.rpv-core__viewer--bootstrap {/* Custom the background color of toolbar in the default layout */--rpv-default-layout__toolbar-background-color: #eee;}
Theme | Description |
---|---|
`<Viewer theme='auto' />` | Switch to the dark or light mode automatically based on the system setting |
`<Viewer theme='dark' />` | The dark theme |
`<Viewer theme='light' />` | The light theme (default) |
`<Viewer theme='' />` | The light theme (default) |
`SwitchTheme`
and `SwitchThemeMenuItem`
components`DownArrowIcon`
and `RightArrowIcon`
const printPluginInstance = printPlugin({// The shortcuts are enabled by defaultenableShortcuts: false,});const zoomPluginInstance = zoomPlugin({// The shortcuts are enabled by defaultenableShortcuts: false,});
`Button`
component provided by the `core`
package is renamed to `MinimalButton`
`prefixClass`
of `Viewer`
is removed`getDocument`
API:<ViewerfileUrl="..."transformGetDocumentParams={(options: PdfJs.GetDocumentParams) =>Object.assign({}, options, {disableRange: false,disableStream: false,})}/>
Component | Provided by plugin | Description |
---|---|---|
`DownloadMenuItem` | Get File | Download the current file |
`EnterFullScreenMenuItem` | Full screen | Enter the full screen mode |
`GoToNextPageMenuItem` | Page Navigation | Go to the next page |
`GoToPreviousPageMenuItem` | Page Navigation | Go to the previous page |
`OpenMenuItem` | Open | Open a new file |
`PrintMenuItem` | Print the current file | |
`ZoomInMenuItem` | Zoom | Zoom in the current file |
`ZoomOutMenuItem` | Zoom | Zoom out the current file |
`Button`
and `MenuItem`
components have disabled state. For example, the button for going to the first page will be disabled if we're at the first page`navigator`
isn't defined`initialPage`
and `defaultScale`
options don't work togetherOld name | New name |
---|---|
`GoToFirstPageProps` | `GoToPageProps` |
`GoToLastPageProps` | `GoToPageProps` |
`GoToNextPageProps` | `GoToPageProps` |
`GoToPreviousPageProps` | `GoToPageProps` |
`RenderGoToFirstPageProps` | `RenderGoToPageProps` |
`RenderGoToLastPageProps` | `RenderGoToPageProps` |
`RenderGoToNextPageProps` | `RenderGoToPageProps` |
`RenderGoToPreviousPageProps` | `RenderGoToPageProps` |
`canvas`
element for all pagesShortcut | Supported plugin | Action |
---|---|---|
`cmd` + `p` or `ctrl` + `p` | Print the document | |
`cmd` + `-` or `ctrl` + `-` | Zoom | Zoom out the document |
`cmd` + `+` or `ctrl` + `+` | Zoom | Zoom in the document |
`cmd` + `0` or `ctrl` + `0` | Zoom | Reset zoom to 100% |
`fileUrl`
changes`Uint8Array`
`Uint8Array`
, the download file is named as `document.pdf`
instead of the document blobMethod | Description |
---|---|
`clearHighlights` | Clear the highlights |
`highlight` | Highlight multiple keywords |
`jumpToNextMatch` | Jump to the next match |
`jumpToPreviousMatch` | Jump to the previous match |
import { searchPlugin } from '@react-pdf-viewer/search';const searchPluginInstance = searchPlugin();const { clearHighlights, highlight, jumpToNextMatch, jumpToPreviousMatch } = searchPluginInstance;<button onClick={() => highlight(['document', 'PDF'])}>Highlight: document, PDF</button>;
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)';}},});
`zoomTo`
function:const { zoomTo } = zoomPluginInstance;// Zoom to a given levelzoomTo(1.5);zoomTo(SpecialZoomLevel.PageFit);
`jumpToPage`
function:const { jumpToPage } = pageNavigationPluginInstance;// Jump to the third pagejumpToPage(2);
const defaultLayoutPluginInstance = defaultLayoutPlugin();const { attachmentPluginInstance, bookmarkPluginInstance, thumbnailPluginInstance, toolbarPluginInstance } =defaultLayoutPluginInstance;
const toolbarPluginInstance = toolbarPlugin();const {dropPluginInstance,fullScreenPluginInstance,getFilePluginInstance,openPluginInstance,pageNavigationPluginInstance,printPluginInstance,propertiesPluginInstance,rotatePluginInstance,scrollModePluginInstance,searchPluginInstance,selectionModePluginInstance,zoomPluginInstance,} = toolbarPluginInstance;
`SingleKeyword`
type in the Search plugin supports flags:interface FlagKeyword {keyword: string;matchCase?: boolean; // `false` by defaultwholeWords?: boolean; // `false` by default}type SingleKeyword = string | RegExp | FlagKeyword;
const searchPluginInstance = searchPlugin({keyword: {keyword: 'document',matchCase: true,},});
`span`
elements`MoreActionsPopover`
component in the Toolbar plugin`Observer`
component is removed from the `@react-pdf-viewer/core`
package`fileUrl`
. In that case, you may see the error message`Worker was destroyed`
`Cannot read property 'sendWithPromise' of null`
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 modeonEnterFullScreen: (zoom) => {zoom(SpecialZoomLevel.PageFit);},onExitFullScreen: (zoom) => {zoom(SpecialZoomLevel.PageFit);},});
`FitH`
or `FitBH`
throws an exception`highlight`
plugin provides the ability of selecting and adding notes for text in the document// `defaultTabs` is the list of default tabs which lists thumbnails, bookmarks and attachments respetivelyconst defaultLayoutPluginInstance = defaultLayoutPlugin({sidebarTabs: defaultTabs => { ... }});
const { activateTab } = defaultLayoutPluginInstance;// Activate a tab// activateTab(index);
`getPagesRef`
method in plugins are changed to `getPagesContainer`
:// Before v2.3.0interface PluginFunctions {getPagesRef(): React.RefObject<HTMLDivElement>;}// From v2.3.0interface PluginFunctions {getPagesContainer(): HTMLElement;}
`authorization`
option is removed. You can use the new `withCredentials`
option:// Before v2.3.0<ViewerfileUrl={...}authorization='Bearer ...'/>// From v2.3.0<ViewerfileUrl={...}withCredentials={true}httpHeaders={{'Authorization': 'Bearer ...',}}/>
`authorization`
option.import { Viewer } from '@react-pdf-viewer/core';<ViewerfileUrl={...}authorization='Bearer ...'/>
`httpHeaders`
option, for example:import { Viewer } from '@react-pdf-viewer/core';<ViewerfileUrl={...}authorization='...'httpHeaders={{key: value,}}/>
`Search`
component:import { RenderSearchProps, Search } from '@react-pdf-viewer/search';<Search>{(renderSearchProps: RenderSearchProps) => (// Your custom search control)}</Search>
`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 |
`rpv-search-text-highlight-current`
. So you can customize the current match by adding CSS properties for the class.`onCanvasLayerRender`
option is removed. Instead, use the `onCanvasLayerRender`
option in your plugin.
Take a look at the Draw on top of the canvas layer example.`TextLayerRenderStatus`
enum is renamed to `LayerRenderStatus`
.`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 the `target="_blank"`
attribute to the links:import { AnnotationType, Plugin, PluginOnAnnotationLayerRender } from '@react-pdf-viewer/core';const customPlugin = (): Plugin => {const onRenderAnnotations = (e: PluginOnAnnotationLayerRender) => {// Find all Link annotatione.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,};};
// Use the search pluginimport { searchPlugin } from '@react-pdf-viewer/search';const searchPluginInstance = searchPlugin({keyword: ['document', 'PDF'],});// Use with default-layout pluginimport { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';const defaultLayoutPluginInstance = defaultLayoutPlugin({toolbarPlugin: {searchPlugin: {keyword: ['document', 'PDF'],},},});
`lib`
directory. For example:// Old versionimport '@react-pdf-viewer/core/styles/index.css';// New versionimport '@react-pdf-viewer/core/lib/styles/index.css';
`Viewer`
is very lightweight, and everything else is powered by plugins.// Import pluginimport { toolbarPlugin } from '@react-pdf-viewer/toolbar';// Import stylesimport '@react-pdf-viewer/toolbar/lib/styles/index.css';// Create the plugin instanceconst toolbarPluginInstance = toolbarPlugin(...);// Register plugins<Viewerplugins={[// Array of pluginstoolbarPlugin,...]}/>
`Viewer`
supports to use a custom loader instead of the default `<Spinner>`
:import { ProgressBar, Viewer } from '@react-pdf-viewer/core';<ViewerrenderLoader={(percentages: number) => (// You can use your own progress bar component<div style={{ width: '240px' }}><ProgressBar progress={Math.round(percentages)} /></div>)}/>;
const getFilePluginInstance = getFilePlugin({fileNameGenerator: (file: OpenFile) => {// `file.name` is the URL of opened fileconst fileName = file.name.substring(file.name.lastIndexOf('/') + 1);return `a-copy-of-${fileName}`;},});
`onPageChange`
could be invoked several times when clicking an outline item`keyword`
option is removed. Use the `keyword`
option provided by the search plugin.`layout`
option is removed`render`
option is removed`selectionMode`
option is removed. Use the `selectionMode`
option provided by the selection-mode plugin.`onTextLayerRender`
option is removed. Instead, use the `onTextLayerRender`
option in your plugin.
Take a look at the Find and replace links found in each page example.npm uninstall pdfjs-distnpm uninstall @phuocng/react-pdf-viewer
npm install pdfjs-dist@2.5.207npm install @react-pdf-viewer/core@2.0.1
`Worker`
with new one:// Remove the old Workerimport { Worker } from '@phuocng/react-pdf-viewer';// Use the new Workerimport { Worker } from '@react-pdf-viewer/core';
`Viewer`
:npm install @react-pdf-viewer/default-layout@2.0.1
`Viewer`
with new one:// Old Viewerimport Viewer from '@phuocng/react-pdf-viewer';// New Viewerimport { Viewer } from '@react-pdf-viewer/core';// Pluginsimport { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';// Import stylesimport '@react-pdf-viewer/core/lib/styles/index.css';import '@react-pdf-viewer/default-layout/lib/styles/index.css';// Create new plugin instanceconst defaultLayoutPluginInstance = defaultLayoutPlugin();// Your render function<ViewerfileUrl='/path/to/document.pdf'plugins={[// Register pluginsdefaultLayoutPluginInstance,...]}/>
`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} />;
`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 elementconst canvas = e.ele;// Do something with the canvas element};<Viewer fileUrl="/path/to/document.pdf" onCanvasLayerRender={onCanvasLayerRender} />;
`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} />;
`characterMap`
optionimport 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" />;
`onDocumentLoad`
and `onZoom`
are changed as following:v1.6.0 | v1.7.0 |
---|---|
`onDocumentLoad(doc)` | `onDocumentLoad({ doc })` |
`onZoom(doc, scale)` | `onZoom({ doc, scale })` |
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} />;
`fileUrl`
option<ViewerfileUrl="/path/to/document.pdf"// The `keyword` option can be a string or a regular expression// keyword='PDF Library'keyword={new RegExp('pdf document', 'i')}/>
const renderPage = (props: RenderPageProps) => {return (<>{props.svgLayer.children}{props.textLayer.children}{props.annotationLayer.children}</>);};<Viewer fileUrl="/path/to/document.pdf" renderPage={renderPage} />;
const renderPage: RenderPage = (props: RenderPageProps) => (<>{props.canvasLayer.children}<divstyle={{alignItems: 'center',display: 'flex',height: '100%',justifyContent: 'center',left: 0,position: 'absolute',top: 0,width: '100%',}}><divstyle={{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} />;
<Viewer fileUrl="/path/to/document.pdf" defaultScale={SpecialZoomLevel.PageFit} />
`fileUrl`
option can be `Uint8Array`
:<ViewerfileUrl={new Uint8Array([...])}/>
<Viewer// The page is zero-based index// We will display the third page initiallyinitialPage={2}/>
<Viewer prefixClass="viewer" />
`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={fileUrl} render={render} />;
`ToolbarSlot`
now includes`goToFirstPageButton`
: the button to go to the first page`goToLastPageButton`
: go to the last page`rotateClockwiseButton`
: rotate the document`rotateCounterclockwiseButton`
: rotate counterclockwise the document`textSelectionButton`
: switch to the text selection mode`handToolButton`
: switch to the hand tool mode`verticalScrollingButton`
: scroll the document vertically`horizontalScrollingButton`
: scroll the document horizontally`wrappedScrollingButton`
: display pages as a grid`documentPropertiesButton`
: show the document properties`selectionMode`
option indicates the selection mode:import Viewer, { SelectionMode } from '@phuocng/react-pdf-viewer';<ViewerfileUrl="..."// By default, it will be SelectionMode.TextselectionMode={SelectionMode.Hand}/>;
`onDocumentLoad`
callback that uis invoked when the document is loaded completelyimport Viewer, { PdfJs } from '@phuocng/react-pdf-viewer';const documentLoad = (doc: PdfJs.PdfDocument) => {console.log(`Document is loaded: ${doc.numPages}`);};<Viewer fileUrl="..." onDocumentLoad={documentLoad} />;
`onZoom`
callback that is invoked when zooming in/out the documentimport 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} />;
`defaultScale`
parameter that indicates the default zoom level:<Viewer defaultScale={1.5} ... />