UNPKG

pdf-e-signature

Version:

A React component that allows users to select positions for e-signatures on PDFs

157 lines (156 loc) 5.36 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = require("react"); var _pdfLib = require("pdf-lib"); const usePDFOperations = () => { const [pdfFile, setPdfFile] = (0, _react.useState)(null); const [pdfUrl, setPdfUrl] = (0, _react.useState)(null); const [numPages, setNumPages] = (0, _react.useState)(null); const [currentPage, setCurrentPage] = (0, _react.useState)(1); const [scale, setScale] = (0, _react.useState)(1.5); const [signaturePositions, setSignaturePositions] = (0, _react.useState)([]); const [isSelectingPosition, setIsSelectingPosition] = (0, _react.useState)(false); const [viewMode, setViewMode] = (0, _react.useState)('upload'); const containerRef = (0, _react.useRef)(null); const [cursorPosition, setCursorPosition] = (0, _react.useState)({ x: 0, y: 0 }); const handleFileChange = e => { const file = e.target.files[0]; if (file && file.type === 'application/pdf') { setPdfFile(file); const fileURL = URL.createObjectURL(file); setPdfUrl(fileURL); setSignaturePositions([]); setViewMode('upload'); } }; const handlePdfClick = e => { if (!isSelectingPosition) return; const container = containerRef.current; const pdfElement = container.querySelector(".react-pdf__Page"); if (!pdfElement) return; const pdfRect = pdfElement.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); const scrollLeft = container.scrollLeft || 0; const scrollTop = container.scrollTop || 0; const normalizedX = (e.clientX + scrollLeft - pdfRect.left) / pdfRect.width; const normalizedY = (e.clientY + scrollTop - pdfRect.top) / pdfRect.height; const newSignaturePosition = { normalizedX, normalizedY, page: currentPage, scale: scale, pdfWidth: pdfRect.width, pdfHeight: pdfRect.height, containerWidth: containerRect.width, containerHeight: containerRect.height }; setSignaturePositions([...signaturePositions, newSignaturePosition]); }; const handleRemoveSign = index => { const signature = signaturePositions.filter((_, i) => i !== index); setSignaturePositions(signature); }; const handleMouseMove = e => { if (isSelectingPosition) { const container = containerRef.current; const pdfElement = container.querySelector(".react-pdf__Page"); if (!pdfElement) return; const pdfRect = pdfElement.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); const scrollLeft = container.scrollLeft || 0; const scrollTop = container.scrollTop || 0; setCursorPosition({ x: (e.clientX + scrollLeft - pdfRect.left) / pdfRect.width, y: (e.clientY + scrollTop - pdfRect.top) / pdfRect.height }); } }; const generateSignedPdf = async document => { try { const response = await fetch(document.pdf); const pdfBlob = await response.blob(); const arrayBuffer = await pdfBlob.arrayBuffer(); const pdfDoc = await _pdfLib.PDFDocument.load(arrayBuffer); for (const position of document.signaturePositions) { if (!position.signature) continue; const page = pdfDoc.getPages()[position.page - 1]; const { width: pdfWidth, height: pdfHeight } = page.getSize(); const signatureImage = await pdfDoc.embedPng(position.signature); const signatureWidth = 150; const signatureHeight = 50; const xPos = position.normalizedX * pdfWidth - signatureWidth / 2; const yPos = pdfHeight - position.normalizedY * pdfHeight - signatureHeight / 2; page.drawImage(signatureImage, { x: xPos, y: Math.max(0, Math.min(yPos, pdfHeight - signatureHeight)), width: signatureWidth, height: signatureHeight }); if (position.timestamp) { page.drawText(position.timestamp, { x: xPos, y: Math.max(0, Math.min(yPos - 15, pdfHeight - signatureHeight)), size: 8 }); } } const pdfBytes = await pdfDoc.save(); const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const url = URL.createObjectURL(blob); const link = document.createElement('a'); link.href = url; link.download = `signed_${document.documentId}.pdf`; document.body.appendChild(link); link.click(); document.body.removeChild(link); URL.revokeObjectURL(url); } catch (error) { console.error('Error generating signed PDF:', error); throw error; } }; const resetState = () => { setPdfFile(null); setPdfUrl(null); setSignaturePositions([]); setViewMode('upload'); }; return { pdfFile, pdfUrl, numPages, currentPage, scale, signaturePositions, isSelectingPosition, viewMode, containerRef, setNumPages, setCurrentPage, setScale, setIsSelectingPosition, setViewMode, setPdfFile, setPdfUrl, setSignaturePositions, handleFileChange, handlePdfClick, generateSignedPdf, resetState, handleMouseMove, cursorPosition, handleRemoveSign }; }; var _default = exports.default = usePDFOperations;