Skip to content

Print preview, PDF export, and React integration - all in one tiny package

License

Notifications You must be signed in to change notification settings

ersinkoc/PrintKit

Repository files navigation

PrintKit

Zero-dependency print management toolkit for web applications

Print preview, PDF export, and React integration - all in one tiny package

npm version bundle size license TypeScript


Features

Feature Description
Print Anything Elements, HTML strings, URLs, images, JSON, tables
Print Preview Modal with zoom, navigation, and keyboard shortcuts
PDF Export Download, Blob, Base64, Data URL - no external deps
Page Layouts A3, A4, A5, Letter, Legal, Tabloid, custom sizes
Headers/Footers Template strings with {page}, {pages}, {title}, {date}
Page Breaks CSS classes and programmatic control
Print Queue Batch printing with priority and retry
React Integration Hooks (usePrint, usePDF) and Components
Zero Dependencies No runtime dependencies
Tiny Bundle < 40KB minified

Installation

npm install @oxog/printkit

Quick Start

Basic Printing

import { createPrinter } from '@oxog/printkit'

const printer = createPrinter()

// Print an element
await printer.print('#invoice')

// Print with options
await printer.print('#report', {
  title: 'Sales Report',
  pageSize: 'A4',
  orientation: 'landscape',
  header: 'Confidential',
  footer: 'Page {page} of {pages}'
})

Print Preview

import { createPrintPreview } from '@oxog/printkit'

const preview = createPrintPreview('#content', {
  pageSize: 'A4',
  modal: { zoom: 75 }
})

preview.open()      // Open preview modal
preview.zoomIn()    // Zoom controls
preview.print()     // Print from preview
preview.download()  // Download as PDF
preview.close()     // Close modal

PDF Export

import { createPDFExporter } from '@oxog/printkit'

const pdf = createPDFExporter()

// Download as PDF file
await pdf.download('#content', 'document.pdf')

// Get as Blob (for upload, etc.)
const blob = await pdf.toBlob('#content')

// Get as Base64
const base64 = await pdf.toBase64('#content')

// Get as Data URL
const dataUrl = await pdf.toDataURL('#content')

React Integration

import { 
  PrintProvider, 
  usePrint, 
  usePDF,
  PrintButton,
  Printable,
  PageBreak,
  NoPrint,
  PrintOnly
} from '@oxog/printkit/react'

function App() {
  return (
    <PrintProvider defaultOptions={{ pageSize: 'A4' }}>
      <Invoice />
    </PrintProvider>
  )
}

function Invoice() {
  const { print, isPrinting } = usePrint()
  const { download, isExporting } = usePDF()
  const contentRef = useRef(null)

  return (
    <div>
      <NoPrint>
        <button onClick={() => print(contentRef.current)}>
          {isPrinting ? 'Printing...' : 'Print'}
        </button>
        <button onClick={() => download(contentRef.current, 'invoice.pdf')}>
          {isExporting ? 'Exporting...' : 'Download PDF'}
        </button>
      </NoPrint>

      <Printable ref={contentRef}>
        <h1>Invoice #12345</h1>
        <p>Content here...</p>
        
        <PageBreak />
        
        <h2>Page 2</h2>
        <p>More content...</p>
        
        <PrintOnly>
          <p>Printed on: {new Date().toLocaleDateString()}</p>
        </PrintOnly>
      </Printable>
    </div>
  )
}

React Hooks

Hook Description
usePrint() Print with loading/error states
usePDF() PDF export with progress tracking
usePrintPreview() Control preview modal
usePrintContext() Access global print options

React Components

Component Description
<PrintProvider> Context provider for global options
<Printable> Wrapper with ref-based print control
<PrintButton> Customizable print trigger
<PrintPreview> Preview modal component
<PageBreak> Insert page break
<NoPrint> Hide content when printing
<PrintOnly> Show only when printing

Print Methods

const printer = createPrinter()

// Print element by selector or reference
await printer.print('#content')
await printer.print(document.getElementById('content'))

// Print HTML string
await printer.printHTML('<h1>Hello World</h1>')

// Print from URL
await printer.printURL('/report.html')

// Print image
await printer.printImage('/chart.png')
await printer.printImages(['/chart1.png', '/chart2.png'])

// Print JSON with syntax highlighting
await printer.printJSON({ user: 'John', age: 30 }, { 
  syntaxHighlight: true 
})

// Print table
await printer.printTable({
  headers: ['Name', 'Email', 'Role'],
  rows: [
    ['John Doe', 'john@example.com', 'Admin'],
    ['Jane Smith', 'jane@example.com', 'User']
  ]
})

Print Queue

import { createPrintQueue } from '@oxog/printkit'

const queue = createPrintQueue({ concurrency: 1 })

// Add jobs
queue.add({ content: '#invoice1', priority: 'high' })
queue.add({ content: '#invoice2', priority: 'normal' })
queue.add({ content: '#invoice3', priority: 'low' })

// Event listeners
queue.on('jobStart', (job) => console.log('Started:', job.id))
queue.on('jobComplete', (job) => console.log('Done:', job.id))
queue.on('jobError', (job, error) => console.error('Failed:', error))

// Process queue
await queue.printAll()

// Or process one by one
await queue.printNext()

Configuration Options

interface PrintOptions {
  // Document
  title?: string
  pageSize?: 'A3' | 'A4' | 'A5' | 'Letter' | 'Legal' | 'Tabloid' | { width, height }
  orientation?: 'portrait' | 'landscape'
  
  // Margins (number = mm, or use '1in', '2cm', etc.)
  margin?: number | { top, right, bottom, left }
  
  // Header/Footer (string or function)
  header?: string | ((info: PageInfo) => string)
  footer?: string | ((info: PageInfo) => string)
  // Placeholders: {page}, {pages}, {title}, {date}, {time}
  
  // Styling
  styles?: string | string[]      // Custom CSS
  styleSheets?: string[]          // External stylesheets
  copyStyles?: boolean            // Copy page styles (default: true)
  printBackground?: boolean       // Print backgrounds (default: true)
  
  // Page breaks (CSS selectors)
  pageBreakBefore?: string        // e.g., '.chapter'
  pageBreakAfter?: string         // e.g., '.section-end'
  avoidBreakInside?: string       // e.g., '.card, table'
  
  // Callbacks
  onBeforePrint?: () => void | Promise<void>
  onAfterPrint?: () => void
  onError?: (error: PrintError) => void
  onProgress?: (percent: number) => void  // PDF export only
}

CSS Classes

PrintKit provides utility classes for print control:

<!-- Hide when printing -->
<nav class="print-hide">Navigation</nav>

<!-- Show only when printing -->
<div class="print-only">Printed on: 2024-01-01</div>

<!-- Page breaks -->
<div class="print-break-before">Starts on new page</div>
<div class="print-break-after">Next content on new page</div>
<div class="print-avoid-break">Keep together on same page</div>

Utility Functions

import {
  // Detection
  isPrintSupported,
  isPDFSupported,
  isBrowser,
  
  // Page breaks
  pageBreak,           // Create page break element
  avoidBreak,          // Mark element to avoid breaks
  breakBefore,         // Mark element to break before
  breakAfter,          // Mark element to break after
  
  // Page dimensions
  getPageDimensions,
  getPagePixelDimensions,
  
  // Style injection
  injectPrintStyles,
  removePrintStyles,
  removeAllPrintStyles,
  
  // Constants
  PAGE_SIZES,          // { A4: {...}, Letter: {...}, ... }
  PRINT_HIDE_CLASS,    // 'print-hide'
  PRINT_ONLY_CLASS,    // 'print-only'
} from '@oxog/printkit'

Browser Support

Browser Version
Chrome 80+
Firefox 75+
Safari 13.1+
Edge 80+

TypeScript

PrintKit is written in TypeScript and provides full type definitions:

import type {
  PrintOptions,
  PDFOptions,
  PreviewOptions,
  PrintTarget,
  PageSize,
  Orientation,
  Printer,
  PDFExporter,
  PrintQueue,
  PrintJob,
} from '@oxog/printkit'

Documentation

For detailed documentation, visit printkit.oxog.dev

Contributing

Contributions are welcome! Please read CONTRIBUTING.md for guidelines.

License

MIT - see LICENSE for details.


Made with care by Ersin KOC

About

Print preview, PDF export, and React integration - all in one tiny package

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages