All Versions
44
Latest Version
Avg Release Cycle
20 days
Latest Release
-

Changelog History
Page 1

  • v3.3.1 Changes

    ๐Ÿ†• New feature

    • ๐Ÿ”Œ The thumbnail plugin adds new option for customizing the width of thumbnails:
    const thumbnailPluginInstance = thumbnailPlugin({
        thumbnailWidth: 150,
    });
    
    // Use with the default layout plugin
    const defaultLayoutPluginInstance = defaultLayoutPlugin({
        thumbnailPlugin: {
            thumbnailWidth: 150,
        },
    });
    

    ๐Ÿ› Bug fix

    • ๐Ÿ‘ Support React 18 strict mode
    <React.StrictMode>
        <Worker workerUrl="...">
            <Viewer fileUrl="..." />
        </Worker>
    </React.StrictMode>
    
  • v3.3.0 Changes

    ๐Ÿ†• New feature

    • The Bookmarks component provides new property that can be used to set a bookmark expanded or collapsed initially. The following sample code expands bookmarks whose depth are smaller or equal to 2:
    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 parent
        return depth <= 2;
    };
    
    <Bookmarks isBookmarkExpanded={setBookmarkExpanded} />;
    

    Expanding or collapsing all bookmarks initially can be done easily:

    // Expand bookmarks initially
    const setBookmarkExpanded = ({ bookmark, depth, doc, index }) => true;
    
    // Collapse bookmarks initially
    const setBookmarkExpanded = ({ bookmark, depth, doc, index }) => false;
    
    • ๐Ÿ”Œ The Page Navigation plugin provides new NumberOfPages component that displays the total number of pages

    ๐Ÿ‘Œ Improvements

    • Align bookmark titles
    • Compatible with React 18
    • 0๏ธโƒฃ In previous versions, all bookmarks were expanded by default. From this version, a bookmark will be shown or hidden initially depending on its data structure. You can see this behaviour on popular viewers such as Acrobat Reader.
    • The toolbar slot NumberOfPages provides the ability of customizing the number of pages

    ๐Ÿ› Bug fixes

    • The hightlights are lost when the whole words option is enabled
    • There is a visible page that isn't rendered when setting the zoom level as page width
  • v3.2.0 Changes

    ๐Ÿ†• New features

    • 0๏ธโƒฃ The Popover component has new prop lockScroll which indicates whether the body element is scrollable or not. By default, it takes the true value
    • The Viewer component adds new onRotate 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, or Cmd + 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);
    
  • v3.1.2 Changes

    ๐Ÿ› Bug fixes

    • Don't highlight spaces between words when searching for a keyword
    • ๐Ÿšš The clearHighlights and clearKeyword() functions provided by the search plugin should remove all highlights when the keyword is empty
    • The current highlight is lost after zooming the document
    • ๐Ÿ”Œ The jumpToMatch() function provided by the search 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 the toolbar 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 after onDocumentLoad()
    • 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 to Spinner
    • The Viewer component provides new scrollMode 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 the renderLoader 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 the Viewer 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} />} />;
    
  • v3.0.0 Changes

    ๐Ÿ†• New features

    • โœ… Add new testId property to MenuItem, 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 default Spinner 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 new renderThumbnailItem 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 the renderToolbar
    • ๐Ÿ‘ป There is an exception of React has detected a change in the order of Hooks when switching documents
  • v2.11.0 Changes

    ๐Ÿ†• New features

    • โœ… The Button component has new testId property that is identical with the data-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 of RenderHighlightContentProps isn't correct
  • v2.10.1 Changes

    ๐Ÿ†• New feature

    • ๐Ÿ”Œ The Zoom and ZoomPopover 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
  • 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 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.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 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>;
    

    ๐Ÿ‘Œ 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