Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/node.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
env:
CYPRESS_INSTALL_BINARY: 0
PUPPETEER_SKIP_DOWNLOAD: true
run: npm ci
run: npm i

- name: Lint
run: npm run lint
Expand Down
26 changes: 14 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,19 @@ A Vue 2 component for rendering PDFs with draggable and resizable element overla

### Props

| Prop | Type | Default |
|------|------|---------|
| `width` | String | `'100%'` |
| `height` | String | `'100%'` |
| `initFiles` | Array | `[]` |
| `initFileNames` | Array | `[]` |
| `initialScale` | Number | `1` |
| `showPageFooter` | Boolean | `true` |
| `hideSelectionUI` | Boolean | `false` |
| `showSelectionHandles` | Boolean | `true` |
| `showElementActions` | Boolean | `true` |
| `pageCountFormat` | String | `'{currentPage} of {totalPages}'` |
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `width` | String | `'100%'` | Container width |
| `height` | String | `'100%'` | Container height |
| `initFiles` | Array | `[]` | PDF files to load |
| `initFileNames` | Array | `[]` | Names for the PDF files |
| `initialScale` | Number | `1` | Initial zoom scale |
| `showPageFooter` | Boolean | `true` | Show page footer with document name and page number |
| `hideSelectionUI` | Boolean | `false` | Hide selection handles and actions UI |
| `showSelectionHandles` | Boolean | `true` | Show resize/move handles on selected elements |
| `showElementActions` | Boolean | `true` | Show action buttons on selected elements |
| `pageCountFormat` | String | `'{currentPage} of {totalPages}'` | Format string for page counter |
| `autoFitZoom` | Boolean | `false` | Automatically adjust zoom to fit viewport on window resize |

### Events

Expand All @@ -35,3 +36,4 @@ A Vue 2 component for rendering PDFs with draggable and resizable element overla
- `element-{type}` - Custom element rendering (e.g., `element-signature`)
- `custom` - Fallback for elements without specific type
- `actions` - Custom action buttons

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@libresign/pdf-elements",
"description": "PDF viewer with draggable and resizable element overlays for Vue 2",
"version": "0.1.2",
"version": "0.2.0",
"author": "LibreCode <contact@librecode.coop>",
"private": false,
"main": "dist/pdf-elements.umd.js",
Expand Down
33 changes: 33 additions & 0 deletions src/components/PDFElements.vue
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,10 @@ export default {
type: String,
default: '{currentPage} of {totalPages}',
},
autoFitZoom: {
type: Boolean,
default: false,
},
},
data() {
return {
Expand Down Expand Up @@ -224,6 +228,9 @@ export default {
window.addEventListener('resize', this.onViewportScroll)
this.$el?.addEventListener('scroll', this.onViewportScroll, { passive: true })
this.$el?.addEventListener('wheel', this.boundHandleWheel, { passive: false })
if (this.autoFitZoom) {
window.addEventListener('resize', this.adjustZoomToFit)
}
},
beforeUnmount() {
if (this.zoomRafId) {
Expand All @@ -241,6 +248,9 @@ export default {
window.removeEventListener('scroll', this.onViewportScroll)
window.removeEventListener('resize', this.onViewportScroll)
this.$el?.removeEventListener('scroll', this.onViewportScroll)
if (this.autoFitZoom) {
window.removeEventListener('resize', this.adjustZoomToFit)
}
if (this.viewportRafId) {
window.cancelAnimationFrame(this.viewportRafId)
this.viewportRafId = 0
Expand Down Expand Up @@ -804,6 +814,29 @@ export default {
const pagesScale = doc.pagesScale[pageIndex] || 1
return pageRef.getCanvasMeasurement().canvasHeight / pagesScale
},
calculateOptimalScale(maxPageWidth) {
const containerWidth = this.$el?.clientWidth || 0
if (!containerWidth || !maxPageWidth) return 1

const availableWidth = containerWidth - 40
return Math.max(0.1, Math.min(2, availableWidth / maxPageWidth))
},
adjustZoomToFit() {
if (!this.autoFitZoom || !this.pdfDocuments.length) return

const canvases = this.$el?.querySelectorAll('canvas')
if (!canvases?.length) return

const maxCanvasWidth = Math.max(...Array.from(canvases).map(canvas =>
canvas.width / (this.scale || 1),
))

const optimalScale = this.calculateOptimalScale(maxCanvasWidth)
if (Math.abs(optimalScale - this.scale) > 0.01) {
this.scale = optimalScale
this.visualScale = optimalScale
}
},
},
}
</script>
Expand Down