pdf-tailwind-forms
Version:
TypeScript Node.js library for generating PDFs with AcroForms and TailwindCSS support
479 lines (401 loc) • 11.7 kB
Markdown
# PDF TailwindCSS Forms
A powerful TypeScript library for generating interactive PDF documents with TailwindCSS styling and AcroForm fields.
## Features
- <� **TailwindCSS Integration** - Style your PDFs with modern CSS framework
- =� **Interactive Forms** - Add text fields, checkboxes, dropdowns, and more
- =' **TypeScript Support** - Full type safety and IntelliSense
- =� **Template System** - Pre-built templates for common use cases
- � **Dual Positioning** - CSS selectors or absolute coordinates
- =
**Form Validation** - Built-in validation for configurations
- =� **Batch Processing** - Generate multiple PDFs efficiently
- =� **Data Extraction** - Extract data from existing PDF forms
## Installation
```bash
npm install pdf-tailwind-forms
# or
pnpm add pdf-tailwind-forms
# or
yarn add pdf-tailwind-forms
```
## Quick Start
```typescript
import PDFGenerator from 'pdf-tailwind-forms';
const generator = new PDFGenerator();
// Simple example
const config = {
content: `
<div class="p-8 max-w-md mx-auto bg-white rounded-xl shadow-lg">
<h1 class="text-2xl font-bold mb-4">Contact Form</h1>
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Name</label>
<div class="name-field border p-2 rounded w-full h-10"></div>
</div>
<div class="mb-4">
<label class="block text-sm font-medium mb-2">Email</label>
<div class="email-field border p-2 rounded w-full h-10"></div>
</div>
</div>
`,
fields: [
{
name: 'fullName',
type: 'text',
selector: '.name-field',
required: true
},
{
name: 'email',
type: 'text',
selector: '.email-field',
required: true
}
],
outputPath: './contact-form.pdf'
};
const result = await generator.generate(config);
console.log(`Generated PDF with ${result.fieldCount} fields`);
// Clean up
await generator.destroy();
```
## Core Concepts
### Two-Step Generation Process
This library uses a unique two-step approach:
1. **Visual Layer**: Puppeteer renders your HTML content with TailwindCSS to create a styled PDF
2. **Interactive Layer**: pdf-lib adds AcroForm fields at calculated positions
This separation allows you to focus on design with TailwindCSS while getting fully interactive forms.
### Field Positioning
Fields can be positioned using two methods:
#### CSS Selectors (Recommended)
```typescript
{
name: 'userName',
type: 'text',
selector: '.user-input-field', // Automatically calculates position
offsetX: 5, // Fine-tune position
offsetY: -2
}
```
#### Absolute Positioning
```typescript
{
name: 'userName',
type: 'text',
position: { x: 100, y: 200, width: 200, height: 30 }
}
```
## Field Types
### Text Fields
```typescript
{
name: 'description',
type: 'text',
selector: '.description-field',
multiline: true,
maxLength: 500,
defaultValue: 'Enter description...',
required: true
}
```
### Checkboxes
```typescript
{
name: 'agreeTerms',
type: 'checkbox',
selector: '.terms-checkbox',
defaultValue: false,
size: 16,
required: true
}
```
### Radio Buttons
```typescript
{
name: 'priority',
type: 'radio',
selector: '.priority-group',
options: [
{ value: 'low', label: 'Low Priority' },
{ value: 'medium', label: 'Medium Priority' },
{ value: 'high', label: 'High Priority' }
],
defaultValue: 'medium',
spacing: 25
}
```
### Dropdowns
```typescript
{
name: 'country',
type: 'dropdown',
selector: '.country-select',
options: ['United States', 'Canada', 'Mexico'],
defaultValue: 'United States',
editable: false
}
```
### Buttons
```typescript
{
name: 'submitForm',
type: 'button',
selector: '.submit-btn',
label: 'Submit Form',
action: 'submit'
}
```
### Signature Fields
```typescript
{
name: 'clientSignature',
type: 'signature',
selector: '.signature-area',
height: 60
}
```
## Template System
### Form Template
```typescript
import { createFormTemplate } from 'pdf-tailwind-forms/templates/form';
const formConfig = createFormTemplate({
title: 'Customer Registration',
description: 'Please fill out all required fields',
theme: 'blue',
fields: [
{ label: 'Full Name', name: 'fullName', type: 'text', required: true },
{ label: 'Email Address', name: 'email', type: 'email', required: true },
{ label: 'Phone Number', name: 'phone', type: 'phone' },
{ label: 'Country', name: 'country', type: 'select',
options: ['US', 'CA', 'UK', 'DE', 'FR'] },
{ label: 'Comments', name: 'comments', type: 'textarea' },
{ label: 'Subscribe to newsletter', name: 'newsletter', type: 'checkbox' }
],
submitLabel: 'Register Now'
});
const generator = new PDFGenerator();
const result = await generator.generate(formConfig);
```
### Invoice Template
```typescript
import { createInvoiceTemplate } from 'pdf-tailwind-forms/templates/invoice';
const invoiceConfig = createInvoiceTemplate({
companyName: 'Acme Corporation',
companyAddress: '123 Business Street\nSuite 100\nNew York, NY 10001',
clientName: 'Client Company Inc.',
clientAddress: '456 Client Avenue\nSuite 200\nBoston, MA 02101',
invoiceNumber: 'INV-2024-001',
date: '2024-01-15',
dueDate: '2024-02-15',
items: [
{ description: 'Web Development Services', quantity: 40, price: 125.00 },
{ description: 'Domain Registration', quantity: 1, price: 15.99 },
{ description: 'SSL Certificate', quantity: 1, price: 89.00 }
],
tax: 8.5,
currency: '$'
});
const generator = new PDFGenerator();
const result = await generator.generate(invoiceConfig);
```
## Advanced Features
### Custom Styling
```typescript
const config = {
content: '<div class="custom-form">...</div>',
customCSS: `
.custom-form {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
font-family: 'Inter', sans-serif;
}
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap');
`,
fields: [...],
pdfOptions: {
format: 'A4',
margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' },
displayHeaderFooter: true,
headerTemplate: '<div class="text-xs text-center w-full">Company Name</div>',
footerTemplate: '<div class="text-xs text-center w-full">Page <span class="pageNumber"></span></div>'
}
};
```
### Configuration Validation
```typescript
import { PDFValidator } from 'pdf-tailwind-forms/validator';
const validator = new PDFValidator();
const validation = validator.validate(config);
if (!validation.valid) {
console.error('Configuration errors:', validation.errors);
return;
}
```
### Working with Existing PDFs
```typescript
// Fill an existing PDF form
const filledPDF = await generator.fillExistingPDF(
'./template.pdf',
{
fullName: 'John Doe',
email: 'john@example.com',
agreeTerms: true
},
'./filled-form.pdf'
);
// Extract data from a PDF
const formData = await generator.extractFormData('./submitted-form.pdf');
console.log(formData); // { fullName: 'John Doe', email: 'john@example.com', ... }
```
### Batch Processing
```typescript
const configs = [
{ content: '<div>Form 1</div>', fields: [], outputPath: './form1.pdf' },
{ content: '<div>Form 2</div>', fields: [], outputPath: './form2.pdf' },
{ content: '<div>Form 3</div>', fields: [], outputPath: './form3.pdf' }
];
const results = await generator.generateBatch(configs);
console.log(`Generated ${results.length} PDFs`);
```
## Configuration Options
### PDFGeneratorOptions
```typescript
const generator = new PDFGenerator({
tailwindCDN: 'https://cdn.tailwindcss.com', // Custom TailwindCSS CDN
defaultFontSize: 12, // Default field font size
defaultBorderWidth: 1, // Default field border width
puppeteerOptions: { // Puppeteer configuration
headless: true,
args: ['--no-sandbox']
}
});
```
### PDF Metadata
```typescript
const config = {
content: '...',
fields: [...],
metadata: {
title: 'Customer Registration Form',
author: 'Your Company',
subject: 'Registration',
keywords: ['form', 'registration', 'customer'],
creator: 'PDF TailwindCSS Forms Library'
}
};
```
## Error Handling
The library provides comprehensive error handling:
```typescript
try {
const result = await generator.generate(config);
console.log('Success:', result);
} catch (error) {
if (error.message.includes('selector not found')) {
console.error('CSS selector invalid:', error);
} else if (error.message.includes('validation')) {
console.error('Configuration error:', error);
} else {
console.error('Generation failed:', error);
}
}
```
## Best Practices
### 1. Resource Management
```typescript
// Always clean up resources
const generator = new PDFGenerator();
try {
const result = await generator.generate(config);
// Process result
} finally {
await generator.destroy(); // Important: prevents memory leaks
}
```
### 2. Field Positioning
```typescript
// Use descriptive CSS classes
const content = `
<div class="form-container p-8">
<div class="user-name-input border rounded p-2"></div>
<div class="user-email-input border rounded p-2 mt-4"></div>
</div>
`;
const fields = [
{ name: 'userName', type: 'text', selector: '.user-name-input' },
{ name: 'userEmail', type: 'text', selector: '.user-email-input' }
];
```
### 3. Responsive Design
```typescript
// Use TailwindCSS responsive utilities
const content = `
<div class="p-4 md:p-8 max-w-2xl mx-auto">
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="name-field h-10 border rounded"></div>
<div class="email-field h-10 border rounded"></div>
</div>
</div>
`;
```
### 4. Validation
```typescript
// Always validate before generation
const validator = new PDFValidator();
const validation = validator.validate(config);
if (!validation.valid) {
throw new Error(`Validation failed: ${validation.errors.join(', ')}`);
}
```
## Performance Considerations
- **Reuse Generator Instances**: Create one generator and reuse it for multiple PDFs
- **Batch Operations**: Use `generateBatch()` for multiple PDFs instead of individual calls
- **Resource Cleanup**: Always call `destroy()` when done to prevent memory leaks
- **Selector Efficiency**: Use specific CSS selectors to improve positioning accuracy
## Browser Compatibility
The library uses Puppeteer which supports:
- Chrome/Chromium (recommended)
- All modern CSS features including Flexbox and Grid
- TailwindCSS responsive utilities
- Custom fonts via CSS imports
## TypeScript Support
The library is written in TypeScript and provides complete type definitions:
```typescript
import PDFGenerator, {
GenerateConfig,
FormField,
TextField,
CheckboxField,
PDFMetadata,
GenerationResult
} from 'pdf-tailwind-forms';
// Full type safety
const config: GenerateConfig = {
content: '...',
fields: [] as FormField[],
metadata: {} as PDFMetadata
};
```
## Examples
See the `/examples` directory for complete working examples:
- **Simple Form**: Basic contact form with validation
- **Multi-page Form**: Complex form spanning multiple pages
- **Invoice Generation**: Professional invoice with calculations
- **Spacing Demo**: Field positioning and spacing examples
## Requirements
- Node.js e 18.0.0
- Dependencies automatically installed:
- `pdf-lib` ^1.17.1
- `puppeteer` ^24.18.0
## Development
```bash
# Install dependencies
pnpm install
# Build the library
pnpm run build
# Run tests
pnpm run test
# Watch mode development
pnpm run dev
```
## License
ISC
## Contributing
Issues and pull requests welcome on [GitHub](https://github.com/AbsolumFrAG/pdf-tailwind-forms).