@libresign/pdf-elements 0.4.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -1
- package/dist/components/DraggableElement.vue.d.ts +240 -0
- package/dist/components/PDFElements.vue.d.ts +552 -0
- package/dist/components/PDFPage.vue.d.ts +40 -0
- package/dist/index.css +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.mjs +1293 -0
- package/dist/pdf-uHvE5neP.mjs +17593 -0
- package/dist/pdf.worker.min-DmO9Xdfo.mjs +4 -0
- package/dist/types.d.ts +30 -0
- package/dist/utils/asyncReader.d.ts +10 -0
- package/dist/utils/geometry.d.ts +5 -0
- package/dist/utils/measurements.d.ts +12 -0
- package/dist/utils/objectStore.d.ts +5 -0
- package/dist/utils/pageBounds.d.ts +5 -0
- package/dist/utils/zoom.d.ts +2 -0
- package/package.json +48 -21
- package/src/components/DraggableElement.vue +18 -15
- package/src/components/PDFElements.vue +87 -60
- package/src/components/PDFPage.vue +11 -7
- package/src/index.ts +18 -0
- package/src/types.ts +35 -0
- package/src/utils/asyncReader.ts +103 -0
- package/src/utils/{geometry.js → geometry.ts} +16 -2
- package/src/utils/{measurements.js → measurements.ts} +20 -1
- package/src/utils/{objectStore.js → objectStore.ts} +15 -4
- package/src/utils/{pageBounds.js → pageBounds.ts} +2 -2
- package/src/utils/{zoom.js → zoom.ts} +3 -1
- package/dist/demo.html +0 -1
- package/dist/pdf-elements.common.js +0 -31760
- package/dist/pdf-elements.common.js.map +0 -1
- package/dist/pdf-elements.css +0 -1
- package/dist/pdf-elements.umd.js +0 -31772
- package/dist/pdf-elements.umd.js.map +0 -1
- package/dist/pdf-elements.umd.min.js +0 -2
- package/dist/pdf-elements.umd.min.js.map +0 -1
- package/dist/pdf.worker.min.mjs +0 -22
- package/src/index.js +0 -17
- package/src/utils/asyncReader.js +0 -44
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface PDFElementObject {
|
|
2
|
+
id?: string;
|
|
3
|
+
x: number;
|
|
4
|
+
y: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
type?: string;
|
|
8
|
+
label?: string;
|
|
9
|
+
icon?: string;
|
|
10
|
+
resizable?: boolean;
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
export interface PDFDocumentEntry {
|
|
14
|
+
name: string;
|
|
15
|
+
file: unknown;
|
|
16
|
+
pdfDoc: unknown;
|
|
17
|
+
numPages: number;
|
|
18
|
+
pages: Promise<unknown>[];
|
|
19
|
+
pageWidths: number[];
|
|
20
|
+
pagesScale: number[];
|
|
21
|
+
allObjects: PDFElementObject[][];
|
|
22
|
+
}
|
|
23
|
+
export interface PDFElementsPublicApi {
|
|
24
|
+
startAddingElement: (templateObject: PDFElementObject) => void;
|
|
25
|
+
addObjectToPage: (object: PDFElementObject, pageIndex?: number, docIndex?: number) => boolean;
|
|
26
|
+
getAllObjects: (docIndex?: number) => PDFElementObject[];
|
|
27
|
+
updateObject: (docIndex: number, objectId: string, payload: Partial<PDFElementObject>) => void;
|
|
28
|
+
deleteObject: (docIndex: number, objectId: string) => void;
|
|
29
|
+
duplicateObject: (docIndex: number, objectId: string) => void;
|
|
30
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { PDFDocumentProxy } from 'pdfjs-dist';
|
|
2
|
+
export declare function setWorkerPath(path: string): void;
|
|
3
|
+
export declare function readAsArrayBuffer(file: Blob): Promise<ArrayBuffer>;
|
|
4
|
+
type PdfInput = string | ArrayBuffer | ArrayBufferView | Blob | {
|
|
5
|
+
url?: string;
|
|
6
|
+
data?: ArrayBuffer | Uint8Array;
|
|
7
|
+
[key: string]: unknown;
|
|
8
|
+
};
|
|
9
|
+
export declare function readAsPDF(file: PdfInput, options?: Record<string, unknown>): Promise<PDFDocumentProxy>;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare function clampPosition(x: number, y: number, width: number, height: number, pageWidth: number, pageHeight: number): {
|
|
2
|
+
x: number;
|
|
3
|
+
y: number;
|
|
4
|
+
};
|
|
5
|
+
export declare function getVisibleArea(newX: number, newY: number, objWidth: number, objHeight: number, pageWidth: number, pageHeight: number): number;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface CanvasMeasurement {
|
|
2
|
+
canvasWidth: number;
|
|
3
|
+
canvasHeight: number;
|
|
4
|
+
}
|
|
5
|
+
export interface PageMeasurement {
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
}
|
|
9
|
+
export interface PageMeasurementProvider {
|
|
10
|
+
getCanvasMeasurement: () => CanvasMeasurement;
|
|
11
|
+
}
|
|
12
|
+
export declare function getCachedMeasurement(cache: Record<string, PageMeasurement>, cacheKey: string, pageRef: PageMeasurementProvider, pagesScale: number): PageMeasurement;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { PDFDocumentEntry, PDFElementObject } from '../types';
|
|
2
|
+
export declare function objectIdExistsInDoc(doc: PDFDocumentEntry | undefined, objectId: string): boolean;
|
|
3
|
+
export declare function findObjectPageIndex(doc: PDFDocumentEntry | undefined, objectId: string): number;
|
|
4
|
+
export declare function updateObjectInDoc(doc: PDFDocumentEntry | undefined, pageIndex: number, objectId: string, payload: Partial<PDFElementObject>): boolean;
|
|
5
|
+
export declare function removeObjectFromDoc(doc: PDFDocumentEntry | undefined, pageIndex: number, objectId: string): boolean;
|
package/package.json
CHANGED
|
@@ -1,11 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@libresign/pdf-elements",
|
|
3
|
-
"description": "PDF viewer with draggable and resizable element overlays for Vue
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "PDF viewer with draggable and resizable element overlays for Vue 3",
|
|
4
|
+
"version": "1.0.1",
|
|
5
5
|
"author": "LibreCode <contact@librecode.coop>",
|
|
6
6
|
"private": false,
|
|
7
|
-
"main": "dist/
|
|
8
|
-
"module": "dist/
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"module": "dist/index.js",
|
|
9
|
+
"types": "dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts"
|
|
14
|
+
},
|
|
15
|
+
"./src/components/PDFElements.vue": "./src/components/PDFElements.vue",
|
|
16
|
+
"./src/utils/asyncReader": "./src/utils/asyncReader.ts"
|
|
17
|
+
},
|
|
9
18
|
"repository": {
|
|
10
19
|
"type": "git",
|
|
11
20
|
"url": "https://github.com/LibreSign/pdf-elements"
|
|
@@ -21,40 +30,58 @@
|
|
|
21
30
|
"draggable",
|
|
22
31
|
"resizable",
|
|
23
32
|
"libresign",
|
|
24
|
-
"
|
|
33
|
+
"vue3"
|
|
25
34
|
],
|
|
26
35
|
"scripts": {
|
|
27
|
-
"
|
|
28
|
-
"build": "
|
|
29
|
-
"build:
|
|
30
|
-
"
|
|
31
|
-
"
|
|
36
|
+
"dev": "vite",
|
|
37
|
+
"build": "vite build",
|
|
38
|
+
"build:report": "vite build --mode report",
|
|
39
|
+
"build:demo": "vite build --mode demo",
|
|
40
|
+
"preview:demo": "vite preview --outDir dist-demo",
|
|
41
|
+
"test": "vitest run",
|
|
42
|
+
"test:watch": "vitest",
|
|
43
|
+
"lint": "eslint . --ext .vue,.ts,.js --max-warnings=0",
|
|
44
|
+
"lint:fix": "eslint . --ext .vue,.ts,.js --fix"
|
|
32
45
|
},
|
|
33
46
|
"dependencies": {
|
|
34
|
-
"pdfjs-dist": "^5.4.
|
|
35
|
-
"vue": "^
|
|
47
|
+
"pdfjs-dist": "^5.4.624",
|
|
48
|
+
"vue": "^3.5.28"
|
|
36
49
|
},
|
|
37
50
|
"devDependencies": {
|
|
38
|
-
"@babel/core": "^7.28.6",
|
|
39
|
-
"@babel/eslint-parser": "^7.28.6",
|
|
40
|
-
"@babel/plugin-transform-private-methods": "^7.28.6",
|
|
41
51
|
"@nextcloud/browserslist-config": "^3.1.2",
|
|
42
|
-
"@
|
|
43
|
-
"@
|
|
44
|
-
"@
|
|
45
|
-
"
|
|
46
|
-
"eslint
|
|
52
|
+
"@eslint/js": "^9.39.3",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^8.56.0",
|
|
54
|
+
"@typescript-eslint/parser": "^8.56.0",
|
|
55
|
+
"@vitejs/plugin-vue": "^6.0.4",
|
|
56
|
+
"eslint": "^9.0.0",
|
|
57
|
+
"eslint-plugin-vue": "^10.8.0",
|
|
58
|
+
"eslint-plugin-vitest": "^0.5.4",
|
|
59
|
+
"globals": "^15.9.0",
|
|
60
|
+
"happy-dom": "^20.7.0",
|
|
47
61
|
"postcss": "^8.5.6",
|
|
48
|
-
"
|
|
62
|
+
"rollup-plugin-visualizer": "^7.0.0",
|
|
63
|
+
"typescript": "^5.9.3",
|
|
64
|
+
"vite": "^7.3.1",
|
|
65
|
+
"vite-plugin-dts": "^4.5.4",
|
|
66
|
+
"vitest": "^4.0.18",
|
|
67
|
+
"@vue/test-utils": "^2.4.6",
|
|
68
|
+
"vue-eslint-parser": "^10.4.0",
|
|
69
|
+
"vue-tsc": "^3.2.4"
|
|
49
70
|
},
|
|
50
71
|
"browserslist": [
|
|
51
72
|
"extends @nextcloud/browserslist-config"
|
|
52
73
|
],
|
|
74
|
+
"overrides": {
|
|
75
|
+
"eslint-plugin-vitest": {
|
|
76
|
+
"@typescript-eslint/utils": "^8.56.0"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
53
79
|
"files": [
|
|
54
80
|
"dist",
|
|
55
81
|
"src",
|
|
56
82
|
"COPYING",
|
|
57
83
|
"README.md"
|
|
58
84
|
],
|
|
85
|
+
"sideEffects": false,
|
|
59
86
|
"license": "AGPL-3.0-or-later"
|
|
60
87
|
}
|
|
@@ -54,12 +54,15 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
54
54
|
</div>
|
|
55
55
|
</template>
|
|
56
56
|
|
|
57
|
-
<script>
|
|
58
|
-
|
|
57
|
+
<script lang="ts">
|
|
58
|
+
import { defineComponent, type PropType, type CSSProperties } from 'vue'
|
|
59
|
+
import type { PDFElementObject } from '../types'
|
|
60
|
+
|
|
61
|
+
export default defineComponent({
|
|
59
62
|
name: 'DraggableElement',
|
|
60
63
|
props: {
|
|
61
64
|
object: {
|
|
62
|
-
type: Object
|
|
65
|
+
type: Object as PropType<PDFElementObject>,
|
|
63
66
|
required: true,
|
|
64
67
|
},
|
|
65
68
|
pagesScale: {
|
|
@@ -75,27 +78,27 @@ export default {
|
|
|
75
78
|
required: true,
|
|
76
79
|
},
|
|
77
80
|
onUpdate: {
|
|
78
|
-
type: Function
|
|
81
|
+
type: Function as PropType<(...args: any[]) => void>,
|
|
79
82
|
default: () => {},
|
|
80
83
|
},
|
|
81
84
|
onDelete: {
|
|
82
|
-
type: Function
|
|
85
|
+
type: Function as PropType<(...args: any[]) => void>,
|
|
83
86
|
default: () => {},
|
|
84
87
|
},
|
|
85
88
|
onDuplicate: {
|
|
86
|
-
type: Function
|
|
89
|
+
type: Function as PropType<(...args: any[]) => void>,
|
|
87
90
|
default: () => {},
|
|
88
91
|
},
|
|
89
92
|
onDragStart: {
|
|
90
|
-
type: Function
|
|
93
|
+
type: Function as PropType<(...args: any[]) => void>,
|
|
91
94
|
default: () => {},
|
|
92
95
|
},
|
|
93
96
|
onDragMove: {
|
|
94
|
-
type: Function
|
|
97
|
+
type: Function as PropType<(...args: any[]) => void>,
|
|
95
98
|
default: () => {},
|
|
96
99
|
},
|
|
97
100
|
onDragEnd: {
|
|
98
|
-
type: Function
|
|
101
|
+
type: Function as PropType<(...args: any[]) => void>,
|
|
99
102
|
default: () => {},
|
|
100
103
|
},
|
|
101
104
|
isBeingDraggedGlobally: {
|
|
@@ -103,7 +106,7 @@ export default {
|
|
|
103
106
|
default: false,
|
|
104
107
|
},
|
|
105
108
|
draggingClientPos: {
|
|
106
|
-
type: Object
|
|
109
|
+
type: Object as PropType<{ x: number; y: number }>,
|
|
107
110
|
default: () => ({ x: 0, y: 0 }),
|
|
108
111
|
},
|
|
109
112
|
currentDocIndex: {
|
|
@@ -135,7 +138,7 @@ export default {
|
|
|
135
138
|
default: false,
|
|
136
139
|
},
|
|
137
140
|
ignoreClickOutsideSelectors: {
|
|
138
|
-
type: Array
|
|
141
|
+
type: Array as PropType<string[]>,
|
|
139
142
|
default: () => [],
|
|
140
143
|
},
|
|
141
144
|
},
|
|
@@ -188,7 +191,7 @@ export default {
|
|
|
188
191
|
width: `${currentWidth * scale}px`,
|
|
189
192
|
height: `${currentHeight * scale}px`,
|
|
190
193
|
pointerEvents: this.readOnly ? 'none' : 'auto',
|
|
191
|
-
}
|
|
194
|
+
} as CSSProperties
|
|
192
195
|
},
|
|
193
196
|
toolbarStyle() {
|
|
194
197
|
const scale = this.pagesScale || 1
|
|
@@ -209,7 +212,7 @@ export default {
|
|
|
209
212
|
left: `${(x + width / 2) * scale}px`,
|
|
210
213
|
top: `${top * scale}px`,
|
|
211
214
|
transform: 'translateX(-50%)',
|
|
212
|
-
}
|
|
215
|
+
} as CSSProperties
|
|
213
216
|
},
|
|
214
217
|
dragElementStyle() {
|
|
215
218
|
if (!this.isBeingDraggedGlobally || !this.draggingClientPos) {
|
|
@@ -218,7 +221,7 @@ export default {
|
|
|
218
221
|
return {
|
|
219
222
|
opacity: 0,
|
|
220
223
|
pointerEvents: 'none',
|
|
221
|
-
}
|
|
224
|
+
} as CSSProperties
|
|
222
225
|
},
|
|
223
226
|
},
|
|
224
227
|
mounted() {
|
|
@@ -476,7 +479,7 @@ export default {
|
|
|
476
479
|
this.currentPageRect = null
|
|
477
480
|
},
|
|
478
481
|
},
|
|
479
|
-
}
|
|
482
|
+
})
|
|
480
483
|
</script>
|
|
481
484
|
|
|
482
485
|
<style scoped>
|
|
@@ -139,18 +139,21 @@ SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
139
139
|
</div>
|
|
140
140
|
</template>
|
|
141
141
|
|
|
142
|
-
<script>
|
|
142
|
+
<script lang="ts">
|
|
143
|
+
import { defineComponent, type PropType, markRaw } from 'vue'
|
|
143
144
|
import PDFPage from './PDFPage.vue'
|
|
144
145
|
import DraggableElement from './DraggableElement.vue'
|
|
145
|
-
import { readAsPDF, readAsArrayBuffer } from '../utils/asyncReader
|
|
146
|
-
import { clampPosition, getVisibleArea } from '../utils/geometry
|
|
147
|
-
import { getViewportWindow, isPageInViewport } from '../utils/pageBounds
|
|
148
|
-
import { applyScaleToDocs } from '../utils/zoom
|
|
149
|
-
import { objectIdExistsInDoc, findObjectPageIndex, updateObjectInDoc, removeObjectFromDoc } from '../utils/objectStore
|
|
150
|
-
import { getCachedMeasurement } from '../utils/measurements
|
|
151
|
-
|
|
152
|
-
|
|
146
|
+
import { readAsPDF, readAsArrayBuffer } from '../utils/asyncReader'
|
|
147
|
+
import { clampPosition, getVisibleArea } from '../utils/geometry'
|
|
148
|
+
import { getViewportWindow, isPageInViewport } from '../utils/pageBounds'
|
|
149
|
+
import { applyScaleToDocs } from '../utils/zoom'
|
|
150
|
+
import { objectIdExistsInDoc, findObjectPageIndex, updateObjectInDoc, removeObjectFromDoc } from '../utils/objectStore'
|
|
151
|
+
import { getCachedMeasurement } from '../utils/measurements'
|
|
152
|
+
import type { PDFDocumentEntry, PDFElementObject } from '../types'
|
|
153
|
+
|
|
154
|
+
export default defineComponent({
|
|
153
155
|
name: 'PDFElements',
|
|
156
|
+
emits: ['pdf-elements:end-init', 'pdf-elements:delete-object', 'pdf-elements:object-click'],
|
|
154
157
|
components: {
|
|
155
158
|
PDFPage,
|
|
156
159
|
DraggableElement,
|
|
@@ -165,11 +168,13 @@ export default {
|
|
|
165
168
|
default: '100%',
|
|
166
169
|
},
|
|
167
170
|
initFiles: {
|
|
168
|
-
type: Array
|
|
171
|
+
type: Array as PropType<
|
|
172
|
+
(string | Blob | ArrayBuffer | ArrayBufferView | Record<string, unknown>)[]
|
|
173
|
+
>,
|
|
169
174
|
default: () => [],
|
|
170
175
|
},
|
|
171
176
|
initFileNames: {
|
|
172
|
-
type: Array
|
|
177
|
+
type: Array as PropType<string[]>,
|
|
173
178
|
default: () => [],
|
|
174
179
|
},
|
|
175
180
|
initialScale: {
|
|
@@ -201,7 +206,7 @@ export default {
|
|
|
201
206
|
default: false,
|
|
202
207
|
},
|
|
203
208
|
ignoreClickOutsideSelectors: {
|
|
204
|
-
type: Array
|
|
209
|
+
type: Array as PropType<string[]>,
|
|
205
210
|
default: () => [],
|
|
206
211
|
},
|
|
207
212
|
pageCountFormat: {
|
|
@@ -212,32 +217,36 @@ export default {
|
|
|
212
217
|
type: Boolean,
|
|
213
218
|
default: false,
|
|
214
219
|
},
|
|
220
|
+
pdfjsOptions: {
|
|
221
|
+
type: Object as PropType<Record<string, unknown>>,
|
|
222
|
+
default: () => ({}),
|
|
223
|
+
},
|
|
215
224
|
},
|
|
216
225
|
data() {
|
|
217
226
|
return {
|
|
218
227
|
scale: this.initialScale,
|
|
219
|
-
pdfDocuments: [],
|
|
228
|
+
pdfDocuments: [] as PDFDocumentEntry[],
|
|
220
229
|
selectedDocIndex: -1,
|
|
221
230
|
selectedPageIndex: -1,
|
|
222
231
|
isAddingMode: false,
|
|
223
|
-
previewElement: null,
|
|
232
|
+
previewElement: null as PDFElementObject | null,
|
|
224
233
|
previewPosition: { x: 0, y: 0 },
|
|
225
234
|
previewScale: { x: 1, y: 1 },
|
|
226
235
|
previewPageDocIndex: -1,
|
|
227
236
|
previewPageIndex: -1,
|
|
228
237
|
previewVisible: false,
|
|
229
238
|
hoverRafId: 0,
|
|
230
|
-
pendingHoverClientPos: null,
|
|
231
|
-
lastHoverRect: null,
|
|
239
|
+
pendingHoverClientPos: null as { x: number; y: number } | null,
|
|
240
|
+
lastHoverRect: null as DOMRect | null,
|
|
232
241
|
addingListenersAttached: false,
|
|
233
242
|
dragRafId: 0,
|
|
234
|
-
pendingDragClientPos: null,
|
|
243
|
+
pendingDragClientPos: null as { x: number; y: number } | null,
|
|
235
244
|
pageBoundsVersion: 0,
|
|
236
245
|
lastScrollTop: 0,
|
|
237
246
|
lastClientWidth: 0,
|
|
238
247
|
nextObjectCounter: 0,
|
|
239
248
|
isDraggingElement: false,
|
|
240
|
-
draggingObject: null,
|
|
249
|
+
draggingObject: null as PDFElementObject | null,
|
|
241
250
|
draggingDocIndex: -1,
|
|
242
251
|
draggingPageIndex: -1,
|
|
243
252
|
draggingClientPosition: { x: 0, y: 0 },
|
|
@@ -246,22 +255,20 @@ export default {
|
|
|
246
255
|
draggingElementShift: { x: 0, y: 0 },
|
|
247
256
|
lastMouseClientPos: { x: 0, y: 0 },
|
|
248
257
|
viewportRafId: 0,
|
|
249
|
-
objectIndexCache: {},
|
|
250
|
-
zoomRafId: null,
|
|
251
|
-
wheelZoomRafId: null,
|
|
252
|
-
boundHandleWheel: null,
|
|
258
|
+
objectIndexCache: markRaw({}) as Record<string, number>,
|
|
259
|
+
zoomRafId: null as number | null,
|
|
260
|
+
wheelZoomRafId: null as number | null,
|
|
261
|
+
boundHandleWheel: null as ((event: WheelEvent) => void) | null,
|
|
253
262
|
visualScale: this.initialScale,
|
|
254
263
|
autoFitApplied: false,
|
|
255
264
|
lastContainerWidth: 0,
|
|
265
|
+
_pagesBoundingRects: markRaw({}) as Record<string, { docIndex: number; pageIndex: number; rect: DOMRect }>,
|
|
266
|
+
_pagesBoundingRectsList: markRaw([]) as { docIndex: number; pageIndex: number; rect: DOMRect }[],
|
|
267
|
+
_pageMeasurementCache: markRaw({}) as Record<string, { width: number; height: number }>,
|
|
268
|
+
_lastPageBoundsScrollTop: 0,
|
|
269
|
+
_lastPageBoundsClientHeight: 0,
|
|
256
270
|
}
|
|
257
271
|
},
|
|
258
|
-
created() {
|
|
259
|
-
this._pagesBoundingRects = {}
|
|
260
|
-
this._pagesBoundingRectsList = []
|
|
261
|
-
this._pageMeasurementCache = {}
|
|
262
|
-
this._lastPageBoundsScrollTop = 0
|
|
263
|
-
this._lastPageBoundsClientHeight = 0
|
|
264
|
-
},
|
|
265
272
|
mounted() {
|
|
266
273
|
this.boundHandleWheel = this.handleWheel.bind(this)
|
|
267
274
|
this.init()
|
|
@@ -301,7 +308,7 @@ export default {
|
|
|
301
308
|
methods: {
|
|
302
309
|
async init() {
|
|
303
310
|
if (!this.initFiles || this.initFiles.length === 0) return
|
|
304
|
-
const docs = []
|
|
311
|
+
const docs: PDFDocumentEntry[] = []
|
|
305
312
|
this.autoFitApplied = false
|
|
306
313
|
|
|
307
314
|
for (let i = 0; i < this.initFiles.length; i++) {
|
|
@@ -311,9 +318,9 @@ export default {
|
|
|
311
318
|
let pdfDoc
|
|
312
319
|
if (file instanceof Blob) {
|
|
313
320
|
const buffer = await readAsArrayBuffer(file)
|
|
314
|
-
pdfDoc = await readAsPDF({ data: buffer })
|
|
321
|
+
pdfDoc = await readAsPDF({ data: buffer }, this.pdfjsOptions)
|
|
315
322
|
} else {
|
|
316
|
-
pdfDoc = await readAsPDF(file)
|
|
323
|
+
pdfDoc = await readAsPDF(file, this.pdfjsOptions)
|
|
317
324
|
}
|
|
318
325
|
|
|
319
326
|
const pages = []
|
|
@@ -329,12 +336,14 @@ export default {
|
|
|
329
336
|
pages.push(pagePromise)
|
|
330
337
|
}
|
|
331
338
|
|
|
339
|
+
const rawPages = markRaw(pages)
|
|
340
|
+
|
|
332
341
|
docs.push({
|
|
333
342
|
name,
|
|
334
343
|
file,
|
|
335
|
-
pdfDoc,
|
|
344
|
+
pdfDoc: markRaw(pdfDoc),
|
|
336
345
|
numPages: pdfDoc.numPages,
|
|
337
|
-
pages,
|
|
346
|
+
pages: rawPages,
|
|
338
347
|
pageWidths,
|
|
339
348
|
pagesScale: Array(pdfDoc.numPages).fill(this.scale),
|
|
340
349
|
allObjects: Array(pdfDoc.numPages).fill(0).map(() => []),
|
|
@@ -342,7 +351,7 @@ export default {
|
|
|
342
351
|
}
|
|
343
352
|
|
|
344
353
|
this.pdfDocuments = docs
|
|
345
|
-
this._pageMeasurementCache = {}
|
|
354
|
+
this._pageMeasurementCache = markRaw({})
|
|
346
355
|
if (docs.length) {
|
|
347
356
|
this.selectedDocIndex = 0
|
|
348
357
|
this.selectedPageIndex = 0
|
|
@@ -394,7 +403,12 @@ export default {
|
|
|
394
403
|
updateDraggingPosition(clientX, clientY) {
|
|
395
404
|
if (!this.isDraggingElement) return
|
|
396
405
|
|
|
397
|
-
this.pendingDragClientPos
|
|
406
|
+
if (this.pendingDragClientPos) {
|
|
407
|
+
this.pendingDragClientPos.x = clientX
|
|
408
|
+
this.pendingDragClientPos.y = clientY
|
|
409
|
+
} else {
|
|
410
|
+
this.pendingDragClientPos = { x: clientX, y: clientY }
|
|
411
|
+
}
|
|
398
412
|
if (this.dragRafId) return
|
|
399
413
|
this.dragRafId = window.requestAnimationFrame(() => {
|
|
400
414
|
this.dragRafId = 0
|
|
@@ -453,6 +467,7 @@ export default {
|
|
|
453
467
|
|
|
454
468
|
cachePageBounds() {
|
|
455
469
|
const nextRects = {}
|
|
470
|
+
const nextList = []
|
|
456
471
|
const container = this.$el
|
|
457
472
|
const scrollTop = container?.scrollTop || 0
|
|
458
473
|
const viewHeight = container?.clientHeight || 0
|
|
@@ -477,22 +492,24 @@ export default {
|
|
|
477
492
|
}
|
|
478
493
|
}
|
|
479
494
|
const rect = canvas.getBoundingClientRect()
|
|
480
|
-
|
|
495
|
+
const entry = {
|
|
481
496
|
docIndex: docIdx,
|
|
482
497
|
pageIndex: pageIdx,
|
|
483
498
|
rect,
|
|
484
499
|
}
|
|
500
|
+
nextRects[`${docIdx}-${pageIdx}`] = entry
|
|
501
|
+
nextList.push(entry)
|
|
485
502
|
}
|
|
486
503
|
}
|
|
487
|
-
this._pagesBoundingRects = nextRects
|
|
488
|
-
this._pagesBoundingRectsList =
|
|
504
|
+
this._pagesBoundingRects = markRaw(nextRects)
|
|
505
|
+
this._pagesBoundingRectsList = markRaw(nextList)
|
|
489
506
|
this.pageBoundsVersion++
|
|
490
507
|
},
|
|
491
508
|
cachePageBoundsForPage(docIndex, pageIndex) {
|
|
492
509
|
const canvas = this.getPageCanvasElement(docIndex, pageIndex)
|
|
493
510
|
if (!canvas) return
|
|
494
511
|
const rect = canvas.getBoundingClientRect()
|
|
495
|
-
|
|
512
|
+
const nextRects = {
|
|
496
513
|
...this._pagesBoundingRects,
|
|
497
514
|
[`${docIndex}-${pageIndex}`]: {
|
|
498
515
|
docIndex,
|
|
@@ -500,7 +517,8 @@ export default {
|
|
|
500
517
|
rect,
|
|
501
518
|
},
|
|
502
519
|
}
|
|
503
|
-
this.
|
|
520
|
+
this._pagesBoundingRects = markRaw(nextRects)
|
|
521
|
+
this._pagesBoundingRectsList = markRaw(Object.values(nextRects))
|
|
504
522
|
this.pageBoundsVersion++
|
|
505
523
|
},
|
|
506
524
|
getPageBoundsMap() {
|
|
@@ -526,7 +544,7 @@ export default {
|
|
|
526
544
|
},
|
|
527
545
|
|
|
528
546
|
getDisplayedPageScale(docIndex, pageIndex) {
|
|
529
|
-
this.pageBoundsVersion
|
|
547
|
+
void this.pageBoundsVersion
|
|
530
548
|
const doc = this.pdfDocuments[docIndex]
|
|
531
549
|
if (!doc) return 1
|
|
532
550
|
const baseWidth = doc.pageWidths?.[pageIndex] || 0
|
|
@@ -589,7 +607,12 @@ export default {
|
|
|
589
607
|
if (!this.isAddingMode || !this.previewElement) return
|
|
590
608
|
const { x, y } = this.getPointerPosition(event)
|
|
591
609
|
if (x === undefined || y === undefined) return
|
|
592
|
-
this.pendingHoverClientPos
|
|
610
|
+
if (this.pendingHoverClientPos) {
|
|
611
|
+
this.pendingHoverClientPos.x = x
|
|
612
|
+
this.pendingHoverClientPos.y = y
|
|
613
|
+
} else {
|
|
614
|
+
this.pendingHoverClientPos = { x, y }
|
|
615
|
+
}
|
|
593
616
|
if (this.hoverRafId) return
|
|
594
617
|
this.hoverRafId = window.requestAnimationFrame(() => {
|
|
595
618
|
this.hoverRafId = 0
|
|
@@ -609,11 +632,11 @@ export default {
|
|
|
609
632
|
rect: this.lastHoverRect,
|
|
610
633
|
}
|
|
611
634
|
} else {
|
|
612
|
-
const
|
|
635
|
+
const rectEntries = this.getPageBoundsList().length
|
|
613
636
|
? this.getPageBoundsList()
|
|
614
637
|
: Object.values(this.getPageBoundsMap())
|
|
615
|
-
for (let i = 0; i <
|
|
616
|
-
const entry =
|
|
638
|
+
for (let i = 0; i < rectEntries.length; i++) {
|
|
639
|
+
const entry = rectEntries[i]
|
|
617
640
|
const rect = entry.rect
|
|
618
641
|
if (cursorX >= rect.left && cursorX <= rect.right &&
|
|
619
642
|
cursorY >= rect.top && cursorY <= rect.bottom) {
|
|
@@ -673,6 +696,7 @@ export default {
|
|
|
673
696
|
|
|
674
697
|
const doc = this.pdfDocuments?.[docIndex]
|
|
675
698
|
const pageObjects = doc?.allObjects?.[pageIndex] || []
|
|
699
|
+
if (pageObjects.length === 0) return
|
|
676
700
|
let hitObject = null
|
|
677
701
|
|
|
678
702
|
for (let i = pageObjects.length - 1; i >= 0; i--) {
|
|
@@ -727,7 +751,7 @@ export default {
|
|
|
727
751
|
|
|
728
752
|
applyScaleToDocs(this.pdfDocuments, this.scale)
|
|
729
753
|
|
|
730
|
-
this._pageMeasurementCache = {}
|
|
754
|
+
this._pageMeasurementCache = markRaw({})
|
|
731
755
|
this.cachePageBounds()
|
|
732
756
|
},
|
|
733
757
|
|
|
@@ -794,7 +818,7 @@ export default {
|
|
|
794
818
|
if (!this.addingListenersAttached) return
|
|
795
819
|
this.addingListenersAttached = false
|
|
796
820
|
document.removeEventListener('mousemove', this.handleMouseMove)
|
|
797
|
-
document.removeEventListener('touchmove', this.handleMouseMove
|
|
821
|
+
document.removeEventListener('touchmove', this.handleMouseMove)
|
|
798
822
|
document.removeEventListener('mouseup', this.finishAdding)
|
|
799
823
|
document.removeEventListener('touchend', this.finishAdding)
|
|
800
824
|
document.removeEventListener('keydown', this.handleKeyDown)
|
|
@@ -813,8 +837,9 @@ export default {
|
|
|
813
837
|
objectToAdd = { ...objectToAdd, id: this.generateObjectId() }
|
|
814
838
|
}
|
|
815
839
|
|
|
816
|
-
const
|
|
817
|
-
const
|
|
840
|
+
const measurement = this.getCachedMeasurement(docIndex, pageIndex, pageRef)
|
|
841
|
+
const pageWidth = measurement.width
|
|
842
|
+
const pageHeight = measurement.height
|
|
818
843
|
|
|
819
844
|
if (objectToAdd.x < 0 || objectToAdd.y < 0 ||
|
|
820
845
|
objectToAdd.x + objectToAdd.width > pageWidth ||
|
|
@@ -862,11 +887,11 @@ export default {
|
|
|
862
887
|
pageNumber: pageIndex + 1,
|
|
863
888
|
scale: pagesScale,
|
|
864
889
|
normalizedCoordinates: {
|
|
865
|
-
llx:
|
|
866
|
-
lly:
|
|
867
|
-
ury:
|
|
868
|
-
width:
|
|
869
|
-
height:
|
|
890
|
+
llx: Math.round(object.x),
|
|
891
|
+
lly: Math.round(normalizedCanvasHeight - object.y),
|
|
892
|
+
ury: Math.round(normalizedCanvasHeight - object.y - object.height),
|
|
893
|
+
width: Math.round(object.width),
|
|
894
|
+
height: Math.round(object.height),
|
|
870
895
|
},
|
|
871
896
|
})
|
|
872
897
|
})
|
|
@@ -1074,9 +1099,11 @@ export default {
|
|
|
1074
1099
|
if (!targetObject) return currentPageIndex
|
|
1075
1100
|
|
|
1076
1101
|
let targetPageIndex = currentPageIndex
|
|
1102
|
+
const pageBoundsList = this.getPageBoundsList()
|
|
1077
1103
|
const pageBoundsMap = this.getPageBoundsMap()
|
|
1078
|
-
|
|
1079
|
-
|
|
1104
|
+
const boundsEntries = pageBoundsList.length ? pageBoundsList : Object.values(pageBoundsMap)
|
|
1105
|
+
for (let i = 0; i < boundsEntries.length; i++) {
|
|
1106
|
+
const { docIndex: rectDocIndex, pageIndex, rect } = boundsEntries[i]
|
|
1080
1107
|
if (rectDocIndex === docIndex &&
|
|
1081
1108
|
mouseX >= rect.left && mouseX <= rect.right &&
|
|
1082
1109
|
mouseY >= rect.top && mouseY <= rect.bottom) {
|
|
@@ -1186,7 +1213,7 @@ export default {
|
|
|
1186
1213
|
this.scheduleAutoFitZoom()
|
|
1187
1214
|
return
|
|
1188
1215
|
}
|
|
1189
|
-
const canvases = this.$el?.querySelectorAll('canvas')
|
|
1216
|
+
const canvases = this.$el?.querySelectorAll('canvas') as NodeListOf<HTMLCanvasElement> | undefined
|
|
1190
1217
|
if (!canvases?.length) return
|
|
1191
1218
|
maxCanvasWidth = Math.max(...Array.from(canvases).map(canvas =>
|
|
1192
1219
|
canvas.width / (this.scale || 1),
|
|
@@ -1199,12 +1226,12 @@ export default {
|
|
|
1199
1226
|
this.scale = optimalScale
|
|
1200
1227
|
this.visualScale = optimalScale
|
|
1201
1228
|
applyScaleToDocs(this.pdfDocuments, this.scale)
|
|
1202
|
-
this._pageMeasurementCache = {}
|
|
1229
|
+
this._pageMeasurementCache = markRaw({})
|
|
1203
1230
|
this.cachePageBounds()
|
|
1204
1231
|
}
|
|
1205
1232
|
},
|
|
1206
1233
|
},
|
|
1207
|
-
}
|
|
1234
|
+
})
|
|
1208
1235
|
</script>
|
|
1209
1236
|
|
|
1210
1237
|
<style scoped>
|