Changelog History
Page 2
-
v3.2.0 Changes
๐ New features
- 0๏ธโฃ The
Popover
component has new proplockScroll
which indicates whether thebody
element is scrollable or not. By default, it takes thetrue
value - The
Viewer
component adds newonRotate
callback that is invoked when users rotate the document:
<Viewer onRotate={({ direction, doc, rotation }) => { // `direction` is the rotate direction // `doc` is the current document // `rotation` is the latest rotation value }} />
- Provide the ability of rotating a particular page. You can customize a thumbnail renderer to add the rotating functionality to each page:
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} />
It's also possible to do it by using the
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} />;
๐ The rotate plugin adds new
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>
- The
onRotatePage
event is triggered when a page is rotated:
<Viewer onRotatePage={({ 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 }} />
๐ Improvements
- ๐ The search popover is opened if users press the shortcuts (
Ctrl + F
, orCmd + F
on macOS) when the mouse is inside the viewer container - It's able to scroll the pages when opening the search popover
- ๐ Support link annotations that have the
unsafeUrl
property
๐ Bug fixes
- Typo in full screen change event
- There is a visible page that isn't rendered when setting the zoom level as page width
- The thumbnails aren't rotated after rotating the document
๐ฅ Breaking changes
- ๐ฆ The
RotateDirection
provided by the@react-pdf-viewer/rotate
package now belongs to the@react-pdf-viewer/core
package:
// v3.1.2 and previous versions import { RotateDirection } from '@react-pdf-viewer/rotate'; // From v3.2.0 import { RotateDirection } from '@react-pdf-viewer/core';
- ๐ The
rotate
function used in the plugins changes the parameter type:
// v3.1.2 and previous versions rotate(90); rotate(-90); // From v3.2.0 rotate(RotateDirection.Forward); rotate(RotateDirection.Backward);
- 0๏ธโฃ The
-
v3.1.2 Changes
๐ Bug fixes
- Don't highlight spaces between words when searching for a keyword
- ๐ The
clearHighlights
andclearKeyword()
functions provided by thesearch
plugin should remove all highlights when the keyword is empty - The current highlight is lost after zooming the document
- ๐ The
jumpToMatch()
function provided by thesearch
plugin does not properly highlight keyword when the page is not in the virtual list - ๐ The
ScrollModePluginProps
type isn't defined in the type definitions of thetoolbar
plugin
-
v3.1.1 Changes
๐ Improvement
- ๐ป The full screen button and menu item are disabled on browsers that don't support full screen APIs. It happens on iOS Safari and iOS Chrome, for example.
๐ Bug fixes
-
onPageChange()
should fire afteronDocumentLoad()
- The pages aren't layouted properly when they have different dimensions
- The pages are blank initially until users scroll or interact with the page
-
v3.1.0 Changes
๐ New features
- โ
Add new
testId
property toSpinner
- The
Viewer
component provides newscrollMode
option:
import { ScrollMode, Viewer } from '@react-pdf-viewer/core'; <Viewer scrollMode={ScrollMode.Horizontal} />;
- ๐ Plugins can register and call the
switchScrollMode
method to switch the scroll mode programatically
๐ Improvements
- The
Viewer
component now works on mobile.
๐ป As we know, the mobile browsers such as iOS Safari have the limit value for canvas size and the maximum memory values (256 MB on iOS Safari, for example) for rendering canvases. ๐ It can cause the
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!- ๐ Improve the performance when rendering a document.
0๏ธโฃ In the previous versions, each page is represented by a separated
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.v3.1.0 brings the optimization to a new level. Instead of keeping the instance of all pages all the time, the
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.๐ Bug fixes
- Keep the current page after switching the scroll mode
- The
Cover
component has the same image source when loading different documents - 0๏ธโฃ The default
Spinner
is used when using therenderLoader
option - The exit full screen button doesn't look good in dark theme
- The
onPageChange
event fires more than once - The
renderThumbnailItem
option doesn't work with dynamic document - The sidebar doesn't fit in its container on Safari
- There is a black area in the full screen mode if the zoom level is small enough
๐ฅ Breaking changes
- ๐ It is not possible to access the page element in a plugin with the
getPageElement
function. The method is removed because the pages are rendered dynamically - ๐ฆ The
ScrollMode
provided by the@react-pdf-viewer/scroll-mode
package now belongs to the@react-pdf-viewer/core
package:
// v3.0.0 and previous versions import { ScrollMode } from '@react-pdf-viewer/scroll-mode'; // From v3.1.0 import { ScrollMode } from '@react-pdf-viewer/core';
- ๐ The inital scroll mode option provided by the
scrollModePlugin
plugin now belongs to theViewer
component:
// v3.0.0 and previous versions import { scrollModePlugin, ScrollMode } from '@react-pdf-viewer/scroll-mode'; const scrollModePluginInstance = scrollModePlugin({ scrollMode: ScrollMode.Horizontal, }); // From v3.1.0 import { ScrollMode } from '@react-pdf-viewer/core'; <Viewer scrollMode={ScrollMode.Horizontal} />;
- ๐
There aren't CSS styles provided by the
@react-pdf-viewer/scroll-mode
package:
// v3.0.0 and previous versions import '@react-pdf-viewer/scroll-mode/lib/styles/index.css'; // From v3.1.0 // Remove the import above
- From v3.1.0, pages are rendered one by one. If you use a custom page renderer, then you have to call the
markRendered
method to mark the page rendered completely. Hence the next page in the queue will be rendered.
// v3.0.0 and previous versions import 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.0 const 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} />} />;
- โ
Add new
-
v3.0.0 Changes
๐ New features
- โ
Add new
testId
property toMenuItem
,MinimalButton
,PrimaryButton
- Be able to customize the button to exit the full screen mode:
const fullScreenPluginInstance = fullScreenPlugin({ renderExitFullScreenButton: (props) => ( <div style={{ bottom: '1rem', position: 'fixed', right: '1rem', }} > <button onClick={props.onClick}>Exit full screen</button> </div> ), });
- ๐ The full screen plugin allows to set the full screen element. The following code will include the pages container and the toolbar in the full screen mode:
const fullScreenPluginInstance = fullScreenPlugin({ // `pagesContainer` is the pages container getFullScreenTarget: (pagesContainer) => pagesContainer.closest('[data-testid="default-layout__body"]'), }),
- 0๏ธโฃ The thumbnail plugin adds new
renderSpinner
property that can be used to replace the defaultSpinner
component. For example, it is displayed when loading the cover or thumbnail of a page:
const thumbnailPluginInstance = thumbnailPlugin({ renderSpinner: () => <div className="square-spinner" />, });
- The
Thumbnails
component adds newrenderThumbnailItem
property that is used to customize the thumbnail renderer:
const renderThumbnailItem = (props: RenderThumbnailItemProps) => ( <div key={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} />;
๐ Improvements
- โ
Add
data-testid
attribute to buttons in the toolbar - The
Cover
component uses the image instead of canvas tag - 0๏ธโฃ The default layout shouldn't have a horizontal scrollbar when the default scale isn't set
๐ Bug fixes
- Navigating between search results should be the same as their appearances on pages
- The internal links don't work properly in some cases
- The thumbnails are stuck at loading spinner
- The
Cover
component position isn't correct - The number of pages slot
<NumberOfPages />
isn't correct when using therenderToolbar
- ๐ป There is an exception of
React has detected a change in the order of Hooks
when switching documents
- โ
Add new
-
v2.11.0 Changes
๐ New features
- โ
The
Button
component has newtestId
property that is identical with thedata-testid
attribute - ๐ The Scroll Mode plugin provides new function to switch mode programmatically:
const scrollModePluginInstance = scrollModePlugin(); const { switchScrollMode } = scrollModePluginInstance; // Switch to Wrapped mode switchScrollMode(ScrollMode.Wrapped);
๐ You might find it useful when using with the full screen plugin. The following sample code switches the scroll mode after entering the full screen mode:
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 ); }, }, }, });
๐ Improvements
- ๐ Cache pages' labels. So we won't see blink in the current page label when navigating between pages
- Keep the file name when downloading a file opened from local
- ๐ It's possible to remove the sidebar created by the default layout plugin:
const defaultLayoutPluginInstance = defaultLayoutPlugin({ sidebarTabs: () => [], });
๐ Bug fixes
- Can't use special characters such as
(
,)
,[
,]
,*
in the keyword - Downloading document doesn't work on iOS Safari and iOS Chrome
- ๐ The Get File plugin doesn't work with a file which is opened with credentials
- The highlight area aren't displayed
- The
selectedText
prop ofRenderHighlightContentProps
isn't correct
- โ
The
-
v2.10.1 Changes
๐ New feature
- ๐ The
Zoom
andZoomPopover
components provided by the zoom plugin adds a custom zoom levels
<Zoom levels={[0.5, 1, 2, 3, 4]} /> <ZoomPopover levels={[0.5, 1, 2, 3, 4]} />
๐ Bug fix
- Clicking the Search button scrolls to the top of page
- ๐ The
-
v2.10.0 Changes
๐ New features
- ๐ Add new
trigger
option for the Highlight plugin
import { Trigger } from '@react-pdf-viewer/highlight'; const highlightPluginInstance = highlightPlugin({ trigger: Trigger.None, });
There are two possible values for the
trigger
option:Value Description 0๏ธโฃ Trigger.TextSelection
(default)Trigger.None
Doesn't trigger the highlight. It is often used to render the highlight areas - ๐ The render props of the
CurrentPageLabel
component provided by the Page Navigation plugin includes newpageLabel
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.numberOfPages} {props.pageLabel !== `${props.currentPage + 1}` && `(${props.pageLabel})`} </> )} </CurrentPageLabel>;
- The
Thumbnails
component displays the page labels if there are. You also can customize the page labels:
const thumbnailPluginInstance = thumbnailPlugin({ renderCurrentPageLabel: (props) => ( <> {props.pageIndex + 1} {props.pageLabel !== `${props.pageIndex + 1}` && `(${props.pageLabel})`} </> ), }); const { Thumbnails } = thumbnailPluginInstance; <Thumbnails />;
- 0๏ธโฃ The Toolbar plugin provides the
renderDefaultToolbar
function to create a custom toolbar from the default toolbar easily. The following sample code prependsof
to theNumberOfPages
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>;
๐ Improvement
- ๐จ Disable the printing functionality if the document doesn't allow to print
๐ Bug fixes
- ๐ป Can't resize the sidebar when using with the Fluent UI library
- Fix the TypeScript definition of the
Cover
component - ๐จ Fix an edge case where there are extra empty pages when printing a document
- ๐ Add new
-
v2.9.2 Changes
๐ New feature
- ๐ Add new
trigger
option for the Highlight plugin
import { Trigger } from '@react-pdf-viewer/highlight'; const highlightPluginInstance = highlightPlugin({ trigger: Trigger.None, });
There are two possible values for the
trigger
option:Value Description 0๏ธโฃ Trigger.TextSelection
(default)Trigger.None
Doesn't trigger the highlight. It is often used to render the highlight areas ๐ Improvements
- ๐จ Disable the printing functionality if the document doesn't allow to print
- Show the page labels if there are
๐ Bug fixes
- ๐ป Can't resize the sidebar when using with the Fluent UI library
- Fix the TypeScript definition of the
Cover
component - ๐จ Fix an edge case where there are extra empty pages when printing a document
- ๐ Add new
-
v2.9.1 Changes
๐ Improvement
๐ As we know, the
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 theSpinner
component can slow down the app if the document has a big number of pages.๐ This version improves the performance by animating the
Spinner
component when it's visible only.