From ad0b6cf2d630bfd52a8271897fd63c6b0e674dcd Mon Sep 17 00:00:00 2001 From: Reece Date: Fri, 10 Oct 2025 12:55:03 +0100 Subject: [PATCH] Viewer tabs, embed update and layout fixes --- frontend/package-lock.json | 273 +++++++++--------- frontend/package.json | 36 +-- .../fileEditor/FileEditorThumbnail.tsx | 7 + frontend/src/components/layout/Workbench.tsx | 2 +- .../src/components/viewer/EmbedPdfViewer.tsx | 152 +++++++++- .../src/components/viewer/LocalEmbedPDF.tsx | 89 +++--- 6 files changed, 348 insertions(+), 211 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b0e6fdae3..cc5a7b735 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -10,24 +10,24 @@ "license": "SEE LICENSE IN https://raw.githubusercontent.com/Stirling-Tools/Stirling-PDF/refs/heads/main/proprietary/LICENSE", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", - "@embedpdf/core": "^1.3.1", - "@embedpdf/engines": "^1.3.1", - "@embedpdf/plugin-annotation": "^1.3.1", - "@embedpdf/plugin-export": "^1.3.1", - "@embedpdf/plugin-history": "^1.3.1", - "@embedpdf/plugin-interaction-manager": "^1.3.1", - "@embedpdf/plugin-loader": "^1.3.1", - "@embedpdf/plugin-pan": "^1.3.1", - "@embedpdf/plugin-render": "^1.3.1", - "@embedpdf/plugin-rotate": "^1.3.1", - "@embedpdf/plugin-scroll": "^1.3.1", - "@embedpdf/plugin-search": "^1.3.1", - "@embedpdf/plugin-selection": "^1.3.1", - "@embedpdf/plugin-spread": "^1.3.1", - "@embedpdf/plugin-thumbnail": "^1.3.1", - "@embedpdf/plugin-tiling": "^1.3.1", - "@embedpdf/plugin-viewport": "^1.3.1", - "@embedpdf/plugin-zoom": "^1.3.1", + "@embedpdf/core": "^1.3.14", + "@embedpdf/engines": "^1.3.14", + "@embedpdf/plugin-annotation": "^1.3.14", + "@embedpdf/plugin-export": "^1.3.14", + "@embedpdf/plugin-history": "^1.3.14", + "@embedpdf/plugin-interaction-manager": "^1.3.14", + "@embedpdf/plugin-loader": "^1.3.14", + "@embedpdf/plugin-pan": "^1.3.14", + "@embedpdf/plugin-render": "^1.3.14", + "@embedpdf/plugin-rotate": "^1.3.14", + "@embedpdf/plugin-scroll": "^1.3.14", + "@embedpdf/plugin-search": "^1.3.14", + "@embedpdf/plugin-selection": "^1.3.14", + "@embedpdf/plugin-spread": "^1.3.14", + "@embedpdf/plugin-thumbnail": "^1.3.14", + "@embedpdf/plugin-tiling": "^1.3.14", + "@embedpdf/plugin-viewport": "^1.3.14", + "@embedpdf/plugin-zoom": "^1.3.14", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@iconify/react": "^6.0.2", @@ -493,13 +493,13 @@ } }, "node_modules/@embedpdf/core": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/core/-/core-1.3.1.tgz", - "integrity": "sha512-2Az6trhiMMBIv+GFvV8H8UOS1gwQn7NK0KaJMcdsZbUHYLO0P95aVd6Pi/GRzEH4XyF51TDIoTOAUtf07TQ5dQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/core/-/core-1.3.14.tgz", + "integrity": "sha512-lE/vfhA53CxamaCfGWEibrEPr+JeZT42QCF+cOELUwv4+Zt6b+IE6+4wsznx/8wjjJYwllXJ3GJ/un1UzTqARw==", "license": "MIT", "dependencies": { - "@embedpdf/engines": "1.3.1", - "@embedpdf/models": "1.3.1" + "@embedpdf/engines": "1.3.14", + "@embedpdf/models": "1.3.14" }, "peerDependencies": { "preact": "^10.26.4", @@ -509,13 +509,13 @@ } }, "node_modules/@embedpdf/engines": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/engines/-/engines-1.3.1.tgz", - "integrity": "sha512-G3pI+18la7spviUMuA5s9/hV95jlfkA2+CNxqlHBO5ocw3641E3d36Lv+mx+6yU7k0B5vEOQPZDGRMg7KFziBQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/engines/-/engines-1.3.14.tgz", + "integrity": "sha512-+/FPW2gAzj2lQYvsMH/Oj9+MEXgkyEuyYDC+HFkltTuXvmiP2S/3BD0YslZDX9K4BzcmMxnWB+BiQpNJokbDVg==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1", - "@embedpdf/pdfium": "1.3.1" + "@embedpdf/models": "1.3.14", + "@embedpdf/pdfium": "1.3.14" }, "peerDependencies": { "preact": "^10.26.4", @@ -525,31 +525,31 @@ } }, "node_modules/@embedpdf/models": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/models/-/models-1.3.1.tgz", - "integrity": "sha512-OzmO1rQAuOP/Y3aYXmW21dPNAx49olhr9ZO2hDdI0fbNBHTVGxnaKqOISxVmUz7TmhTwVBljERACnaA8Ib4b4Q==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/models/-/models-1.3.14.tgz", + "integrity": "sha512-BujY4bmr8b2DQdoZkOge03SzoRVoWxzfIQATLSPPtp4WiFh1U4BPp6cADlGuCwGkp6zBcH/aM4h8PwwA75d/eg==", "license": "MIT" }, "node_modules/@embedpdf/pdfium": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/pdfium/-/pdfium-1.3.1.tgz", - "integrity": "sha512-qYGSS5ntz6DSY9Cxw/aigvHqGB+AKJLEcymNTZOL0GdlBzZpL++dOIYNEYHO2Tm/lOQVpE7I0e+Xh2TvD8O1zQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/pdfium/-/pdfium-1.3.14.tgz", + "integrity": "sha512-TQMZabXzHmzvvfPwopubFcYgQuYV7POvMgjICYu3Pgfn3sgr+UdIUh3aNXR/COcl3q8sXPMFQ2GDuyOHR9QQnA==", "license": "MIT" }, "node_modules/@embedpdf/plugin-annotation": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-annotation/-/plugin-annotation-1.3.1.tgz", - "integrity": "sha512-mmePRYYBB8v8NIZ95XVfFkpyQ2QiKIGdWyvrPeJXSbL3/K6d6ix+o/jHBVvBWyTsQzdIlzs+FW8+iT0M1zkEow==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-annotation/-/plugin-annotation-1.3.14.tgz", + "integrity": "sha512-JJYqEWwUKCdBZsXCDq/CW96p3pVLn8N+XZ4W3OyL7djI2fvYC9x6ys9m82vwlSathAVOxk1D7xXiY8AzJQVF0Q==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1", - "@embedpdf/utils": "1.3.1" + "@embedpdf/models": "1.3.14", + "@embedpdf/utils": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-history": "1.3.1", - "@embedpdf/plugin-interaction-manager": "1.3.1", - "@embedpdf/plugin-selection": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-history": "1.3.14", + "@embedpdf/plugin-interaction-manager": "1.3.14", + "@embedpdf/plugin-selection": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -557,15 +557,15 @@ } }, "node_modules/@embedpdf/plugin-export": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-export/-/plugin-export-1.3.1.tgz", - "integrity": "sha512-reb03vNPFP5GuIAFExMcuYBVYu/deVO2v8EoCwRZ/lzzYMORIkJjpNWDQPo9VfyGBh1x4/o3CHvxisU1Y1tDLg==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-export/-/plugin-export-1.3.14.tgz", + "integrity": "sha512-fMGp2YxvI4uTRIViUKxfnJts2Jw/vktEM45XUNGNSjT/kAW6znVNgdceYjpK++xU8CGs2grAQ1i5UvMd3aRNDA==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -573,15 +573,15 @@ } }, "node_modules/@embedpdf/plugin-history": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-history/-/plugin-history-1.3.1.tgz", - "integrity": "sha512-HrPkWQmAk08mbHiOcIN4htVq5KJMqI9zSjAqaYQEhV/TugeHfWVpK+xMst/PzuFb14HWgk5gWXjtV5E4SDlw9w==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-history/-/plugin-history-1.3.14.tgz", + "integrity": "sha512-77hnNLp0W0FHw8lT7SeqzCgp8bOClfeOAPZdcInu/jPDhVASUGYbtE/0fkLhiaqPH7kyMirNCLif4sF6n4b5vg==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -589,15 +589,15 @@ } }, "node_modules/@embedpdf/plugin-interaction-manager": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-interaction-manager/-/plugin-interaction-manager-1.3.1.tgz", - "integrity": "sha512-8h3y5a9tQ1fZlc4mP1/+XKyuHWwcQEm9AujKxy+6f6omtCBzpnKrH95bURgYOzQEBGY7d5C3HvG6JOlh0o1x3A==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-interaction-manager/-/plugin-interaction-manager-1.3.14.tgz", + "integrity": "sha512-nR0ZxNoTQtGqOHhweFh6QJ+nUJ4S4Ag1wWur6vAUAi8U95HUOfZhOEa0polZo0zR9WmmblGqRWjFM+mVSOoi1w==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -605,15 +605,15 @@ } }, "node_modules/@embedpdf/plugin-loader": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-loader/-/plugin-loader-1.3.1.tgz", - "integrity": "sha512-NjNmA7TOs3E/zwb9I+YohzyGkxq8y5NUGu0MKgh2g41lZoFvyqTAjFPar+RjEiLX8iiJiwNZswyJsNrytmS3Xg==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-loader/-/plugin-loader-1.3.14.tgz", + "integrity": "sha512-KoJX1MacEWE2DrO1OeZeG/Ehz76//u+ida/xb4r9BfwqAp5TfYlksq09cOvcF8LMW5FY4pbAL+AHKI1Hjz+HNA==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -621,17 +621,17 @@ } }, "node_modules/@embedpdf/plugin-pan": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-pan/-/plugin-pan-1.3.1.tgz", - "integrity": "sha512-lF1gkz/a77G3+Rr8MOefkGnPJ1i5xWnClXm2ZzYAl7PbOScp59/PaP7qeU7eMPC4FHQM81ZhCgVYGXogbaB8ww==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-pan/-/plugin-pan-1.3.14.tgz", + "integrity": "sha512-7EG+I5nn8yDCV8pT4x/g5mv7zJli2t3wPrh6Kt8uIpUorPHNb6J0Z67gl0uc/8rEasNzuKOuT0er46Y6/UYLzQ==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-interaction-manager": "1.3.1", - "@embedpdf/plugin-viewport": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-interaction-manager": "1.3.14", + "@embedpdf/plugin-viewport": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -639,15 +639,15 @@ } }, "node_modules/@embedpdf/plugin-render": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-render/-/plugin-render-1.3.1.tgz", - "integrity": "sha512-c9oH097e1CVUpYF9RgZRfV/7XCJ0pf+svdT1wyM2MbWby06ti20oCwT9wf7BLY0hPQ7+eO3wunr1I1/y3MnVrw==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-render/-/plugin-render-1.3.14.tgz", + "integrity": "sha512-IPj7GCQXJBsY++JaU+z7y+FwX5NaDBj4YYV6hsHNtSGf42Y1AdlwJzDYetivG2bA84xmk7KgD1X2Y3eIFBhjwA==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -655,15 +655,15 @@ } }, "node_modules/@embedpdf/plugin-rotate": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-rotate/-/plugin-rotate-1.3.1.tgz", - "integrity": "sha512-mRAlIW7IZAnCyDuYqN13yDc6yoNIYLUB4uYTUAR7vTIt021C8H5jDHk9TmLwcH0tQ8/R3yHuDm/XPAe0zfs81g==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-rotate/-/plugin-rotate-1.3.14.tgz", + "integrity": "sha512-OroEm11x/fPPXI9C0X+nm9LOjwaI0MvsToZRH+HpV60/FbQeOJvt6D8wThCDVLK95Na6A+JeYIMEu+Hiix7H+A==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -671,16 +671,16 @@ } }, "node_modules/@embedpdf/plugin-scroll": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-scroll/-/plugin-scroll-1.3.1.tgz", - "integrity": "sha512-mDvK3DyBZC8/8pOEdJsWtSjCmV2ZuZJJ6xfspJpsaDVywo1Vq6M55BtKThkhqED6mqbFWTN9rP9cbWG8KDBWVA==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-scroll/-/plugin-scroll-1.3.14.tgz", + "integrity": "sha512-fQbt7OlRMLQJMuZj/Bzh0qpRxMw1ld5Qe/OTw8N54b/plljnFA52joE7cITl3H03huWWyHS3NKOScbw7f34dog==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-viewport": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-viewport": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -688,16 +688,16 @@ } }, "node_modules/@embedpdf/plugin-search": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-search/-/plugin-search-1.3.1.tgz", - "integrity": "sha512-SLwYPQg1NJWytq2sd4MnWFmRVGgzwbohBedB2kH0ALsvdnoRYqgjR5HqAsKgoRJO/pphQhHlk3L1gLW62r6hqQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-search/-/plugin-search-1.3.14.tgz", + "integrity": "sha512-tlZEgR2tG+GSNnh2u1SjCxhUHfTDgcr38sE/xRK1bRLDGPZWlr6Ln7qP7JSWqeYBGni75sGrj0iZqcZbPWyJag==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-loader": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-loader": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -705,17 +705,17 @@ } }, "node_modules/@embedpdf/plugin-selection": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-selection/-/plugin-selection-1.3.1.tgz", - "integrity": "sha512-yef2XB/zR7zjyeUB3Ul0SbTcXqu5isR0GtINkFwL7bJMok6HpYNDnMXSuo55BaxI0dOCnnCSZfoRkAgosnZ1uQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-selection/-/plugin-selection-1.3.14.tgz", + "integrity": "sha512-EXENuaAsse3rT6cjA1nYzyrNvoy62ojJl28wblCng6zcs3HSlGPemIQZAvaYKPUxoY608M+6nKlcMQ5neRnk/A==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-interaction-manager": "1.3.1", - "@embedpdf/plugin-viewport": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-interaction-manager": "1.3.14", + "@embedpdf/plugin-viewport": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -723,16 +723,16 @@ } }, "node_modules/@embedpdf/plugin-spread": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-spread/-/plugin-spread-1.3.1.tgz", - "integrity": "sha512-RJ/kgJsFRdtWlPMXTW1feUSb6WHIvxtNRLgqzX8dlFIoyc4oZex2Vw+URo/VZuWSe/NvCIihQ20rkNAQJMnNMQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-spread/-/plugin-spread-1.3.14.tgz", + "integrity": "sha512-DVlk6tDgUoDRkp2S4Jc3LrRTuf4DPMlph9vywJw5z6Qpbh0vgcMnObg896/S0Eu5FgACNAj0WGcXpLrcrn5b9Q==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-loader": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-loader": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -740,34 +740,35 @@ } }, "node_modules/@embedpdf/plugin-thumbnail": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-thumbnail/-/plugin-thumbnail-1.3.1.tgz", - "integrity": "sha512-xv96ESa7JgD5z+TzcOK18/u0gq3d9v7QPv2wpr0ZhcnwLwf4sH0eUJZIsv7z7DMOpBNz7o7jJbrtxDUdCEHGhg==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-thumbnail/-/plugin-thumbnail-1.3.14.tgz", + "integrity": "sha512-cnwb5dG8Jph8XSArys1WFCQ6kK2R5FKoO0B5mDrHFv9Fcm2pKszlmZC/NDoskX4pgNUgSnwhI1X3cP37ebF9Ng==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-render": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-render": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "react-dom": ">=16.8.0", + "vue": ">=3.2.0" } }, "node_modules/@embedpdf/plugin-tiling": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-tiling/-/plugin-tiling-1.3.1.tgz", - "integrity": "sha512-Q8RF80fb6y9GDAKwvgsu0BsWJlQuhNCtSKWwp3YcZJtIBFm94DVcg0zTgvDmE9/WNOmn4Z1Edt86usmYauHolw==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-tiling/-/plugin-tiling-1.3.14.tgz", + "integrity": "sha512-SaCTo2LdZwGeE6jCqkwJxvwt8YKbsI3QGxa9S7Ez+5OcBchlhHeTfLQswcErDQ3WH2p8WHtGuucAcOLrVVOm0A==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-render": "1.3.1", - "@embedpdf/plugin-scroll": "1.3.1", - "@embedpdf/plugin-viewport": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-render": "1.3.14", + "@embedpdf/plugin-scroll": "1.3.14", + "@embedpdf/plugin-viewport": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -775,15 +776,15 @@ } }, "node_modules/@embedpdf/plugin-viewport": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-viewport/-/plugin-viewport-1.3.1.tgz", - "integrity": "sha512-gzosrWL18ZhN175Kxocf/p7uqYBhNHvEuV1CpJQmN7ys48aew6Qq8z7MjAsCnJBANXk/8syNdo3qWwBriyjQNg==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-viewport/-/plugin-viewport-1.3.14.tgz", + "integrity": "sha512-mfJ7EbbU68eKk6oFvQ4ozGJNpxUxWbjQ5Gm3uuB+Gj5/tWgBocBOX36k/9LgivEEeX7g2S0tOgyErljApmH8Vg==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1" + "@embedpdf/models": "1.3.14" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", + "@embedpdf/core": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -791,19 +792,19 @@ } }, "node_modules/@embedpdf/plugin-zoom": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/plugin-zoom/-/plugin-zoom-1.3.1.tgz", - "integrity": "sha512-3GXpgv6XmZiQnjaPbsxblTqUn84ALFiyONh2gwrEU9apB6STT3TQiY0QRindwrUXdQLpCSjRSB9PpDBCtTww7w==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/plugin-zoom/-/plugin-zoom-1.3.14.tgz", + "integrity": "sha512-/N5tyMk+8OzhObrS3O9yPkcmX8EPiuTo+WaT2QCVSmIUqKnOO4AnKpHJ6Vl0uVhcuXHCMwLucZKyhJ7tRqavwg==", "license": "MIT", "dependencies": { - "@embedpdf/models": "1.3.1", + "@embedpdf/models": "1.3.14", "hammerjs": "^2.0.8" }, "peerDependencies": { - "@embedpdf/core": "1.3.1", - "@embedpdf/plugin-interaction-manager": "1.3.1", - "@embedpdf/plugin-scroll": "1.3.1", - "@embedpdf/plugin-viewport": "1.3.1", + "@embedpdf/core": "1.3.14", + "@embedpdf/plugin-interaction-manager": "1.3.14", + "@embedpdf/plugin-scroll": "1.3.14", + "@embedpdf/plugin-viewport": "1.3.14", "preact": "^10.26.4", "react": ">=16.8.0", "react-dom": ">=16.8.0", @@ -811,9 +812,9 @@ } }, "node_modules/@embedpdf/utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@embedpdf/utils/-/utils-1.3.1.tgz", - "integrity": "sha512-6trYysnggwCCTB2q7cX6tkOTbZJNtt2YYZohPCmh0yaDpkfNSgwDwD0jCLtEU2UZLQoH4+2GvNo+4xe+KAGlIQ==", + "version": "1.3.14", + "resolved": "https://registry.npmjs.org/@embedpdf/utils/-/utils-1.3.14.tgz", + "integrity": "sha512-gxEJD12nageCMqAjdbicNfDQolXU3nvnV0EX96OdZITRNj0Q1tisutVYoaxcCiJu3vvIEOzipjsAnQOubbFCEA==", "license": "MIT", "peerDependencies": { "preact": "^10.26.4", diff --git a/frontend/package.json b/frontend/package.json index 77ce581b5..f4a0f4f90 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,24 +6,24 @@ "proxy": "http://localhost:8080", "dependencies": { "@atlaskit/pragmatic-drag-and-drop": "^1.7.7", - "@embedpdf/core": "^1.3.1", - "@embedpdf/engines": "^1.3.1", - "@embedpdf/plugin-annotation": "^1.3.1", - "@embedpdf/plugin-export": "^1.3.1", - "@embedpdf/plugin-history": "^1.3.1", - "@embedpdf/plugin-interaction-manager": "^1.3.1", - "@embedpdf/plugin-loader": "^1.3.1", - "@embedpdf/plugin-pan": "^1.3.1", - "@embedpdf/plugin-render": "^1.3.1", - "@embedpdf/plugin-rotate": "^1.3.1", - "@embedpdf/plugin-scroll": "^1.3.1", - "@embedpdf/plugin-search": "^1.3.1", - "@embedpdf/plugin-selection": "^1.3.1", - "@embedpdf/plugin-spread": "^1.3.1", - "@embedpdf/plugin-thumbnail": "^1.3.1", - "@embedpdf/plugin-tiling": "^1.3.1", - "@embedpdf/plugin-viewport": "^1.3.1", - "@embedpdf/plugin-zoom": "^1.3.1", + "@embedpdf/core": "^1.3.14", + "@embedpdf/engines": "^1.3.14", + "@embedpdf/plugin-annotation": "^1.3.14", + "@embedpdf/plugin-export": "^1.3.14", + "@embedpdf/plugin-history": "^1.3.14", + "@embedpdf/plugin-interaction-manager": "^1.3.14", + "@embedpdf/plugin-loader": "^1.3.14", + "@embedpdf/plugin-pan": "^1.3.14", + "@embedpdf/plugin-render": "^1.3.14", + "@embedpdf/plugin-rotate": "^1.3.14", + "@embedpdf/plugin-scroll": "^1.3.14", + "@embedpdf/plugin-search": "^1.3.14", + "@embedpdf/plugin-selection": "^1.3.14", + "@embedpdf/plugin-spread": "^1.3.14", + "@embedpdf/plugin-thumbnail": "^1.3.14", + "@embedpdf/plugin-tiling": "^1.3.14", + "@embedpdf/plugin-viewport": "^1.3.14", + "@embedpdf/plugin-zoom": "^1.3.14", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.1", "@iconify/react": "^6.0.2", diff --git a/frontend/src/components/fileEditor/FileEditorThumbnail.tsx b/frontend/src/components/fileEditor/FileEditorThumbnail.tsx index f09bfeeb1..7f24b0841 100644 --- a/frontend/src/components/fileEditor/FileEditorThumbnail.tsx +++ b/frontend/src/components/fileEditor/FileEditorThumbnail.tsx @@ -45,6 +45,7 @@ const FileEditorThumbnail = ({ selectedFiles, onToggleFile, onDeleteFile, + onViewFile, _onSetStatus, onReorderFiles, onDownloadFile, @@ -205,6 +206,11 @@ const FileEditorThumbnail = ({ onToggleFile(file.id); }; + const handleCardDoubleClick = () => { + if (!isSupported) return; + onViewFile(file.id); + }; + // ---- Style helpers ---- const getHeaderClassName = () => { if (hasError) return styles.headerError; @@ -226,6 +232,7 @@ const FileEditorThumbnail = ({ role="listitem" aria-selected={isSelected} onClick={handleCardClick} + onDoubleClick={handleCardDoubleClick} > {/* Header bar */}
0 ? '3.5rem' : '0', + paddingTop: currentView === 'viewer' ? '0' : (activeFiles.length > 0 ? '3.5rem' : '0'), }} > {renderMainContent()} diff --git a/frontend/src/components/viewer/EmbedPdfViewer.tsx b/frontend/src/components/viewer/EmbedPdfViewer.tsx index 71dbfa90b..5cc5375b4 100644 --- a/frontend/src/components/viewer/EmbedPdfViewer.tsx +++ b/frontend/src/components/viewer/EmbedPdfViewer.tsx @@ -1,7 +1,10 @@ -import React, { useCallback, useEffect, useRef } from 'react'; -import { Box, Center, Text, ActionIcon } from '@mantine/core'; +import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { Box, Center, Text, ActionIcon, Tabs, Collapse, Group, Button, Tooltip } from '@mantine/core'; import { useMantineTheme, useMantineColorScheme } from '@mantine/core'; import CloseIcon from '@mui/icons-material/Close'; +import ExpandMoreIcon from '@mui/icons-material/ExpandMore'; +import ExpandLessIcon from '@mui/icons-material/ExpandLess'; +import { useTranslation } from 'react-i18next'; import { useFileState, useFileActions } from "../../contexts/FileContext"; import { useFileWithUrl } from "../../hooks/useFileWithUrl"; @@ -28,8 +31,9 @@ const EmbedPdfViewerContent = ({ onClose, previewFile, }: EmbedPdfViewerProps) => { + const { t } = useTranslation(); const theme = useMantineTheme(); - const { colorScheme: _colorScheme } = useMantineColorScheme(); + const { colorScheme } = useMantineColorScheme(); const viewerRef = React.useRef(null); const [isViewerHovered, setIsViewerHovered] = React.useState(false); @@ -52,10 +56,11 @@ const EmbedPdfViewerContent = ({ const { signatureApiRef, historyApiRef } = useSignature(); // Get current file from FileContext - const { selectors } = useFileState(); + const { selectors, state } = useFileState(); const { actions } = useFileActions(); const activeFiles = selectors.getFiles(); const activeFileIds = activeFiles.map(f => f.fileId); + const selectedFileIds = state.ui.selectedFileIds; // Navigation guard for unsaved changes const { setHasUnsavedChanges, registerUnsavedChangesChecker, unregisterUnsavedChangesChecker } = useNavigationGuard(); @@ -67,15 +72,56 @@ const EmbedPdfViewerContent = ({ // Enable annotations when: in sign mode, OR annotation mode is active, OR we want to show existing annotations const shouldEnableAnnotations = isSignatureMode || isAnnotationMode || isAnnotationsVisible; + // Track which file tab is active + const [activeFileIndex, setActiveFileIndex] = useState(0); + const [tabsExpanded, setTabsExpanded] = useState(true); + const tabsContainerRef = useRef(null); + const hasInitializedFromSelection = useRef(false); + + // When viewer opens with a selected file, switch to that file + useEffect(() => { + if (!hasInitializedFromSelection.current && selectedFileIds.length > 0 && activeFiles.length > 0) { + const selectedFileId = selectedFileIds[0]; + const index = activeFiles.findIndex(f => f.fileId === selectedFileId); + if (index !== -1 && index !== activeFileIndex) { + setActiveFileIndex(index); + } + hasInitializedFromSelection.current = true; + } + }, [selectedFileIds, activeFiles, activeFileIndex]); + + // Reset active tab if it's out of bounds + useEffect(() => { + if (activeFileIndex >= activeFiles.length && activeFiles.length > 0) { + setActiveFileIndex(0); + } + }, [activeFiles.length, activeFileIndex]); + + // Minimize when clicking outside + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if (tabsContainerRef.current && !tabsContainerRef.current.contains(event.target as Node)) { + setTabsExpanded(false); + } + }; + + if (tabsExpanded) { + document.addEventListener('mousedown', handleClickOutside); + return () => { + document.removeEventListener('mousedown', handleClickOutside); + }; + } + }, [tabsExpanded]); + // Determine which file to display const currentFile = React.useMemo(() => { if (previewFile) { return previewFile; } else if (activeFiles.length > 0) { - return activeFiles[0]; // Use first file for simplicity + return activeFiles[activeFileIndex] || activeFiles[0]; } return null; - }, [previewFile, activeFiles]); + }, [previewFile, activeFiles, activeFileIndex]); // Get file with URL for rendering const fileWithUrl = useFileWithUrl(currentFile); @@ -244,12 +290,96 @@ const EmbedPdfViewerContent = ({ ) : ( <> - {/* Tabs for multiple files */} + {/* Floating tabs for multiple files */} {activeFiles.length > 1 && !previewFile && ( - - - Multiple files loaded - showing first file for now - + + setTabsExpanded(!tabsExpanded)} + > + + {tabsExpanded ? : } + + {t('viewer.files', 'Files')} ({activeFiles.length}) + + + + + + + setActiveFileIndex(parseInt(value || '0'))} + variant="pills" + orientation="vertical" + styles={(theme) => ({ + tab: { + justifyContent: 'flex-start', + '&[data-active]': { + backgroundColor: 'rgba(147, 197, 253, 0.8)', + }, + }, + })} + > + + {activeFiles.map((file, index) => { + const stub = selectors.getStirlingFileStub(file.fileId); + const displayName = file.name.length > 25 ? `${file.name.substring(0, 25)}...` : file.name; + + return ( + + + + + {displayName} + + {stub?.versionNumber && stub.versionNumber > 1 && ( + + v{stub.versionNumber} + + )} + + + + ); + })} + + + + )} diff --git a/frontend/src/components/viewer/LocalEmbedPDF.tsx b/frontend/src/components/viewer/LocalEmbedPDF.tsx index a7fe26d6e..338ceb9a4 100644 --- a/frontend/src/components/viewer/LocalEmbedPDF.tsx +++ b/frontend/src/components/viewer/LocalEmbedPDF.tsx @@ -18,7 +18,6 @@ import { SearchPluginPackage } from '@embedpdf/plugin-search/react'; import { ThumbnailPluginPackage } from '@embedpdf/plugin-thumbnail/react'; import { RotatePluginPackage, Rotate } from '@embedpdf/plugin-rotate/react'; import { ExportPluginPackage } from '@embedpdf/plugin-export/react'; -import { Rotation } from '@embedpdf/models'; // Import annotation plugins import { HistoryPluginPackage } from '@embedpdf/plugin-history/react'; @@ -78,7 +77,7 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur }, }), createPluginRegistration(ViewportPluginPackage, { - viewportGap: 10, + viewportGap: 56, // 3.5rem = 56px to match nav pill height }), createPluginRegistration(ScrollPluginPackage, { strategy: ScrollStrategy.Vertical, @@ -134,9 +133,7 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur createPluginRegistration(ThumbnailPluginPackage), // Register rotate plugin - createPluginRegistration(RotatePluginPackage, { - defaultRotation: Rotation.Degree0, // Start with no rotation - }), + createPluginRegistration(RotatePluginPackage), // Register export plugin for downloading PDFs createPluginRegistration(ExportPluginPackage, { @@ -288,48 +285,50 @@ export function LocalEmbedPDF({ file, url, enableAnnotations = false, onSignatur }} > ( - - -
e.preventDefault()} - onDrop={(e) => e.preventDefault()} - onDragOver={(e) => e.preventDefault()} - > - {/* High-resolution tile layer */} - + renderPage={({ document, width, height, pageIndex, scale, rotation }) => { + return ( + + +
e.preventDefault()} + onDrop={(e) => e.preventDefault()} + onDragOver={(e) => e.preventDefault()} + > + {/* High-resolution tile layer */} + - {/* Search highlight layer */} - + {/* Search highlight layer */} + - {/* Selection layer for text interaction */} - - {/* Annotation layer for signatures (only when enabled) */} - {enableAnnotations && ( - - )} -
-
-
- )} + {/* Selection layer for text interaction */} + + {/* Annotation layer for signatures (only when enabled) */} + {enableAnnotations && ( + + )} +
+
+
+ ); + }} />