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

pandadoc-signing

v0.0.0-a.2

Published

The `pandadoc-signing` can be used to embed the PandaDoc Document Signing experience in your web application.

Readme

pandadoc-signing Library

The pandadoc-signing library provides an easy way to embed the PandaDoc Document Signing experience in your web application using Session id.

Features

  • Embedded Document Signing
  • Session ID authentication (simplified setup)
  • Event handling with type-safe callbacks
  • Debug mode for troubleshooting
  • Region support (COM/EU)
  • Lightweight and easy to integrate

Installation

To install pandadoc-signing, you can use either npm or yarn:

npm install pandadoc-signing

or

yarn add pandadoc-signing

Quick Start

First, import the library in your project:

import { Signing } from "pandadoc-signing";

Then, initialize and open the signing experience:

const signing = new Signing(
  "signing-container",
  {},
  {
    region: "com", // Optional: specify region ('com' or 'eu')
  }
);

// Open the signing experience
await signing.open({
  sessionId: "your-session-id-here", // Session ID for authentication
});

API Reference

Constructor

const signing = new Signing(elementId, config, pdConfig);

Parameters:

  • elementId (string): The ID of the DOM element to replace with the signing iframe
  • config (SigningConfig): Signing configuration options
  • pdConfig (PDConfigModel): PandaDoc server configuration

Note: If sessionId is provided in the configuration, the signing experience will automatically open once the iframe is ready and initialized.

Config Options:

interface SigningConfig {
  width?: number | string; // Width of the iframe
  height?: number | string; // Height of the iframe
  sessionId?: string; // Session ID for authentication
  debugMode?: boolean; // Enable debug logging
}

PDConfig Options:

const signing = new Signing(
  "signing-container",
  {
    sessionId: "your-session-id-here",
  },
  {
    region: "eu", // Preferred: Use region for better maintainability
    host: "https://custom.pandadoc.com/", // Deprecated: Use region instead
  }
);

Methods

open(options)

Opens the signing experience with the specified session ID.

await signing.open({
  sessionId: "your-session-id-here",
});

// Or, if sessionId was provided in the constructor config:
await signing.open();

Parameters:

  • options (optional): Partial SigningConfig object
    • sessionId (string, optional): Session ID for authentication. If not provided, uses the sessionId from the constructor configuration.

Returns: Promise

Behavior:

  • If no sessionId is provided (neither in options nor in config), the method returns early without opening.
  • If the signing instance is not yet initialized (iframe not ready), the method returns early.
  • The method will use the sessionId from the constructor config if not provided in the options.

close()

Closes the signing experience by dispatching a close command to the iframe.

await signing.close();

Returns: Promise

Behavior:

  • If the signing experience is not in a ready state, the method returns early without dispatching the close command.
  • When successful, the signing status is set to CLOSED.

destroy()

Destroys the signing instance and cleans up resources to prevent memory leaks. This method:

  • Destroys the event bus and command bus
  • Removes the iframe from the DOM
  • Should be called when you no longer need the signing instance
signing.destroy();

Important: After calling destroy(), the signing instance cannot be reused. Create a new instance if needed.

on(event, handler)

Registers an event handler for signing session events.

signing.on("document.loaded", (payload) => {
  console.log("Document loaded:", payload);
});

signing.on("document.completed", (payload) => {
  console.log("Document completed:", payload);
});

signing.on("document.exception", (payload) => {
  console.error("Document exception:", payload);
});

Parameters:

  • event (string): Event name. Available events:
    • 'document.loaded': Triggered when the document is loaded in the signing session
    • 'document.completed': Triggered when a recipient completes the document
    • 'document.exception': Triggered if an error occurs during document finalization
  • handler (function): Callback function that receives the event payload

Returns: The Signing instance (for method chaining)

TypeScript:

signing.on("document.loaded", (payload: DocumentEventPayload) => {
  // payload is fully typed
});

signing.on("document.completed", (payload: DocumentEventPayload) => {
  // payload is fully typed
});

signing.on("document.exception", (payload: DocumentExceptionPayload) => {
  // payload is fully typed
});

off(event, handler?)

Removes an event handler. If no handler is specified, removes all handlers for the event.

// Remove specific handler
const handler = (payload) => console.log(payload);
signing.on("document.completed", handler);
signing.off("document.completed", handler);

// Remove all handlers for an event
signing.off("document.completed");

Parameters:

  • event (string): Event name
  • handler (function, optional): Specific handler to remove

Returns: The Signing instance (for method chaining)

once(event, handler)

Registers an event handler that will be called only once.

signing.once("document.completed", (payload) => {
  console.log("Document completed (one-time handler):", payload);
});

Parameters:

  • event (string): Event name
  • handler (function): Callback function

Returns: The Signing instance (for method chaining)

Event Handling

The library supports event handling through an EventEmitter-style API using .on(), .off(), and .once() methods.

Available Events

  1. 'document.loaded': Triggered when the document is loaded in the signing session.
  2. 'document.completed': Triggered when a recipient completes the document.
  3. 'document.exception': Triggered if an error occurs during signing.

Basic Usage Example

import { Signing } from "pandadoc-signing";

const signing = new Signing(
  "signing-container",
  {
    sessionId: "your-session-id-here",
  },
  {
    region: "com",
  }
);

// Register event handlers
signing.on("document.loaded", (payload) => {
  console.log("Document loaded:", payload);
  // Hide loading spinner, show signing UI, etc.
});

signing.on("document.completed", (payload) => {
  console.log("Document completed:", payload);
  // Redirect user, update UI, notify backend, etc.
  window.location.href = "/thank-you";
});

signing.on("document.exception", (payload) => {
  console.error("Document exception:", payload);
  // Show error message, log error, etc.
});

await signing.open();

Advanced Usage

Multiple Handlers for Same Event

// You can register multiple handlers for the same event
signing.on("document.completed", (payload) => {
  updateUI(payload);
});

signing.on("document.completed", (payload) => {
  notifyBackend(payload);
});

signing.on("document.completed", (payload) => {
  trackAnalytics(payload);
});

One-Time Handlers

// Handler will be called only once, then automatically removed
signing.once("document.completed", (payload) => {
  console.log("Document completed:", payload);
});

Removing Handlers

const handler = (payload) => {
  console.log("Document completed:", payload);
};

// Register handler
signing.on("document.completed", handler);

// Later, remove specific handler
signing.off("document.completed", handler);

// Or remove all handlers for an event
signing.off("document.completed");

Method Chaining

signing
  .on("document.loaded", handleLoaded)
  .on("document.completed", handleCompleted)
  .on("document.exception", handleException);

Debug Mode

Enable debug mode to get detailed logging of signing operations:

const signing = new Signing("signing-container", {
  sessionId: "your-session-id",
  debugMode: true,
});

When debug mode is enabled, you'll see console logs for:

  • Constructor initialization
  • Open/close operations with parameters
  • Command dispatching
  • iframe creation
  • Event subscription
  • Error conditions and their reasons
  • Resource cleanup during destroy

Debug logs are prefixed with [Signing Debug] and include relevant data for troubleshooting.

Region Configuration

You can specify which PandaDoc region to use by setting the region parameter:

// For global region (default)
const signing = new Signing(
  "signing-container",
  {
    sessionId: "your-session-id-here",
  },
  {
    region: "com", // Global region - app.pandadoc.com
  }
);

// For EU region
const signing = new Signing(
  "signing-container",
  {
    sessionId: "your-session-id-here",
  },
  {
    region: "eu", // EU region - app.pandadoc.eu
  }
);

Available Regions

  • 'com': Global region (app.pandadoc.com) - Default
  • 'eu': EU region (app.pandadoc.eu)

Complete Usage Example

import { Signing } from "pandadoc-signing";

// Initialize the signing experience
const signing = new Signing(
  "signing-container",
  {
    sessionId: "your-session-id-here",
    debugMode: true, // Enable for development
    width: 800,
    height: 600,
  },
  {
    region: "com", // Use global region (default)
  }
);

try {
  // Open the signing experience
  await signing.open();

  // ... user signs the document ...

  // Close when done (optional - usually handled by the signing flow)
  await signing.close();
} finally {
  // Always clean up resources
  signing.destroy();
}

HTML Integration Example

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document Signing</title>
    <style>
      body,
      html {
        margin: 0;
        padding: 0;
        overflow: hidden;
      }

      iframe {
        width: 100vw;
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="signing-container"></div>
    <script type="module">
      import { Signing } from "pandadoc-signing";

      const signing = new Signing(
        "signing-container",
        {
          sessionId: "your-session-id-here",
          debugMode: true,
        },
        {
          region: "com",
        }
      );

      await signing.open();
    </script>
  </body>
</html>

Getting an Session ID

To use this library, you need to obtain an Session ID from the PandaDoc API:

  1. Call the Create Document Signing Session API endpoint
  2. Extract the id session ID from the response
  3. Use the session ID with the pandadoc-signing library

Example API call:

const response = await fetch(
  "https://api.pandadoc.com/public/v1/documents/{document_id}/session",
  {
    method: "POST",
    headers: {
      Authorization: "API-Key your-api-key",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      recipient: "[email protected]",
      lifetime: 3600, // Session lifetime in seconds
    }),
  }
);

const data = await response.json();
const sessionId = data.id; // This is your session ID

Performance Optimization

Pre-initialize for Instant Loading

For the best user experience, you can initialize the Signing widget before requesting the session ID from the API. This allows the iframe and all static resources to load in advance, so when the session ID is ready, the document opens almost instantly.

Recommended Pattern:

import { Signing } from "pandadoc-signing";

// Step 1: Initialize the signing widget immediately (without session ID)
const signing = new Signing(
  "signing-container",
  {
    debugMode: true,
  },
  {
    region: "com",
  }
);

// Step 2: Request session ID from your backend in parallel
const sessionPromise = fetch("/api/create-signing-session", {
  method: "POST",
  body: JSON.stringify({ documentId: "your-document-id" }),
})
  .then((response) => response.json())
  .then((data) => data.sessionId);

// Step 3: Once session ID is ready, open immediately (resources already loaded!)
const sessionId = await sessionPromise;
await signing.open({ sessionId });

// The document will open almost instantly because the iframe is already initialized

Benefits:

  • ✅ Static resources (iframe, scripts, styles) load in parallel with your API call
  • ✅ Reduces perceived loading time significantly
  • ✅ Document opens quickly when session ID is available
  • ✅ Better user experience, especially on slower connections

Without Pre-initialization (Slower):

// ❌ Not recommended: Initialize only after getting session ID
const sessionId = await getSessionIdFromAPI();
const signing = new Signing("signing-container"); // Resources start loading NOW
await signing.open({ sessionId }); // User waits for iframe + resources + document

With Pre-initialization (Faster):

// ✅ Recommended: Initialize while fetching session ID
const signing = new Signing("signing-container"); // Resources start loading NOW
const sessionId = await getSessionIdFromAPI(); // Parallel execution
await signing.open({ sessionId }); // Only document loading time, resources ready!

Common Use Cases

1. Basic Signing Flow

const signing = new Signing("signing-container", {
  sessionId: "session-id-from-api",
});

await signing.open();

2. Custom Size

const signing = new Signing("signing-container", {
  sessionId: "session-id-from-api",
  width: 1024,
  height: 768,
});

await signing.open();

3. EU Region

const signing = new Signing(
  "signing-container",
  {
    sessionId: "session-id-from-api",
  },
  {
    region: "eu",
  }
);

await signing.open();

4. Development with Debug Mode

const signing = new Signing("signing-container", {
  sessionId: "session-id-from-api",
  debugMode: true,
});

await signing.open();
// Check console for detailed logs

5. Event Handling

const signing = new Signing("signing-container", {
  sessionId: "session-id-from-api",
});

signing.on("document.loaded", (payload) => {
  // Document is ready for signing
  hideLoadingSpinner();
});

signing.on("document.completed", (payload) => {
  // Handle successful completion
  showSuccessMessage();
  redirectToThankYouPage();
});

signing.on("document.exception", (payload) => {
  // Handle errors
  showErrorMessage(payload || "An error occurred");
});

await signing.open();

Browser Support

The library supports all modern browsers that support:

  • ES2015+
  • iframe embedding
  • Promises/async-await

Building

To build the library, run:

vite build

This will generate the library bundle in the dist directory.

TypeScript Support

The library includes TypeScript definitions out of the box. Import types as needed:

import {
  Signing,
  SigningConfig,
  PDConfigModel,
  Region,
  DocumentEventPayload,
  DocumentExceptionPayload,
} from "pandadoc-signing";

const config: SigningConfig = {
  sessionId: "your-session-id-here",
  debugMode: true,
  width: 800,
  height: 600,
};

const pdConfig: PDConfigModel = {
  region: Region.COM,
};

const signing = new Signing("signing-container", config, pdConfig);

// Event handlers with full type safety
signing.on("document.loaded", (payload: DocumentEventPayload) => {
  console.log("Document loaded");
});

signing.on("document.completed", (payload: DocumentEventPayload) => {
  console.log("Document completed:", payload.status);
});

signing.on("document.exception", (payload: DocumentExceptionPayload) => {
  console.error("Error:", payload.error);
});

Resources