PDFViewer
A full-featured PDF viewing component with form fields, digital signatures, zoom controls, and document submission capabilities.
Import
import { PDFViewer } from '@mims/sdk-react';Basic Usage
<PDFViewer
documentId="doc_abc123"
documentUrl="https://example.com/document.pdf"
onSubmit={(payload) => console.log('Submitted:', payload)}
/>Props
Required Props
| Prop | Type | Default | Description |
|---|---|---|---|
documentIdrequired | string | — | Unique identifier for the document. Used for submission tracking. |
documentUrlrequired | string | — | URL to the PDF document. Can be a signed URL from your backend. |
Display Options
| Prop | Type | Default | Description |
|---|---|---|---|
initialScale | number | 1 | Initial zoom level. 1 = 100%, 0.5 = 50%, 2 = 200%. |
showToolbar | boolean | true | Show/hide the toolbar with navigation and zoom controls. |
editable | boolean | true | Allow users to interact with and fill form fields. |
showFieldTools | boolean | true | Show field creation tools in the toolbar (requires editable=true). |
height | string | number | "100%" | Height of the viewer container. |
className | string | — | Additional CSS class names for the container. |
style | React.CSSProperties | — | Inline styles for the container. |
Initial Data
| Prop | Type | Default | Description |
|---|---|---|---|
initialFields | AnyFieldDefinition[] | [] | Pre-defined fields to display on the document. |
Event Callbacks
| Prop | Type | Default | Description |
|---|---|---|---|
onDocumentLoad | (pages: PageInfo[]) => void | — | Called when the PDF is successfully loaded. |
onDocumentError | (error: Error) => void | — | Called when the PDF fails to load. |
onFieldAdd | (field: AnyFieldDefinition) => void | — | Called when a new field is added. |
onFieldUpdate | (fieldId: string, updates: Partial<AnyFieldDefinition>) => void | — | Called when a field position or properties change. |
onFieldValueChange | (fieldId: string, value: AnyFieldValue) => void | — | Called when a field value changes. |
onFieldRemove | (fieldId: string) => void | — | Called when a field is removed. |
onBeforeSubmit | (payload: DocumentSubmissionPayload) => boolean | Promise<boolean> | — | Called before submission. Return false to cancel. |
onSubmit | (payload: DocumentSubmissionPayload) => void | Promise<void> | — | Called after successful submission. |
onSubmitError | (error: Error) => void | — | Called when submission fails. |
Examples
Basic Document Viewer
function BasicViewer() {
return (
<div style={{ height: '600px' }}>
<PDFViewer
documentId="doc_123"
documentUrl="/contracts/agreement.pdf"
showToolbar={true}
editable={false}
/>
</div>
);
}With Pre-defined Fields
1const fields = [2 {3 id: 'name_field',4 type: 'text' as const,5 page: 1,6 x: 0.1,7 y: 0.3,8 width: 0.3,9 height: 0.04,10 required: true,11 editable: true,12 label: 'Full Name',13 placeholder: 'Enter your full name',14 },15 {16 id: 'signature_field',17 type: 'signature' as const,18 page: 1,19 x: 0.1,20 y: 0.7,21 width: 0.3,22 height: 0.1,23 required: true,24 editable: true,25 label: 'Signature',26 },27 {28 id: 'date_field',29 type: 'date' as const,30 page: 1,31 x: 0.5,32 y: 0.7,33 width: 0.2,34 height: 0.04,35 required: true,36 editable: true,37 label: 'Date',38 },39];4041function DocumentWithFields() {42 return (43 <PDFViewer44 documentId="contract_456"45 documentUrl="/contracts/nda.pdf"46 initialFields={fields}47 onFieldValueChange={(fieldId, value) => {48 console.log(`Field ${fieldId} changed:`, value);49 }}50 />51 );52}Full Submission Flow
1function ContractSigningPage({ documentId }: { documentId: string }) {2 const [isSubmitting, setIsSubmitting] = useState(false);3 const [submitSuccess, setSubmitSuccess] = useState(false);4 const router = useRouter();56 const handleBeforeSubmit = async (payload: DocumentSubmissionPayload) => {7 // Validate all required fields are filled8 const requiredFields = payload.fields.filter(f => f.required);9 const missingFields = requiredFields.filter(f => !f.value);10 11 if (missingFields.length > 0) {12 alert('Please fill all required fields');13 return false;14 }15 16 return true;17 };1819 const handleSubmit = async (payload: DocumentSubmissionPayload) => {20 setIsSubmitting(true);21 22 // The SDK automatically sends to MIMS API23 // You can also send to your own backend24 await fetch('/api/contracts/complete', {25 method: 'POST',26 headers: { 'Content-Type': 'application/json' },27 body: JSON.stringify({28 documentId: payload.documentId,29 submittedAt: payload.submittedAt,30 }),31 });32 33 setSubmitSuccess(true);34 setIsSubmitting(false);35 36 // Redirect after 2 seconds37 setTimeout(() => {38 router.push('/contracts/completed');39 }, 2000);40 };4142 const handleSubmitError = (error: Error) => {43 setIsSubmitting(false);44 alert(`Submission failed: ${error.message}`);45 };4647 if (submitSuccess) {48 return (49 <div className="flex flex-col items-center justify-center h-64">50 <CheckCircle className="w-16 h-16 text-green-500" />51 <h2 className="mt-4 text-xl font-semibold">Document Submitted!</h2>52 <p className="text-gray-500">Redirecting...</p>53 </div>54 );55 }5657 return (58 <PDFViewer59 documentId={documentId}60 documentUrl={`/api/documents/${documentId}/download`}61 onDocumentLoad={(pages) => {62 console.log(`Loaded ${pages.length} pages`);63 }}64 onBeforeSubmit={handleBeforeSubmit}65 onSubmit={handleSubmit}66 onSubmitError={handleSubmitError}67 />68 );69}Field Positioning
Fields use normalized coordinates (0-1) relative to page dimensions. This ensures fields are positioned correctly regardless of zoom level or rendering size.
// Field at 10% from left, 30% from top
// Width: 30% of page, Height: 4% of page
{
x: 0.1,
y: 0.3,
width: 0.3,
height: 0.04,
}Coordinate System
x: 0= left edge,x: 1= right edgey: 0= top edge,y: 1= bottom edge- Width and height are also normalized (0-1)
Toolbar Features
The default toolbar includes:
- Page Navigation: Previous/next page, page number input
- Zoom Controls: Zoom in, zoom out, fit to width/page
- Field Tools: Add text, signature, checkbox, date, initials fields
- Submit Button: Validates and submits the document
Styling
Customize the viewer appearance:
<PDFViewer
documentId="..."
documentUrl="..."
className="my-custom-viewer"
style={{
borderRadius: '8px',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
}}
/>
/* CSS */
.my-custom-viewer {
background: #f5f5f5;
}
.my-custom-viewer .mims-pdf-toolbar {
background: #1a1a1a;
color: white;
}Error Handling
<PDFViewer
documentId="..."
documentUrl="..."
onDocumentError={(error) => {
if (error.message.includes('404')) {
showNotification('Document not found');
} else if (error.message.includes('403')) {
showNotification('Access denied');
} else {
showNotification('Failed to load document');
logError(error);
}
}}
onSubmitError={(error) => {
if (error.message.includes('validation')) {
showNotification('Please fill all required fields');
} else {
showNotification(`Submission failed: ${error.message}`);
}
}}
/>TypeScript Types
import type {
PDFViewerProps,
AnyFieldDefinition,
AnyFieldValue,
DocumentSubmissionPayload,
PageInfo,
FieldType,
} from '@mims/sdk-react';
// Field types: 'text' | 'signature' | 'checkbox' | 'date' | 'initials'