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

Changelog History
Page 1

  • v3.5.0 Changes

    ๐Ÿ†• New feature

    • Be able to customize the highlight elements when searching for a keyword:
    const searchPluginInstance = searchPlugin({
        renderHighlights: (highlightPositions: HighlightPosition[]) => (
            // Your custom highlight elements
        ),
    });
    

    ๐Ÿ‘Œ Improvements

    • ๐Ÿ”Œ The highlight plugin supports double click. Users can double click to select the entire text of a given element

    • ๐Ÿ”Œ The page navigation plugin allows to jump to the previous and next pages with shortcuts.

    Shortcut Action
    PageUp or Alt + ArrowUp Go to the previous page
    PageDown or Alt + ArrowDown Go to the next page

    0๏ธโƒฃ The shortcuts are enabled by default. It's possible to disable them, for example:

    // Use the standalone page navigation plugin
    const pageNavigationPluginInstance = pageNavigationPlugin({
        enableShortcuts: false,
    });
    
    // Use the default layout plugin
    const defaultLayoutPluginInstance = defaultLayoutPlugin({
        toolbarPlugin: {
            pageNavigationPlugin: {
                enableShortcuts: false,
            },
        },
    });
    

    ๐Ÿ› Bug fixes

    • Don't highlight the entire page when selecting multiple lines
    • 0๏ธโƒฃ The default layout plugin throws an exception if the setInitialTabFromPageMode function returns a Promise which resolves an invalid tab index
    • ๐Ÿ”Œ The highlight plugin throws an exception when double click a page without selecting any text
    • ๐Ÿ”Œ The search plugin can't set the initial keyword when using with the highlight plugins
  • v3.4.0 Changes

    ๐Ÿ†• New feature

    • It's possible to set the initial tab
    import { defaultLayoutPlugin } from '@react-pdf-viewer/default-layout';
    
    const defaultLayoutPluginInstance = defaultLayoutPlugin({
        // The `Bookmark` tab is active initially
        setInitialTab: () => Promise.resolve(1),
    });
    

    According to the PDF specifications, the initial tab can be determined based on the document's page mode. If you want to follow that behaviour, then you can use the setInitialTabFromPageMode function:

    import { defaultLayoutPlugin, setInitialTabFromPageMode } from '@react-pdf-viewer/default-layout';
    
    const defaultLayoutPluginInstance = defaultLayoutPlugin({
        setInitialTab: setInitialTabFromPageMode,
    });
    

    ๐Ÿ‘Œ Improvement

    • Smooth scroll when jumping to a given page or destination (clicking a bookmark, for example)

    ๐Ÿ› Bug fixes

    • Can't add highlight to selected text
    • Keep current position after zooming
  • v3.3.3 Changes

    ๐Ÿ‘Œ Improvements

    • Clicking Enter automatically jumps to the next match when being focused on the keyword field
    • โšก๏ธ Support documents which are optimized for web. Users don't have to wait the full document loaded to see the first page.

    ๐Ÿ› Bug fixes

    • Automatically scroll to the thumbnail of the initial page when it's set
    • ๐Ÿ”Œ The text might not be selectable if a plugin registers the renderPageLayer method
    • There is a page that is not rendered even it is visible when users zoom the document
  • v3.3.2 Changes

    ๐Ÿ› Bug fixes

    ๐Ÿ›  Fix more issues that only happen with React 18's Strict mode:

    • The initialPage option doesn't work
    • The pages are flickering when zooming the document
    • There is a page that is not rendered even it is visible when users zoom the document continuously
  • 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} />} />;