React Logoreact-pdf

react-pdf is a powerful and flexible library that allows developers to create dynamic, data-driven PDF documents using React components. It provides a declarative API, enabling you to define your PDF structure and content in a way very similar to how you build web interfaces with React, but instead of rendering to the HTML DOM, it renders to a PDF document tree.

Core Functionality:
At its heart, react-pdf provides a set of React components (e.g., <Document>, <Page>, <View>, <Text>, <Image>) that correspond to standard PDF elements. You compose these components to build your desired document layout and content. It leverages a styling system inspired by React Native, allowing you to use a StyleSheet API for applying CSS-like properties (including flexbox for layout, colors, fonts, etc.) to your PDF components.

Key Features:
* Declarative API: Build complex PDF layouts and content using familiar React component patterns.
* Styling with StyleSheet: Apply styles using an object-based CSS-in-JS approach, supporting common properties like flexbox for advanced layouts, font styling, colors, and more.
* Cross-platform: Generate PDFs both client-side in the browser (often displayed within an iframe using `PDFViewer`) and server-side using Node.js, making it highly versatile for various application architectures.
* Flexbox Layout: Offers robust layout capabilities with full flexbox support, simplifying the creation of responsive and complex page designs.
* Dynamic Content: Easily integrate data from your application state or props to generate personalized invoices, reports, certificates, or any other data-driven document.
* Custom Fonts and Images: Supports embedding custom TrueType fonts and rendering images within your PDFs.

Use Cases:
* Generating invoices, receipts, and order confirmations.
* Creating custom reports, certificates, and resumes dynamically.
* Providing print-ready versions of web content.
* Any scenario where sophisticated, styled PDF documents need to be created programmatically from a React application.

How it Works:
You define your PDF structure using react-pdf components within a regular React component. You apply styling using `StyleSheet.create()`. To display the PDF in the browser, you typically wrap your document component with `PDFViewer`. For server-side generation or to create a downloadable file, you can use methods like `pdf().toBlob()`, `pdf().toBuffer()`, or `pdf().toStream()` from the `@react-pdf/renderer` package.

Installation:
To get started, you can install the library using npm or yarn:
`npm install @react-pdf/renderer` or `yarn add @react-pdf/renderer`

Example Code

import React from 'react';
import { Page, Text, View, Document, StyleSheet, PDFViewer } from '@react-pdf/renderer';

// Create styles for your document
const styles = StyleSheet.create({
  page: {
    flexDirection: 'column',
    backgroundColor: '#FAFAFA',
    padding: 30,
    fontFamily: 'Helvetica'
  },
  section: {
    margin: 10,
    padding: 10,
    flexGrow: 1,
    borderBottom: '1px solid #EEEEEE'
  },
  header: {
    fontSize: 24,
    marginBottom: 20,
    textAlign: 'center',
    color: '#333',
    fontWeight: 'bold'
  },
  subHeader: {
    fontSize: 16,
    marginBottom: 10,
    color: '#555'
  },
  text: {
    fontSize: 12,
    marginBottom: 5,
    color: '#444'
  },
  strongText: {
    fontSize: 14,
    fontWeight: 'bold',
    marginBottom: 5,
    color: '#222'
  },
  tableRow: {
    flexDirection: 'row',
    borderBottom: '1px solid #EEE',
    paddingVertical: 5,
  },
  tableCol: {
    width: '33%',
    textAlign: 'left',
    paddingHorizontal: 5,
  },
  tableHeader: {
    fontWeight: 'bold',
    fontSize: 12,
    color: '#333'
  }
});

// Create Document Component
const MyInvoiceDocument = ({ invoiceData }) => (
  <Document>
    <Page size="A4" style={styles.page}>
      <View style={styles.section}>
        <Text style={styles.header}>Invoice</Text>
        <Text style={styles.subHeader}>#{invoiceData.invoiceNumber}</Text>
        <Text style={styles.text}>Date: {invoiceData.date}</Text>
      </View>

      <View style={styles.section}>
        <Text style={styles.strongText}>Billed To:</Text>
        <Text style={styles.text}>{invoiceData.customerName}</Text>
        <Text style={styles.text}>{invoiceData.customerAddress.street}</Text>
        <Text style={styles.text}>{invoiceData.customerAddress.city}, {invoiceData.customerAddress.zip}</Text>
      </View>

      <View style={{ ...styles.section, flexGrow: 2 }}>
        <Text style={styles.strongText}>Items:</Text>
        {/* Table Header */}
        <View style={styles.tableRow}>
          <View style={styles.tableCol}><Text style={styles.tableHeader}>Description</Text></View>
          <View style={styles.tableCol}><Text style={styles.tableHeader}>Quantity</Text></View>
          <View style={styles.tableCol}><Text style={styles.tableHeader}>Amount</Text></View>
        </View>
        {/* Table Rows */}
        {invoiceData.items.map((item, index) => (
          <View key={index} style={styles.tableRow}>
            <View style={styles.tableCol}><Text style={styles.text}>{item.description}</Text></View>
            <View style={styles.tableCol}><Text style={styles.text}>{item.quantity}</Text></View>
            <View style={styles.tableCol}><Text style={styles.text}>${item.amount.toFixed(2)}</Text></View>
          </View>
        ))}
      </View>

      <View style={styles.section}>
        <Text style={{ ...styles.strongText, textAlign: 'right' }}>Subtotal: ${invoiceData.subtotal.toFixed(2)}</Text>
        <Text style={{ ...styles.strongText, textAlign: 'right' }}>Tax ({invoiceData.taxRate * 100}%): ${invoiceData.taxAmount.toFixed(2)}</Text>
        <Text style={{ ...styles.header, fontSize: 20, textAlign: 'right', marginTop: 10 }}>Total: ${invoiceData.total.toFixed(2)}</Text>
      </View>

      <View style={{ ...styles.section, marginTop: 'auto', borderBottom: 'none' }}>
        <Text style={{ ...styles.text, textAlign: 'center', color: '#888' }}>
          Thank you for your business! Please pay within 30 days.
        </Text>
      </View>
    </Page>
  </Document>
);

// Example usage in a React component to display the PDF in a viewer
function App() {
  const exampleInvoiceData = {
    invoiceNumber: '2023-10-001',
    date: '2023-10-26',
    customerName: 'Acme Corporation',
    customerAddress: {
      street: '123 Tech Park Ave',
      city: 'Innoville',
      zip: '98765'
    },
    items: [
      { description: 'Premium Software License', quantity: 1, amount: 299.99 },
      { description: 'Consulting Services (10 hrs)', quantity: 10, amount: 150.00 },
      { description: 'On-demand Support Package', quantity: 1, amount: 75.00 }
    ],
    subtotal: 1874.99,
    taxRate: 0.08,
    taxAmount: 149.9992,
    total: 2024.9892
  };

  // Calculate totals properly
  exampleInvoiceData.subtotal = exampleInvoiceData.items.reduce((acc, item) => acc + (item.quantity * item.amount), 0);
  exampleInvoiceData.taxAmount = exampleInvoiceData.subtotal * exampleInvoiceData.taxRate;
  exampleInvoiceData.total = exampleInvoiceData.subtotal + exampleInvoiceData.taxAmount;

  return (
    <div style={{ height: '100vh', display: 'flex', flexDirection: 'column', padding: 20 }}>
      <h1 style={{ textAlign: 'center', color: '#333' }}>React PDF Invoice Generator</h1>
      <p style={{ textAlign: 'center', color: '#666', marginBottom: 20 }}>
        Below is a dynamically generated PDF invoice using the react-pdf library.
      </p>
      <PDFViewer style={{ flex: 1, border: '1px solid #DDD', borderRadius: 8 }}>
        <MyInvoiceDocument invoiceData={exampleInvoiceData} />
      </PDFViewer>
    </div>
  );
}

export default App;