npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-acroform

v1.0.1

Published

React component for rendering PDFs with full AcroForm support and bi-directional data binding

Readme

react-acroform

A React component library for rendering PDFs with full AcroForm support, enabling bi-directional data binding between PDF form fields and React state.

Features

  • Render PDFs using Mozilla's PDF.js
  • Full AcroForm support (text fields, checkboxes, radio buttons, dropdowns, signatures)
  • Bi-directional data binding between PDF fields and React state
  • Page navigation with thumbnail sidebar
  • Zoom controls
  • PDF export with filled form data
  • Field name aliasing for friendly API
  • TypeScript support with full type definitions

Installation

npm install react-acroform pdfjs-dist

Basic Usage

import { PDFViewer } from 'react-acroform';

function App() {
  const [formData, setFormData] = useState({});

  const handleChange = (fieldName, value, allValues) => {
    setFormData(allValues);
    console.log(`Field "${fieldName}" changed to:`, value);
  };

  return (
    <PDFViewer
      src="/path/to/document.pdf"
      values={formData}
      onChange={handleChange}
      showNavigation={true}
      showThumbnails={true}
      scale={1}
    />
  );
}

Props

PDFViewer

| Prop | Type | Default | Description | |------|------|---------|-------------| | src | string \| ArrayBuffer \| Uint8Array | required | PDF source (URL, ArrayBuffer, or Uint8Array) | | values | Record<string, FormFieldValue> | - | Controlled form values (inbound) | | defaultValues | Record<string, FormFieldValue> | - | Default values for fields | | onChange | (fieldName, value, allValues) => void | - | Callback when a field value changes (outbound) | | fieldNameMap | Record<string, string> | - | Map friendly names to PDF field names | | onDocumentLoad | (doc: PDFDocumentInfo) => void | - | Callback when document loads | | onPageChange | (page: number) => void | - | Callback when page changes | | showNavigation | boolean | true | Show navigation controls | | showThumbnails | boolean | false | Show thumbnail sidebar | | scale | number \| 'auto' \| 'page-fit' \| 'page-width' | 1 | Zoom scale | | initialPage | number | 1 | Initial page to display | | className | string | - | Container class name | | pageClassName | string | - | CSS class for page elements | | thumbnailClassName | string | - | CSS class for thumbnail elements | | workerSrc | string | CDN URL | PDF.js worker source URL |

Types

FormFieldValue

type FormFieldValue = string | boolean | string[];

FormField

interface FormField {
  name: string;
  type: 'text' | 'checkbox' | 'radio' | 'dropdown' | 'signature';
  value: FormFieldValue;
  options?: string[];        // For dropdown/radio
  required?: boolean;
  readOnly?: boolean;
  rect: [number, number, number, number];  // Position [x1, y1, x2, y2]
  page: number;
  maxLength?: number;
  multiline?: boolean;
  fontSize?: number;
  fontColor?: string;
  backgroundColor?: string;
  borderColor?: string;
}

PDFDocumentInfo

interface PDFDocumentInfo {
  numPages: number;
  fields: FormField[];
  metadata: Record<string, string>;
  document?: PDFDocumentProxy;  // PDF.js document proxy for advanced operations
}

Hooks

usePDFDocument

Load and manage a PDF document.

import { usePDFDocument } from 'react-acroform';

const { document, loading, error, numPages, reload } = usePDFDocument({
  src: '/path/to/document.pdf',
  workerSrc: '/pdf.worker.min.js', // optional
});

useFormFields

Extract form fields from a PDF document.

import { useFormFields } from 'react-acroform';

const {
  fields,
  loading,
  error,
  getFieldsForPage,
  getFieldByName,
  getInitialFormData,
  radioGroups,
} = useFormFields({
  document,
  onFieldsExtracted: (fields) => console.log('Found fields:', fields),
});

useFormState

Bi-directional sync between form fields and external state.

import { useFormState } from 'react-acroform';

const {
  getValue,
  setValue,
  getAllValues,
  initializeFromPDF,
  resolveFieldName,
  reverseResolveFieldName,
  version,
} = useFormState({
  values: externalValues,
  defaultValues: { firstName: 'John' },
  onChange: (name, value, allValues) => console.log(name, value),
  fieldNameMap: { firstName: 'form1[0].firstName[0]' },
});

usePDFExport

Export PDFs with filled form data.

import { usePDFExport } from 'react-acroform';

const { exportPDF, downloading, error } = usePDFExport();

usePageRenderer

Render PDF pages to canvas.

import { usePageRenderer } from 'react-acroform';

const { canvasRef, rendering, error } = usePageRenderer({
  page,
  scale: 1.5,
});

Custom Field Components

You can use the individual field components for custom layouts:

import {
  TextField,
  CheckboxField,
  RadioField,
  DropdownField,
  SignatureField,
  BaseField,
} from 'react-acroform';

<TextField
  field={field}
  scale={1}
  pageHeight={792}
/>

<SignatureField
  field={field}
  scale={1}
  pageHeight={792}
  onSignatureClick={(field) => console.log('Sign:', field.name)}
/>

Additional Components

import {
  PDFPage,
  PDFNavigation,
  PDFThumbnails,
  FormStateProvider,
} from 'react-acroform';

// FormStateProvider wraps components that need form state context
<FormStateProvider
  values={formData}
  onChange={handleChange}
  fieldNameMap={fieldNameMap}
>
  <YourCustomViewer />
</FormStateProvider>

Utilities

Coordinate Transformation

import { pdfRectToScreen, getFieldPositionStyle, calculateFitScale } from 'react-acroform';

// Convert PDF coordinates to screen coordinates
const screenRect = pdfRectToScreen(pdfRect, pageHeight, scale);

// Get CSS position style for a field
const style = getFieldPositionStyle(field.rect, pageHeight, scale);

// Calculate scale to fit page in container
const scale = calculateFitScale(pageWidth, pageHeight, containerWidth, containerHeight, 'fit');

Field Extraction

import { extractAllFields, fieldsToFormData } from 'react-acroform';

// Extract all fields from a PDF document
const fields = await extractAllFields(document);

// Convert fields to form data object
const initialData = fieldsToFormData(fields);

Field Mapping

import { groupFieldsByName, getFieldsForPage, updateFormData } from 'react-acroform';

// Group fields by name (useful for radio buttons)
const groups = groupFieldsByName(fields);

// Get fields for a specific page
const pageFields = getFieldsForPage(fields, 1);

PDF Export

import { fillPDF, downloadPDF, fillAndDownloadPDF } from 'react-acroform';

// Fill a PDF with form data and get bytes
const { pdfBytes, fieldCount } = await fillPDF(pdfSource, formData);

// Download a filled PDF
await downloadPDF(pdfBytes, 'filled-form.pdf');

// Fill and download in one step
await fillAndDownloadPDF(pdfSource, formData, 'filled-form.pdf');

Canvas Export

import { exportPDFFromCanvas, downloadCanvasExportedPDF } from 'react-acroform';

// Export PDF pages as images in a new PDF
const result = await exportPDFFromCanvas(canvasElements);

// Download the exported PDF
await downloadCanvasExportedPDF(canvasElements, 'exported.pdf');

Field Name Mapping

import { createFieldNameMapper } from 'react-acroform';

// Create a mapper for friendly field names
const mapper = createFieldNameMapper({
  firstName: 'form1[0].firstName[0]',
  lastName: 'form1[0].lastName[0]',
});

const pdfName = mapper.resolve('firstName'); // 'form1[0].firstName[0]'
const friendlyName = mapper.reverseResolve('form1[0].firstName[0]'); // 'firstName'

PDF.js Worker

For production use, you should host the PDF.js worker yourself:

<PDFViewer
  src={pdfUrl}
  workerSrc="/pdf.worker.min.js"
/>

Copy node_modules/pdfjs-dist/build/pdf.worker.min.js to your public directory.

License

MIT