@veztraa/report-designer
v0.3.3
Published
Embeddable React drag-and-drop PDF report designer — visual canvas, live preview, undo/redo, dark mode, signature element (draw/type/upload), handwriting fonts, multilingual Noto fonts, and data-bound repeating containers.
Maintainers
Readme
@veztraa/report-designer
Embeddable React drag-and-drop PDF report designer for any React app. Features a signature element (draw on pad, type in handwriting font, or upload an image), multilingual text (Chinese, Japanese, Korean, Arabic, Hebrew, Hindi, Thai via Noto fonts), repeating container bands, live PDF preview, 50-step undo/redo, dark mode, and {{field}} data bindings.
Styles auto-inject on mount — no CSS import required.
Installation
npm install @veztraa/report-designerQuick start
import { ReportDesigner } from "@veztraa/report-designer";
// No CSS import needed — styles inject automatically.
export default function App() {
return (
<div style={{ height: "100vh" }}>
<ReportDesigner />
</div>
);
}The designer fills its parent — give the parent a
height(e.g.100vhor a fixed px value).
Load and save templates
Pass an existing template via report (the designer reloads whenever it changes), and capture the user's work via toolbar.onSave, which receives the current template when they click Save:
import { ReportDesigner } from "@veztraa/report-designer";
import type { Template } from "@veztraa/report-core";
export default function ReportEditor({ saved }: { saved: Template }) {
const handleSave = async (template: Template) => {
await fetch("/api/templates", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(template),
});
};
return (
<div style={{ height: "100vh" }}>
<ReportDesigner
report={saved}
data={{ company: { name: "Acme Corp" }, items: [] }}
theme="light"
accentColor="#6c63ff"
toolbar={{ onSave: handleSave }}
/>
</div>
);
}Props
Every prop is optional — <ReportDesigner /> is fully functional with none.
| Prop | Type | Default | Description |
|---|---|---|---|
| report | Template | blank A4 | Template JSON to load. Reloads the designer whenever it changes. |
| data | string \| object | "{}" | Preview data for {{field}} bindings — JSON string or plain object. |
| onDataChange | (data: string) => void | — | Fires when the user edits preview data inside the designer. |
| theme | "light" \| "dark" | "light" | Controlled color theme. Sync with your app's theme toggle. |
| onThemeChange | (t: "light" \| "dark") => void | — | Fires when the user toggles the theme inside the designer. |
| accentColor | string | "#6c63ff" | Primary accent (6-digit hex). All buttons, rings, and indicators derive from it. |
| defaultZoom | number | 1 | Initial canvas zoom (0.25–2.0). Applied once on mount. |
| toolbar | ToolbarConfig | show all | Hide built-in actions, override Save / Load, or add custom buttons. |
| elements | ElementsConfig | all types | Whitelist or blacklist which element types appear in the palette. |
| style | CSSProperties | — | Inline styles for the root container. |
| className | string | — | Extra class names for the root container. |
ToolbarConfig
Passed as the toolbar prop. Every boolean defaults to true (visible).
| Field | Type | Description |
|---|---|---|
| hidden | boolean | Hide the entire toolbar. |
| load / save | boolean | Show the Load / Save buttons. |
| history | boolean | Show Undo / Redo. |
| duplicate / delete | boolean | Show Duplicate / Delete. |
| sections | boolean | Show the Header / Body / Footer switcher. |
| preview | boolean | Show the Preview PDF button. |
| theme / zoom | boolean | Show the theme toggle / zoom controls. |
| onSave | (t: Template) => void | Override Save — receives the current template instead of downloading JSON. |
| onLoad | () => void | Override Load — the default opens a JSON file picker. |
| actions | ToolbarAction[] | Custom buttons injected before the Preview button. |
ElementsConfig
Passed as the elements prop. Use include (whitelist) or exclude (blacklist), not both.
| Field | Type | Description |
|---|---|---|
| hidden | boolean | Hide the Elements palette entirely. |
| include | ElementType[] | Only these types appear, in this order. |
| exclude | ElementType[] | Hide these types (ignored when include is set). |
ElementType is one of: text · richtext · table · container · image · chart · barcode · qrcode · rectangle · line · pagebreak · signature
Features
- Drag-and-drop canvas — snap-to-grid with alignment guides, 8-handle resize, arrow-key nudge
- Live PDF preview rendered off the main thread (Web Worker) — debounced 400ms with an adaptive loading UI, so even large multi-hundred-page reports never freeze the tab
- Repeating containers (data-bound bands) with automatic pagination — tables, rich text, and bands flow across pages, keeping items together where they fit
- Signature element — draw on a pad, type a name in a handwriting font (Great Vibes, Dancing Script, Pacifico, Sacramento), or upload an image; editable after creation
- Multilingual text — set
fontFamilyto any Noto font to render Chinese, Japanese, Korean, Arabic, Hebrew, Hindi, Thai, or Latin/Cyrillic/Greek content in the same PDF - 50-step undo / redo
- Light / dark theme and a fully customizable accent color
- Header, body, and footer sections
- Layers panel with lock / hide / reorder
- Data panel for
{{field}}preview bindings - JSON-first — the designer is a visual editor for a plain
Templateobject; load withreport, save withtoolbar.onSave
Signature element
Add a signature block from the palette (or include type: "signature" in your template). In the Properties panel you can:
- Draw — freehand on a signature pad, then click Use
- Type — enter a name displayed in a handwriting font (Great Vibes, Dancing Script, Pacifico, or Sacramento)
- Upload — paste or upload a signature image (PNG/JPEG)
- Set signer name, title, label, and date sub-fields
- Choose alignment (left / center / right), ink color, and line color
- Toggle the baseline rule on/off
Drawn signatures are stored as base64 PNGs inside the template JSON and render identically in the PDF.
Multilingual support
Set style.fontFamily on any text element to a Noto family to render non-Latin scripts:
| Font family | Script |
|---|---|
| Noto Sans | Latin, Cyrillic, Greek |
| Noto Sans SC | Chinese Simplified |
| Noto Sans JP | Japanese |
| Noto Sans KR | Korean |
| Noto Sans Arabic | Arabic |
| Noto Sans Hebrew | Hebrew |
| Noto Sans Devanagari | Hindi |
| Noto Sans Thai | Thai |
Fonts are loaded from CDN on first use and are available in both the canvas preview and the rendered PDF. CJK fonts include automatic per-character line-breaking.
Keyboard shortcuts
| Shortcut | Action |
|---|---|
| Del / Backspace | Delete selected element |
| Ctrl/Cmd + Z | Undo |
| Ctrl/Cmd + Y (or Ctrl/Cmd + Shift + Z) | Redo |
| Ctrl/Cmd + D | Duplicate selected element |
| Arrow keys | Nudge 1px |
| Shift + Arrows | Nudge 10px |
| Esc | Close the PDF preview |
Template format
See @veztraa/report-core for the full template schema, element types, and expression syntax. Generate PDFs from a template on the server or in the browser with @veztraa/report-renderer.
License
MIT © Veztraa Solutions
