> ## Documentation Index
> Fetch the complete documentation index at: https://docs.superdoc.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Configuration

All eSign options and customization

## Document options

Control how the document is displayed and what's required:

```jsx theme={null}
document={{
  // Required - the document to display
  source: File | Blob | string,

  // Display mode
  mode: 'full',        // 'full' (default) or 'download'

  // View options (recommended)
  viewOptions: { layout: 'web' },  // 'print' (default) or 'web'

  // Requirements
  validation: {
    scroll: { required: true }  // Must scroll to bottom
  }
}}
```

### View options

Control how the document is displayed using `viewOptions.layout`:

* **`print`** (default) - Fixed page width, displays document as it prints
* **`web`** - Content reflows to fit container width (mobile/accessibility)

Use `web` when you want text to reflow to fit the container. This is recommended for mobile devices and WCAG AA reflow compliance (Success Criterion 1.4.10).

```jsx theme={null}
// Mobile-friendly responsive layout
document={{
  source: contractFile,
  viewOptions: { layout: 'web' }
}}
```

<Warning>
  **Deprecated options**: `layoutMode` and `layoutMargins` are deprecated since v2.0. Use `viewOptions` instead:

  * `layoutMode: 'responsive'` → `viewOptions: { layout: 'web' }`
  * `layoutMode: 'paginated'` → `viewOptions: { layout: 'print' }`
  * `layoutMargins` is no longer supported. Use CSS to control margins.
</Warning>

When `mode` is set to `download`, the submit button is hidden.

## Field system

Fields use a unique `id` system for identifying and updating content:

* **`id`** - Unique identifier for the field

### Document fields (injected values)

Document fields populate placeholders in your document. Three types are supported:

#### Text fields

Simple text replacement (type is optional, defaults to `'text'`):

```jsx theme={null}
fields={{
  document: [
    { id: '1', value: 'Jane Smith' },
    { id: '2', value: '2024-01-15' },
    { id: '3', value: '$50,000' }
  ]
}}
```

#### Table fields

Populate table rows with a 2D array. The first row in the document serves as a template and is preserved, while new rows are appended with the same styling:

```jsx theme={null}
fields={{
  document: [
    {
      id: '1',
      type: 'table',
      value: [
        ['Item 1', '$100', '2'],
        ['Item 2', '$200', '1'],
        ['Item 3', '$150', '3']
      ]
    }
  ]
}}
```

These update fields with matching IDs in your document.

<Note>
  Signature fields from the signer are automatically converted to images when injected into the document. Use the `textToImageDataUrl` utility if you need to generate signature images programmatically.
</Note>

### Signer fields (interactive)

```jsx theme={null}
fields={{
  signer: [
    {
      id: '1',
      type: 'signature',
      label: 'Your Signature',
      validation: { required: true }
    },
    {
      id: '2',
      type: 'checkbox',
      label: 'I accept the terms',
      validation: { required: true }
    },
    {
      id: '3',
      type: 'checkbox',
      label: 'Send me updates',
      validation: { required: false }
    }
  ]
}}
```

Field types:

* `signature` - Default text input (use a custom component for other UI)
* `checkbox` - Checkbox field
* `text` - Text input field

## Custom components

Three levels of customization:

### Level 1: Use defaults

```jsx theme={null}
<SuperDocESign document={{ source: "document.docx" }} onSubmit={handleSubmit} />
```

### Level 2: Customize labels

```jsx theme={null}
submit={{ label: "I Agree" }}
download={{ label: "Save Copy", fileName: "agreement.pdf" }}
```

### Level 3: Custom components

```jsx theme={null}
// Custom submit button
submit={{
  component: ({ onClick, isValid, isDisabled, isSubmitting }) => (
    <button
      onClick={onClick}
      disabled={!isValid || isDisabled}
      className="my-custom-button"
    >
      {isSubmitting ? <Spinner /> : 'Sign Document'}
    </button>
  )
}}

// Custom signature field
fields={{
  signer: [{
    id: '1',
    type: 'signature',
    component: ({ value, onChange, isDisabled, label }) => (
      <SignaturePad
        value={value}
        onComplete={onChange}
        disabled={isDisabled}
        title={label}
      />
    )
  }]
}}
```

## Event handlers

```jsx theme={null}
// Main submission
onSubmit={async (data) => {
  // data.eventId - Your session ID
  // data.auditTrail - Complete interaction log
  // data.signerFields - User inputs
  await api.save(data);
}}

// Download handling
onDownload={async (data) => {
  // data.documentSource - Original .docx file
  // data.fileName - Suggested filename
  // Send to backend for PDF conversion
  const response = await fetch('/api/generate-pdf', {
    method: 'POST',
    body: JSON.stringify(data)
  });
  const blob = await response.blob();
  saveAs(blob, data.fileName);
}}

// State monitoring
onStateChange={(state) => {
  // state.scrolled - Has scrolled to bottom
  // state.fields - Current field values
  // state.isValid - Ready to submit
  console.log('Ready:', state.isValid);
}}

// Field changes
onFieldChange={(field) => {
  // field.id - Field identifier
  // field.value - New value
  // field.previousValue - Old value
  analytics.track('field_changed', field);
}}

// Document analysis
onFieldsDiscovered={(fields) => {
  // All fields found in document
  console.log('Document has fields:', fields);
}}

// Zoom changes
onZoomChange={({ zoom }) => {
  // zoom - New zoom level as percentage (100, 150, etc.)
  console.log('Zoom:', zoom);
}}
```

## Zoom

Control document zoom programmatically via the component ref:

```tsx theme={null}
import { useRef, useState } from 'react';
import type { SuperDocESignHandle } from '@superdoc-dev/esign';

const ref = useRef<SuperDocESignHandle>(null);
const [zoom, setZoom] = useState(100);

// Set zoom
ref.current?.setZoom(150);

// Get current zoom
const currentZoom = ref.current?.getZoom();

// Listen for changes
<SuperDocESign
  ref={ref}
  onZoomChange={({ zoom }) => setZoom(zoom)}
  // ...
/>
```

### Example: zoom controls

```tsx theme={null}
const ZoomControls = ({ esignRef, zoom, setZoom }) => (
  <div>
    <button onClick={() => esignRef.current?.setZoom(Math.max(25, zoom - 25))}>-</button>
    <span>{zoom}%</span>
    <button onClick={() => esignRef.current?.setZoom(Math.min(400, zoom + 25))}>+</button>
  </div>
);
```

<Note>
  Zoom works with both `print` and `web` layout modes. In `print` mode, zoom is applied through the layout engine (ProseMirror). In `web` mode, zoom is applied via CSS transforms.
</Note>

## PDF support

Render PDF documents in eSign by passing the `pdf` prop. This forwards the PDF module config to SuperDoc internally. The component handles format detection automatically: when `pdf` is provided with a URL source, it tells SuperDoc to use the PDF renderer.

```jsx theme={null}
import * as pdfjsLib from 'pdfjs-dist/build/pdf.mjs';

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

<SuperDocESign
  eventId="session-1"
  document={{
    source: "https://example.com/document.pdf",
    mode: "full",
    viewOptions: { layout: "print" },
    validation: { scroll: { required: true } },
  }}
  pdf={{
    pdfLib: pdfjsLib,
    workerSrc: pdfWorkerUrl,
    setWorker: true,
    outputScale: 2,
  }}
  fields={{
    signer: [
      {
        id: "1",
        type: "checkbox",
        label: "I have read and agree to these terms",
        validation: { required: true },
      },
    ],
  }}
  download={{ label: "Download PDF" }}
  onDownload={async (data) => {
    // Browser-side download: no server needed
    const response = await fetch(data.documentSource);
    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = data.fileName || "document.pdf";
    a.click();
    URL.revokeObjectURL(url);
  }}
  onSubmit={handleSubmit}
/>
```

### `pdf` prop

| Property      | Type      | Description                                               |
| ------------- | --------- | --------------------------------------------------------- |
| `pdfLib`      | `object`  | **Required.** The `pdfjs-dist` library instance           |
| `workerSrc`   | `string`  | PDF.js worker source URL (falls back to CDN when omitted) |
| `setWorker`   | `boolean` | Whether to auto-configure the pdf.js worker               |
| `textLayer`   | `boolean` | Enable text layer for text selection (default: `false`)   |
| `outputScale` | `number`  | Canvas render scale: higher values produce sharper output |

### How it works

* SuperDoc fires `onPdfDocumentReady` instead of `onReady` for PDFs. The eSign component handles both callbacks, so it works regardless of document type.
* PDFs don't have a ProseMirror editor, so `fields.document` has no effect. Use `fields.signer` for interactive fields like checkboxes and signatures.
* Use `viewOptions: { layout: 'print' }` for fixed page widths that match the original PDF layout.

<Note>
  Memoize the `pdf` config object to avoid unnecessary re-initialization. Use `useMemo` in React or a stable reference from the caller.
</Note>

## Styling

The component can be styled using standard CSS. Optionally import default styles:

```jsx theme={null}
// Optional: import default styles
import '@superdoc-dev/esign/styles.css';

<SuperDocESign
  className="my-esign-container"
  style={{ maxWidth: "800px" }}
  documentHeight="500px" // Height of document viewer
/>
```

### CSS classes

Target these classes to customize appearance:

| Class                               | Description                                    |
| ----------------------------------- | ---------------------------------------------- |
| `.superdoc-esign-container`         | Root container (also accepts `className` prop) |
| `.superdoc-esign-document`          | Document section wrapper                       |
| `.superdoc-esign-document-toolbar`  | Toolbar with download button                   |
| `.superdoc-esign-document-controls` | Control buttons container                      |
| `.superdoc-esign-document-viewer`   | Scroll container (SuperDoc mounts inside)      |
| `.superdoc-esign-controls`          | Fields and buttons area                        |
| `.superdoc-esign-fields`            | Field container                                |
| `.superdoc-esign-actions`           | Action buttons container                       |
| `.superdoc-esign-form-actions`      | Form submit button container                   |

### Customizing with CSS

Style the component using standard CSS - no special variables needed:

```css theme={null}
.superdoc-esign-document-viewer {
  background: #f8fafc;
}

.superdoc-esign-controls {
  margin-top: 0; /* Remove gap between viewer and controls */
  padding: 20px 24px;
  background: #ffffff;
  border-top: 1px solid #e2e8f0;
}

.superdoc-esign-fields {
  margin-bottom: 16px;
}

.superdoc-esign-actions {
  gap: 12px;
}
```

## Themed example

Style the component to match your brand.

### Structure

```
.superdoc-esign-container
├── .superdoc-esign-document
│   ├── .superdoc-esign-document-toolbar
│   │   └── .superdoc-esign-document-controls
│   └── .superdoc-esign-document-viewer
│       └── .super-editor (the document)
└── .superdoc-esign-controls
    ├── .superdoc-esign-fields
    └── .superdoc-esign-actions
```

### CSS

```css theme={null}
/* Card-like container */
.brand-signer {
  border: 1px solid #e2e8f0;
  border-radius: 12px;
  overflow: hidden;
}

/* Document viewer background */
.brand-signer .superdoc-esign-document-viewer {
  background: #f8fafc;
}

/* Controls area styling */
.brand-signer .superdoc-esign-controls {
  margin-top: 0;
  padding: 20px 24px;
  background: #ffffff;
  border-top: 1px solid #e2e8f0;
}

/* Style the document editor */
.brand-signer .super-editor {
  border-radius: 12px 12px 0 0;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}
```

### Component

```jsx theme={null}
<SuperDocESign
  className="brand-signer"
  documentHeight="500px"
  // ... other props
/>
```

## Telemetry

Telemetry is enabled by default with `source: 'esign'` metadata. You can override or extend the defaults:

```jsx theme={null}
<SuperDocESign
  licenseKey="your-license-key"
  telemetry={{ enabled: true, metadata: { source: "my-app", environment: "production" } }}
  // ... other props
/>
```

To disable telemetry:

```jsx theme={null}
<SuperDocESign telemetry={{ enabled: false }} />
```

For more details on how telemetry works, see the [Telemetry](/resources/telemetry) page.

### License key

Pass `licenseKey` to identify your organization in telemetry:

```jsx theme={null}
<SuperDocESign licenseKey="your-license-key" />
```

The key is used solely for organization identification. It does not enable or disable any features, and nothing is blocked if a usage quota is reached. The key is forwarded to the underlying SuperDoc instance.

## Complete example

```jsx theme={null}
<SuperDocESign
  eventId={`session-${Date.now()}`}
  document={{
    source: contractFile,
    mode: "full",
    viewOptions: { layout: "web" },
    validation: {
      scroll: { required: true },
    },
  }}
  fields={{
    document: [
      { id: "1", value: companyName },
      { id: "2", value: new Date().toLocaleDateString() },
    ],
    signer: [
      {
        id: "1",
        type: "signature",
        validation: { required: true },
        label: "Sign here",
      },
      {
        id: "2",
        type: "checkbox",
        validation: { required: true },
        label: "I accept all terms",
      },
    ],
  }}
  download={{
    fileName: "signed-contract.pdf",
    label: "Download Copy",
  }}
  submit={{
    label: "Complete Signing",
  }}
  onSubmit={handleSubmit}
  onStateChange={updateUI}
  className="contract-signer"
  documentHeight="600px"
/>
```
