Skip to content

Commit

Permalink
Add PdfDocument, PdfHeader, PdfFooter. Render to TDocumentDefinitions…
Browse files Browse the repository at this point in the history
… instead of Content.
  • Loading branch information
danvim committed Nov 23, 2023
1 parent c2a3a31 commit e464ecd
Show file tree
Hide file tree
Showing 23 changed files with 617 additions and 257 deletions.
99 changes: 75 additions & 24 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,16 @@ npm i react-pdfmake-reconciler

- Write complex PDF in JSX. Render JSX into PDF Make content structure.
- Utilize React features like:
- Context. Note that outside React context does not penetrate into PDF renderer.
- Context. Note that outside React contexts do not penetrate into PDF renderer.
- Components
- Hooks
- Working React update loop, (although it is unlikely to trigger user events inside PDF.)
- e.g. async setState calls
- Code autocomplete in JSX for "PDF Make components"
- Working React update loop, (although it is unlikely to trigger user events inside PDF.), e.g.
- async setState calls
- useEffect call
- TypeScript typing for PDF Make Components (`<pdf-*>` components)
- React Developer Tools support

![React Developer Tools Demo](./screenshots/react-devtools-demo.png)

## Running demo

Expand All @@ -32,56 +36,103 @@ pnpm dev

## Usage

See `/demo` and tests for more extensive examples.
See `/demo` and [tests](./src/__tests__/PdfRenderer.test.tsx) for more extensive examples.

### Simple examples

```tsx
/// <reference types="react-pdfmake-reconciler/react-jsx" />

import { PdfRenderer } from 'react-pdfmake-reconciler/PdfRenderer'
import { PdfRenderer } from "react-pdfmake-reconciler/PdfRenderer";

const {unmount} = PdfRenderer.render(
const { unmount } = PdfRenderer.render(
<pdf-text bold>Hello World!</pdf-text>,
content => console.log(content)
)
(document) => console.log(document),
);

/*
Console:
{
$__reactPdfMakeType: 'pdf-text',
text: 'Hello World!',
bold: true
content: {
$__reactPdfMakeType: 'pdf-text',
text: 'Hello World!',
bold: true
}
}
*/

// Call unmount to detach node tree.
unmount()
unmount();
```

```tsx
import { PdfRenderer } from 'react-pdfmake-reconciler/PdfRenderer'
import { PdfRenderer } from "react-pdfmake-reconciler/PdfRenderer";

const content = await PdfRenderer.renderOnce(<pdf-text bold>Hello World!</pdf-text>)
const document = PdfRenderer.renderOnce(<pdf-text bold>Hello World!</pdf-text>);
```

### PDF elements

Newly defined intrinsic elements have the `pdf-` prefix. Roughly, each type of PDF Make node corresponds to one element type, where the property specifying `Content` is mapped to the `children` prop. For example:
Newly defined intrinsic elements by this package have the `pdf-` prefix. Roughly speaking, each type of PDF Make content object corresponds to one element type, where the property specifying the `Content` is mapped to the `children` prop. For example:

```tsx
const pdfMakeContent = {
text: 'GitHub',
link: 'https://www.github.com'
}
text: "GitHub",
link: "https://www.github.com",
};

// is mapped to

const pdfNode = <pdf-text link="https://www.github.com">GitHub</pdf-text>;
```

There are also virtual element types. For more information, read [JSDocs in types](./src/types/PdfElements.ts) for more information.

### Document, Header, and Footer

You can easily define extra document definition props straight inside your JSX using `<PdfDocument>`. It is optional to put the body of the document inside this component.

Implemented using React Portals, you can define static/dynamic header and footer using `<PdfHeader>` and `<PdfFooter>`.

These components can appear anywhere within your JSX structure, although you may follow this convention for a better looking structure:

```tsx
import { PdfDocument, PdfHeader, PdfFooter } from "react-pdfmake-reconciler";

const pdfNode = (
<pdf-text link="https://www.github.com">
GitHub
</pdf-text>
)
<PdfDocument orientation="landscape">
{/* Example static header */}
<PdfHeader>This is a header</PdfHeader>
{/* Example dynmaic footer */}
<PdfFooter>
{(pageNumber, pageCount) => (
<pdf-text>
Page {pageNumber} / {pageCount}
</pdf-text>
)}
</PdfFooter>
{bodyGoesHere}
</PdfDocument>
);
```

There are also virtual element types. For more information, read JSDocs in types.
### PdfPreview

`<PdfPreview>` provides an easy way to render your React PDF Make Reconciler JSX in the browser. You can also debug your PDF JSX using the [React Developer Tools](https://chromewebstore.google.com/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi) browser extension.

```tsx
import { FC, StrictMode } from "react";
import { PdfPreview } from "react-pdfmake-reconciler";

const App: FC = () => (
<div>
<PdfPreview>
{/* Optional */}
<StrictMode>
{/* Only use components that resolves to pdf-* components from here on out. DOM elements won't work. */}
<pdf-text>Hello World!</pdf-text>
</StrictMode>
</PdfPreview>
</div>
);
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
"prettier": "^3.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"typescript": "^5.2.2",
"typescript": "^5.3.2",
"vite": "^5.0.0",
"vite-plugin-dts": "^3.6.3",
"vitest": "^0.34.6"
Expand Down
Loading

0 comments on commit e464ecd

Please sign in to comment.