| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422 |
- 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>
|