diff --git a/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor b/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor
index 9af9dc61..80135751 100644
--- a/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor
+++ b/EnvelopeGenerator.ReceiverUI/Pages/EnvelopeViewer.razor
@@ -13,6 +13,7 @@
+
@@ -151,7 +152,10 @@
}
diff --git a/EnvelopeGenerator.ReceiverUI/wwwroot/css/envelope-viewer.css b/EnvelopeGenerator.ReceiverUI/wwwroot/css/envelope-viewer.css
index 3e2e5464..cfd7408a 100644
--- a/EnvelopeGenerator.ReceiverUI/wwwroot/css/envelope-viewer.css
+++ b/EnvelopeGenerator.ReceiverUI/wwwroot/css/envelope-viewer.css
@@ -434,9 +434,14 @@ body.resizing {
justify-content: flex-start;
}
-.pdf-canvas {
+.pdf-page-container {
+ position: relative;
display: inline-block;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
+}
+
+.pdf-canvas {
+ display: block;
vertical-align: top;
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
@@ -447,6 +452,34 @@ body.resizing {
opacity: 0;
}
+.pdf-text-layer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ overflow: hidden;
+ opacity: 1;
+ line-height: 1.0;
+ pointer-events: auto;
+}
+
+.pdf-text-layer > span {
+ color: transparent;
+ position: absolute;
+ white-space: pre;
+ cursor: text;
+ transform-origin: 0% 0%;
+}
+
+.pdf-text-layer ::selection {
+ background: rgba(126, 34, 206, 0.3);
+}
+
+.pdf-text-layer ::-moz-selection {
+ background: rgba(126, 34, 206, 0.3);
+}
+
.error-container {
display: flex;
align-items: center;
diff --git a/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js b/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js
index f44479f5..0cd9b978 100644
--- a/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js
+++ b/EnvelopeGenerator.ReceiverUI/wwwroot/js/pdf-viewer.js
@@ -176,6 +176,9 @@ window.pdfViewer = {
this.currentRenderTask = page.render(renderContext);
await this.currentRenderTask.promise;
+ // Render text layer for copy-paste functionality
+ await this.renderTextLayer(page, viewport, dpr);
+
// Restore viewport center position AFTER rendering
if (container && oldWidth > 0 && oldHeight > 0) {
const scaleX = this.canvas.width / oldWidth;
@@ -210,6 +213,41 @@ window.pdfViewer = {
}
},
+ async renderTextLayer(page, viewport, dpr) {
+ try {
+ const textLayerDiv = document.getElementById('pdf-text-layer');
+ if (!textLayerDiv) {
+ console.warn('Text layer div not found');
+ return;
+ }
+
+ // Clear previous text layer
+ textLayerDiv.innerHTML = '';
+
+ // Set text layer dimensions to match canvas display size
+ textLayerDiv.style.width = `${viewport.width / dpr}px`;
+ textLayerDiv.style.height = `${viewport.height / dpr}px`;
+
+ // Get text content from PDF
+ const textContent = await page.getTextContent();
+
+ // Create viewport for text layer (without DPR scaling for positioning)
+ const textViewport = page.getViewport({ scale: this.scale });
+
+ // Render text layer using PDF.js built-in function
+ const pdfjsLib = window.pdfjsLib;
+ await pdfjsLib.renderTextLayer({
+ textContentSource: textContent,
+ container: textLayerDiv,
+ viewport: textViewport,
+ textDivs: []
+ }).promise;
+
+ } catch (error) {
+ console.error('Error rendering text layer:', error);
+ }
+ },
+
queueRenderPage(num) {
if (this.pageRendering) {
this.pageNumPending = num;