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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@equitylist-co/pdf-editor

v1.0.33

Published

A modern, aesthetic React-based PDF annotation application that allows users to intuitively drag and drop placeholder fields onto PDF documents. Features a sleek interface with full-screen PDF viewing, precise coordinate tracking, and advanced field manag

Downloads

88

Readme

PDF Annotation Studio

A modern, aesthetic React-based PDF annotation application that allows users to intuitively drag and drop placeholder fields onto PDF documents. Features a sleek interface with full-screen PDF viewing, precise coordinate tracking, and advanced field management capabilities.

Features

  • 📄 PDF Rendering: Display PDF documents using react-pdf
  • 🎯 Drag & Drop: Intuitive drag-and-drop interface for placing annotation fields
  • 📐 Coordinate Capture: Precise coordinate tracking as percentages (0-1) relative to page dimensions
  • 🔄 Field Management: Move, resize, and delete annotation fields
  • 👁️ Preview Mode: View-only mode to display saved annotations
  • 🎨 Modern UI: Clean Tailwind CSS styling with responsive design
  • 📱 Zoom Control: Adjustable zoom levels for precise field placement
  • 📝 Text Fields: Editable text areas for custom content input
  • 🖼️ Image Fields: File picker integration for image placement
  • 👥 Assignee Selection: Multi-user assignment for signature, initials, name, and title fields
  • 🔄 Smart Duplication: Automatic field duplication for multiple assignees

Components

PdfAnnotatorCreate

Interactive component for creating and editing PDF annotations with drag-and-drop functionality.

Props:

  • fileUrl: PDF file URL
  • placeholderTypes: Array of placeholder type configurations with icons and assignee options
  • initialFields?: Optional array of existing fields for editing
  • onSave: Callback function when saving fields

PlaceholderType Configuration:

{
  value: string;           // Field type identifier (e.g., "signature", "text", "image")
  label: string;           // Display name (e.g., "Signature", "Text Field", "Image")
  icon: () => React.ReactNode;  // Icon component for the sidebar
  assigneeOptions?: {      // Optional user assignment for multi-user fields
    name: string;
    id: string;
  }[];
}

Features:

  • Drag & Drop Interface: Drag placeholder types from sidebar onto PDF pages
  • Field Management: Click and drag to reposition fields, resize using corner handles
  • Field Types: Support for text fields, image fields, and assignee-based fields
  • Multi-User Assignment: Fields with assignee options automatically duplicate for multiple users
  • Interactive Editing:
    • Text fields: Direct text input with real-time updates
    • Image fields: File picker integration for image uploads
    • Assignee fields: Dropdown selection for user assignment
  • Visual Controls: Delete fields with × button, zoom control for precise placement
  • Smart Positioning: Automatic field positioning when multiple assignees are selected

PdfAnnotatorDisplay

Read-only component for viewing PDF documents with saved annotations and interactive navigation.

Props:

  • fileUrl: PDF file URL
  • fields: Array of Field objects to display
  • showSidebar?: Optional boolean to show/hide the sidebar (default: true)

Features:

  • PDF Rendering: Display PDF with overlay annotations using react-pdf
  • Interactive Sidebar: Field summary with statistics and detailed field list
  • Field Navigation: Clickable field items that scroll to and highlight fields on the PDF
  • Zoom Control: Adjustable zoom levels with smooth scaling
  • Field Statistics: Automatic grouping and counting of fields by type
  • Programmatic Control: External control via useImperativeHandle for programmatic field navigation
  • Visual Feedback: Temporary field highlighting with smooth animations

Ref Methods:

  • scrollToField(fieldId: string): Smoothly scrolls to a specific field and centers it
  • highlightField(fieldId: string): Highlights a field temporarily (2-second duration)

Data Model

Field Type

type Field = {
  page: number;   // 1-based page number
  type: string;   // placeholder type (e.g., "signature", "text", "image")
  x: number;      // left position (0–1, relative to width)
  y: number;      // top position (0–1, relative to height)
  width: number;  // width (0–1, relative to width)
  height: number; // height (0–1, relative to height)
  metadata?: {    // optional field-specific data
    textValue?: string;           // for text fields
    imageUrl?: string;            // for image fields
    assignedUserIds?: string[];   // for assignee-based fields
    [key: string]: any;           // additional custom metadata
  };
  id: string;     // unique identifier for the field
};

DragItem Type

interface DragItem {
  type: string;           // drag item type
  fieldType: string;      // field type being dragged
  isNew?: boolean;        // true for new fields from sidebar
  fieldIndex?: number;    // index for existing field repositioning
  field?: Field;          // field data for existing fields
}

Installation

  1. Install dependencies:
yarn install
  1. Start the development server:
yarn dev

Usage

Basic Example

import PdfAnnotatorCreate from './components/PdfAnnotatorCreate';
import PdfAnnotatorDisplay, { type PdfAnnotatorDisplayRef } from './components/PdfAnnotatorDisplay';
import { Field } from './types/Field';
import { useRef, useState } from 'react';
import { v4 as uuidv4 } from 'uuid';

function App() {
  const [fields, setFields] = useState<Field[]>([]);
  const [showSidebar, setShowSidebar] = useState(true);
  const pdfDisplayRef = useRef<PdfAnnotatorDisplayRef>(null);
  
  // Configure placeholder types with icons and assignee options
  const placeholderTypes = [
    {
      value: 'signature',
      label: 'Signature',
      icon: () => <span>✍️</span>,
      assigneeOptions: [
        { name: 'John Doe', id: 'user1' },
        { name: 'Jane Smith', id: 'user2' }
      ]
    },
    {
      value: 'text',
      label: 'Text Field',
      icon: () => <span>📝</span>
    },
    {
      value: 'image',
      label: 'Image',
      icon: () => <span>🖼️</span>
    },
    {
      value: 'date',
      label: 'Date',
      icon: () => <span>📅</span>
    }
  ];
  
  const pdfUrl = 'path/to/your/document.pdf';

  const handleSave = (newFields: Field[]) => {
    const fieldsWithIds = newFields.map((field) => ({
      ...field,
      id: field.id || uuidv4()
    }));
    setFields(fieldsWithIds);
  };

  const scrollToFirstField = () => {
    if (fields.length > 0 && pdfDisplayRef.current) {
      pdfDisplayRef.current.scrollToField(fields[0].id);
      pdfDisplayRef.current.highlightField(fields[0].id);
    }
  };

  return (
    <div>
      <PdfAnnotatorCreate
        fileUrl={pdfUrl}
        placeholderTypes={placeholderTypes}
        initialFields={fields}
        onSave={handleSave}
      />

      <div>
        <button onClick={() => setShowSidebar(!showSidebar)}>
          {showSidebar ? 'Hide Sidebar' : 'Show Sidebar'}
        </button>
        <button onClick={scrollToFirstField}>
          Scroll to First Field
        </button>
        
        <PdfAnnotatorDisplay
          ref={pdfDisplayRef}
          fileUrl={pdfUrl}
          fields={fields}
          showSidebar={showSidebar}
        />
      </div>
    </div>
  );
}

Advanced Features

Multi-User Field Assignment

Fields with assignee options automatically duplicate when multiple users are selected:

const placeholderTypes = [
  {
    value: 'signature',
    label: 'Signature',
    icon: () => <span>✍️</span>,
    assigneeOptions: [
      { name: 'John Doe', id: 'user1' },
      { name: 'Jane Smith', id: 'user2' },
      { name: 'Bob Johnson', id: 'user3' }
    ]
  }
];

// When a user selects multiple assignees, the system automatically:
// 1. Creates separate fields for each assignee
// 2. Positions them vertically below the original field
// 3. Each field contains only one assigned user ID

Field Types and Metadata

Different field types support specific metadata:

// Text fields store user input
{
  type: 'text',
  metadata: {
    textValue: 'User entered text here'
  }
}

// Image fields store file URLs
{
  type: 'image',
  metadata: {
    imageUrl: '/path/to/uploaded/image.jpg'
  }
}

// Assignee fields store user assignments
{
  type: 'signature',
  metadata: {
    assignedUserIds: ['user1', 'user2']
  }
}

Hiding the Sidebar

You can display only the PDF without the sidebar by setting showSidebar={false}:

<PdfAnnotatorDisplay
  fileUrl={pdfUrl}
  fields={fields}
  showSidebar={false}
/>

Programmatic Field Navigation

Use the ref to programmatically scroll to and highlight fields:

const pdfDisplayRef = useRef<PdfAnnotatorDisplayRef>(null);

// Scroll to a specific field
pdfDisplayRef.current?.scrollToField('550e8400-e29b-41d4-a716-446655440000');

// Highlight a field temporarily
pdfDisplayRef.current?.highlightField('550e8400-e29b-41d4-a716-446655440000');

// Combined: scroll and highlight
pdfDisplayRef.current?.scrollToField('550e8400-e29b-41d4-a716-446655440000');
pdfDisplayRef.current?.highlightField('550e8400-e29b-41d4-a716-446655440000');

Interactive Field Management

  • Drag & Drop: Drag fields from sidebar to create new annotations
  • Repositioning: Click and drag existing fields to move them
  • Resizing: Use corner handles to resize fields
  • Deletion: Click the × button to remove fields
  • Real-time Updates: Text and image fields update immediately as you type or upload

Coordinate System

The coordinate system uses percentages (0-1) relative to the PDF page dimensions:

  • x: 0 = left edge of page
  • x: 1 = right edge of page
  • y: 0 = top edge of page
  • y: 1 = bottom edge of page

This ensures annotations maintain their relative positions across different zoom levels and screen sizes.

Technologies Used

  • React 19 with TypeScript
  • react-pdf for PDF rendering and document management
  • react-dnd for drag-and-drop functionality with HTML5 backend
  • Radix UI for accessible dropdown menus and UI components
  • Tailwind CSS for styling with scoped library classes
  • Vite for build tooling and development server
  • UUID for unique field identification

Browser Support

  • Modern browsers with ES6+ support
  • PDF.js worker for cross-browser PDF rendering

Steps to deploy library

  • Run publish.sh script to deploy to npm.

License

MIT License