@melihbirim/signature-pad
v1.0.0
Published
A React signature pad component with draw and type modes
Downloads
98
Maintainers
Readme
@melihbirim/signature-pad
A lightweight React component for collecting signatures with draw and type modes. Zero dependencies beyond React.
Installation
npm install @melihbirim/signature-padRequires React 18+.
Quick Start
import { SignaturePad } from '@melihbirim/signature-pad';
import { useState } from 'react';
function App() {
const [signature, setSignature] = useState<string>();
const handleUpload = async (file: File): Promise<string> => {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/api/upload', { method: 'POST', body: formData });
const data = await response.json();
return data.path;
};
return (
<SignaturePad
value={signature}
onChange={setSignature}
onUpload={handleUpload}
/>
);
}Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| value | string \| undefined | - | Current signature path/URL |
| onChange | (value?: string) => void | - | Called when signature changes |
| onUpload | (file: File) => Promise<string> | Required | Upload function, returns path/URL |
| width | number | 600 | Canvas width in pixels |
| height | number | 200 | Canvas height in pixels |
| getFullUrl | (path: string) => string | (p) => p | Convert path to full URL for display |
| watermark | WatermarkConfig | - | Add metadata overlay (IP, timestamp, timezone) |
| typedFont | string | "Brush Script MT", cursive | Font for typed signatures |
| labels | LabelsConfig | - | Customize button/label text |
| styles | StylesConfig | - | Custom CSS styles |
| headless | boolean | false | Render only canvas, no UI |
| renderToolbar | (props) => ReactNode | - | Custom toolbar component |
| renderSignature | (props) => ReactNode | - | Custom signature display |
| onUploadStart | () => void | - | Called before upload starts |
| onUploadEnd | (path: string) => void | - | Called after upload succeeds |
| onUploadError | (error: Error) => void | - | Called on upload failure |
| onMessage | (type, text) => void | - | Custom message handler |
Imperative API
Access methods via ref:
const ref = useRef<SignaturePadRef>(null);
<SignaturePad ref={ref} onUpload={handleUpload} />
// Methods
ref.current?.clear(); // Clear canvas
ref.current?.uploadSignature(); // Trigger upload
ref.current?.setMode('draw' | 'type'); // Switch modes
ref.current?.getCanvas(); // Get canvas elementUpload Examples
AWS S3 with Presigned URL
const handleUpload = async (file: File): Promise<string> => {
const { data } = await axios.post('/api/s3/presigned-url', {
filename: file.name,
contentType: file.type,
});
await axios.put(data.uploadUrl, file, {
headers: { 'Content-Type': file.type },
});
return data.key;
};Direct Server Upload
const handleUpload = async (file: File): Promise<string> => {
const formData = new FormData();
formData.append('signature', file);
const response = await fetch('/api/signatures', {
method: 'POST',
headers: { 'Authorization': `Bearer ${token}` },
body: formData,
});
const { filePath } = await response.json();
return filePath;
};Customization
Custom Labels
<SignaturePad
onUpload={handleUpload}
labels={{
draw: 'Draw',
type: 'Type',
clear: 'Clear',
useSignature: 'Save',
removeSignature: 'Remove',
typePlaceholder: 'Your name',
}}
/>Custom Styles
<SignaturePad
onUpload={handleUpload}
styles={{
container: { border: '2px solid #000' },
canvas: { borderRadius: 8 },
preview: { maxWidth: 400 },
}}
/>Watermark
<SignaturePad
onUpload={handleUpload}
watermark={{
enabled: true,
ipAddress: '192.168.1.1',
timezone: 'America/New_York',
fontSize: 10,
color: '#666',
}}
/>Headless Mode
<SignaturePad
value={signature}
onChange={setSignature}
onUpload={handleUpload}
headless={true}
renderToolbar={({ mode, onModeChange, onClear, onUpload }) => (
<div>
<button onClick={() => onModeChange('draw')}>Draw</button>
<button onClick={() => onModeChange('type')}>Type</button>
<button onClick={onClear}>Clear</button>
<button onClick={onUpload}>Save</button>
</div>
)}
/>Upload State Tracking
function App() {
const [uploading, setUploading] = useState(false);
return (
<SignaturePad
onUpload={handleUpload}
onUploadStart={() => setUploading(true)}
onUploadEnd={() => setUploading(false)}
onUploadError={(err) => {
setUploading(false);
console.error(err);
}}
/>
);
}Features
- Draw with mouse or touch (smooth Bezier curves)
- Type signatures with custom fonts
- DPI-aware rendering for Retina displays
- Imperative API via ref
- Upload lifecycle hooks
- Watermark support
- Headless mode for custom UI
- TypeScript support
- Zero dependencies
License
MIT
