import "./App.css"; import { useRef, useState } from "react"; import Drop from "./Drop"; import { Document, Page, pdfjs } from "react-pdf"; import { PDFDocument, rgb } from "pdf-lib"; import { blobToURL } from "./utils/Utils"; import PagingControl from "./components/PagingControl"; import { AddSigDialog } from "./components/AddSigDialog"; import { Header } from "./Header"; import { BigButton } from "./components/BigButton"; import DraggableSignature from "./components/DraggableSignature"; import DraggableText from "./components/DraggableText"; import dayjs from "dayjs"; pdfjs.GlobalWorkerOptions.workerSrc = `//cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.js`; function downloadURI(uri, name) { var link = document.createElement("a"); link.download = name; link.href = uri; document.body.appendChild(link); link.click(); document.body.removeChild(link); } function App() { const styles = { container: { maxWidth: 900, margin: "0 auto", }, sigBlock: { display: "inline-block", border: "1px solid #000", }, documentBlock: { maxWidth: 800, margin: "20px auto", marginTop: 8, border: "1px solid #999", }, controls: { maxWidth: 800, margin: "0 auto", marginTop: 8, }, }; const [pdf, setPdf] = useState(null); const [autoDate, setAutoDate] = useState(true); const [signatureURL, setSignatureURL] = useState(null); const [position, setPosition] = useState(null); const [signatureDialogVisible, setSignatureDialogVisible] = useState(false); const [textInputVisible, setTextInputVisible] = useState(false); const [pageNum, setPageNum] = useState(0); const [totalPages, setTotalPages] = useState(0); const [pageDetails, setPageDetails] = useState(null); const documentRef = useRef(null); return (
{signatureDialogVisible ? ( setSignatureDialogVisible(false)} onConfirm={(url) => { setSignatureURL(url); setSignatureDialogVisible(false); }} /> ) : null} {!pdf ? ( { const URL = await blobToURL(files[0]); setPdf(URL); }} /> ) : null} {pdf ? (
{!signatureURL ? ( setSignatureDialogVisible(true)} /> ) : null} setTextInputVisible("date")} /> setTextInputVisible(true)} /> { setTextInputVisible(false); setSignatureDialogVisible(false); setSignatureURL(null); setPdf(null); setTotalPages(0); setPageNum(0); setPageDetails(null); }} /> {pdf ? ( { downloadURI(pdf, "file.pdf"); }} /> ) : null}
{textInputVisible ? ( setTextInputVisible(false)} onEnd={setPosition} onSet={async (text) => { const { originalHeight, originalWidth } = pageDetails; const scale = originalWidth / documentRef.current.clientWidth; const y = documentRef.current.clientHeight - (position.y + (12 * scale) - position.offsetY - documentRef.current.offsetTop); const x = position.x - 166 - position.offsetX - documentRef.current.offsetLeft; // new XY in relation to actual document size const newY = (y * originalHeight) / documentRef.current.clientHeight; const newX = (x * originalWidth) / documentRef.current.clientWidth; const pdfDoc = await PDFDocument.load(pdf); const pages = pdfDoc.getPages(); const firstPage = pages[pageNum]; firstPage.drawText(text, { x: newX, y: newY, size: 20 * scale, }); const pdfBytes = await pdfDoc.save(); const blob = new Blob([new Uint8Array(pdfBytes)]); const URL = await blobToURL(blob); setPdf(URL); setPosition(null); setTextInputVisible(false); }} /> ) : null} {signatureURL ? ( { setSignatureURL(null); }} onSet={async () => { const { originalHeight, originalWidth } = pageDetails; const scale = originalWidth / documentRef.current.clientWidth; const y = documentRef.current.clientHeight - (position.y - position.offsetY + 64 - documentRef.current.offsetTop); const x = position.x - 160 - position.offsetX - documentRef.current.offsetLeft; // new XY in relation to actual document size const newY = (y * originalHeight) / documentRef.current.clientHeight; const newX = (x * originalWidth) / documentRef.current.clientWidth; const pdfDoc = await PDFDocument.load(pdf); const pages = pdfDoc.getPages(); const firstPage = pages[pageNum]; const pngImage = await pdfDoc.embedPng(signatureURL); const pngDims = pngImage.scale( scale * .3); firstPage.drawImage(pngImage, { x: newX, y: newY, width: pngDims.width, height: pngDims.height, }); if (autoDate) { firstPage.drawText( `Signed ${dayjs().format( "M/d/YYYY HH:mm:ss ZZ" )}`, { x: newX, y: newY - 10, size: 14 * scale, color: rgb(0.074, 0.545, 0.262), } ); } const pdfBytes = await pdfDoc.save(); const blob = new Blob([new Uint8Array(pdfBytes)]); const URL = await blobToURL(blob); setPdf(URL); setPosition(null); setSignatureURL(null); }} onEnd={setPosition} /> ) : null} { setTotalPages(data.numPages); }} > { setPageDetails(data); }} />
) : null}
); } export default App;