Skip to content

Library for creating and printing pdf documents using React.

Notifications You must be signed in to change notification settings

krupinskij/react-pdf-printer

Repository files navigation

React Pdf Printer

Description

Library for creating and printing pdf documents using React.

This library is for you if you:

  • want to create pdf document from scratch,
  • have working project and now you want to print pdf document using components you already have with little to none changes to them

NOTE: Saying "print" I mean creating pdf document in your browser calling window.print().

This library provides control over:

  • placing content on proper page (especially when it comes to spliting large components into different pages),
  • dealing with asynchronous content (e.g. fetching data, loading images),
  • adding header and footer to every page with information about current page and number of all pages

Example usage

Installation

$ npm install react-pdf-printer
$ yarn add react-pdf-printer

Usage

Importing

import {
  PrinterProvider,
  Document,
  PortalDocument,
  Page,
  Pages,
  Pagination,
  usePrinter,
} from 'react-pdf-printer';

PrinterProvider

Printer provider configurating every pdf document (some fields can later be overwritten for particular document).

Name Desc Type Required Default value
configuration Configuration for every document PrinterConfiguration no (see below)
configuration.useAsync Enable async data fetching (see usePrinter) boolean no false
configuration.size Size of the document according to mdn number | [number, number] | 'a3' | 'a4' | 'a5' | 'b4' | 'b5' | 'jis-b4' | 'jis-b5' | 'letter' | 'legal' | 'ledger' no 'a4'
configuration.orientation Orientation of the document 'landscape' | 'portrait' no 'portrait'
configuration.pagination Configuration of pagination PaginationConfiguration no (see below)
configuration.pagination.format Text of the paging string no '#p / #t'
configuration.pagination.formatPage Token in format which later will be replaced by current page string no '#p'
configuration.pagination.formatTotal Token in format which later will be replaced by number of all pages string no '#t'
configuration.pagination.style Style of pagination (see mdn). Value to provide is <counter-style-name> (see mdn) string no 'decimal'
children Content of the application React.ReactNode yes ---

Document

Document component configurating and wrapping content of the pdf component.

NOTE: This component is intended to be the only and top level component of the route (see example usage)

Name Desc Type Required Default value
header Default header for the document React.ReactNode yes ---
footer Default footer for the document React.ReactNode yes ---
children Content of the document React.ReactNode yes ---
title Title of the document (filename) string no (document.title is used)
screen Hides document view from the user and show the substitute screen React.ReactNode | (({ isPrinting }) => React.ReactNode) yes ---
configuration Configuration of the document DocumentConfiguration = Omit<PrinterConfiguration, 'orientation' | 'size'> no (see below)
configuration.useAsync Enable async data fetching (see PrinterProvider) boolean no (PrinterProvider's configuration.useAsync)
configuration.pagination Configuration for pagination (see PrinterProvider) PaginationConfiguration no (PrinterProvider's configuration.pagination)
onRender Function fired after rendering pdf document () => void no window.print
renderOnInit Flag indicating if document should be rendered on init (or on user action (see ref)) boolean no true
ref Reference prop with render function (can be used when renderOnInit is set to false) DocumentRef no ---

PortalDocument

Document component configurating and wrapping content of the pdf component.

This component allows to render pdf when other content is visible (see example usage)

Name Desc Type Required Default value
header Default header for the document React.ReactNode yes ---
footer Default footer for the document React.ReactNode yes ---
children Content of the document React.ReactNode yes ---
configuration Configuration of the document DocumentConfiguration = Omit<PrinterConfiguration, 'orientation' | 'size'> no (see below)
configuration.useAsync Enable async data fetching (see PrinterProvider) boolean no (PrinterProvider's configuration.useAsync)
configuration.pagination Configuration for pagination (see PrinterProvider) PaginationConfiguration no (PrinterProvider's configuration.pagination)
onRender Function fired after rendering pdf document () => void no window.print
ref Reference prop with render function DocumentRef no ---

Page

Component undivisible into many pages.

Name Desc Type Required Default value
header Header for the page React.ReactNode no (Document's or PortalDocument's header)
footer Footer for the page React.ReactNode no (Document's or PortalDocument's footer
children Content for the page React.ReactNode yes ---

NOTE: If the content of the Page is larger than the height of the page overflow content is hidden.

Pages

Component divisible into many pages.

Name Desc Type Required Default value
header Header for the page React.ReactNode no (Document's or PortalDocument's header)
footer Footer for the page React.ReactNode no (Document's or PortalDocument's footer)
children Content for the page React.ReactNode yes ---

NOTE: Inner components that can be divided into many pages should have data-printer-divisible attribute (see). Rare use of this attribute can cause overflowed content and weird behaviour.

NOTE: Both Page and Pages have to be placed inside Document or PortalDocument component.

Pagination

Component for marking number of current page. Configured by Document and PortalDocument.

NOTE: This component should be placed only in your header or footer.

usePrinter

Printer hook

const { isPrinter, isRendering, subscribe, run } = usePrinter(key?: string);
Name Desc Type
isPrinter Flag indicating if it component inside Document or PortalDocument component boolean
isRendering Flag indicating if any pdf document is currently rendering boolean
subscribe Function subscribing for asynchronous action () => void
run Function to run after resolving asynchronous action () => void

subscribe and run functions are useful when dealing with some asynchronous code (e.g. fetching some data from backend) and not wanting to print document immediately.

const MyComponent = () => {
  const { subscribe, run } = usePrinter('my-unique-key');
  const [data, setData] = useState([]);

  useEffect(() => {
    subscribe();
    fetch('...')
      .then(resp => resp.json())
      .then(resp => {
        setData(resp);
      })
      .finally(() => {
        run()
      })
  }, [subscribe, run]);

  return <div>{ data.map(item => ...) }</div>;
};

NOTE: Running subscribe and run from usePrinter with no key passed or outside Document or PortalDocument has no effect (they are empty functions).

NOTE: Using subscribe and run functions works only when useAsync flag is set to true.

NOTE: Setting useAsync flag to true and not running subscribe and run blocks rendering (these functions have to be used at least once).

data-printer-divisible

HTML dataset attribute indicating that direct children of marked element can be splitted into many pages. Otherwise whole element will stay in one page (unless any of his nested children has such attribute).

This attribute can be used anywhere in the document tree and can be used recursively inside direct or indirect parent element with this attribute.

This attribute don't need any value.

NOTE: Using data-printer-divisible attribute on elements in Page has no effect.

<div data-printer-divisible>
  <div>This text</div>
  <div>can be</div>
  <div>splitted into</div>
  <div>many pages.</div>
</div>
<div>
  <div>And this</div>
  <div>will stay</div>
  <div>in one page</div>
</div>

data-printer-span

HTML dataset attribute indicating how many direct next siblings will be treated as one element and won't be splitted into different pages.

This attribute takes a positive natural number (default value is 1). Floating point number are rounded down to nearest integer number. Any value that eventually won't be positive natural number will fallback to 1.

<div data-printer-divisible>
  {/* 1 */} <h1 data-printer-span="3">This is a header</h1> {/* span = 3 */}
  {/* 2 */} <h2>This is a subheader</h2>
  {/* 3 */} <div>This still will be in the same page!</div>
  {/* 4 */} <div>This may or may not be moved to the next page</div>
</div>

Notes

Due to poor browser compatibility e.g. lack of vh css unit in context of @media print doesn't work on Firefox.

Development

# building
$ npm run build

# building in development mode
$ npm run build:dev

# building in watch mode
$ npm run build:watch

About

Library for creating and printing pdf documents using React.

Resources

Stars

Watchers

Forks