Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion apps/docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@
},
"modules/comments",
"modules/toolbar",
"modules/context-menu"
"modules/context-menu",
"modules/pdf",
"modules/whiteboard"
]
},
{
Expand Down
6 changes: 6 additions & 0 deletions apps/docs/modules/overview.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ const superdoc = new SuperDoc({
<Card title="Context Menu" icon="menu" href="/modules/context-menu">
Right-click actions and custom commands
</Card>
<Card title="PDF" icon="file-text" href="/modules/pdf">
PDF viewer setup and configuration
</Card>
<Card title="Whiteboard" icon="pencil" href="/modules/whiteboard">
Annotation layer for documents
</Card>
</CardGroup>

Each module is configured via `modules.<name>` in the [SuperDoc configuration](/core/superdoc/configuration). See individual module pages for all available options.
Expand Down
101 changes: 101 additions & 0 deletions apps/docs/modules/pdf.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
---
title: PDF
keywords: "pdf viewer, pdf.js, pdf rendering, text layer, zoom, annotations"
---

Render PDFs in SuperDoc. The PDF viewer is configured through `modules.pdf`.

## Install pdf.js

Install `pdfjs-dist` in your app:

```bash
npm i pdfjs-dist
```

Supported versions: `>= 5.4.296`.

## Quick start

```javascript
import { SuperDoc } from 'superdoc';
import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';

const pathToWorker = new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString(); // example in Vite

const superdoc = new SuperDoc({
selector: '#viewer',
document: fileBlob,
modules: {
pdf: {
pdfLib: pdfjsLib, // required
setWorker: true, // auto-configure worker
workerSrc: pathToWorker, // path to worker (falls back to CDN if omitted)
},
},
onPdfDocumentReady: () => {
console.log('PDF ready');
},
});
```

## Worker setup (recommended)

This is the recommended approach because the worker is configured once for the whole application.

```javascript
import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';

pdfjsLib.GlobalWorkerOptions.workerSrc =
new URL('pdfjs-dist/build/pdf.worker.min.mjs', import.meta.url).toString();
```

Then disable auto-setup:

```javascript
modules: {
pdf: {
pdfLib: pdfjsLib,
setWorker: false,
},
}
```

## Configuration

<ParamField path="modules.pdf.pdfLib" type="Object" required>
Preloaded pdf.js library instance
</ParamField>

<ParamField path="modules.pdf.workerSrc" type="string">
PDF.js worker source URL (falls back to CDN when omitted)
</ParamField>

<ParamField path="modules.pdf.setWorker" type="boolean" default="false">
Whether to auto-configure pdf.js worker
</ParamField>

<ParamField path="modules.pdf.textLayer" type="boolean" default="false">
Enable text layer rendering (for text selection)
</ParamField>

<ParamField path="modules.pdf.outputScale" type="number" default="2">
Canvas render scale (quality)
</ParamField>

## Events

### `pdf:document-ready`

Fired when all PDF pages are rendered.

```javascript
superdoc.on('pdf:document-ready', () => {
console.log('PDF ready');
});
```

## Notes

- `outputScale` affects render quality; zooming does not re-render the canvas.
- If you need text selection, enable `textLayer: true`.
177 changes: 177 additions & 0 deletions apps/docs/modules/whiteboard.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
---
title: Whiteboard
keywords: "whiteboard, pdf annotations, draw, erase, stickers, text"
---

Lightweight annotation layer for documents. Supports drawing, text, and stickers.

<Note>
Whiteboard currently works **only with PDF documents**. See [PDF](/modules/pdf) setup first.
</Note>

## Quick start

```javascript
const superdoc = new SuperDoc({
modules: {
whiteboard: {
enabled: true, // show whiteboard layer by default
},
},
});
```

<Note>
To disable the whiteboard layer entirely, set `modules.whiteboard` to `false`:

```javascript
modules: {
whiteboard: false;
}
```
</Note>

## Tools / modes

- **select** — default; select/drag/resize, drop stickers/text
- **draw** — draw strokes only
- **erase** — erases strokes only
- **text** — click to add text

These modes are intentionally strict to avoid ambiguous interactions.

## API methods

All APIs are exposed via `superdoc.whiteboard`.

### `register`

Register palette items (e.g. stickers, comments).

```javascript
superdoc.whiteboard.register('stickers', [
{ id: 'check-mark', label: 'Check', src: '/stickers/check-mark.svg', width: 100, height: 83 },
]);

superdoc.whiteboard.register('comments', [
{ id: 'great-job', text: 'Great job!' },
]);
```

### `getType`

Get registered items by type.

```javascript
const stickers = superdoc.whiteboard.getType('stickers');
```

### `setTool`

Set the current tool: `select`, `draw`, `erase`, `text`.

```javascript
superdoc.whiteboard.setTool('draw');
```

### `setEnabled`

Enable or disable whiteboard interactivity.

```javascript
superdoc.whiteboard.setEnabled(true);
```

### `setOpacity`

Set overlay opacity (0–1).

```javascript
superdoc.whiteboard.setOpacity(0.8);
```

### `getWhiteboardData`

Export annotations (normalized coordinates).

```javascript
const data = superdoc.whiteboard.getWhiteboardData();
```

### `setWhiteboardData`

Import annotations.

```javascript
superdoc.whiteboard.setWhiteboardData(json);
```

### `rerender`

Force re-render for all pages.

```javascript
superdoc.whiteboard.rerender();
```

## Events

### `whiteboard:init`

Fired when the whiteboard instance is created.

```javascript
superdoc.on('whiteboard:init', ({ whiteboard }) => {
console.log('Whiteboard instance ready');
});
```

### `whiteboard:ready`

Fired when all whiteboard pages are ready.

```javascript
superdoc.on('whiteboard:ready', ({ whiteboard }) => {
console.log('Whiteboard pages ready');
});
```

### `whiteboard:change`

Fired on any data change. Receives full whiteboard JSON.

```javascript
superdoc.on('whiteboard:change', (data) => {
console.log(data);
});
```

### `whiteboard:enabled`

Fired when interactivity is toggled.

```javascript
superdoc.on('whiteboard:enabled', (enabled) => {
console.log(enabled);
});
```

### `whiteboard:tool`

Fired when the active tool changes.

```javascript
superdoc.on('whiteboard:tool', (tool) => {
console.log(tool);
});
```

## Import / export

Whiteboard data is stored in normalized coordinates so annotations stay stable across zoom levels.

```javascript
const saved = superdoc.whiteboard.getWhiteboardData();

superdoc.whiteboard.setWhiteboardData(saved);
```
2 changes: 2 additions & 0 deletions apps/docs/scripts/validate-code-imports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ const EXACT_EXTERNAL_IMPORTS = new Set([
'react-dom',
'react-dom/client',
'vue',
'pdfjs-dist',
'pdfjs-dist/build/pdf.mjs',
'yjs',
'y-prosemirror',
'y-websocket',
Expand Down
Loading