Complete clickwrap solution with built-in document viewing. Track agreements, signatures, and consents.
npm install clickwrapOrchestrate legal agreements with SuperDoc. Track document reading, signatures, and consent checkboxes without the UI overhead.
SuperDoc is great at rendering documents. But legal agreements need more - scroll tracking, signatures, consent checkboxes. This orchestrator handles that coordination while you keep full control of your UI.
Note: Clickwrap includes SuperDoc internally. You don't need to install or initialize SuperDoc separately.
``bash`
npm install clickwrap
`javascript
import Clickwrap from 'clickwrap'
import SignaturePad from 'signature_pad'
// Initialize Clickwrap with built-in SuperDoc
const clickwrap = new Clickwrap({
// Document configuration - Clickwrap handles SuperDoc internally!
document: '/terms.pdf', // PDF/DOCX file or URL
documentElement: '#document', // Where to render
documentId: 'terms-v2.1', // Optional document identifier
// UI Components
signaturePad: new SignaturePad(canvas),
consentElements: document.querySelectorAll('.consent'),
acceptButton: document.querySelector('#accept'),
// Requirements
requirements: {
scrollThreshold: 0.95,
signature: true,
consents: ['terms', 'privacy']
},
// Callbacks
onReady: () => console.log('Document loaded!'),
onAccept: async (data) => {
// Send to your backend
await api.saveAgreement(data)
}
})
`
✅ Handles SuperDoc initialization internally
✅ Tracks document scroll progress
✅ Validates signatures (bring your own signature library)
✅ Manages consent checkboxes
✅ Enables accept button when requirements are met
✅ Collects timestamped agreement data
✅ Provides progress tracking and validation states
❌ No UI components - you build the interface
❌ No backend - you handle data storage
❌ No styling - you control the look
When a user accepts, you receive everything needed for legal compliance:
`javascript`
{
timestamp: "2024-01-15T10:30:00Z",
documentId: "terms-v2.1",
documentUrl: "/terms.pdf", // if document was a URL
duration: 47, // seconds spent
scrollProgress: "100%", // how far they scrolled
signature: "data:image/png;...", // signature image (if required)
consents: {
terms: true,
privacy: true,
marketing: false
},
action: "accepted" // or "declined"
}
`javascript`
new Clickwrap({
// Document configuration
document: '/terms.pdf', // URL or File object (PDF/DOCX)
documentElement: '#document', // Selector or element where to render
documentId: 'terms-v2.1', // Optional document identifier
superdocConfig: {}, // Optional SuperDoc configuration
// Components (bring your own)
signaturePad: pad, // SignaturePad or compatible
consentElements: checkboxes, // Your checkbox elements
acceptButton: button, // Gets enabled when valid
declineButton: button, // Optional decline
// Requirements
requirements: {
scrollThreshold: 0.95, // 0-1 (95% = nearly complete)
signature: true, // Signature required?
consents: ['terms', 'privacy'] // Required checkbox names
},
// Callbacks
onReady: () => {}, // Document loaded and ready
onProgress: (state) => {}, // Track completion
onAccept: async (data) => {}, // Handle acceptance
onDecline: async (data) => {} // Handle rejection
})
- validate() - Check if all requirements are metgetData()
- - Get current agreement datareset()
- - Clear all inputs and start overgetProgress()
- - Get completion percentage (returns {completed, total, percentage})destroy()
- - Clean up instance and SuperDoc
`jsx`
function AgreementModal({ document }) {
const canvasRef = useRef()
const clickwrapRef = useRef()
useEffect(() => {
// Initialize Clickwrap with built-in SuperDoc
const signaturePad = new SignaturePad(canvasRef.current)
clickwrapRef.current = new Clickwrap({
// Document configuration
document: document.url, // PDF/DOCX URL
documentElement: '#agreement-doc', // Where to render
documentId: document.id,
// UI Components
signaturePad,
consentElements: document.querySelectorAll('.consent'),
acceptButton: document.querySelector('#accept'),
// Requirements
requirements: {
scrollThreshold: 0.95,
signature: true,
consents: ['terms']
},
// Callbacks
onReady: () => {
console.log('Document loaded!')
},
onAccept: async (data) => {
await api.recordAgreement(data)
closeModal()
}
})
return () => {
clickwrapRef.current?.destroy()
}
}, [document])
return (
)
}
`vue
`
Works with any scrollable element if you don't need document rendering:
`javascript`
const clickwrap = new Clickwrap({
// No 'document' parameter - just track existing element
documentElement: document.querySelector('.terms-text'),
documentId: 'terms-v2.1',
signaturePad: new SignaturePad(canvas),
consentElements: document.querySelectorAll('.consent'),
acceptButton: document.querySelector('#accept'),
requirements: {
scrollThreshold: 0.95,
signature: true,
consents: ['terms']
},
onAccept: async (data) => {
await api.saveAgreement(data)
}
})
Works with any signature library that has isEmpty() and clear()` methods:
- signature_pad ✅
- React Signature Canvas ✅
- Vue Signature Pad ✅
- Custom implementations ✅
Modern browsers only. No IE11.
MIT
Built by the SuperDoc team to make legal agreements easier. Part of the SuperDoc ecosystem.