|
|
|
@@ -0,0 +1,422 @@
|
|
|
|
|
export const metadata = { title: "@json-render/react-pdf API" }
|
|
|
|
|
|
|
|
|
|
# @json-render/react-pdf
|
|
|
|
|
|
|
|
|
|
PDF document renderer. Turn JSON specs into PDFs using `@react-pdf/renderer`.
|
|
|
|
|
|
|
|
|
|
## Install
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
npm install @json-render/core @json-render/react-pdf
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
See the [React PDF example](https://github.com/vercel-labs/json-render/tree/main/examples/react-pdf) for a full working example.
|
|
|
|
|
|
|
|
|
|
## schema
|
|
|
|
|
|
|
|
|
|
The PDF element schema for document specs. Use with `defineCatalog` from core.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
import { defineCatalog } from '@json-render/core';
|
|
|
|
|
import { schema, standardComponentDefinitions } from '@json-render/react-pdf';
|
|
|
|
|
|
|
|
|
|
const catalog = defineCatalog(schema, {
|
|
|
|
|
components: standardComponentDefinitions,
|
|
|
|
|
});
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Render Functions
|
|
|
|
|
|
|
|
|
|
Server-side functions for producing PDF output. All accept a spec and optional `RenderOptions`.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
import { renderToBuffer, renderToStream, renderToFile } from '@json-render/react-pdf';
|
|
|
|
|
|
|
|
|
|
const buffer = await renderToBuffer(spec);
|
|
|
|
|
|
|
|
|
|
const stream = await renderToStream(spec);
|
|
|
|
|
stream.pipe(res);
|
|
|
|
|
|
|
|
|
|
await renderToFile(spec, './output.pdf');
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### RenderOptions
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
interface RenderOptions {
|
|
|
|
|
registry?: ComponentRegistry;
|
|
|
|
|
includeStandard?: boolean; // default: true
|
|
|
|
|
state?: Record<string, unknown>;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Option</th>
|
|
|
|
|
<th>Description</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>registry</code></td>
|
|
|
|
|
<td>Custom component map (merged with standard components)</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>includeStandard</code></td>
|
|
|
|
|
<td>Include built-in standard components (default: <code>true</code>)</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>state</code></td>
|
|
|
|
|
<td>Initial state for <code>$state</code> / <code>$cond</code> dynamic prop resolution</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
## defineRegistry
|
|
|
|
|
|
|
|
|
|
Create a type-safe component registry from a catalog. Components receive `{ props, children, emit, bindings, loading }`.
|
|
|
|
|
|
|
|
|
|
```tsx
|
|
|
|
|
import { defineRegistry } from '@json-render/react-pdf';
|
|
|
|
|
import { View, Text } from '@react-pdf/renderer';
|
|
|
|
|
|
|
|
|
|
const { registry } = defineRegistry(catalog, {
|
|
|
|
|
components: {
|
|
|
|
|
Badge: ({ props }) => (
|
|
|
|
|
<View style={{ backgroundColor: props.color ?? '#e5e7eb', padding: 4, borderRadius: 4 }}>
|
|
|
|
|
<Text style={{ fontSize: 10 }}>{props.label}</Text>
|
|
|
|
|
</View>
|
|
|
|
|
),
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const buffer = await renderToBuffer(spec, { registry });
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## createRenderer
|
|
|
|
|
|
|
|
|
|
Create a standalone renderer component wired to state, actions, and validation.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
import { createRenderer } from '@json-render/react-pdf';
|
|
|
|
|
|
|
|
|
|
const PDFRenderer = createRenderer(catalog, components);
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
interface CreateRendererProps {
|
|
|
|
|
spec: Spec | null;
|
|
|
|
|
state?: Record<string, unknown>;
|
|
|
|
|
onAction?: (actionName: string, params?: Record<string, unknown>) => void;
|
|
|
|
|
onStateChange?: (path: string, value: unknown) => void;
|
|
|
|
|
loading?: boolean;
|
|
|
|
|
fallback?: ComponentRenderer;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Renderer
|
|
|
|
|
|
|
|
|
|
The main component that renders a spec to `@react-pdf/renderer` elements.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
interface RendererProps {
|
|
|
|
|
spec: Spec | null;
|
|
|
|
|
registry?: ComponentRegistry;
|
|
|
|
|
includeStandard?: boolean; // default: true
|
|
|
|
|
loading?: boolean;
|
|
|
|
|
fallback?: ComponentRenderer;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Standard Components
|
|
|
|
|
|
|
|
|
|
### Document Structure
|
|
|
|
|
|
|
|
|
|
#### Document
|
|
|
|
|
|
|
|
|
|
Top-level PDF wrapper. Must be the root element. Children must be `Page` components.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
title: string | null;
|
|
|
|
|
author: string | null;
|
|
|
|
|
subject: string | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Page
|
|
|
|
|
|
|
|
|
|
A page in the document with configurable size, orientation, and margins.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
size: "A4" | "A3" | "A5" | "LETTER" | "LEGAL" | "TABLOID" | null;
|
|
|
|
|
orientation: "portrait" | "landscape" | null;
|
|
|
|
|
marginTop: number | null;
|
|
|
|
|
marginBottom: number | null;
|
|
|
|
|
marginLeft: number | null;
|
|
|
|
|
marginRight: number | null;
|
|
|
|
|
backgroundColor: string | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Layout
|
|
|
|
|
|
|
|
|
|
#### View
|
|
|
|
|
|
|
|
|
|
Generic container with padding, margin, background, border, and flex alignment.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
padding: number | null;
|
|
|
|
|
paddingTop: number | null;
|
|
|
|
|
paddingBottom: number | null;
|
|
|
|
|
paddingLeft: number | null;
|
|
|
|
|
paddingRight: number | null;
|
|
|
|
|
margin: number | null;
|
|
|
|
|
backgroundColor: string | null;
|
|
|
|
|
borderWidth: number | null;
|
|
|
|
|
borderColor: string | null;
|
|
|
|
|
borderRadius: number | null;
|
|
|
|
|
flex: number | null;
|
|
|
|
|
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
|
|
|
|
|
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Row
|
|
|
|
|
|
|
|
|
|
Horizontal flex layout with optional wrapping.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
gap: number | null;
|
|
|
|
|
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
|
|
|
|
|
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
|
|
|
|
|
padding: number | null;
|
|
|
|
|
flex: number | null;
|
|
|
|
|
wrap: boolean | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Column
|
|
|
|
|
|
|
|
|
|
Vertical flex layout.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
gap: number | null;
|
|
|
|
|
alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
|
|
|
|
|
justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
|
|
|
|
|
padding: number | null;
|
|
|
|
|
flex: number | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Content
|
|
|
|
|
|
|
|
|
|
#### Heading
|
|
|
|
|
|
|
|
|
|
h1-h4 heading text with configurable color and alignment.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
text: string;
|
|
|
|
|
level: "h1" | "h2" | "h3" | "h4" | null;
|
|
|
|
|
color: string | null;
|
|
|
|
|
align: "left" | "center" | "right" | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Text
|
|
|
|
|
|
|
|
|
|
Body text with full styling control.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
text: string;
|
|
|
|
|
fontSize: number | null;
|
|
|
|
|
color: string | null;
|
|
|
|
|
align: "left" | "center" | "right" | null;
|
|
|
|
|
fontWeight: "normal" | "bold" | null;
|
|
|
|
|
fontStyle: "normal" | "italic" | null;
|
|
|
|
|
lineHeight: number | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Image
|
|
|
|
|
|
|
|
|
|
Image from a URL with optional dimensions and fit.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
src: string;
|
|
|
|
|
width: number | null;
|
|
|
|
|
height: number | null;
|
|
|
|
|
objectFit: "contain" | "cover" | "fill" | "none" | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Link
|
|
|
|
|
|
|
|
|
|
Hyperlink with visible text.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
text: string;
|
|
|
|
|
href: string;
|
|
|
|
|
fontSize: number | null;
|
|
|
|
|
color: string | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Data
|
|
|
|
|
|
|
|
|
|
#### Table
|
|
|
|
|
|
|
|
|
|
Data table with typed columns and string rows. Supports header styling and striped rows.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
columns: { header: string; width?: string; align?: "left" | "center" | "right" }[];
|
|
|
|
|
rows: string[][];
|
|
|
|
|
headerBackgroundColor: string | null;
|
|
|
|
|
headerTextColor: string | null;
|
|
|
|
|
borderColor: string | null;
|
|
|
|
|
fontSize: number | null;
|
|
|
|
|
striped: boolean | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### List
|
|
|
|
|
|
|
|
|
|
Ordered or unordered list.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
items: string[];
|
|
|
|
|
ordered: boolean | null;
|
|
|
|
|
fontSize: number | null;
|
|
|
|
|
color: string | null;
|
|
|
|
|
spacing: number | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Decorative
|
|
|
|
|
|
|
|
|
|
#### Divider
|
|
|
|
|
|
|
|
|
|
Horizontal line separator.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
color: string | null;
|
|
|
|
|
thickness: number | null;
|
|
|
|
|
marginTop: number | null;
|
|
|
|
|
marginBottom: number | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
#### Spacer
|
|
|
|
|
|
|
|
|
|
Empty vertical space.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
height: number | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Page-Level
|
|
|
|
|
|
|
|
|
|
#### PageNumber
|
|
|
|
|
|
|
|
|
|
Renders current page number and total pages. Format uses `{pageNumber}` and `{totalPages}` placeholders.
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
{
|
|
|
|
|
format: string | null; // default: "{pageNumber} / {totalPages}"
|
|
|
|
|
fontSize: number | null;
|
|
|
|
|
color: string | null;
|
|
|
|
|
align: "left" | "center" | "right" | null;
|
|
|
|
|
}
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Server-Safe Import
|
|
|
|
|
|
|
|
|
|
Import schema and catalog definitions without pulling in React or `@react-pdf/renderer`:
|
|
|
|
|
|
|
|
|
|
```typescript
|
|
|
|
|
import { schema, standardComponentDefinitions } from '@json-render/react-pdf/server';
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Sub-path Exports
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Export</th>
|
|
|
|
|
<th>Description</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>@json-render/react-pdf</code></td>
|
|
|
|
|
<td>Full package: schema, renderer, components, render functions</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>@json-render/react-pdf/server</code></td>
|
|
|
|
|
<td>Schema and catalog definitions only (no React)</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>@json-render/react-pdf/catalog</code></td>
|
|
|
|
|
<td>Standard component definitions and types</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>@json-render/react-pdf/render</code></td>
|
|
|
|
|
<td>Server-side render functions only</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
## Types
|
|
|
|
|
|
|
|
|
|
<table>
|
|
|
|
|
<thead>
|
|
|
|
|
<tr>
|
|
|
|
|
<th>Export</th>
|
|
|
|
|
<th>Description</th>
|
|
|
|
|
</tr>
|
|
|
|
|
</thead>
|
|
|
|
|
<tbody>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>ReactPdfSchema</code></td>
|
|
|
|
|
<td>Schema type for PDF specs</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>ReactPdfSpec</code></td>
|
|
|
|
|
<td>Spec type for PDF documents</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>RenderOptions</code></td>
|
|
|
|
|
<td>Options for render functions</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>ComponentContext</code></td>
|
|
|
|
|
<td>Typed component render function context</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>ComponentFn</code></td>
|
|
|
|
|
<td>Component render function type</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>StandardComponentDefinitions</code></td>
|
|
|
|
|
<td>Type of the standard component definitions object</td>
|
|
|
|
|
</tr>
|
|
|
|
|
<tr>
|
|
|
|
|
<td><code>StandardComponentProps<K></code></td>
|
|
|
|
|
<td>Inferred props type for a standard component by name</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</tbody>
|
|
|
|
|
</table>
|