kviewer 0.3.1 → 0.3.2
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/dist/module.d.mts +1 -1
- package/dist/module.json +1 -1
- package/dist/module.mjs +4 -0
- package/dist/runtime/annotation/engine/editor/editor.js +10 -12
- package/dist/runtime/annotation/engine/editor/selector.js +3 -1
- package/dist/runtime/annotation/engine/tools/arrow.js +24 -14
- package/dist/runtime/annotation/engine/tools/circle.js +24 -13
- package/dist/runtime/annotation/engine/tools/cloud.js +27 -18
- package/dist/runtime/annotation/engine/tools/free-highlight.js +24 -15
- package/dist/runtime/annotation/engine/tools/freehand.js +21 -12
- package/dist/runtime/annotation/engine/tools/highlight.d.ts +2 -0
- package/dist/runtime/annotation/engine/tools/highlight.js +20 -10
- package/dist/runtime/annotation/engine/tools/note.js +3 -1
- package/dist/runtime/annotation/engine/tools/rectangle.js +19 -8
- package/dist/runtime/annotation/engine/tools/signature.js +2 -1
- package/dist/runtime/annotation/engine/tools/stamp.js +2 -1
- package/dist/runtime/annotation/engine/utils.js +2 -1
- package/dist/runtime/annotation/pdf-export/download.js +1 -1
- package/dist/runtime/annotation/pdf-export/export.js +1 -1
- package/dist/runtime/annotation/pdf-export/parse_polyline.js +5 -1
- package/dist/runtime/annotation/pdf-export/parse_stamp.js +4 -4
- package/dist/runtime/annotation/pdf-export/unicode-font.js +1 -4
- package/dist/runtime/annotation/pdf-import/decode_stamp.js +3 -2
- package/dist/runtime/annotation/pdf-import/extract_stamp_appearance.js +1 -1
- package/dist/runtime/annotation/pdf-import/utils.js +1 -1
- package/dist/runtime/components/FormFieldLayer.d.vue.ts +1 -1
- package/dist/runtime/components/FormFieldLayer.vue.d.ts +1 -1
- package/dist/runtime/components/PdfPage.vue +3 -3
- package/dist/runtime/components/Viewer.vue +3 -1
- package/dist/runtime/components/ViewerTabs.vue +1 -1
- package/dist/runtime/components/panels/SignaturePicker.vue +8 -2
- package/dist/runtime/composables/useSearchIndex.js +1 -1
- package/dist/runtime/embed/bridge-host.d.ts +1 -1
- package/dist/runtime/embed/bridge-host.js +3 -3
- package/dist/runtime/imports.d.ts +19 -0
- package/dist/types.d.mts +1 -1
- package/package.json +2 -2
package/dist/module.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _nuxt_schema from '@nuxt/schema';
|
|
2
|
-
export { ActiveTool, AddFormFieldPayload, CheckboxStyle, ExportPdfOptions, FormFieldDefinition, FormFieldOrigin, FormFieldType, FormFieldValue, KVIEWER_EMBED_PROTOCOL_VERSION, KViewerApi, KViewerEmbedBridgeOptions, KViewerEmbedClient, KViewerEmbedClientOptions, KViewerEmbedEventName, KViewerEmbedEventPayloads, KViewerEmbedMethodName, SignatureData, SignatureHandlers, ViewMode, ViewerBottomToolId, ViewerLayoutToolId, ViewerMenuButtonItem, ViewerMenuCheckboxItem, ViewerMenuItem, ViewerMenuSeparatorItem, ViewerState, ViewerToolEntry, ViewerToolId, ViewerToolSlot, ViewerTopToolId, useKViewerEmbedBridge } from '../dist/runtime/public-types.js';
|
|
2
|
+
export { ActiveTool, AddFormFieldPayload, CheckboxStyle, ExportPdfOptions, FormFieldDefinition, FormFieldOrigin, FormFieldType, FormFieldValue, KVIEWER_EMBED_PROTOCOL_VERSION, KViewerApi, KViewerEmbedBridgeOptions, KViewerEmbedClient, KViewerEmbedClientOptions, KViewerEmbedEventName, KViewerEmbedEventPayloads, KViewerEmbedMethodName, PlacedFieldDefaults, SignatureData, SignatureFieldStatus, SignatureHandlers, ViewMode, ViewerBottomToolId, ViewerLayoutToolId, ViewerMenuButtonItem, ViewerMenuCheckboxItem, ViewerMenuItem, ViewerMenuSeparatorItem, ViewerState, ViewerToolEntry, ViewerToolId, ViewerToolSlot, ViewerTopToolId, useKViewerEmbedBridge } from '../dist/runtime/public-types.js';
|
|
3
3
|
|
|
4
4
|
interface ModuleOptions {
|
|
5
5
|
/**
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -56,6 +56,10 @@ const module$1 = defineNuxtModule({
|
|
|
56
56
|
locale: options.locale ?? "en"
|
|
57
57
|
};
|
|
58
58
|
nuxt.options.css.push("pdfjs-dist/web/pdf_viewer.css");
|
|
59
|
+
const cssnano = nuxt.options.postcss?.plugins?.cssnano;
|
|
60
|
+
if (cssnano && typeof cssnano === "object" && !cssnano.preset) {
|
|
61
|
+
cssnano.preset = ["default", { svgo: false }];
|
|
62
|
+
}
|
|
59
63
|
nuxt.options.css.push(resolve("./runtime/assets/kviewer.css"));
|
|
60
64
|
addPlugin(resolve("./runtime/plugin"));
|
|
61
65
|
addComponentsDir({
|
|
@@ -57,18 +57,14 @@ export class Editor {
|
|
|
57
57
|
id,
|
|
58
58
|
pageNumber,
|
|
59
59
|
konvaString: konvaGroup.toJSON(),
|
|
60
|
-
// Do NOT use konvaGroup.getClientRect()
|
|
61
|
-
// stage
|
|
62
|
-
//
|
|
60
|
+
// Do NOT use konvaGroup.getClientRect() without relativeTo here — it is
|
|
61
|
+
// in absolute stage coordinates, which bake in the stage's zoom scale
|
|
62
|
+
// AND the windowed stage position (setStageWindow shifts stage.position
|
|
63
|
+
// at high zoom). relativeTo undoes both, yielding page-space
|
|
64
|
+
// coordinates regardless of the zoom state at placement time.
|
|
63
65
|
konvaClientRect: (() => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
return {
|
|
67
|
-
x: raw.x / scale,
|
|
68
|
-
y: raw.y / scale,
|
|
69
|
-
width: raw.width / scale,
|
|
70
|
-
height: raw.height / scale
|
|
71
|
-
};
|
|
66
|
+
const stage = konvaGroup.getStage();
|
|
67
|
+
return stage ? konvaGroup.getClientRect({ relativeTo: stage }) : konvaGroup.getClientRect();
|
|
72
68
|
})(),
|
|
73
69
|
title: this.userName,
|
|
74
70
|
type: annotation.type,
|
|
@@ -144,7 +140,9 @@ export class Editor {
|
|
|
144
140
|
this.konvaStage.off("click mousedown mousemove mouseup touchstart touchmove touchend");
|
|
145
141
|
}
|
|
146
142
|
getBgLayer(konvaStage) {
|
|
147
|
-
|
|
143
|
+
const layer = konvaStage ? konvaStage.getLayers()[0] : this.konvaStage.getLayers()[0];
|
|
144
|
+
if (!layer) throw new Error("Annotation stage has no background layer");
|
|
145
|
+
return layer;
|
|
148
146
|
}
|
|
149
147
|
delShapeGroup(id) {
|
|
150
148
|
this.shapeGroupStore.delete(id);
|
|
@@ -99,7 +99,9 @@ export class Selector {
|
|
|
99
99
|
});
|
|
100
100
|
}
|
|
101
101
|
getBackgroundLayer(konvaStage) {
|
|
102
|
-
|
|
102
|
+
const layer = konvaStage.getLayers()[0];
|
|
103
|
+
if (!layer) throw new Error("Annotation stage has no background layer");
|
|
104
|
+
return layer;
|
|
103
105
|
}
|
|
104
106
|
getPageShapeGroups(konvaStage) {
|
|
105
107
|
return this.getBackgroundLayer(konvaStage).getChildren(
|
|
@@ -13,17 +13,21 @@ export class EditorArrow extends Editor {
|
|
|
13
13
|
}
|
|
14
14
|
mouseDownHandler(e) {
|
|
15
15
|
if (e.currentTarget !== this.konvaStage) return;
|
|
16
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
17
|
+
const annotation = this.currentAnnotation;
|
|
18
|
+
const style = annotation?.style;
|
|
19
|
+
if (!pos || !annotation || !style) return;
|
|
16
20
|
this.arrow = null;
|
|
17
21
|
this.isPainting = true;
|
|
18
|
-
|
|
19
|
-
this.
|
|
20
|
-
|
|
22
|
+
const shapeGroup = this.createShapeGroup();
|
|
23
|
+
this.currentShapeGroup = shapeGroup;
|
|
24
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
21
25
|
this.startPoint = { x: pos.x, y: pos.y };
|
|
22
26
|
this.arrow = new Konva.Arrow({
|
|
23
27
|
points: [pos.x, pos.y, pos.x, pos.y],
|
|
24
|
-
stroke:
|
|
25
|
-
strokeWidth:
|
|
26
|
-
fill:
|
|
28
|
+
stroke: style.color,
|
|
29
|
+
strokeWidth: style.strokeWidth,
|
|
30
|
+
fill: style.color,
|
|
27
31
|
pointerLength: 10,
|
|
28
32
|
pointerWidth: 10,
|
|
29
33
|
hitStrokeWidth: 20,
|
|
@@ -31,15 +35,16 @@ export class EditorArrow extends Editor {
|
|
|
31
35
|
lineCap: "round",
|
|
32
36
|
lineJoin: "round",
|
|
33
37
|
visible: false,
|
|
34
|
-
opacity:
|
|
38
|
+
opacity: style.opacity
|
|
35
39
|
});
|
|
36
|
-
|
|
40
|
+
shapeGroup.konvaGroup.add(this.arrow);
|
|
37
41
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
38
42
|
}
|
|
39
43
|
mouseMoveHandler(e) {
|
|
40
44
|
if (!this.isPainting) return;
|
|
41
45
|
e.evt.preventDefault();
|
|
42
46
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
47
|
+
if (!pos) return;
|
|
43
48
|
const points = [this.startPoint.x, this.startPoint.y, pos.x, pos.y];
|
|
44
49
|
this.arrow?.show();
|
|
45
50
|
this.arrow?.setAttrs({ points });
|
|
@@ -47,20 +52,24 @@ export class EditorArrow extends Editor {
|
|
|
47
52
|
mouseUpHandler() {
|
|
48
53
|
if (!this.isPainting) return;
|
|
49
54
|
this.isPainting = false;
|
|
50
|
-
const
|
|
51
|
-
|
|
55
|
+
const arrow = this.arrow;
|
|
56
|
+
const group = arrow?.getParent();
|
|
57
|
+
if (!arrow || !group) return;
|
|
58
|
+
if (!arrow.isVisible() && group.getType() === "Group") {
|
|
52
59
|
this.delShapeGroup(group.id());
|
|
53
60
|
return;
|
|
54
61
|
}
|
|
55
62
|
if (this.isTooShort()) {
|
|
56
|
-
|
|
63
|
+
arrow.destroy();
|
|
57
64
|
this.delShapeGroup(group.id());
|
|
58
65
|
this.arrow = null;
|
|
59
66
|
return;
|
|
60
67
|
}
|
|
68
|
+
const style = this.currentAnnotation?.style;
|
|
69
|
+
if (!style) return;
|
|
61
70
|
this.setShapeGroupDone({
|
|
62
71
|
id: group.id(),
|
|
63
|
-
color:
|
|
72
|
+
color: style.color,
|
|
64
73
|
contentsObj: {
|
|
65
74
|
text: ""
|
|
66
75
|
}
|
|
@@ -76,8 +85,9 @@ export class EditorArrow extends Editor {
|
|
|
76
85
|
if (!this.arrow) return true;
|
|
77
86
|
const points = this.arrow.points();
|
|
78
87
|
if (points.length !== 4) return true;
|
|
79
|
-
const
|
|
80
|
-
const
|
|
88
|
+
const [x1, y1, x2, y2] = points;
|
|
89
|
+
const dx = x2 - x1;
|
|
90
|
+
const dy = y2 - y1;
|
|
81
91
|
return Math.hypot(dx, dy) < Editor.MinSize;
|
|
82
92
|
}
|
|
83
93
|
/**
|
|
@@ -23,11 +23,15 @@ export class EditorCircle extends Editor {
|
|
|
23
23
|
if (e.currentTarget !== this.konvaStage) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
27
|
+
const annotation = this.currentAnnotation;
|
|
28
|
+
const style = annotation?.style;
|
|
29
|
+
if (!pos || !annotation || !style) return;
|
|
26
30
|
this.ellipse = null;
|
|
27
31
|
this.isPainting = true;
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
|
|
32
|
+
const shapeGroup = this.createShapeGroup();
|
|
33
|
+
this.currentShapeGroup = shapeGroup;
|
|
34
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
31
35
|
this.vertex = { x: pos.x, y: pos.y };
|
|
32
36
|
this.ellipse = new Konva.Ellipse({
|
|
33
37
|
radiusX: 0,
|
|
@@ -36,14 +40,14 @@ export class EditorCircle extends Editor {
|
|
|
36
40
|
y: pos.y,
|
|
37
41
|
visible: false,
|
|
38
42
|
// Start hidden
|
|
39
|
-
stroke:
|
|
43
|
+
stroke: style.color,
|
|
40
44
|
// Set the ellipse stroke color
|
|
41
|
-
strokeWidth:
|
|
45
|
+
strokeWidth: style.strokeWidth,
|
|
42
46
|
// Set the ellipse stroke width
|
|
43
|
-
opacity:
|
|
47
|
+
opacity: style.opacity
|
|
44
48
|
// Set the ellipse opacity
|
|
45
49
|
});
|
|
46
|
-
|
|
50
|
+
shapeGroup.konvaGroup.add(this.ellipse);
|
|
47
51
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
48
52
|
}
|
|
49
53
|
/**
|
|
@@ -55,8 +59,10 @@ export class EditorCircle extends Editor {
|
|
|
55
59
|
return;
|
|
56
60
|
}
|
|
57
61
|
e.evt.preventDefault();
|
|
58
|
-
this.ellipse.show();
|
|
59
62
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
63
|
+
const ellipse = this.ellipse;
|
|
64
|
+
if (!pos || !ellipse) return;
|
|
65
|
+
ellipse.show();
|
|
60
66
|
const radiusX = Math.abs(pos.x - this.vertex.x) / 2;
|
|
61
67
|
const radiusY = Math.abs(pos.y - this.vertex.y) / 2;
|
|
62
68
|
const areaAttr = {
|
|
@@ -65,7 +71,7 @@ export class EditorCircle extends Editor {
|
|
|
65
71
|
radiusX,
|
|
66
72
|
radiusY
|
|
67
73
|
};
|
|
68
|
-
|
|
74
|
+
ellipse.setAttrs(areaAttr);
|
|
69
75
|
}
|
|
70
76
|
/**
|
|
71
77
|
* Handles mouse or touch pointer-up events and finishes drawing the ellipse.
|
|
@@ -75,20 +81,24 @@ export class EditorCircle extends Editor {
|
|
|
75
81
|
return;
|
|
76
82
|
}
|
|
77
83
|
this.isPainting = false;
|
|
78
|
-
const
|
|
79
|
-
|
|
84
|
+
const ellipse = this.ellipse;
|
|
85
|
+
const group = ellipse?.getParent();
|
|
86
|
+
if (!ellipse || !group) return;
|
|
87
|
+
if (!ellipse.isVisible() && group.getType() === "Group") {
|
|
80
88
|
this.delShapeGroup(group.id());
|
|
81
89
|
return;
|
|
82
90
|
}
|
|
83
91
|
if (this.isTooSmall()) {
|
|
84
|
-
|
|
92
|
+
ellipse.destroy();
|
|
85
93
|
this.delShapeGroup(group.id());
|
|
86
94
|
this.ellipse = null;
|
|
87
95
|
return;
|
|
88
96
|
}
|
|
97
|
+
const style = this.currentAnnotation?.style;
|
|
98
|
+
if (!style) return;
|
|
89
99
|
this.setShapeGroupDone({
|
|
90
100
|
id: group.id(),
|
|
91
|
-
color:
|
|
101
|
+
color: style.color,
|
|
92
102
|
contentsObj: {
|
|
93
103
|
text: ""
|
|
94
104
|
}
|
|
@@ -109,6 +119,7 @@ export class EditorCircle extends Editor {
|
|
|
109
119
|
* @returns True if the ellipse width or height is smaller than the minimum size, otherwise false.
|
|
110
120
|
*/
|
|
111
121
|
isTooSmall() {
|
|
122
|
+
if (!this.ellipse) return true;
|
|
112
123
|
const { width, height } = this.ellipse.size();
|
|
113
124
|
return Math.max(width, height) < Editor.MinSize;
|
|
114
125
|
}
|
|
@@ -35,23 +35,27 @@ export class EditorCloud extends Editor {
|
|
|
35
35
|
}
|
|
36
36
|
mouseDownHandler(_e) {
|
|
37
37
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
38
|
+
const annotation = this.currentAnnotation;
|
|
39
|
+
const style = annotation?.style;
|
|
40
|
+
if (!pos || !annotation || !style) return;
|
|
38
41
|
this.points.push(pos);
|
|
39
42
|
if (!this.isPainting) {
|
|
40
43
|
this.isPainting = true;
|
|
41
|
-
|
|
42
|
-
this.
|
|
44
|
+
const shapeGroup = this.createShapeGroup();
|
|
45
|
+
this.currentShapeGroup = shapeGroup;
|
|
46
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
43
47
|
this.cloudPath = new Konva.Path({
|
|
44
48
|
data: "",
|
|
45
|
-
stroke:
|
|
46
|
-
strokeWidth:
|
|
49
|
+
stroke: style.color,
|
|
50
|
+
strokeWidth: style.strokeWidth,
|
|
47
51
|
fillEnabled: false,
|
|
48
52
|
lineJoin: "round",
|
|
49
53
|
lineCap: "round",
|
|
50
54
|
hitStrokeWidth: 20,
|
|
51
55
|
// Set the hit detection width
|
|
52
|
-
opacity:
|
|
56
|
+
opacity: style.opacity
|
|
53
57
|
});
|
|
54
|
-
|
|
58
|
+
shapeGroup.konvaGroup.add(this.cloudPath);
|
|
55
59
|
this.drawStartRect(pos);
|
|
56
60
|
}
|
|
57
61
|
this.updateCloudPreview();
|
|
@@ -59,6 +63,7 @@ export class EditorCloud extends Editor {
|
|
|
59
63
|
mouseMoveHandler(_e) {
|
|
60
64
|
if (!this.isPainting || !this.cloudPath) return;
|
|
61
65
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
66
|
+
if (!pos) return;
|
|
62
67
|
this.updateCloudPreview(pos);
|
|
63
68
|
}
|
|
64
69
|
mouseUpHandler(_e) {
|
|
@@ -73,9 +78,12 @@ export class EditorCloud extends Editor {
|
|
|
73
78
|
const closedPoints = [...this.points, this.points[0]];
|
|
74
79
|
const pathData = this.generateCloudPathData(closedPoints);
|
|
75
80
|
this.cloudPath.data(pathData);
|
|
81
|
+
const shapeGroup = this.currentShapeGroup;
|
|
82
|
+
const style = this.currentAnnotation?.style;
|
|
83
|
+
if (!shapeGroup || !style) return;
|
|
76
84
|
this.setShapeGroupDone({
|
|
77
|
-
id:
|
|
78
|
-
color:
|
|
85
|
+
id: shapeGroup.konvaGroup.id(),
|
|
86
|
+
color: style.color,
|
|
79
87
|
contentsObj: { text: "" }
|
|
80
88
|
});
|
|
81
89
|
this.cloudPath = null;
|
|
@@ -179,7 +187,7 @@ export class EditorCloud extends Editor {
|
|
|
179
187
|
height: this.startRectSize,
|
|
180
188
|
stroke: "#000",
|
|
181
189
|
strokeWidth: 2,
|
|
182
|
-
|
|
190
|
+
fillEnabled: false,
|
|
183
191
|
cornerRadius: 2,
|
|
184
192
|
hitStrokeWidth: 10,
|
|
185
193
|
// Increase the hit detection area
|
|
@@ -187,26 +195,27 @@ export class EditorCloud extends Editor {
|
|
|
187
195
|
dash: [4, 2],
|
|
188
196
|
name: "startRect"
|
|
189
197
|
});
|
|
190
|
-
this.
|
|
191
|
-
this.
|
|
192
|
-
|
|
198
|
+
const startRect = this.startRect;
|
|
199
|
+
this.getBgLayer().add(startRect);
|
|
200
|
+
startRect.moveToTop();
|
|
201
|
+
startRect.on(
|
|
193
202
|
"mouseup",
|
|
194
203
|
(_e) => {
|
|
195
204
|
this.handleDoubleClick();
|
|
196
205
|
}
|
|
197
206
|
);
|
|
198
|
-
|
|
207
|
+
startRect.on(
|
|
199
208
|
"mousemove",
|
|
200
209
|
(_e) => {
|
|
201
|
-
|
|
202
|
-
|
|
210
|
+
startRect.stroke("#1677ff");
|
|
211
|
+
startRect.getLayer()?.batchDraw();
|
|
203
212
|
}
|
|
204
213
|
);
|
|
205
|
-
|
|
214
|
+
startRect.on(
|
|
206
215
|
"mouseout",
|
|
207
216
|
(_e) => {
|
|
208
|
-
|
|
209
|
-
|
|
217
|
+
startRect.stroke("#000");
|
|
218
|
+
startRect.getLayer()?.batchDraw();
|
|
210
219
|
}
|
|
211
220
|
);
|
|
212
221
|
}
|
|
@@ -16,16 +16,20 @@ export class EditorFreeHighlight extends Editor {
|
|
|
16
16
|
if (e.currentTarget !== this.konvaStage) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
19
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
20
|
+
const annotation = this.currentAnnotation;
|
|
21
|
+
const style = annotation?.style;
|
|
22
|
+
if (!pos || !annotation || !style) return;
|
|
19
23
|
this.line = null;
|
|
20
24
|
this.isPainting = true;
|
|
21
|
-
|
|
22
|
-
this.
|
|
23
|
-
|
|
25
|
+
const shapeGroup = this.createShapeGroup();
|
|
26
|
+
this.currentShapeGroup = shapeGroup;
|
|
27
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
24
28
|
this.line = new Konva.Line({
|
|
25
|
-
stroke:
|
|
26
|
-
strokeWidth:
|
|
27
|
-
opacity:
|
|
28
|
-
hitStrokeWidth:
|
|
29
|
+
stroke: style.color,
|
|
30
|
+
strokeWidth: style.strokeWidth,
|
|
31
|
+
opacity: style.opacity,
|
|
32
|
+
hitStrokeWidth: style.strokeWidth,
|
|
29
33
|
lineCap: "round",
|
|
30
34
|
lineJoin: "round",
|
|
31
35
|
visible: false,
|
|
@@ -33,7 +37,7 @@ export class EditorFreeHighlight extends Editor {
|
|
|
33
37
|
points: [pos.x, pos.y]
|
|
34
38
|
// Initialize the starting point
|
|
35
39
|
});
|
|
36
|
-
|
|
40
|
+
shapeGroup.konvaGroup.add(this.line);
|
|
37
41
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
38
42
|
}
|
|
39
43
|
/**
|
|
@@ -45,10 +49,12 @@ export class EditorFreeHighlight extends Editor {
|
|
|
45
49
|
return;
|
|
46
50
|
}
|
|
47
51
|
e.evt.preventDefault();
|
|
48
|
-
this.line.show();
|
|
49
52
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
50
|
-
const
|
|
51
|
-
|
|
53
|
+
const line = this.line;
|
|
54
|
+
if (!pos || !line) return;
|
|
55
|
+
line.show();
|
|
56
|
+
const newPoints = line.points().concat([pos.x, pos.y]);
|
|
57
|
+
line.points(newPoints);
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
60
|
* Handles mouse or touch pointer-up events and finishes drawing the freeform curve.
|
|
@@ -58,8 +64,9 @@ export class EditorFreeHighlight extends Editor {
|
|
|
58
64
|
return;
|
|
59
65
|
}
|
|
60
66
|
this.isPainting = false;
|
|
61
|
-
const
|
|
62
|
-
|
|
67
|
+
const line = this.line;
|
|
68
|
+
const group = line?.getParent();
|
|
69
|
+
if (group && line && !line.isVisible() && group.getType() === "Group") {
|
|
63
70
|
this.delShapeGroup(group.id());
|
|
64
71
|
return;
|
|
65
72
|
}
|
|
@@ -71,13 +78,14 @@ export class EditorFreeHighlight extends Editor {
|
|
|
71
78
|
this.line = null;
|
|
72
79
|
return;
|
|
73
80
|
}
|
|
74
|
-
|
|
81
|
+
const style = this.currentAnnotation?.style;
|
|
82
|
+
if (this.line && group && style) {
|
|
75
83
|
const originalPoints = this.line.points();
|
|
76
84
|
const correctedPoints = this.correctLineIfStraight(originalPoints);
|
|
77
85
|
this.line.points(correctedPoints);
|
|
78
86
|
this.setShapeGroupDone({
|
|
79
87
|
id: group.id(),
|
|
80
|
-
color:
|
|
88
|
+
color: style.color,
|
|
81
89
|
contentsObj: {
|
|
82
90
|
text: ""
|
|
83
91
|
}
|
|
@@ -100,6 +108,7 @@ export class EditorFreeHighlight extends Editor {
|
|
|
100
108
|
* @returns The corrected points
|
|
101
109
|
*/
|
|
102
110
|
correctLineIfStraight(points) {
|
|
111
|
+
if (points.length < 4) return points;
|
|
103
112
|
const THRESHOLD_ANGLE_DEGREES = 2;
|
|
104
113
|
const startX = points[0];
|
|
105
114
|
const startY = points[1];
|
|
@@ -20,6 +20,10 @@ export class EditorFreeHand extends Editor {
|
|
|
20
20
|
if (e.currentTarget !== this.konvaStage) {
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
24
|
+
const annotation = this.currentAnnotation;
|
|
25
|
+
const style = annotation?.style;
|
|
26
|
+
if (!pos || !annotation || !style) return;
|
|
23
27
|
Editor.TimerClear(this.pageNumber);
|
|
24
28
|
this.line = null;
|
|
25
29
|
this.isPainting = true;
|
|
@@ -27,13 +31,12 @@ export class EditorFreeHand extends Editor {
|
|
|
27
31
|
this.currentShapeGroup = this.createShapeGroup();
|
|
28
32
|
this.getBgLayer().add(this.currentShapeGroup.konvaGroup);
|
|
29
33
|
}
|
|
30
|
-
const pos = this.konvaStage.getRelativePointerPosition();
|
|
31
34
|
this.line = new Konva.Line({
|
|
32
|
-
stroke:
|
|
35
|
+
stroke: style.color,
|
|
33
36
|
// Set the line color
|
|
34
|
-
strokeWidth:
|
|
37
|
+
strokeWidth: style.strokeWidth,
|
|
35
38
|
// Set the line width
|
|
36
|
-
opacity:
|
|
39
|
+
opacity: style.opacity,
|
|
37
40
|
// Set the line opacity
|
|
38
41
|
lineCap: "round",
|
|
39
42
|
// Set rounded line caps
|
|
@@ -59,10 +62,12 @@ export class EditorFreeHand extends Editor {
|
|
|
59
62
|
return;
|
|
60
63
|
}
|
|
61
64
|
e.evt.preventDefault();
|
|
62
|
-
this.line.show();
|
|
63
65
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
+
const line = this.line;
|
|
67
|
+
if (!pos || !line) return;
|
|
68
|
+
line.show();
|
|
69
|
+
const newPoints = line.points().concat([pos.x, pos.y]);
|
|
70
|
+
line.points(newPoints);
|
|
66
71
|
}
|
|
67
72
|
/**
|
|
68
73
|
* Handles mouse or touch pointer-up events and finishes drawing the freeform curve.
|
|
@@ -72,13 +77,17 @@ export class EditorFreeHand extends Editor {
|
|
|
72
77
|
return;
|
|
73
78
|
}
|
|
74
79
|
this.isPainting = false;
|
|
75
|
-
const
|
|
80
|
+
const line = this.line;
|
|
81
|
+
const group = line?.getParent();
|
|
82
|
+
const style = this.currentAnnotation?.style;
|
|
83
|
+
if (!line || !group || !style) return;
|
|
84
|
+
const color = style.color;
|
|
76
85
|
if (this.isTooSmall()) {
|
|
77
|
-
|
|
86
|
+
line.destroy();
|
|
78
87
|
Editor.TimerStart(this.pageNumber, () => {
|
|
79
88
|
this.setShapeGroupDone({
|
|
80
89
|
id: group.id(),
|
|
81
|
-
color
|
|
90
|
+
color,
|
|
82
91
|
contentsObj: {
|
|
83
92
|
text: ""
|
|
84
93
|
}
|
|
@@ -90,7 +99,7 @@ export class EditorFreeHand extends Editor {
|
|
|
90
99
|
Editor.TimerStart(this.pageNumber, () => {
|
|
91
100
|
this.setShapeGroupDone({
|
|
92
101
|
id: group.id(),
|
|
93
|
-
color
|
|
102
|
+
color,
|
|
94
103
|
contentsObj: {
|
|
95
104
|
text: ""
|
|
96
105
|
}
|
|
@@ -113,7 +122,7 @@ export class EditorFreeHand extends Editor {
|
|
|
113
122
|
* @returns True if the line point count is less than 5, otherwise false
|
|
114
123
|
*/
|
|
115
124
|
isTooSmall() {
|
|
116
|
-
return this.line.points().length < Editor.MinSize;
|
|
125
|
+
return !this.line || this.line.points().length < Editor.MinSize;
|
|
117
126
|
}
|
|
118
127
|
/**
|
|
119
128
|
* @description Update annotation styles
|
|
@@ -5,6 +5,8 @@ import { Editor, type IEditorOptions } from '../editor/editor.js';
|
|
|
5
5
|
* EditorHighLight is a highlight editor class that extends Editor.
|
|
6
6
|
*/
|
|
7
7
|
export declare class EditorHighLight extends Editor {
|
|
8
|
+
private get activeAnnotation();
|
|
9
|
+
private get activeStyle();
|
|
8
10
|
/**
|
|
9
11
|
* Creates an EditorHighLight instance.
|
|
10
12
|
* @param EditorOptions Options used to initialize the editor
|
|
@@ -2,6 +2,15 @@ import Konva from "konva";
|
|
|
2
2
|
import { AnnotationType } from "../types.js";
|
|
3
3
|
import { Editor } from "../editor/editor.js";
|
|
4
4
|
export class EditorHighLight extends Editor {
|
|
5
|
+
get activeAnnotation() {
|
|
6
|
+
if (!this.currentAnnotation) throw new Error("Highlight editor is not active");
|
|
7
|
+
return this.currentAnnotation;
|
|
8
|
+
}
|
|
9
|
+
get activeStyle() {
|
|
10
|
+
const style = this.activeAnnotation.style;
|
|
11
|
+
if (!style) throw new Error("Highlight annotation has no style");
|
|
12
|
+
return style;
|
|
13
|
+
}
|
|
5
14
|
/**
|
|
6
15
|
* Creates an EditorHighLight instance.
|
|
7
16
|
* @param EditorOptions Options used to initialize the editor
|
|
@@ -16,8 +25,9 @@ export class EditorHighLight extends Editor {
|
|
|
16
25
|
* @param fixElement Element used as the positioning reference
|
|
17
26
|
*/
|
|
18
27
|
convertTextSelection(elements, fixElement) {
|
|
19
|
-
|
|
20
|
-
this.
|
|
28
|
+
const shapeGroup = this.createShapeGroup();
|
|
29
|
+
this.currentShapeGroup = shapeGroup;
|
|
30
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
21
31
|
const fixBounding = fixElement.getBoundingClientRect();
|
|
22
32
|
elements.forEach((spanEl) => {
|
|
23
33
|
const bounding = spanEl.getBoundingClientRect();
|
|
@@ -26,14 +36,14 @@ export class EditorHighLight extends Editor {
|
|
|
26
36
|
fixBounding
|
|
27
37
|
);
|
|
28
38
|
const shape = this.createShape(x, y, width, height);
|
|
29
|
-
|
|
39
|
+
shapeGroup.konvaGroup.add(shape);
|
|
30
40
|
});
|
|
31
41
|
this.setShapeGroupDone({
|
|
32
|
-
id:
|
|
42
|
+
id: shapeGroup.id,
|
|
33
43
|
contentsObj: {
|
|
34
44
|
text: this.getElementOuterText(elements)
|
|
35
45
|
},
|
|
36
|
-
color: this.
|
|
46
|
+
color: this.activeStyle.color
|
|
37
47
|
});
|
|
38
48
|
}
|
|
39
49
|
/**
|
|
@@ -67,7 +77,7 @@ export class EditorHighLight extends Editor {
|
|
|
67
77
|
* @returns A concrete Konva.Shape instance
|
|
68
78
|
*/
|
|
69
79
|
createShape(x, y, width, height) {
|
|
70
|
-
switch (this.
|
|
80
|
+
switch (this.activeAnnotation.type) {
|
|
71
81
|
case AnnotationType.HIGHLIGHT:
|
|
72
82
|
return this.createHighlightShape(x, y, width, height);
|
|
73
83
|
case AnnotationType.UNDERLINE:
|
|
@@ -76,7 +86,7 @@ export class EditorHighLight extends Editor {
|
|
|
76
86
|
return this.createStrikeoutShape(x, y, width, height);
|
|
77
87
|
default:
|
|
78
88
|
throw new Error(
|
|
79
|
-
`Unsupported annotation type: ${this.
|
|
89
|
+
`Unsupported annotation type: ${this.activeAnnotation.type}`
|
|
80
90
|
);
|
|
81
91
|
}
|
|
82
92
|
}
|
|
@@ -95,7 +105,7 @@ export class EditorHighLight extends Editor {
|
|
|
95
105
|
width,
|
|
96
106
|
height,
|
|
97
107
|
opacity: 0.5,
|
|
98
|
-
fill: this.
|
|
108
|
+
fill: this.activeStyle.color
|
|
99
109
|
});
|
|
100
110
|
}
|
|
101
111
|
/**
|
|
@@ -111,7 +121,7 @@ export class EditorHighLight extends Editor {
|
|
|
111
121
|
x,
|
|
112
122
|
y: height + y - 2,
|
|
113
123
|
width,
|
|
114
|
-
stroke: this.
|
|
124
|
+
stroke: this.activeStyle.color,
|
|
115
125
|
opacity: 1,
|
|
116
126
|
strokeWidth: 1,
|
|
117
127
|
hitStrokeWidth: 10,
|
|
@@ -131,7 +141,7 @@ export class EditorHighLight extends Editor {
|
|
|
131
141
|
x,
|
|
132
142
|
y: y + height / 2,
|
|
133
143
|
width,
|
|
134
|
-
stroke: this.
|
|
144
|
+
stroke: this.activeStyle.color,
|
|
135
145
|
opacity: 1,
|
|
136
146
|
strokeWidth: 1,
|
|
137
147
|
hitStrokeWidth: 10,
|
|
@@ -11,10 +11,12 @@ export class EditorNote extends Editor {
|
|
|
11
11
|
}
|
|
12
12
|
async mouseUpHandler(e) {
|
|
13
13
|
const color = "rgb(255, 222, 33)";
|
|
14
|
-
const { x, y } = this.konvaStage.getRelativePointerPosition();
|
|
15
14
|
if (e.currentTarget !== this.konvaStage) {
|
|
16
15
|
return;
|
|
17
16
|
}
|
|
17
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
18
|
+
if (!pos) return;
|
|
19
|
+
const { x, y } = pos;
|
|
18
20
|
this.isPainting = true;
|
|
19
21
|
this.currentShapeGroup = this.createShapeGroup();
|
|
20
22
|
this.getBgLayer().add(this.currentShapeGroup.konvaGroup);
|
|
@@ -23,11 +23,15 @@ export class EditorRectangle extends Editor {
|
|
|
23
23
|
if (e.currentTarget !== this.konvaStage) {
|
|
24
24
|
return;
|
|
25
25
|
}
|
|
26
|
+
const pos = this.konvaStage.getRelativePointerPosition();
|
|
27
|
+
const annotation = this.currentAnnotation;
|
|
28
|
+
const style = annotation?.style;
|
|
29
|
+
if (!pos || !annotation || !style) return;
|
|
26
30
|
this.rect = null;
|
|
27
31
|
this.isPainting = true;
|
|
28
|
-
|
|
29
|
-
this.
|
|
30
|
-
|
|
32
|
+
const shapeGroup = this.createShapeGroup();
|
|
33
|
+
this.currentShapeGroup = shapeGroup;
|
|
34
|
+
this.getBgLayer().add(shapeGroup.konvaGroup);
|
|
31
35
|
this.vertex = { x: pos.x, y: pos.y };
|
|
32
36
|
this.rect = new Konva.Rect({
|
|
33
37
|
x: pos.x,
|
|
@@ -35,11 +39,11 @@ export class EditorRectangle extends Editor {
|
|
|
35
39
|
width: 0,
|
|
36
40
|
height: 0,
|
|
37
41
|
visible: false,
|
|
38
|
-
stroke:
|
|
39
|
-
strokeWidth:
|
|
40
|
-
opacity:
|
|
42
|
+
stroke: style.color,
|
|
43
|
+
strokeWidth: style.strokeWidth || 2,
|
|
44
|
+
opacity: style.opacity
|
|
41
45
|
});
|
|
42
|
-
|
|
46
|
+
shapeGroup.konvaGroup.add(this.rect);
|
|
43
47
|
window.addEventListener("mouseup", this.globalPointerUpHandler);
|
|
44
48
|
}
|
|
45
49
|
/**
|
|
@@ -51,8 +55,10 @@ export class EditorRectangle extends Editor {
|
|
|
51
55
|
return;
|
|
52
56
|
}
|
|
53
57
|
e.evt.preventDefault();
|
|
58
|
+
if (!this.rect) return;
|
|
54
59
|
this.rect.show();
|
|
55
60
|
const pos = this.konvaStage.getRelativePointerPosition();
|
|
61
|
+
if (!pos) return;
|
|
56
62
|
const areaAttr = {
|
|
57
63
|
x: Math.min(this.vertex.x, pos.x),
|
|
58
64
|
y: Math.min(this.vertex.y, pos.y),
|
|
@@ -69,7 +75,9 @@ export class EditorRectangle extends Editor {
|
|
|
69
75
|
return;
|
|
70
76
|
}
|
|
71
77
|
this.isPainting = false;
|
|
78
|
+
if (!this.rect) return;
|
|
72
79
|
const group = this.rect.getParent();
|
|
80
|
+
if (!group) return;
|
|
73
81
|
if (!this.rect.isVisible() && group.getType() === "Group") {
|
|
74
82
|
this.delShapeGroup(group.id());
|
|
75
83
|
return;
|
|
@@ -80,9 +88,11 @@ export class EditorRectangle extends Editor {
|
|
|
80
88
|
this.rect = null;
|
|
81
89
|
return;
|
|
82
90
|
}
|
|
91
|
+
const style = this.currentAnnotation?.style;
|
|
92
|
+
if (!style) return;
|
|
83
93
|
this.setShapeGroupDone({
|
|
84
94
|
id: group.id(),
|
|
85
|
-
color:
|
|
95
|
+
color: style.color,
|
|
86
96
|
contentsObj: {
|
|
87
97
|
text: ""
|
|
88
98
|
}
|
|
@@ -103,6 +113,7 @@ export class EditorRectangle extends Editor {
|
|
|
103
113
|
* @returns true if the rectangle is too small, false otherwise
|
|
104
114
|
*/
|
|
105
115
|
isTooSmall() {
|
|
116
|
+
if (!this.rect) return true;
|
|
106
117
|
const { width, height } = this.rect.size();
|
|
107
118
|
return Math.max(width, height) < Editor.MinSize;
|
|
108
119
|
}
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
import { cursorPreviewSize, placementSize } from "../../utils/placement_size.js";
|
|
12
12
|
export class EditorSignature extends Editor {
|
|
13
13
|
signatureUrl;
|
|
14
|
-
signatureImage;
|
|
14
|
+
signatureImage = null;
|
|
15
15
|
constructor(editorOptions, defaultSignatureUrl) {
|
|
16
16
|
super({ ...editorOptions, editorType: AnnotationType.SIGNATURE });
|
|
17
17
|
this.signatureUrl = defaultSignatureUrl;
|
|
@@ -54,6 +54,7 @@ export class EditorSignature extends Editor {
|
|
|
54
54
|
const crosshair = { x: newWidth / 2, y: newHeight / 2 };
|
|
55
55
|
this.signatureImage = image;
|
|
56
56
|
this.signatureImage.setAttrs({
|
|
57
|
+
image: image.image(),
|
|
57
58
|
x: pos.x - crosshair.x,
|
|
58
59
|
y: pos.y - crosshair.y,
|
|
59
60
|
width: newWidth,
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
} from "../../utils/placement_size.js";
|
|
15
15
|
export class EditorStamp extends Editor {
|
|
16
16
|
stampUrl;
|
|
17
|
-
stampImage;
|
|
17
|
+
stampImage = null;
|
|
18
18
|
stampWidth = null;
|
|
19
19
|
stampHeight = null;
|
|
20
20
|
constructor(editorOptions, defaultStampUrl) {
|
|
@@ -92,6 +92,7 @@ export class EditorStamp extends Editor {
|
|
|
92
92
|
const crosshair = { x: newWidth / 2, y: newHeight / 2 };
|
|
93
93
|
this.stampImage = image;
|
|
94
94
|
this.stampImage.setAttrs({
|
|
95
|
+
image: image.image(),
|
|
95
96
|
x: pos.x - crosshair.x,
|
|
96
97
|
y: pos.y - crosshair.y,
|
|
97
98
|
width: newWidth,
|
|
@@ -58,6 +58,7 @@ export function removeCssCustomProperty(propertyName) {
|
|
|
58
58
|
}
|
|
59
59
|
export async function base64ToImageBitmap(base64) {
|
|
60
60
|
const base64Data = base64.split(",")[1];
|
|
61
|
+
if (!base64Data) throw new Error("Invalid base64 image data");
|
|
61
62
|
const binaryString = atob(base64Data);
|
|
62
63
|
const length = binaryString.length;
|
|
63
64
|
const bytes = new Uint8Array(length);
|
|
@@ -134,7 +135,7 @@ export function getPDFDateTimestamp(dateString) {
|
|
|
134
135
|
let tzOffset = 0;
|
|
135
136
|
if (tzMatch) {
|
|
136
137
|
const sign = tzMatch[1] === "+" ? 1 : -1;
|
|
137
|
-
const hours = Number.parseInt(tzMatch[2], 10) || 0;
|
|
138
|
+
const hours = Number.parseInt(tzMatch[2] ?? "0", 10) || 0;
|
|
138
139
|
const minutes = Number.parseInt(tzMatch[3] || "0", 10) || 0;
|
|
139
140
|
tzOffset = sign * (hours * 60 + minutes);
|
|
140
141
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function downloadPdfBytes(data, fileName) {
|
|
2
|
-
const arrayBuffer =
|
|
2
|
+
const arrayBuffer = Uint8Array.from(data).buffer;
|
|
3
3
|
const blob = new Blob([arrayBuffer], { type: "application/pdf" });
|
|
4
4
|
const link = document.createElement("a");
|
|
5
5
|
const url = URL.createObjectURL(blob);
|
|
@@ -192,7 +192,7 @@ async function flattenPageAnnotations(pdfDoc, page, annotations) {
|
|
|
192
192
|
for (const annotation of annotations) {
|
|
193
193
|
try {
|
|
194
194
|
const node = Konva.Node.create(annotation.konvaString);
|
|
195
|
-
if (node instanceof Konva.
|
|
195
|
+
if (node instanceof Konva.Group || node instanceof Konva.Shape) {
|
|
196
196
|
layer.add(node);
|
|
197
197
|
imageLoaders.push(...loadImagesForNode(node));
|
|
198
198
|
}
|
|
@@ -12,7 +12,11 @@ function parseSvgPathToPoints(data) {
|
|
|
12
12
|
const nums = cmd.slice(1).trim().split(/[\s,]+/).map((value) => Number.parseFloat(value));
|
|
13
13
|
if (type === "M" || type === "L") {
|
|
14
14
|
for (let i = 0; i < nums.length; i += 2) {
|
|
15
|
-
|
|
15
|
+
const x = nums[i];
|
|
16
|
+
const y = nums[i + 1];
|
|
17
|
+
if (x !== void 0 && y !== void 0) {
|
|
18
|
+
points.push(x, y);
|
|
19
|
+
}
|
|
16
20
|
}
|
|
17
21
|
} else if (type === "Q") {
|
|
18
22
|
if (nums.length >= 4) {
|
|
@@ -177,10 +177,10 @@ export class StampParser extends AnnotationParser {
|
|
|
177
177
|
...this.ownerDateEntries(annotation.title, annotation.date),
|
|
178
178
|
Open: false
|
|
179
179
|
};
|
|
180
|
-
|
|
181
|
-
stampAnnDict
|
|
182
|
-
|
|
183
|
-
|
|
180
|
+
const stampAnn = context.obj({
|
|
181
|
+
...stampAnnDict,
|
|
182
|
+
...apDict ? { AP: apDict } : {}
|
|
183
|
+
});
|
|
184
184
|
const stampAnnRef = context.register(stampAnn);
|
|
185
185
|
this.addAnnotationToPage(page, stampAnnRef);
|
|
186
186
|
for (const comment of annotation.comments || []) {
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
import fontkit from "@pdf-lib/fontkit";
|
|
2
2
|
let fontBytesPromise = null;
|
|
3
3
|
let loadFontBytes = async () => {
|
|
4
|
-
const { default: fontUrl } = await import(
|
|
5
|
-
// @ts-expect-error -- Vite asset import, no type declaration
|
|
6
|
-
"../../assets/fonts/LiberationSans-Regular.ttf?url"
|
|
7
|
-
);
|
|
4
|
+
const { default: fontUrl } = await import("../../assets/fonts/LiberationSans-Regular.ttf?url");
|
|
8
5
|
const response = await fetch(fontUrl);
|
|
9
6
|
if (!response.ok) {
|
|
10
7
|
throw new Error(`Failed to load Unicode fallback font (${response.status})`);
|
|
@@ -16,13 +16,14 @@ export function decodeStampAnnotation(annotation, context) {
|
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
18
|
const group = createGhostGroup(annotation.id);
|
|
19
|
-
|
|
19
|
+
const imageConfig = {
|
|
20
20
|
x: rect.x,
|
|
21
21
|
y: rect.y,
|
|
22
22
|
width: rect.width > 0 ? rect.width : appearance.width,
|
|
23
23
|
height: rect.height > 0 ? rect.height : appearance.height,
|
|
24
24
|
base64: appearance.dataUrl
|
|
25
|
-
}
|
|
25
|
+
};
|
|
26
|
+
group.add(new Konva.Image(imageConfig));
|
|
26
27
|
const store = createAnnotationStore({
|
|
27
28
|
annotation,
|
|
28
29
|
allAnnotations: context.allAnnotations,
|
|
@@ -88,7 +88,7 @@ async function renderPageToCanvas(page, canvas, annotationMode, scale) {
|
|
|
88
88
|
if (!context) throw new Error("Unable to create canvas context for stamp extraction");
|
|
89
89
|
const viewport = page.getViewport({ scale });
|
|
90
90
|
const task = page.render({
|
|
91
|
-
|
|
91
|
+
canvas,
|
|
92
92
|
viewport,
|
|
93
93
|
annotationMode
|
|
94
94
|
});
|
|
@@ -104,7 +104,7 @@ export function getComments(annotation, allAnnotations) {
|
|
|
104
104
|
if (candidate.annotationType !== 1) continue;
|
|
105
105
|
if (candidate.inReplyTo !== annotation.id) continue;
|
|
106
106
|
comments.push({
|
|
107
|
-
id: candidate.id,
|
|
107
|
+
id: typeof candidate.id === "string" ? candidate.id : "",
|
|
108
108
|
title: getAnnotationTitle(candidate),
|
|
109
109
|
date: getAnnotationDate(candidate),
|
|
110
110
|
content: getAnnotationText(candidate)
|
|
@@ -5,7 +5,7 @@ type __VLS_Props = {
|
|
|
5
5
|
/** Carries displayed width/height plus the page's `/Rotate` and MediaBox
|
|
6
6
|
* origin — the single source of truth for mapping `/Rect` to canvas. */
|
|
7
7
|
pageTransform: PageTransform;
|
|
8
|
-
pointerEvents:
|
|
8
|
+
pointerEvents: 'auto' | 'none';
|
|
9
9
|
zIndex: number;
|
|
10
10
|
};
|
|
11
11
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -5,7 +5,7 @@ type __VLS_Props = {
|
|
|
5
5
|
/** Carries displayed width/height plus the page's `/Rotate` and MediaBox
|
|
6
6
|
* origin — the single source of truth for mapping `/Rect` to canvas. */
|
|
7
7
|
pageTransform: PageTransform;
|
|
8
|
-
pointerEvents:
|
|
8
|
+
pointerEvents: 'auto' | 'none';
|
|
9
9
|
zIndex: number;
|
|
10
10
|
};
|
|
11
11
|
declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
|
|
@@ -272,7 +272,7 @@ async function renderCanvas(opts) {
|
|
|
272
272
|
tmp.height = viewport.height;
|
|
273
273
|
try {
|
|
274
274
|
currentRenderTask = proxy.render({
|
|
275
|
-
|
|
275
|
+
canvas: tmp,
|
|
276
276
|
viewport,
|
|
277
277
|
annotationMode: PDFJS_ANNOTATION_MODE_DISABLE
|
|
278
278
|
});
|
|
@@ -293,7 +293,7 @@ async function renderCanvas(opts) {
|
|
|
293
293
|
canvas.height = viewport.height;
|
|
294
294
|
try {
|
|
295
295
|
currentRenderTask = proxy.render({
|
|
296
|
-
|
|
296
|
+
canvas,
|
|
297
297
|
viewport,
|
|
298
298
|
annotationMode: PDFJS_ANNOTATION_MODE_DISABLE
|
|
299
299
|
});
|
|
@@ -349,7 +349,7 @@ async function renderWindowCanvas() {
|
|
|
349
349
|
tmp.height = Math.floor(h * k);
|
|
350
350
|
try {
|
|
351
351
|
windowRenderTask = proxy.render({
|
|
352
|
-
|
|
352
|
+
canvas: tmp,
|
|
353
353
|
viewport,
|
|
354
354
|
transform: [1, 0, 0, 1, -x * k, -y * k],
|
|
355
355
|
annotationMode: PDFJS_ANNOTATION_MODE_DISABLE
|
|
@@ -1022,7 +1022,9 @@ onMounted(() => {
|
|
|
1022
1022
|
if (isIPad()) {
|
|
1023
1023
|
viewerState.setStylusMode(true);
|
|
1024
1024
|
}
|
|
1025
|
-
setDownloadPdfFn(() =>
|
|
1025
|
+
setDownloadPdfFn(async () => {
|
|
1026
|
+
await exportPdf({ download: true });
|
|
1027
|
+
});
|
|
1026
1028
|
loadDocument();
|
|
1027
1029
|
window.addEventListener("keydown", onGlobalKeydown);
|
|
1028
1030
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<UPopover>
|
|
2
|
+
<UPopover v-model:open="popoverOpen">
|
|
3
3
|
<button
|
|
4
4
|
class="relative flex items-center justify-center w-8 h-8 rounded-md transition-colors cursor-pointer"
|
|
5
5
|
:class="isActive ? 'bg-default text-highlighted' : 'text-muted hover:bg-default/50 hover:text-highlighted'"
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
color="neutral"
|
|
44
44
|
size="xs"
|
|
45
45
|
block
|
|
46
|
-
@click="
|
|
46
|
+
@click="openDrawModal"
|
|
47
47
|
>
|
|
48
48
|
{{ t("addSignature") }}
|
|
49
49
|
</UButton>
|
|
@@ -69,10 +69,16 @@ import SignatureDrawModal from "../modals/SignatureDrawModal.vue";
|
|
|
69
69
|
const state = useViewerState();
|
|
70
70
|
const { t } = useKviewerI18n();
|
|
71
71
|
const drawModalOpen = ref(false);
|
|
72
|
+
const popoverOpen = ref(false);
|
|
72
73
|
const isActive = computed(() => state.activeTool.value === AnnotationType.SIGNATURE);
|
|
73
74
|
function selectSignature(sig) {
|
|
74
75
|
state.activeSignature.value = sig;
|
|
75
76
|
state.selectTool(AnnotationType.SIGNATURE, sig.imageUrl);
|
|
77
|
+
popoverOpen.value = false;
|
|
78
|
+
}
|
|
79
|
+
function openDrawModal() {
|
|
80
|
+
popoverOpen.value = false;
|
|
81
|
+
drawModalOpen.value = true;
|
|
76
82
|
}
|
|
77
83
|
async function onDrawSubmit(imageUrl) {
|
|
78
84
|
drawModalOpen.value = false;
|
|
@@ -15,7 +15,7 @@ export function createSearchIndex() {
|
|
|
15
15
|
includeMarkedContent: false,
|
|
16
16
|
disableNormalization: false
|
|
17
17
|
});
|
|
18
|
-
return content.items.
|
|
18
|
+
return content.items.map((item) => "str" in item ? item.str : "").join("");
|
|
19
19
|
}
|
|
20
20
|
async function buildIndex(doc) {
|
|
21
21
|
destroyed = false;
|
|
@@ -32,7 +32,7 @@ export interface KViewerApi {
|
|
|
32
32
|
allSigned: boolean;
|
|
33
33
|
fields: SignatureFieldStatus[];
|
|
34
34
|
}) => void) => () => void;
|
|
35
|
-
formEditMode: Ref<boolean>;
|
|
35
|
+
formEditMode: boolean | Ref<boolean>;
|
|
36
36
|
setFormEditMode: (enabled: boolean) => void;
|
|
37
37
|
toggleFormEditMode: () => boolean;
|
|
38
38
|
allPagesRead: () => boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { onScopeDispose, watch } from "vue";
|
|
1
|
+
import { onScopeDispose, unref, watch } from "vue";
|
|
2
2
|
import {
|
|
3
3
|
EVENT_KIND,
|
|
4
4
|
KVIEWER_EMBED_PROTOCOL_VERSION,
|
|
@@ -81,7 +81,7 @@ export function useKViewerEmbedBridge(viewerRef, options) {
|
|
|
81
81
|
case "getSignatureFieldStatus":
|
|
82
82
|
return viewer.getSignatureFieldStatus();
|
|
83
83
|
case "getFormEditMode":
|
|
84
|
-
return viewer.formEditMode
|
|
84
|
+
return unref(viewer.formEditMode);
|
|
85
85
|
case "setFormEditMode": {
|
|
86
86
|
const [enabled] = req.args;
|
|
87
87
|
viewer.setFormEditMode(enabled);
|
|
@@ -141,7 +141,7 @@ export function useKViewerEmbedBridge(viewerRef, options) {
|
|
|
141
141
|
postEvent("ready", { protocolVersion: KVIEWER_EMBED_PROTOCOL_VERSION });
|
|
142
142
|
stopViewerStateWatches.push(
|
|
143
143
|
watch(
|
|
144
|
-
viewer.formEditMode,
|
|
144
|
+
() => unref(viewer.formEditMode),
|
|
145
145
|
(enabled) => postEvent("formEditMode-changed", { enabled })
|
|
146
146
|
),
|
|
147
147
|
viewer.onFieldPlaced(
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
declare module '*?url' {
|
|
2
|
+
const url: string;
|
|
3
|
+
export default url;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
declare module 'pngjs' {
|
|
7
|
+
export class PNG {
|
|
8
|
+
constructor(options?: { width?: number; height?: number });
|
|
9
|
+
|
|
10
|
+
static sync: {
|
|
11
|
+
read(data: Buffer): PNG;
|
|
12
|
+
write(image: PNG): Buffer;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
width: number;
|
|
16
|
+
height: number;
|
|
17
|
+
data: Buffer;
|
|
18
|
+
}
|
|
19
|
+
}
|
package/dist/types.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type ActiveTool, type AddFormFieldPayload, type CheckboxStyle, type ExportPdfOptions, type FormFieldDefinition, type FormFieldOrigin, type FormFieldType, type FormFieldValue, type KVIEWER_EMBED_PROTOCOL_VERSION, type KViewerApi, type KViewerEmbedBridgeOptions, type KViewerEmbedClient, type KViewerEmbedClientOptions, type KViewerEmbedEventName, type KViewerEmbedEventPayloads, type KViewerEmbedMethodName, type SignatureData, type SignatureHandlers, type ViewMode, type ViewerBottomToolId, type ViewerLayoutToolId, type ViewerMenuButtonItem, type ViewerMenuCheckboxItem, type ViewerMenuItem, type ViewerMenuSeparatorItem, type ViewerState, type ViewerToolEntry, type ViewerToolId, type ViewerToolSlot, type ViewerTopToolId, type useKViewerEmbedBridge } from '../dist/runtime/public-types.js'
|
|
1
|
+
export { type ActiveTool, type AddFormFieldPayload, type CheckboxStyle, type ExportPdfOptions, type FormFieldDefinition, type FormFieldOrigin, type FormFieldType, type FormFieldValue, type KVIEWER_EMBED_PROTOCOL_VERSION, type KViewerApi, type KViewerEmbedBridgeOptions, type KViewerEmbedClient, type KViewerEmbedClientOptions, type KViewerEmbedEventName, type KViewerEmbedEventPayloads, type KViewerEmbedMethodName, type PlacedFieldDefaults, type SignatureData, type SignatureFieldStatus, type SignatureHandlers, type ViewMode, type ViewerBottomToolId, type ViewerLayoutToolId, type ViewerMenuButtonItem, type ViewerMenuCheckboxItem, type ViewerMenuItem, type ViewerMenuSeparatorItem, type ViewerState, type ViewerToolEntry, type ViewerToolId, type ViewerToolSlot, type ViewerTopToolId, type useKViewerEmbedBridge } from '../dist/runtime/public-types.js'
|
|
2
2
|
|
|
3
3
|
export { default } from './module.mjs'
|
|
4
4
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kviewer",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "Kabema PDF Editor",
|
|
5
5
|
"repository": "kabema/kviewer",
|
|
6
6
|
"license": "MIT",
|
|
@@ -65,7 +65,7 @@
|
|
|
65
65
|
"lint": "eslint .",
|
|
66
66
|
"test": "vitest run --exclude '**/e2e/**'",
|
|
67
67
|
"test:watch": "vitest watch",
|
|
68
|
-
"test:types": "vue-tsc --noEmit &&
|
|
68
|
+
"test:types": "pnpm run dev:prepare && pnpm --dir docs exec nuxt prepare && vue-tsc --noEmit && pnpm --dir playground exec vue-tsc --noEmit && pnpm --dir docs exec vue-tsc --noEmit",
|
|
69
69
|
"test:e2e": "playwright test",
|
|
70
70
|
"test:e2e:ui": "playwright test --ui"
|
|
71
71
|
}
|