page.mdx 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. import { pageMetadata } from "@/lib/page-metadata"
  2. export const metadata = pageMetadata("docs/api/react-pdf")
  3. # @json-render/react-pdf
  4. PDF document renderer. Turn JSON specs into PDFs using `@react-pdf/renderer`.
  5. ## Install
  6. ```bash
  7. npm install @json-render/core @json-render/react-pdf
  8. ```
  9. See the [React PDF example](https://github.com/vercel-labs/json-render/tree/main/examples/react-pdf) for a full working example.
  10. ## schema
  11. The PDF element schema for document specs. Use with `defineCatalog` from core.
  12. ```typescript
  13. import { defineCatalog } from '@json-render/core';
  14. import { schema, standardComponentDefinitions } from '@json-render/react-pdf';
  15. const catalog = defineCatalog(schema, {
  16. components: standardComponentDefinitions,
  17. });
  18. ```
  19. ## Render Functions
  20. Server-side functions for producing PDF output. All accept a spec and optional `RenderOptions`.
  21. ```typescript
  22. import { renderToBuffer, renderToStream, renderToFile } from '@json-render/react-pdf';
  23. const buffer = await renderToBuffer(spec);
  24. const stream = await renderToStream(spec);
  25. stream.pipe(res);
  26. await renderToFile(spec, './output.pdf');
  27. ```
  28. ### RenderOptions
  29. ```typescript
  30. interface RenderOptions {
  31. registry?: ComponentRegistry;
  32. includeStandard?: boolean; // default: true
  33. state?: Record<string, unknown>;
  34. }
  35. ```
  36. <table>
  37. <thead>
  38. <tr>
  39. <th>Option</th>
  40. <th>Description</th>
  41. </tr>
  42. </thead>
  43. <tbody>
  44. <tr>
  45. <td><code>registry</code></td>
  46. <td>Custom component map (merged with standard components)</td>
  47. </tr>
  48. <tr>
  49. <td><code>includeStandard</code></td>
  50. <td>Include built-in standard components (default: <code>true</code>)</td>
  51. </tr>
  52. <tr>
  53. <td><code>state</code></td>
  54. <td>Initial state for <code>$state</code> / <code>$cond</code> dynamic prop resolution</td>
  55. </tr>
  56. </tbody>
  57. </table>
  58. ## defineRegistry
  59. Create a type-safe component registry from a catalog. Components receive `{ props, children, emit, bindings, loading }`.
  60. ```tsx
  61. import { defineRegistry } from '@json-render/react-pdf';
  62. import { View, Text } from '@react-pdf/renderer';
  63. const { registry } = defineRegistry(catalog, {
  64. components: {
  65. Badge: ({ props }) => (
  66. <View style={{ backgroundColor: props.color ?? '#e5e7eb', padding: 4, borderRadius: 4 }}>
  67. <Text style={{ fontSize: 10 }}>{props.label}</Text>
  68. </View>
  69. ),
  70. },
  71. });
  72. const buffer = await renderToBuffer(spec, { registry });
  73. ```
  74. ## createRenderer
  75. Create a standalone renderer component wired to state, actions, and validation.
  76. ```typescript
  77. import { createRenderer } from '@json-render/react-pdf';
  78. const PDFRenderer = createRenderer(catalog, components);
  79. ```
  80. ```typescript
  81. interface CreateRendererProps {
  82. spec: Spec | null;
  83. state?: Record<string, unknown>;
  84. onAction?: (actionName: string, params?: Record<string, unknown>) => void;
  85. onStateChange?: (path: string, value: unknown) => void;
  86. loading?: boolean;
  87. fallback?: ComponentRenderer;
  88. }
  89. ```
  90. ## Renderer
  91. The main component that renders a spec to `@react-pdf/renderer` elements.
  92. ```typescript
  93. interface RendererProps {
  94. spec: Spec | null;
  95. registry?: ComponentRegistry;
  96. includeStandard?: boolean; // default: true
  97. loading?: boolean;
  98. fallback?: ComponentRenderer;
  99. }
  100. ```
  101. ## Standard Components
  102. ### Document Structure
  103. #### Document
  104. Top-level PDF wrapper. Must be the root element. Children must be `Page` components.
  105. ```typescript
  106. {
  107. title: string | null;
  108. author: string | null;
  109. subject: string | null;
  110. }
  111. ```
  112. #### Page
  113. A page in the document with configurable size, orientation, and margins.
  114. ```typescript
  115. {
  116. size: "A4" | "A3" | "A5" | "LETTER" | "LEGAL" | "TABLOID" | null;
  117. orientation: "portrait" | "landscape" | null;
  118. marginTop: number | null;
  119. marginBottom: number | null;
  120. marginLeft: number | null;
  121. marginRight: number | null;
  122. backgroundColor: string | null;
  123. }
  124. ```
  125. ### Layout
  126. #### View
  127. Generic container with padding, margin, background, border, and flex alignment.
  128. ```typescript
  129. {
  130. padding: number | null;
  131. paddingTop: number | null;
  132. paddingBottom: number | null;
  133. paddingLeft: number | null;
  134. paddingRight: number | null;
  135. margin: number | null;
  136. backgroundColor: string | null;
  137. borderWidth: number | null;
  138. borderColor: string | null;
  139. borderRadius: number | null;
  140. flex: number | null;
  141. alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
  142. justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
  143. }
  144. ```
  145. #### Row
  146. Horizontal flex layout with optional wrapping.
  147. ```typescript
  148. {
  149. gap: number | null;
  150. alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
  151. justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
  152. padding: number | null;
  153. flex: number | null;
  154. wrap: boolean | null;
  155. }
  156. ```
  157. #### Column
  158. Vertical flex layout.
  159. ```typescript
  160. {
  161. gap: number | null;
  162. alignItems: "flex-start" | "center" | "flex-end" | "stretch" | null;
  163. justifyContent: "flex-start" | "center" | "flex-end" | "space-between" | "space-around" | null;
  164. padding: number | null;
  165. flex: number | null;
  166. }
  167. ```
  168. ### Content
  169. #### Heading
  170. h1-h4 heading text with configurable color and alignment.
  171. ```typescript
  172. {
  173. text: string;
  174. level: "h1" | "h2" | "h3" | "h4" | null;
  175. color: string | null;
  176. align: "left" | "center" | "right" | null;
  177. }
  178. ```
  179. #### Text
  180. Body text with full styling control.
  181. ```typescript
  182. {
  183. text: string;
  184. fontSize: number | null;
  185. color: string | null;
  186. align: "left" | "center" | "right" | null;
  187. fontWeight: "normal" | "bold" | null;
  188. fontStyle: "normal" | "italic" | null;
  189. lineHeight: number | null;
  190. }
  191. ```
  192. #### Image
  193. Image from a URL with optional dimensions and fit.
  194. ```typescript
  195. {
  196. src: string;
  197. width: number | null;
  198. height: number | null;
  199. objectFit: "contain" | "cover" | "fill" | "none" | null;
  200. }
  201. ```
  202. #### Link
  203. Hyperlink with visible text.
  204. ```typescript
  205. {
  206. text: string;
  207. href: string;
  208. fontSize: number | null;
  209. color: string | null;
  210. }
  211. ```
  212. ### Data
  213. #### Table
  214. Data table with typed columns and string rows. Supports header styling and striped rows.
  215. ```typescript
  216. {
  217. columns: { header: string; width?: string; align?: "left" | "center" | "right" }[];
  218. rows: string[][];
  219. headerBackgroundColor: string | null;
  220. headerTextColor: string | null;
  221. borderColor: string | null;
  222. fontSize: number | null;
  223. striped: boolean | null;
  224. }
  225. ```
  226. #### List
  227. Ordered or unordered list.
  228. ```typescript
  229. {
  230. items: string[];
  231. ordered: boolean | null;
  232. fontSize: number | null;
  233. color: string | null;
  234. spacing: number | null;
  235. }
  236. ```
  237. ### Decorative
  238. #### Divider
  239. Horizontal line separator.
  240. ```typescript
  241. {
  242. color: string | null;
  243. thickness: number | null;
  244. marginTop: number | null;
  245. marginBottom: number | null;
  246. }
  247. ```
  248. #### Spacer
  249. Empty vertical space.
  250. ```typescript
  251. {
  252. height: number | null;
  253. }
  254. ```
  255. ### Page-Level
  256. #### PageNumber
  257. Renders current page number and total pages. Format uses `{pageNumber}` and `{totalPages}` placeholders.
  258. ```typescript
  259. {
  260. format: string | null; // default: "{pageNumber} / {totalPages}"
  261. fontSize: number | null;
  262. color: string | null;
  263. align: "left" | "center" | "right" | null;
  264. }
  265. ```
  266. ## Server-Safe Import
  267. Import schema and catalog definitions without pulling in React or `@react-pdf/renderer`:
  268. ```typescript
  269. import { schema, standardComponentDefinitions } from '@json-render/react-pdf/server';
  270. ```
  271. ## Sub-path Exports
  272. <table>
  273. <thead>
  274. <tr>
  275. <th>Export</th>
  276. <th>Description</th>
  277. </tr>
  278. </thead>
  279. <tbody>
  280. <tr>
  281. <td><code>@json-render/react-pdf</code></td>
  282. <td>Full package: schema, renderer, components, render functions</td>
  283. </tr>
  284. <tr>
  285. <td><code>@json-render/react-pdf/server</code></td>
  286. <td>Schema and catalog definitions only (no React)</td>
  287. </tr>
  288. <tr>
  289. <td><code>@json-render/react-pdf/catalog</code></td>
  290. <td>Standard component definitions and types</td>
  291. </tr>
  292. <tr>
  293. <td><code>@json-render/react-pdf/render</code></td>
  294. <td>Server-side render functions only</td>
  295. </tr>
  296. </tbody>
  297. </table>
  298. ## Types
  299. <table>
  300. <thead>
  301. <tr>
  302. <th>Export</th>
  303. <th>Description</th>
  304. </tr>
  305. </thead>
  306. <tbody>
  307. <tr>
  308. <td><code>ReactPdfSchema</code></td>
  309. <td>Schema type for PDF specs</td>
  310. </tr>
  311. <tr>
  312. <td><code>ReactPdfSpec</code></td>
  313. <td>Spec type for PDF documents</td>
  314. </tr>
  315. <tr>
  316. <td><code>RenderOptions</code></td>
  317. <td>Options for render functions</td>
  318. </tr>
  319. <tr>
  320. <td><code>ComponentContext</code></td>
  321. <td>Typed component render function context</td>
  322. </tr>
  323. <tr>
  324. <td><code>ComponentFn</code></td>
  325. <td>Component render function type</td>
  326. </tr>
  327. <tr>
  328. <td><code>StandardComponentDefinitions</code></td>
  329. <td>Type of the standard component definitions object</td>
  330. </tr>
  331. <tr>
  332. <td><code>StandardComponentProps&lt;K&gt;</code></td>
  333. <td>Inferred props type for a standard component by name</td>
  334. </tr>
  335. </tbody>
  336. </table>