@snakeroads-soft/pdf-editor

Framework-agnostic visual PDF report designer and jsPDF compiler in pure TypeScript with Angular, React, Vue, and Vanilla JS support.
2,033
Install
npm install @snakeroads-soft/pdf-editor@1.0.0
Latest Version:1.0.0
License:MIT
Last Updated:Oct 12, 2026
Links: npm
Maintainer: eliasdominguez

@snakeroads-soft/pdf-editor 🚀

Framework-Agnostic, High-Performance PDF Studio & Editor for TypeScript, Angular, React, Vue, Svelte, and Vanilla JS.

A modern, glassmorphism-styled, plug-and-play PDF designer and compilation engine built with 100% pure TypeScript and jsPDF.


✨ Features

  • 🌐 Framework-Agnostic: Zero framework lock-in. Works as a Web Component <pdf-studio>, a JavaScript class new PdfStudio(), or an Angular component/service.
  • 📄 Multi-Format & Multi-Orientation: Native A4, Letter, Legal, A3, A5 with portrait and landscape modes.
  • 📊 Decoupled Dynamic Data Tables & Lists:
    • Pass runtime JSON arrays (datasets: { estudiantes: [...], productos: [...] }) from code without modifying template design.
    • One-click auto-mapping (🪄 Auto-Mapear Columnas) of object keys to table columns with balanced 100% widths.
    • #index virtual field support for automatic 1-based row numbering.
    • Interactive table column % width drag-resizing and inspector sliders.
    • Column visibility toggles and alignment controls.
  • 🌊 Smart Dynamic Flow & Multi-Page Interference Engine:
    • Automatically shifts elements positioned below multi-page tables or long markdown blocks down to avoid overlaps.
    • Multi-column spatial interference detection (only displaces elements sharing horizontal X-coordinate boundaries).
  • 📝 Multi-Page Markdown Auto-Breaking:
    • Full GitHub-flavored markdown with bold, headers, lists, code, and tables.
    • Auto-Split Across Pages: Automatically splits long markdown text across multiple PDF pages when it exceeds page boundaries.
  • 🧩 Dynamic Variable Engine:
    • Auto-discovery of {{variable_name}} and {{dataset.length}} tokens across text, tables, and lists.
    • Variable chip injector in toolbox & inspector.
    • Live preview and batch compilation with dynamic runtime data.
  • 📐 Millimeter Precision Workspace:
    • Real-time horizontal and vertical mm rulers.
    • 8-direction resize handles and 360° rotation handle.
    • Grid snap system with configurable millimeter step.
    • Backspace-protected deletion (only Delete key deletes elements to prevent accidental removal while typing).
  • ☁️ Storage & Cloud Ready: Local Storage, REST API, Azure Blob Storage, and AWS S3 integration.
  • 🎨 Built-in Business Templates: Modern Invoices, Achievement Certificates, Reports, and Shipping Labels.

📦 Installation

npm install @snakeroads-soft/pdf-editor jspdf jspdf-autotable marked dompurify

🅰️ Angular Integration

1. In Standalone Components (Angular 14+)

import { Component, ElementRef, ViewChild, AfterViewInit, OnDestroy } from '@angular/core';
import { PdfStudio, DocumentSchema } from '@snakeroads-soft/pdf-editor';
import '@snakeroads-soft/pdf-editor/style.css';

@Component({
  selector: 'app-pdf-designer',
  standalone: true,
  template: `
    <div class="editor-container" #editorContainer style="width: 100%; height: 90vh;"></div>
  `
})
export class PdfDesignerComponent implements AfterViewInit, OnDestroy {
  @ViewChild('editorContainer', { static: true }) editorContainer!: ElementRef<HTMLElement>;
  private studio!: PdfStudio;

  ngAfterViewInit(): void {
    this.studio = new PdfStudio({
      container: this.editorContainer.nativeElement,
      variables: {
        company_name: 'Acme Corp',
        invoice_total: '$1,450.00'
      },
      onChange: (schema: DocumentSchema) => {
        console.log('Schema updated:', schema);
      },
      onSave: (schema: DocumentSchema) => {
        console.log('Document saved:', schema);
      }
    });
  }

  exportPdf(): void {
    this.studio.downloadPdf('my-document.pdf');
  }

  ngOnDestroy(): void {
    this.studio?.destroy();
  }
}

2. Using the Web Component <pdf-studio> in Angular

Add CUSTOM_ELEMENTS_SCHEMA to your component or module:

import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import '@snakeroads-soft/pdf-editor';
import '@snakeroads-soft/pdf-editor/style.css';

@Component({
  selector: 'app-pdf-page',
  standalone: true,
  schemas: [CUSTOM_ELEMENTS_SCHEMA],
  template: `
    <pdf-studio
      style="width: 100%; height: 100vh; display: block;"
      (schemaChange)="onSchemaChange($event)"
      (save)="onSave($event)"
    ></pdf-studio>
  `
})
export class PdfPageComponent {
  onSchemaChange(event: any) {
    console.log('Schema:', event.detail);
  }

  onSave(event: any) {
    console.log('Save:', event.detail);
  }
}

3. Headless PDF Generation in Angular (Without UI)

Use SnakeroadsPdfService or JsPdfEngine directly to render PDFs in background services:

import { Injectable } from '@angular/core';
import { SnakeroadsPdfService, DocumentSchema } from '@snakeroads-soft/pdf-editor';

@Injectable({ providedIn: 'root' })
export class InvoiceService {
  private pdfService = new SnakeroadsPdfService();

  async downloadInvoice(schema: DocumentSchema, invoiceData: any) {
    await this.pdfService.downloadPdf(schema, invoiceData, 'invoice.pdf');
  }

  async getInvoiceBlob(schema: DocumentSchema, invoiceData: any): Promise<Blob> {
    return await this.pdfService.generatePdf(schema, invoiceData);
  }
}

⚛️ React Integration

import React, { useEffect, useRef } from 'react';
import { PdfStudio } from '@snakeroads-soft/pdf-editor';
import '@snakeroads-soft/pdf-editor/style.css';

export const PdfEditor: React.FC = () => {
  const containerRef = useRef<HTMLDivElement>(null);
  const studioRef = useRef<PdfStudio | null>(null);

  useEffect(() => {
    if (containerRef.current) {
      studioRef.current = new PdfStudio({
        container: containerRef.current,
        onChange: (schema) => console.log('Schema:', schema),
      });
    }

    return () => {
      studioRef.current?.destroy();
    };
  }, []);

  return <div ref={containerRef} style={{ width: '100%', height: '100vh' }} />;
};

🟢 Vue 3 Integration

<template>
  <div ref="editorContainer" style="width: 100%; height: 100vh;"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { PdfStudio } from '@snakeroads-soft/pdf-editor';
import '@snakeroads-soft/pdf-editor/style.css';

const editorContainer = ref<HTMLElement | null>(null);
let studio: PdfStudio | null = null;

onMounted(() => {
  if (editorContainer.value) {
    studio = new PdfStudio({
      container: editorContainer.value,
      onChange: (schema) => console.log('Schema:', schema),
    });
  }
});

onUnmounted(() => {
  studio?.destroy();
});
</script>

🍦 Vanilla TypeScript / JavaScript

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <link rel="stylesheet" href="node_modules/@snakeroads-soft/pdf-editor/dist/style.css" />
</head>
<body>
  <div id="pdf-editor" style="width: 100vw; height: 100vh;"></div>

  <script type="module">
    import { PdfStudio } from './node_modules/@snakeroads-soft/pdf-editor/dist/index.mjs';

    const studio = new PdfStudio({
      container: '#pdf-editor',
      variables: {
        user_name: 'Arturo Schloss',
        project: 'Cloud Infrastructure'
      }
    });
  </script>
</body>
</html>

🛠️ API Reference

new PdfStudio(options)

Option Type Description
container HTMLElement | string DOM element or CSS selector to mount the studio into.
schema DocumentSchema (optional) Initial document schema to load.
variables Record<string, any> (optional) Key-value dictionary for {{variable}} interpolation.
datasets Record<string, any[]> (optional) Named collections of dynamic JSON objects for tables and lists.
storageConfig StorageConfig (optional) Storage provider config (local, rest, azure-blob, s3).
onChange (schema: DocumentSchema) => void Triggered on every element change or layout modification.
onSave (schema: DocumentSchema) => void Triggered when user clicks Save.
onPdfGenerated (blob: Blob) => void Triggered when a PDF is compiled.

Instance Methods

  • studio.getSchema(): DocumentSchema
  • studio.loadSchema(schema: DocumentSchema): void
  • studio.setVariables(vars: Record<string, string>): void
  • studio.getVariables(): Record<string, string>
  • studio.setDatasets(datasets: Record<string, any[]>): void
  • studio.setDataset(name: string, data: any[]): void
  • studio.getDatasets(): Record<string, any[]>
  • studio.exportPdfBlob(options?: GeneratePdfOptions): Promise<Blob>
  • studio.downloadPdf(filename?: string, options?: GeneratePdfOptions): Promise<void>
  • studio.save(): Promise<{ id: string; success: boolean }>
  • studio.undo(): boolean
  • studio.redo(): boolean
  • studio.destroy(): void

Headless Engine (JspdfEngine)

import { JspdfEngine } from '@snakeroads-soft/pdf-editor';

const result = JspdfEngine.generatePdf(schema, {
  variables: { empresa: 'Snakeroads' },
  datasets: { estudiantes: dataArray }
});

console.log(result.blobUrl);

📄 License

MIT © Snakeroads Technologies

Related Packages

@mecorelabs/free-pdf-sdk

Free PDF SDK: an embeddable, white-label PDF viewer, annotator and editor for th...

207 0
@aspect-ui-01/toast

Lightweight framework-agnostic toast notifications (~2KB)

3,926
web-c-theme

功能介绍 这是一个基于 **Web Component** 技术的主题组件库,主要功能是前端 **"主题...

3,688
aurebesh

A lightweight, dependency-free WYSIWYG editor for the web. Rich text, tables, co...

590 1

Version History

Version Released License
1.0.0 MIT
Pre-releases (18)
Version Released License
1.0.0-beta.19 MIT
1.0.0-beta.18 MIT
1.0.0-beta.17 MIT
1.0.0-beta.16 MIT
1.0.0-beta.15 MIT