# JSX (beta) `@pdfme/jsx` lets you author pdfme templates with JSX layout primitives such as `Document`, `Page`, `Stack`, `Row`, `Box`, `Text`, `Table`, `Header`, `Footer`, and `Absolute`. It is an authoring layer only. The output is a normal pdfme `Template` plus `inputs`, so you can pass the result to `generate`, `Designer`, `Form`, or `Viewer` with the usual plugins and fonts. You can try the browser version in the [JSX playground](https://playground.pdfme.com/jsx). The playground includes sample presets and can switch the preview between `Viewer` and `Form`. ## Installation ```bash npm install @pdfme/jsx ``` If you write JSX in TypeScript, configure the JSX runtime: ```json { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "@pdfme/jsx" } } ``` ## Basic Usage ```tsx import { generate } from '@pdfme/generator'; import { text, table } from '@pdfme/schemas'; import { Document, Page, Stack, Text, Table, renderToTemplate } from '@pdfme/jsx'; const { template, inputs } = await renderToTemplate( Invoice Generated from JSX, rendered by pdfme. , ); const pdf = await generate({ template, inputs, plugins: { text, table }, }); ``` ## Layout Primitives - `Document` is the root component for shared page settings and repeated static content. - `Page` creates a page in the generated template. Multiple `Page` nodes become multiple entries in `template.schemas`. If `Page` is inside `Document`, it inherits `size`, `orientation`, `margin`, and `font` from `Document` unless those props are specified on the `Page`. - `Document` props are defaults, not deep-merged style objects. If a `Page` specifies `margin`, `size`, `orientation`, or `font`, that `Page` value replaces the `Document` value for that prop. The generated blank `basePdf.padding` comes from the resolved margin of the first rendered page. - `Stack` lays children vertically. `Row` lays children horizontally. - `Box` adds padding, background, and border around nested content. - `Spacer` reserves empty layout space. - `Header` and `Footer` render repeated static schemas in the top and bottom margin areas of a blank base PDF. `Static` is the lower-level full-page repeated overlay. - `Absolute` is an escape hatch for badges, watermarks, and small overlays. It does not affect flow. The layout API intentionally borrows useful ideas from Flexbox without trying to be CSS-compatible. Use `gap`, `margin`, `alignItems`, `justifyContent`, and `flex` / `flexGrow` for compact templates. `Text`, `MultiVariableText`, `List`, and `Table` can usually omit `height`. JSX measures their initial content while rendering and advances the surrounding `Stack`, `Row`, or `Box`. Use explicit `height` when you want a fixed field, a fixed visual area, or predictable form input box. A `Box` without `height` grows around its children during JSX rendering. ## Schema Components `@pdfme/jsx` currently includes the main static and form-oriented schemas: - `Text` - `MultiVariableText` - `Image` - `Svg` - `Rectangle` - `Ellipse` - `Line` - `List` - `Table` If a component has a `name`, it becomes input-backed by default. If it has no `name`, it is rendered as read-only content. This mirrors the pdfme template data model. Because the output is a normal pdfme template, Designer edits apply to the generated `Template`. JSX is the seed authoring surface; it is not a lossless source format after the template has been edited in Designer. `Table` uses `columnWeights` for relative column sizing. The values are normalized to pdfme `headWidthPercentages`, so `columnWeights={[30, 70]}` means a 30/70 split, not `30mm` / `70mm`. Missing or invalid weights default to `1`, so pass one weight per column when the exact ratio matters. Earlier beta builds used `widths`; use `columnWeights` going forward. ## JSX Playground Beta The playground accepts a function body, not a full module: ```tsx return ( Hello from JSX ); ``` For now, the playground injects pdfme JSX components into the evaluation scope. It runs rendering in a Web Worker, blocks common browser globals, and does not support `import` or `export` statements yet. This keeps the browser sandbox and module resolution small while the API is still beta. For repeated content, prefer `Document` with document-level `Header` / `Footer`: ```tsx return (
Report
{'Page {currentPage} of {totalPages}'}
Body
); ``` To migrate from the earlier beta static API, move `Header` / `Footer` / `Static` out of `Page` and place them directly inside `Document`. `Header` and `Footer` are margin-aware. Their coordinate origin is the page margin area, so they are usually the right choice for titles, page numbers, and repeated document chrome. `Static` uses the full page coordinate system and is intended for advanced overlays such as watermarks, crop marks, or stamps. ## Current Limitations - `@pdfme/jsx` is still beta. Component names and layout details may still be refined. - The playground is intended for trusted examples and experimentation, not for executing untrusted code. - It does not parse CSS and is not a React renderer. Components produce pdfme schema objects. - Full Flexbox features such as `flexWrap`, `flexShrink`, media queries, and CSS percentages are not implemented. - The output is a `Template + inputs` pair. Runtime rendering still depends on the usual pdfme plugins, fonts, and generator/viewer options. - `Header`, `Footer`, and `Static` are supported only as direct children of `Document`. They generate blank `basePdf.staticSchema` and cannot be used with a custom PDF `basePdf`. - If a form input later expands at runtime, a parent `Box` rectangle is not dynamically resized yet. Dynamic parent/child container reflow is a future layout feature.