import { Eraser } from 'lucide-react'; import { useEffect, useRef } from 'react'; import SignatureCanvasImport from 'react-signature-canvas'; import InputError from '@/components/input-error'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; // react-signature-canvas ships as a CommonJS/UMD bundle. Vite's dev-server // pre-bundling wraps its `module.exports` (itself `{ __esModule: true, // default: SignatureCanvas }`) as the ESM default export, so the default // import resolves one layer too shallow. Unwrap it before use. const SignatureCanvas = (( SignatureCanvasImport as unknown as { default?: typeof SignatureCanvasImport; } ).default ?? SignatureCanvasImport) as typeof SignatureCanvasImport; type SignaturePadProps = { name: string; error?: string; /** Renders a small, chrome-free pad sized to sit inline with other * compact signature placeholders (e.g. a document's signature row). */ compact?: boolean; /** Fires with the captured signature file whenever the drawing changes, * for callers that submit it outside a native
(e.g. via router). */ onCapture?: (file: File | null) => void; }; export function SignaturePad({ name, error, compact, onCapture, }: SignaturePadProps) { const padRef = useRef(null); const fileInputRef = useRef(null); // The canvas element's drawing-surface resolution (width/height // attributes) does not automatically follow its CSS-rendered size, so // without this, pointer coordinates drift from where ink is drawn — // worse on HiDPI screens. Size the backing buffer to match on mount and // whenever the layout might change. useEffect(() => { function resizeCanvas() { const canvas = padRef.current?.getCanvas(); if (!canvas) { return; } const ratio = Math.max(window.devicePixelRatio || 1, 1); canvas.width = canvas.offsetWidth * ratio; canvas.height = canvas.offsetHeight * ratio; canvas.getContext('2d')?.scale(ratio, ratio); padRef.current?.clear(); } resizeCanvas(); window.addEventListener('resize', resizeCanvas); return () => window.removeEventListener('resize', resizeCanvas); }, []); function syncFileInput() { const pad = padRef.current; const input = fileInputRef.current; if (!pad || !input || pad.isEmpty()) { return; } pad.getTrimmedCanvas().toBlob((blob: Blob | null) => { if (!blob) { return; } const file = new File([blob], 'signature.png', { type: 'image/png', }); const dataTransfer = new DataTransfer(); dataTransfer.items.add(file); input.files = dataTransfer.files; onCapture?.(file); }, 'image/png'); } function handleClear() { padRef.current?.clear(); if (fileInputRef.current) { fileInputRef.current.value = ''; } onCapture?.(null); } if (compact) { return (
); } return (

Gambar tanda tangan Anda pada kotak di atas menggunakan mouse atau layar sentuh.

); }