diff --git a/README.md b/README.md index e983b62..9ac089b 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ A Vue 2 component for rendering PDFs with draggable and resizable element overla | `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 | +| `readOnly` | Boolean | `false` | Disable drag, resize, and actions for elements | | `pageCountFormat` | String | `'{currentPage} of {totalPages}'` | Format string for page counter | | `autoFitZoom` | Boolean | `false` | Automatically adjust zoom to fit viewport on window resize | diff --git a/src/components/DraggableElement.vue b/src/components/DraggableElement.vue index b8341fb..4c73ebb 100644 --- a/src/components/DraggableElement.vue +++ b/src/components/DraggableElement.vue @@ -120,6 +120,10 @@ export default { showDefaultActions: { type: Boolean, default: true, + }, + readOnly: { + type: Boolean, + default: false, } }, data() { @@ -170,6 +174,7 @@ export default { top: `${currentY * scale}px`, width: `${currentWidth * scale}px`, height: `${currentHeight * scale}px`, + pointerEvents: this.readOnly ? 'none' : 'auto', } }, toolbarStyle() { @@ -218,6 +223,9 @@ export default { }, methods: { handleElementClick(event) { + if (this.readOnly) { + return + } if (event.target.closest('.delete-handle') || event.target.closest('[data-stop-drag]') || event.target.closest('.actions-toolbar')) { return } @@ -235,6 +243,7 @@ export default { this.startResize(direction, event) }, startDrag(event) { + if (this.readOnly) return if (event.target.classList.contains('delete')) return if (event.target.classList.contains('resize-handle')) return this.mode = 'drag' @@ -271,6 +280,7 @@ export default { window.addEventListener('touchend', this.boundStopInteraction) }, startResize(direction, event) { + if (this.readOnly) return this.mode = 'resize' this.direction = direction this.startX = event.type.includes('touch') ? event.touches[0].clientX : event.clientX diff --git a/src/components/PDFElements.vue b/src/components/PDFElements.vue index 0219c96..4761791 100644 --- a/src/components/PDFElements.vue +++ b/src/components/PDFElements.vue @@ -58,6 +58,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later :pages-scale="getRenderPageScale(docIndex, pIndex)" :page-width="getPageWidth(docIndex, pIndex)" :page-height="getPageHeight(docIndex, pIndex)" + :read-only="readOnly" :on-update="(payload) => updateObject(docIndex, object.id, payload)" :on-delete="() => deleteObject(docIndex, object.id)" :on-drag-start="(mouseX, mouseY, pointerOffset, dragShift) => startDraggingElement(docIndex, pIndex, object, mouseX, mouseY, pointerOffset, dragShift)" @@ -183,6 +184,10 @@ export default { type: Boolean, default: true, }, + readOnly: { + type: Boolean, + default: false, + }, pageCountFormat: { type: String, default: '{currentPage} of {totalPages}', @@ -222,6 +227,7 @@ export default { debouncedApplyZoom: null, visualScale: this.initialScale, autoFitApplied: false, + lastContainerWidth: 0, } }, mounted() { @@ -450,6 +456,14 @@ export default { if (this.isAddingMode || this.isDraggingElement) { this.cachePageBounds() } + if (this.autoFitZoom && !this.isAddingMode && !this.isDraggingElement) { + const containerWidth = this.$el?.clientWidth || 0 + if (containerWidth && containerWidth !== this.lastContainerWidth) { + this.lastContainerWidth = containerWidth + this.autoFitApplied = false + this.scheduleAutoFitZoom() + } + } this.viewportRafId = 0 }) },