diagview
v1.0.12
Published
A lightweight framework-agnostic viewer for SVG diagrams (Mermaid, Graphviz, etc). Adds interactive Zoom, Pan, Search, Export, and Presentation Mode.
Maintainers
Readme
DiagView
A lightweight, framework-agnostic interactive viewer for SVG diagrams.
Adds Zoom · Pan · Search · Export · Minimap · Rotation · Presentation Mode to any SVG on your page.

Table of Contents
- Features
- Installation
- Quick Start
- Layout Modes
- Per-Diagram Overrides
- Keyboard Shortcuts
- Export Formats
- Framework Integration
- Configuration
- Screenshots
- Live Demo
- Documentation
- Contributing
- License
✨ Features
| Feature | Description |
| ---------------------------- | ---------------------------------------------------------------------- |
| 🎨 Auto-Theming | Detects Tailwind, Bootstrap, and system dark/light mode automatically |
| 🔍 Node Search | Instant search with pulsing glow highlights on matching nodes |
| 📤 Multi-Format Export | PNG, SVG, PDF, JPEG, WebP — with transparent background option |
| 📋 Clipboard Copy | Copy diagrams directly to the clipboard |
| ⌨️ Keyboard Shortcuts | Full keyboard navigation (zoom, pan, search, share, rotate) |
| 📱 Mobile Optimized | Pinch-to-zoom, double-tap to reset, Visual Viewport sync for stability |
| 🗺️ Smart Minimap | Accurate portrait/landscape scaling; click-to-navigate |
| 🎯 Meeting Mode | Laser pointer that follows the cursor for presentations |
| 🔗 Precision Share Links | Share exact zoom/pan position via URL parameters |
| 🔄 Rotation | 90° rotation steps with correct Panzoom recalibration |
| 📝 Text Select Mode | Toggle SVG text selection for copying node labels |
| 🔒 SVG Sanitization | Three-tier security model (strict/permissive/off) |
| 🎭 3 Layout Modes | Header toolbar, floating FAB, or invisible click-to-open |
| 🔧 Per-Diagram Overrides | Set layout, accent, scale per diagram via data-* attributes |
| 🌐 Shadow DOM Support | Works inside Shadow DOM roots |
| 🔄 Remember Zoom | Persist zoom/pan state per diagram across modal opens (session) |
| 📦 Minimal Dependencies | Only requires @panzoom/panzoom core module |
| 🚫 Framework Agnostic | Works with React, Vue, Svelte, Angular, or plain HTML |
| 🏷️ Silent Branding | Invisible in UI; professional attribution added during export |
📦 Installation
CDN (Recommended for quick start)
<!-- 1. Required: Panzoom for zoom/pan physics -->
<script src="https://cdn.jsdelivr.net/npm/@panzoom/[email protected]/dist/panzoom.min.js"></script>
<!-- 2. DiagView (latest stable) -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/diagview.umd.min.js"></script>
<!-- For auto-updates within v1: use diagview@1 instead -->To disable auto-initialization and configure manually:
<script
src="https://cdn.jsdelivr.net/npm/[email protected]/dist/diagview.umd.min.js"
data-diagview-no-auto-init
></script>
<script>
DiagView.init({ layout: "floating", accentColor: "#3b82f6" });
</script>Auto-init is deferred by one task, so an init() call issued synchronously from a module, defer or bundler entry script always wins over it; the attribute is only needed when your init() runs later (after an await, in a framework effect).
NPM
npm install diagview @panzoom/panzoomimport DiagView from "diagview";
DiagView.init({ layout: "floating" });ESM (Bundlers / Vite / Webpack)
import DiagView from "diagview"; // resolves dist/esm/index.jsStyles are injected automatically at runtime — no CSS import is required. The raw stylesheet is also exported for advanced setups (inspecting the rules, building theme overrides, or processing it through your build pipeline):
import "diagview/style"; // optional: resolves dist/diagview.css🚀 Quick Start
Step 1 — Wrap your SVG
DiagView matches any element that contains an <svg> tag. By default it targets .diagram, .chart, and [data-diagram]:
<div class="diagram" data-title="System Overview">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 600">
<!-- your SVG content -->
</svg>
</div>Step 2 — Initialize
DiagView.init({
layout: "floating", // 'header' | 'floating' | 'off'
accentColor: "#3b82f6", // optional brand color
highResScale: 4, // export resolution (1–10)
showKeyboardHelp: true, // show shortcuts on first open
});Step 3 — Done 🎉
DiagView automatically:
- Wraps each matching diagram with interactive controls
- Adds copy, download, and fullscreen buttons
- Enables zoom, pan, and search in fullscreen mode
- Handles keyboard shortcuts, theme sync, and mobile touch
🎨 Layout Modes
Floating (Default)
A circular FAB button appears at the bottom-right of the fullscreen viewer. Controls on the diagram card hover in at the bottom. Ideal for clean, minimal UIs.
DiagView.init({ layout: "floating" });Header
A full-width toolbar is always visible above the diagram. Best for documentation sites and dashboards where discoverability matters.
DiagView.init({ layout: "header" });Off (Click-to-open)
No controls are rendered on the diagram card. The diagram itself is the trigger — clicking it opens the fullscreen viewer. Perfect for tight layouts and embeds.
DiagView.init({ layout: "off" });🎛️ Per-Diagram Overrides
Any diagram can override the global configuration using data-diagview-* attributes. This lets you mix layout modes and accent colors on a single page.
<!-- Use header layout with a purple accent for this diagram only -->
<div
class="diagram"
data-diagview-layout="header"
data-diagview-accent="#8b5cf6"
data-diagview-scale="6"
data-title="My Architecture"
>
<svg>...</svg>
</div>
<!-- This diagram uses the global defaults -->
<div class="diagram">
<svg>...</svg>
</div>| Attribute | Values | Description |
| --------------------------------- | ----------------------------------- | --------------------------------------- |
| data-diagview-layout | header | floating | off | Layout for this diagram only |
| data-diagview-accent | Any CSS color | Accent color for this diagram only |
| data-diagview-scale | 1–10 | Export resolution for this diagram only |
| data-diagview-sanitize | strict | permissive | off | SVG sanitization mode |
| data-diagview-allow-remote | true | false | Allow remote CSS/fonts in SVG |
| data-diagview-watermark | true | false | Enable branding for this diagram only |
| data-diagview-watermark-text | Any string | Custom brand text (e.g. your name) |
| data-diagview-watermark-style | corner | background | both | Style override for this diagram |
| data-diagview-watermark-pos | top-left | ... | four-sides | Position override for this diagram |
| data-diagview-watermark-opacity | 0.1–1.0 | Transparency override for this diagram |
| data-title | Any string | Title shown in header layout label |
Security note:
data-diagview-sanitize="off"anddata-diagview-allow-remote="true"only work whensecurity.allowOverridesistruein the global config (the default). Use these only with SVGs from fully trusted sources.
⌨️ Keyboard Shortcuts
All shortcuts are active when the fullscreen modal is open.
| Key | Action |
| ---------------- | ------------------------------------------------------- |
| Esc | Close fullscreen (keyboard help and search close first) |
| Space / 0 | Reset zoom — fit diagram to screen |
| + / = | Zoom in |
| - / _ | Zoom out |
| ↑ ↓ ← → | Pan diagram |
| Shift + ↑↓←→ | Fast pan (3× speed) |
| F | Focus search input |
| T | Toggle text-select mode (copy SVG labels) |
| R | Rotate 90° clockwise |
| M | Toggle meeting mode (laser pointer) |
| L | Copy share link to clipboard |
| ? | Show/hide keyboard shortcuts panel |
📤 Export Formats
| Format | Transparent | Notes | | ------ | ----------- | ------------------------------------- | | PNG | ✅ | High-res raster; default 4× scale | | SVG | ✅ | Fully scalable vector | | JPEG | ❌ | Smallest file size | | WebP | ✅ | Modern format; good compression | | PDF | ❌ | Requires jsPDF (lazy-loaded from CDN) | | Copy | ❌ | Copies PNG to system clipboard |
Programmatic export
const el = document.querySelector(".diagram");
// Format shortcuts
await DiagView.exportToPNG(el, { transparent: true });
await DiagView.exportToSVG(el);
await DiagView.exportToJPEG(el, { filename: "my-diagram" });
await DiagView.exportToWebP(el, { transparent: true });
await DiagView.exportToPDF(el);
await DiagView.copyToClipboard(el);
// Generic dispatcher (used internally by the UI)
await DiagView.exportDiagram(el, "png", { transparent: true });🌐 Framework Integration
Live example: React 18 + StrictMode demo (mount, unmount, remount, replace).
One rule for component frameworks (React, Vue, Svelte, Angular): keep the diagram element nested inside a container that your component renders and owns, as in the examples below. With the
floatingandheaderlayouts DiagView moves the diagram element into a wrapper to place the toolbar. Frameworks that later remove that exact element themselves will fail, because it is no longer where they left it. Removing the outer container is always safe. If you would rather DiagView never touch the surrounding DOM, uselayout: "off"; fullscreen, zoom, search and export still work, only the inline toolbar is dropped.
React
import { useEffect } from "react";
import DiagView from "diagview";
export default function App() {
useEffect(() => {
DiagView.init({ layout: "floating" });
return () => {
DiagView.destroy();
};
}, []);
return (
<div className="diagram-host">
<div className="diagram">
<svg viewBox="0 0 400 300">{/* ... */}</svg>
</div>
</div>
);
}Vue 3
<script setup>
import { onMounted, onUnmounted } from "vue";
import DiagView from "diagview";
onMounted(() => DiagView.init({ layout: "floating" }));
onUnmounted(() => DiagView.destroy());
</script>
<template>
<div class="diagram-host">
<div class="diagram">
<svg viewBox="0 0 400 300"><!-- ... --></svg>
</div>
</div>
</template>Svelte
<script>
import { onMount, onDestroy } from 'svelte';
import DiagView from 'diagview';
onMount(() => DiagView.init({ layout: 'floating' }));
onDestroy(() => DiagView.destroy());
</script>
<div class="diagram-host">
<div class="diagram">
<svg viewBox="0 0 400 300"><!-- ... --></svg>
</div>
</div>Shadow DOM
const shadow = myElement.attachShadow({ mode: "open" });
// ... render content into shadow root ...
DiagView.init(); // init normally first
DiagView.initShadowRoot(shadow); // then scan the shadow rootThe stylesheet is installed inside the shadow root, so the inline toolbar is styled without any extra CSS.
Mermaid.js
Always render Mermaid first, then initialize DiagView:
await mermaid.run();
DiagView.init({ diagramSelector: ".mermaid" });⚙️ Configuration
Full configuration reference:
DiagView.init({
// ── Selectors ────────────────────────────────────
diagramSelector: ".diagram, .chart, [data-diagram]",
// ── Theme ────────────────────────────────────────
accentColor: null, // null = auto-detect from CSS vars / OS
backgroundColor: null, // null = auto-detect
textColor: null, // null = auto-detect
// ── Layout ───────────────────────────────────────
layout: "floating", // 'header' | 'floating' | 'off'
// ── UI ───────────────────────────────────────────
ui: {
buttons: {
style: "accent", // 'transparent' | 'accent' | 'solid' | 'neutral'
icons: {
copy: null, // null = built-in icon, or pass an SVG string
download: null,
fullscreen: null,
},
},
},
showBranding: true, // Show DiagView branding link
showKeyboardHelp: true, // Show shortcut panel on first open
helpTimeout: 8000, // ms before shortcut panel auto-closes (0 = never)
animateOpen: true, // CSS scale animation when opening fullscreen
// ── Interaction ──────────────────────────────────
naturalPanning: false, // true = scroll-like pan direction
rememberZoom: false, // true = restore zoom/pan across modal opens (session)
showMinimap: true, // Show minimap when diagram overflows viewport
// ── Zoom / Pan ───────────────────────────────────
maxZoomScale: 25, // Upper zoom limit (1–50)
minZoomScale: 0.05, // Lower zoom limit (0.01–1)
zoomAnimationDuration: 200, // ms
panAnimationDuration: 200, // ms
// ── Export ───────────────────────────────────────
highResScale: 4, // Desktop export multiplier (1–10)
mobileScale: 2, // Mobile export multiplier (1–5)
maxPixels: 16777216, // Safety cap (default 16MP = 4096×4096)
// ── Security ─────────────────────────────────────
security: {
mode: "strict", // 'strict' | 'permissive' | 'off'
allowOverrides: true, // Allow data-diagview-sanitize per element
allowRemoteResources: false, // Allow @import / url() to external URLs
},
allowedImageTypes: ["png", "jpeg", "webp", "gif"],
// ── Performance ──────────────────────────────────
performance: {
largeFileThreshold: 1000000, // 1 MB — skip style baking above this
criticalFileLimit: 50000000, // 50 MB — hard block above this
},
// ── Notifications ────────────────────────────────
toastDuration: 2500, // Success toast duration (ms)
errorToastDuration: 5000, // Error toast duration (ms)
// ── PDF ──────────────────────────────────────────
pdfLibraryUrl: "https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js",
// pdfLibraryIntegrity is auto-set when using the default URL above.
// Set to null if you provide a custom pdfLibraryUrl.
// ── Callbacks ────────────────────────────────────
onOpen: null, // () => void — modal opened
onClose: null, // () => void — modal closed
onExport: null, // (format, filename) => void — export complete
onZoomChange: null, // (scale) => void — zoom level changed
onError: null, // (error) => void — SVG validation failed
// ── Watermark (Silent Branding) ──────────────────
watermark: {
enabled: false, // true = inject branding on export/download
text: "", // The text to display (e.g. "yourdomain.com")
style: "corner", // 'corner' | 'background' | 'both'
position: "bottom-right", // 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'four-sides'
opacity: 0.2, // 0.1 - 1.0 (default 0.2)
},
});🚀 Live Demo
Experience all features including Search, Export, and Meeting Mode in our interactive playground:
📸 Screenshots
Fullscreen Viewer
The heart of DiagView. A dedicated, distraction-free environment for deep diagram analysis with integrated tools.

Smart Minimap
Real-time navigation with accurate portrait/landscape scaling. Click anywhere to jump to that part of the diagram.

Mobile Optimized
A first-class mobile experience with pinch-to-zoom, double-tap to reset, and visual viewport stability.

Flexible Layouts
Choose the layout that fits your site: Floating HUD, Header Controls, or Minimalist (Off).
📚 Documentation
| Document | Description | | ---------------------------------------------------- | --------------------------------------- | | Live Demo | Interactive online playground | | docs/USAGE.md | Complete usage guide (basic → advanced) | | docs/API.md | Full public API reference | | docs/FAQ.md | Frequently asked questions | | BUILD.md | Local development & build instructions | | CONTRIBUTING.md | How to contribute | | SECURITY.md | Security policy | | CHANGELOG.md | Version history |
🤝 Contributing
Contributions are welcome! See CONTRIBUTING.md for guidelines.
git clone https://github.com/khadirullah/diagview.git
cd diagview
npm install
npm run dev # watch mode
npm test # run unit tests📝 License
MIT © Khadirullah Mohammad
🙏 Credits
- Panzoom — zoom/pan physics
- jsPDF — PDF export (lazy-loaded)
- Lucide Icons — icon design inspiration
🤖 Authenticity Statement
This library was conceptually designed and architected by the author to solve real-world SVG documentation needs. Implementation was produced with AI assistance under strict human supervision and code review.
