> ## Documentation Index
> Fetch the complete documentation index at: https://docs.formepdf.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Components

> All Forme React components for PDF generation - Document, Page, View, Text, Image, Table, Row, Cell, Fixed, PageBreak, Svg, QrCode, Barcode, BarChart, LineChart, PieChart, AreaChart, DotPlot, Canvas, and Watermark.

Forme provides 19 components for building PDF documents. All components are imported from `@formepdf/react`.

```tsx theme={null}
import {
  Document, Page, View, Text, Image, Svg, QrCode, Barcode,
  Table, Row, Cell, Fixed, PageBreak, Canvas, Watermark,
  BarChart, LineChart, PieChart, AreaChart, DotPlot,
} from '@formepdf/react';
```

> **Svelte, Vue, or Preact users:** every component below is also exported from [`@formepdf/svelte`](/svelte), [`@formepdf/vue`](/vue), and [`@formepdf/preact`](/preact) with identical props. Swap the import path and the examples carry over unchanged (`.svelte` markup for Svelte; `.vue` single-file components for Vue; Preact JSX for Preact).

***

## Styling

Styles are plain objects passed to the `style` prop. You can write them inline or extract them with `StyleSheet.create()` for TypeScript autocomplete:

```tsx theme={null}
import { StyleSheet } from '@formepdf/react';

const styles = StyleSheet.create({
  heading: { fontSize: 24, fontWeight: 700 },
  body: { fontSize: 10, lineHeight: 1.6 },
});

<Text style={styles.heading}>Title</Text>
```

`StyleSheet.create()` is an identity function. It returns the same object you pass in. Its purpose is to provide autocomplete and type checking on style properties.

***

## Document

Root container for every Forme document. All other components must be descendants of `<Document>`.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `title` | `string` | - | PDF metadata title |
| `author` | `string` | - | PDF metadata author |
| `subject` | `string` | - | PDF metadata subject |
| `creator` | `string` | - | PDF metadata creator application |
| `style` | `Style` | - | Default style for the entire document. Sets global `fontFamily`, `fontSize`, `color`, etc. Inherited by all children. |
| `fonts` | `FontRegistration[]` | - | Custom fonts to register for this document. See [Fonts](/fonts). |

### Example

```tsx theme={null}
<Document title="Quarterly Report" author="Acme Corp" style={{ fontFamily: 'Inter', fontSize: 12 }}>
  <Page size="A4" margin={54}>
    <Text>Hello World</Text>
  </Page>
</Document>
```

Every Forme document starts with `<Document>`. If no `<Page>` children are provided, content uses the default page configuration (Letter size, 54pt margins).

***

## Page

Defines a page boundary with explicit size and margin configuration. Content inside each `<Page>` is laid out independently.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `size` | `"A4"` \| `"Letter"` \| `"Legal"` \| `"A3"` \| `"A5"` \| `"Tabloid"` \| `{ width, height }` | `"Letter"` | Page dimensions. Custom sizes are in points (72 points = 1 inch). |
| `margin` | `number` \| `{ top, right, bottom, left }` | `54` | Page margins in points. A single number applies to all sides. |
| `backgroundImage` | `string` | - | URL or `data:` URI for a page background. Painted behind all content. Identical URLs across pages share a single embedded XObject. |
| `backgroundSize` | `"fill"` \| `"cover"` \| `"contain"` | `"fill"` | How the background image fills the page. `fill` stretches to the page bounds; `cover` and `contain` preserve aspect ratio. |
| `backgroundPosition` | `"center"` \| `"top-left"` \| `"top-right"` \| `"bottom-left"` \| `"bottom-right"` | `"top-left"` | Positioning for `cover` and `contain` modes. |
| `backgroundOpacity` | `number` | `1.0` | Opacity for the background image (0.0 to 1.0). Useful for watermark-style overlays. |

### Example

```tsx theme={null}
{/* Standard Letter page with 1-inch margins */}
<Page size="Letter" margin={72}>
  <Text>US Letter</Text>
</Page>

{/* Custom 4x6 shipping label */}
<Page size={{ width: 288, height: 432 }} margin={16}>
  <Text>Shipping Label</Text>
</Page>

{/* A4 with different margins per side */}
<Page size="A4" margin={{ top: 72, right: 54, bottom: 72, left: 54 }}>
  <Text>A4 with asymmetric margins</Text>
</Page>

{/* Letter page with a logo watermark */}
<Page
  size="Letter"
  margin={54}
  backgroundImage="https://cdn.example.com/logo.png"
  backgroundSize="cover"
  backgroundPosition="center"
  backgroundOpacity={0.08}
>
  <Text>Watermarked content</Text>
</Page>
```

Content that exceeds the page height automatically flows to additional pages with the same size and margins.

***

## View

A flex container, analogous to an HTML `<div>`. Defaults to column layout.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `style` | `Style` | - | CSS-like style properties |
| `wrap` | `boolean` | `true` | Whether this container can break across pages. Set to `false` to keep all children on the same page. |
| `href` | `string` | - | URL to link to. Makes the entire View a clickable link in the PDF. |
| `bookmark` | `string` | - | Adds a PDF outline (bookmark) entry with this label. Readers can jump to this View from the bookmark panel. |

### Example

```tsx theme={null}
{/* Row layout with gap */}
<View style={{ flexDirection: 'row', gap: 12 }}>
  <Text>Left</Text>
  <Text>Right</Text>
</View>

{/* Card that stays on one page */}
<View wrap={false} style={{ padding: 16, backgroundColor: '#f8fafc', borderRadius: 8 }}>
  <Text style={{ fontWeight: 700 }}>Important Card</Text>
  <Text>This content will not split across pages.</Text>
</View>

{/* Absolute positioning */}
<View style={{ position: 'relative', width: 200, height: 80, backgroundColor: '#f1f5f9' }}>
  <Text>Card content</Text>
  <View style={{ position: 'absolute', top: 4, right: 4, padding: 4, backgroundColor: '#ef4444', borderRadius: 4 }}>
    <Text style={{ fontSize: 8, color: '#fff', fontWeight: 700 }}>SALE</Text>
  </View>
</View>
```

Views use flexbox column layout by default. All flex properties (`flexDirection`, `justifyContent`, `alignItems`, `flexWrap`, `gap`, `flexGrow`, `flexShrink`) are supported. Set `position: 'absolute'` to position a View relative to its **nearest positioned ancestor** — an element with `position: 'relative'` or `'absolute'` — or the page content box if there is none. Give the intended container `position: 'relative'` (as the card above does), or the absolute box will resolve against the page.

***

## Text

Renders text content with font properties, colors, and alignment.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `style` | `Style` | - | Typography and color styles |
| `children` | `string \| number \| Text` | - | Text content. Nest `<Text>` inside `<Text>` for inline styling (bold a word, change colors mid-sentence). |
| `href` | `string` | - | URL to link to. Makes this text a clickable link in the PDF. |
| `bookmark` | `string` | - | Adds a PDF outline (bookmark) entry with this label. |

### Example

```tsx theme={null}
{/* Heading */}
<Text style={{ fontSize: 24, fontWeight: 700, color: '#1e293b' }}>
  Invoice #2024-001
</Text>

{/* Body text with line height */}
<Text style={{ fontSize: 10, lineHeight: 1.6, color: '#475569' }}>
  Payment is due within 30 days of the invoice date. Late payments
  are subject to a 1.5% monthly finance charge.
</Text>

{/* Clickable link */}
<Text href="https://example.com" style={{ color: '#2563eb', textDecoration: 'underline' }}>
  Visit our website
</Text>

{/* Bookmark (appears in PDF outline panel) */}
<Text bookmark="Chapter 1" style={{ fontSize: 20, fontWeight: 700 }}>
  Chapter 1: Introduction
</Text>

{/* Inline styling with nested Text */}
<Text style={{ fontSize: 10 }}>
  This sentence has a <Text style={{ fontWeight: 700 }}>bold word</Text> and a{' '}
  <Text style={{ color: '#ef4444' }}>red word</Text> in the middle.
</Text>

{/* Strikethrough pricing */}
<Text style={{ fontSize: 14 }}>
  $42.00 <Text style={{ textDecoration: 'line-through', color: '#94a3b8' }}>$56.00</Text>
</Text>

{/* Dynamic page numbers */}
<Text style={{ fontSize: 9, textAlign: 'center' }}>
  Page {'{{pageNumber}}'} of {'{{totalPages}}'}
</Text>
```

Text wraps automatically based on the available width. Use `{{pageNumber}}` and `{{totalPages}}` placeholders for dynamic page numbering. Nested `<Text>` elements share the same line and can have different styles, which is useful for inline formatting like bold words, colored spans, or strikethrough pricing.

***

## Image

Embeds a JPEG or PNG image. Aspect ratio is preserved when only one dimension is specified.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `src` | `string` | (required) | Image source: base64 data URI (`data:image/png;base64,...`) or file path |
| `width` | `number` | - | Display width in points |
| `height` | `number` | - | Display height in points |
| `style` | `Style` | - | Additional style properties (margin, etc.) |

### Example

```tsx theme={null}
{/* From file path */}
<Image src="./logo.png" width={120} />

{/* From data URI with both dimensions */}
<Image src="data:image/png;base64,iVBOR..." width={200} height={100} />

{/* With margin */}
<Image src="./photo.jpg" width={300} style={{ marginBottom: 16 }} />
```

If only `width` is provided, height is calculated from the image's aspect ratio (and vice versa). Both JPEG and PNG formats are supported, including PNG transparency.

***

## Table

Table container with column definitions. Children should be `<Row>` elements.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `columns` | `ColumnDef[]` | - | Column width definitions |
| `style` | `Style` | - | Style properties for the table container |

### Column width types

| Type | Example | Description |
| - | - | - |
| `{ fraction: number }` | `{ fraction: 0.5 }` | Proportional width (0.5 = 50% of table width) |
| `{ fixed: number }` | `{ fixed: 100 }` | Fixed width in points |
| `"auto"` | `"auto"` | Size to content |

### Example

```tsx theme={null}
<Table columns={[
  { width: { fraction: 0.5 } },
  { width: { fraction: 0.2 } },
  { width: { fraction: 0.15 } },
  { width: { fraction: 0.15 } }
]}>
  <Row header style={{ backgroundColor: '#1e293b' }}>
    <Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Item</Text></Cell>
    <Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Qty</Text></Cell>
    <Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Price</Text></Cell>
    <Cell style={{ padding: 8 }}><Text style={{ color: '#fff', fontWeight: 700 }}>Total</Text></Cell>
  </Row>
  <Row>
    <Cell style={{ padding: 8 }}><Text>Widget</Text></Cell>
    <Cell style={{ padding: 8 }}><Text>5</Text></Cell>
    <Cell style={{ padding: 8 }}><Text>$10.00</Text></Cell>
    <Cell style={{ padding: 8 }}><Text>$50.00</Text></Cell>
  </Row>
</Table>
```

Tables automatically break across pages between rows. Header rows (marked with `header`) are repeated at the top of each continuation page.

***

## Row

A table row. Must be a direct child of `<Table>`.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `header` | `boolean` | `false` | Whether this is a header row. Header rows repeat on every page when a table spans multiple pages. |
| `style` | `Style` | - | Style properties (e.g., `backgroundColor` for alternating rows) |

### Example

```tsx theme={null}
{/* Header row that repeats on page breaks */}
<Row header style={{ backgroundColor: '#f1f5f9' }}>
  <Cell><Text style={{ fontWeight: 700 }}>Name</Text></Cell>
  <Cell><Text style={{ fontWeight: 700 }}>Value</Text></Cell>
</Row>

{/* Alternating row colors */}
<Row style={{ backgroundColor: '#ffffff' }}>
  <Cell><Text>Row 1</Text></Cell>
  <Cell><Text>Value 1</Text></Cell>
</Row>
<Row style={{ backgroundColor: '#f8fafc' }}>
  <Cell><Text>Row 2</Text></Cell>
  <Cell><Text>Value 2</Text></Cell>
</Row>
```

***

## Cell

A table cell inside a `<Row>`.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `colSpan` | `number` | `1` | Number of columns this cell spans |
| `rowSpan` | `number` | `1` | Number of rows this cell spans |
| `style` | `Style` | - | Style properties (padding, background, etc.) |

### Example

```tsx theme={null}
{/* Standard cell */}
<Cell style={{ padding: 8 }}>
  <Text>Cell content</Text>
</Cell>

{/* Spanning two columns */}
<Cell colSpan={2} style={{ padding: 8, backgroundColor: '#f1f5f9' }}>
  <Text>This spans two columns</Text>
</Cell>
```

Cells can contain any Forme element, not just Text.

***

## Svg

Renders inline SVG graphics. Supports basic SVG elements: `rect`, `circle`, `ellipse`, `line`, `polyline`, `polygon`, and `path`. Elements support `opacity`, `fill-opacity`, and `stroke-opacity` attributes with proper inheritance through `<g>` groups.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `width` | `number` | (required) | Display width in points |
| `height` | `number` | (required) | Display height in points |
| `viewBox` | `string` | - | SVG viewBox attribute (e.g., `"0 0 100 100"`) |
| `content` | `string` | - | SVG markup string containing the elements to render |
| `children` | `ReactNode` | - | JSX children as an alternative to `content` |
| `style` | `Style` | - | Additional style properties (margin, etc.) |

Provide either `content` (a raw SVG string) or JSX `children` — not both. If both are provided, `content` takes priority.

### Example — content string

```tsx theme={null}
{/* Simple shapes */}
<Svg width={100} height={100} viewBox="0 0 100 100"
  content='<rect x="10" y="10" width="80" height="80" fill="#3b82f6" rx="8" />' />

{/* Circle with stroke */}
<Svg width={60} height={60} viewBox="0 0 60 60"
  content='<circle cx="30" cy="30" r="25" fill="none" stroke="#1e293b" stroke-width="2" />' />

{/* Path element */}
<Svg width={200} height={100} viewBox="0 0 200 100"
  content='<path d="M10 80 Q 95 10 180 80" fill="none" stroke="#ef4444" stroke-width="3" />' />
```

### Example — JSX children

```tsx theme={null}
{/* Same shapes using JSX syntax */}
<Svg width={100} height={100} viewBox="0 0 100 100">
  <rect x="10" y="10" width="80" height="80" fill="#3b82f6" rx="8" />
</Svg>

{/* Grouped elements with inherited opacity */}
<Svg width={200} height={100} viewBox="0 0 200 100">
  <g opacity="0.5">
    <rect x="10" y="10" width="80" height="80" fill="#3b82f6" />
    <circle cx="150" cy="50" r="40" fill="#ef4444" />
  </g>
</Svg>
```

JSX children are serialized to SVG XML automatically. CamelCase props like `strokeWidth` are converted to their kebab-case SVG equivalents (`stroke-width`).

SVG content is rendered directly into the PDF using native PDF drawing operations, not rasterized. This produces crisp vector output at any zoom level.

***

## QrCode

Renders a QR code from a data string. Output is vector-based (not a raster image), so it stays crisp at any zoom level.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `data` | `string` | (required) | The data to encode (URL, text, etc.) |
| `size` | `number` | - | Display size in points. QR codes are always square. Defaults to the available width. |
| `color` | `string` | `"#000000"` | Color of the dark modules |
| `style` | `Style` | - | Additional style properties (margin, etc.) |

### Example

```tsx theme={null}
{/* QR code linking to a URL */}
<QrCode data="https://formepdf.com" size={100} />

{/* QR code with custom color */}
<QrCode data="https://example.com/order/12345" size={80} color="#1e293b" />

{/* QR code with margin */}
<QrCode data="SKU-9876" size={60} style={{ marginTop: 12 }} />
```

QR codes are rendered as filled rectangles in the PDF — one rectangle per dark module. This is a native vector representation, not an embedded image, which keeps file sizes small and output sharp.

***

## Barcode

Renders a 1D barcode from a data string. Output is vector-based (filled rectangles), crisp at any zoom level.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `data` | `string` | (required) | The data to encode |
| `format` | `"Code128"` \| `"Code39"` \| `"EAN13"` \| `"EAN8"` \| `"Codabar"` | `"Code128"` | Barcode format |
| `width` | `number` | - | Display width in points. Defaults to available width. |
| `height` | `number` | `60` | Bar height in points |
| `color` | `string` | `"#000000"` | Color of the bars |
| `style` | `Style` | - | Additional style properties (margin, etc.) |

### Example

```tsx theme={null}
{/* Code 128 barcode (default format) */}
<Barcode data="ABC-123" width={200} height={50} />

{/* EAN-13 barcode */}
<Barcode data="5901234123457" format="EAN13" width={180} height={60} />

{/* Code 39 with custom color */}
<Barcode data="HELLO" format="Code39" width={250} height={40} color="#1e293b" />
```

Barcodes are rendered as filled rectangles in the PDF — one rectangle per dark bar. Supported formats: Code 128 (general purpose), Code 39 (alphanumeric), EAN-13 (retail products), EAN-8 (small packages), and Codabar (libraries, blood banks).

***

## Fixed

An element that repeats on every page as a header or footer. Reduces the available content area on each page.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `position` | `"header"` \| `"footer"` | (required) | Whether to place at the top or bottom of each page |
| `style` | `Style` | - | Style properties |

### Example

```tsx theme={null}
<Page size="Letter" margin={54}>
  <Fixed position="header">
    <View style={{ flexDirection: 'row', justifyContent: 'space-between', paddingBottom: 8, borderWidth: { top: 0, right: 0, bottom: 1, left: 0 }, borderColor: '#e2e8f0' }}>
      <Text style={{ fontSize: 10, fontWeight: 700 }}>Acme Corp</Text>
      <Text style={{ fontSize: 10, color: '#64748b' }}>Confidential</Text>
    </View>
  </Fixed>

  <Fixed position="footer">
    <Text style={{ fontSize: 9, textAlign: 'center', color: '#94a3b8' }}>
      Page {'{{pageNumber}}'} of {'{{totalPages}}'}
    </Text>
  </Fixed>

  {/* Page content goes here */}
  <Text>This content area is reduced by the header and footer heights.</Text>
</Page>
```

Use `{{pageNumber}}` and `{{totalPages}}` placeholders inside Fixed elements for automatic page numbering.

***

## PageBreak

Forces content after this element to start on a new page.

### Props

None.

### Example

```tsx theme={null}
<Text>This is on page 1.</Text>
<PageBreak />
<Text>This is on page 2.</Text>
```

PageBreak is useful for separating document sections (e.g., cover page from content, or chapters from each other).

***

## Canvas

Renders arbitrary vector graphics via a `draw` callback. The callback receives a recording context with a Canvas-like API. All drawing commands are serialized and rendered as native PDF vector operations.

### Props

| Prop | Type | Description |
| - | - | - |
| `width` | `number` | Canvas width in points. |
| `height` | `number` | Canvas height in points. |
| `draw` | `(ctx: CanvasContext) => void` | Drawing callback. |

### CanvasContext methods

`moveTo(x, y)`, `lineTo(x, y)`, `line(x1, y1, x2, y2)`, `bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)`, `quadraticCurveTo(cpx, cpy, x, y)`, `arc(cx, cy, r, startAngle, endAngle, counterclockwise?)`, `circle(cx, cy, r)`, `rect(x, y, w, h)`, `ellipse(cx, cy, rx, ry)`, `closePath()`, `stroke()`, `fill()`, `setFillColor(r, g, b)`, `setStrokeColor(r, g, b)`, `setLineWidth(w)`, `setLineCap(cap)`, `setLineJoin(join)`, `save()`, `restore()`.

`line(x1, y1, x2, y2)` is a convenience that emits `moveTo` + `lineTo` + `stroke` in one call.

Colors use 0-255 RGB values (like HTML Canvas). Content is clipped to the canvas bounds (matching HTML Canvas behavior).

### Example

```tsx theme={null}
<Canvas
  width={200}
  height={100}
  draw={(ctx) => {
    ctx.setFillColor(59, 130, 246);
    ctx.rect(10, 10, 80, 80);
    ctx.fill();

    ctx.setStrokeColor(15, 23, 42);
    ctx.setLineWidth(2);
    ctx.arc(150, 50, 40, 0, Math.PI * 2);
    ctx.stroke();
  }}
/>
```

***

## BarChart

Engine-native bar chart rendered directly to PDF vector graphics.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `width` | `number` | — | Chart width in points. |
| `height` | `number` | — | Chart height in points. |
| `data` | `ChartDataPoint[]` | — | Data points (`{ label, value, color? }`). |
| `color` | `string` | `'#1a365d'` | Default bar color (hex). Per-item `color` overrides this. |
| `showLabels` | `boolean` | `true` | Show category labels on the X axis. |
| `showGrid` | `boolean` | `false` | Show horizontal grid lines. |
| `showValues` | `boolean` | `false` | Show value labels above bars. |
| `title` | `string` | — | Chart title displayed above the chart. |

### Example

```tsx theme={null}
<BarChart
  width={400}
  height={200}
  data={[
    { label: 'Jan', value: 42 },
    { label: 'Feb', value: 58 },
    { label: 'Mar', value: 45 },
  ]}
  color="#3b82f6"
  showGrid
  showValues
/>
```

***

## LineChart

Engine-native multi-series line chart with optional data points and grid.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `width` | `number` | — | Chart width in points. |
| `height` | `number` | — | Chart height in points. |
| `series` | `ChartSeries[]` | — | Data series (`{ name, data: number[], color? }`). |
| `labels` | `string[]` | — | X-axis labels (one per data point). |
| `showPoints` | `boolean` | `false` | Show dots at data points. |
| `showGrid` | `boolean` | `false` | Show horizontal grid lines. |
| `title` | `string` | — | Chart title. |

### Example

```tsx theme={null}
<LineChart
  width={400}
  height={200}
  series={[
    { name: 'Revenue', data: [120, 190, 160, 220], color: '#3b82f6' },
    { name: 'Expenses', data: [80, 110, 95, 130], color: '#ef4444' },
  ]}
  labels={['Q1', 'Q2', 'Q3', 'Q4']}
  showGrid
  showPoints
/>
```

***

## PieChart

Engine-native pie or donut chart with optional legend.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `width` | `number` | — | Chart width in points. |
| `height` | `number` | — | Chart height in points. |
| `data` | `ChartDataPoint[]` | — | Slices (`{ label, value, color? }`). Each slice should have a `color`. |
| `donut` | `boolean` | `false` | Cut out the center to create a donut chart. |
| `showLegend` | `boolean` | `false` | Show a legend beside the chart. |
| `title` | `string` | — | Chart title. |

### Example

```tsx theme={null}
<PieChart
  width={200}
  height={200}
  data={[
    { label: 'Product', value: 42, color: '#3b82f6' },
    { label: 'Services', value: 28, color: '#0f172a' },
    { label: 'Other', value: 30, color: '#cbd5e1' },
  ]}
  donut
  showLegend
/>
```

***

## AreaChart

Engine-native multi-series area chart — like LineChart with semi-transparent fill under each line.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `width` | `number` | — | Chart width in points. |
| `height` | `number` | — | Chart height in points. |
| `series` | `ChartSeries[]` | — | Data series (`{ name, data: number[], color? }`). |
| `labels` | `string[]` | — | X-axis labels. |
| `showGrid` | `boolean` | `false` | Show horizontal grid lines. |
| `title` | `string` | — | Chart title. |

### Example

```tsx theme={null}
<AreaChart
  width={400}
  height={200}
  series={[
    { name: 'Organic', data: [500, 800, 1200, 1800], color: '#3b82f6' },
    { name: 'Paid', data: [200, 400, 600, 900], color: '#f59e0b' },
  ]}
  labels={['Q1', 'Q2', 'Q3', 'Q4']}
  showGrid
  title="Traffic Sources"
/>
```

***

## DotPlot

Engine-native scatter plot for (x, y) data with multiple groups.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `width` | `number` | — | Chart width in points. |
| `height` | `number` | — | Chart height in points. |
| `groups` | `DotPlotGroup[]` | — | Groups (`{ name, color?, data: [x, y][] }`). |
| `xMin` / `xMax` | `number` | auto | X-axis range. |
| `yMin` / `yMax` | `number` | auto | Y-axis range. |
| `xLabel` | `string` | — | X-axis label. |
| `yLabel` | `string` | — | Y-axis label. |
| `showLegend` | `boolean` | `false` | Show legend. |
| `dotSize` | `number` | `4` | Dot radius in points. |

### Example

```tsx theme={null}
<DotPlot
  width={300}
  height={200}
  groups={[
    { name: 'API v1', color: '#3b82f6', data: [[10, 45], [50, 120], [100, 230]] },
    { name: 'API v2', color: '#10b981', data: [[10, 25], [50, 60], [100, 110]] },
  ]}
  xLabel="Requests"
  yLabel="Latency (ms)"
  showLegend
/>
```

***

## Watermark

Renders rotated text behind all page content. Automatically repeated on every page.

### Props

| Prop | Type | Default | Description |
| - | - | - | - |
| `text` | `string` | — | Watermark text. |
| `fontSize` | `number` | `60` | Font size in points. |
| `color` | `string` | `'rgba(0,0,0,0.1)'` | Text color (supports `rgba()`). |
| `angle` | `number` | `-45` | Rotation angle in degrees. |

### Example

```tsx theme={null}
<Page size="Letter" margin={54}>
  <Watermark text="DRAFT" fontSize={72} color="rgba(0,0,0,0.05)" angle={-45} />
  <Text>Document content here...</Text>
</Page>
```

***

## Forms

Forme supports AcroForm components for creating fillable PDF forms. See the [Forms](/forms) page for full documentation.

| Component | Description |
| - | - |
| `<TextField>` | Text input field. Supports multiline, password, read-only. |
| `<Checkbox>` | Checkbox with checked/unchecked state. |
| `<Dropdown>` | Select dropdown with predefined options. |
| `<RadioButton>` | Radio button, grouped by shared name. |
