mirror of
https://github.com/pdfme/pdfme.git
synced 2026-06-02 11:17:32 -04:00
* feat(playground): improve jsx authoring starters * refactor(playground): store authoring starters as template assets * fix(playground): address authoring starter review
@pdfme/jsx
Small JSX authoring layer for creating pdfme templates from stacking layout primitives.
/** @jsxImportSource @pdfme/jsx */
import { Document, MultiVariableText, Page, Stack, Text, renderToTemplate } from '@pdfme/jsx';
const { template, inputs } = await renderToTemplate(
<Document margin={{ x: 12, y: 16 }}>
<Page>
<Stack gap={4}>
<Text size={18}>Invoice</Text>
<Text name="customerName">Alice</Text>
<MultiVariableText
name="message"
text="Hello **{name}**, status: `{status}`"
values={{ name: 'Alice **literal**', status: 'draft' }}
textFormat="inline-markdown"
/>
</Stack>
</Page>
</Document>,
);
This package emits regular pdfme Template and inputs values. It does not depend on React;
it provides its own jsx-runtime and jsx-dev-runtime.
renderToTemplate is async because automatic text height measurement may need font data.
MVP constraints
TextandMultiVariableTextheights are measured with pdfme's text/rich text wrapping helpers whenheightis omitted. Pass an explicitheightwhen you need a fixed field box.Text textFormat="inline-markdown"is read-only only. EditableTextvalues use plain content.MultiVariableTextusestextor children as the template string and storesvaluesas the JSON input. Variable names are inferred from{name}placeholders and can also be passed withvariables.Imageusessrcas its initial content and is intended to be self-closing.Svgusessvgor children as its initial content.- With
name,ImageandSvgbecome input-backed schemas; withoutname, they are read-only content. Rectangle,Ellipse, andLineare static visual schemas for backgrounds, dividers, and simple shapes.Documentis the root component for document-level settings and repeated static content. It can containHeader,Footer,Static, andPagechildren.Documentprops are defaults, not deep-merged style objects. If aPagespecifiesmargin,size,orientation, orfont, thatPagevalue replaces theDocumentvalue for that prop. The generated blankbasePdf.paddingcomes from the resolved margin of the first rendered page.HeaderandFooterrender read-only content into blankbasePdf.staticSchema.Headeruses the top margin area andFooteruses the bottom margin area, so body content stays inside thePagemargin frame.Staticis a lower-level repeated overlay that uses full-page coordinates. It is useful for watermarks and other fixed page-coordinate content. CustombasePdfis not supported when document static content is present.
<Document size="A4" margin={{ x: 16, y: 18 }}>
<Header>
<Text height={8}>Header</Text>
</Header>
<Footer>
<Text height={8}>Footer</Text>
</Footer>
<Page>
<Text height={8}>Body</Text>
</Page>
</Document>
Header,Footer, andStaticmust be direct children ofDocument. They are intentionally not allowed insidePage, because they render into document-levelstaticSchemaand are repeated on every page.- Multiple
Staticblocks with the same placement are concatenated in declaration order. Top blocks start at the top of the page; bottom blocks are stacked together in declaration order and anchored to the page bottom, so the last bottom block sits at the page edge. If static content overlaps the header/footer/body areas, pdfme will draw the schemas in static schema order. - Static content currently accepts read-only
Stack,Row,Box,Spacer,Text,Image,Svg,Rectangle,Ellipse, andLinecontent.MultiVariableText,List,Table, input-backed schemas, andPageBreakare rejected. Absolutecan be used insidePage,Header,Footer, topStatic, orBoxas a small manual placement escape hatch. It uses the parent layout frame as its coordinate origin and does not advance the surrounding stack/row flow. Whenwidthorheightis omitted, it uses the remaining parent frame size fromx/y. DirectStack/Rowsupport is intentionally left for later; wrap with an explicit-sizeBoxwhen you need a local manual-placement frame inside flow content.
<Page margin={12}>
<Text height={8}>Body starts here</Text>
<Absolute x={120} y={0} width={60}>
<Text height={6}>Top-right note</Text>
</Absolute>
</Page>
- Layout children can use
margin.StackandRowsupportalignItemsfor simple cross-axis alignment without trying to implement full CSS/Flexbox. StackandRowsupportjustifyContent="start" | "center" | "end" | "space-between"for main-axis spacing.Stackuses this most predictably with an explicitheight;Rowuses it most predictably with an explicitwidth.Stackdefaults toalignItems="stretch"to preserve full-width stacking. Use an explicit childwidthwhen you wantalignItems="center"or"end"to visibly move that child.Rowdefaults toalignItems="start"and intentionally does not support cross-axis stretch yet.- Row children can use
flexGroworflexas a grow weight. Ifwidthis also set, it is used as the basis before remaining width is distributed.flexis only a short alias forflexGrow, not the CSSflexshorthand.
<Row width={120}>
<Text width={20} flex={1}>A</Text>
<Text width={20} flex={3}>B</Text>
</Row>
// A width: 40, B width: 80
flexGrow={0}withoutwidthproduces a zero-width Row child.PageBreakis supported only along aPage/Stack/Boxlayout path. It is rejected insideRow, leaf schemas,List, andTable.- All
Pagenodes in onerenderToTemplatecall must use the same page size, orientation, and margin because a pdfme blankbasePdfhas one shared size and padding. Table columnWeightsare relative column width weights, not millimeter widths. They are normalized to pdfmeheadWidthPercentages, for examplecolumnWeights={[70, 30]}. Missing or invalid weights default to1, so pass one weight per column when you need exact ratios. Earlier beta builds usedwidths; usecolumnWeightsgoing forward.