@embedpdf/plugin-annotation 1.0.7 → 1.0.9
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/index.cjs +48 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -7
- package/dist/index.d.ts +29 -7
- package/dist/index.js +51 -6
- package/dist/index.js.map +1 -1
- package/dist/preact/index.cjs +795 -148
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.d.cts +4 -1
- package/dist/preact/index.d.ts +4 -1
- package/dist/preact/index.js +795 -146
- package/dist/preact/index.js.map +1 -1
- package/package.json +8 -8
package/dist/preact/index.cjs
CHANGED
|
@@ -33,74 +33,243 @@ var useAnnotationPlugin = () => (0, import_preact.usePlugin)(import_plugin_annot
|
|
|
33
33
|
var useAnnotationCapability = () => (0, import_preact.useCapability)(import_plugin_annotation.AnnotationPlugin.id);
|
|
34
34
|
|
|
35
35
|
// src/preact/components/annotations.tsx
|
|
36
|
-
var
|
|
37
|
-
var
|
|
36
|
+
var import_models3 = require("@embedpdf/models");
|
|
37
|
+
var import_preact2 = require("@embedpdf/plugin-interaction-manager/preact");
|
|
38
38
|
var import_plugin_annotation2 = require("@embedpdf/plugin-annotation");
|
|
39
|
-
var
|
|
39
|
+
var import_hooks5 = require("preact/hooks");
|
|
40
40
|
|
|
41
|
-
// src/preact/components/
|
|
41
|
+
// src/preact/components/annotation-container.tsx
|
|
42
42
|
var import_hooks = require("preact/hooks");
|
|
43
|
-
var
|
|
43
|
+
var import_models = require("@embedpdf/models");
|
|
44
44
|
var import_jsx_runtime = require("preact/jsx-runtime");
|
|
45
|
-
function
|
|
46
|
-
trackedAnnotation,
|
|
45
|
+
function AnnotationContainer({
|
|
47
46
|
scale,
|
|
48
|
-
isSelected = false,
|
|
49
47
|
pageIndex,
|
|
50
|
-
|
|
48
|
+
rotation,
|
|
49
|
+
trackedAnnotation,
|
|
50
|
+
children,
|
|
51
|
+
style,
|
|
52
|
+
outlineOffset = 1,
|
|
53
|
+
isSelected = false,
|
|
54
|
+
isDraggable = true,
|
|
55
|
+
isResizable = true,
|
|
56
|
+
computeResizePatch,
|
|
57
|
+
...props
|
|
51
58
|
}) {
|
|
52
59
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
53
|
-
const
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
+
const ref = (0, import_hooks.useRef)(null);
|
|
61
|
+
const [dragState, setDragState] = (0, import_hooks.useState)("idle");
|
|
62
|
+
const [resizeDirection, setResizeDirection] = (0, import_hooks.useState)(null);
|
|
63
|
+
const [startPos, setStartPos] = (0, import_hooks.useState)(null);
|
|
64
|
+
const [startRect, setStartRect] = (0, import_hooks.useState)(null);
|
|
65
|
+
const [currentRect, setCurrentRect] = (0, import_hooks.useState)(trackedAnnotation.object.rect);
|
|
66
|
+
const [previewObject, setPreviewObject] = (0, import_hooks.useState)(null);
|
|
67
|
+
(0, import_hooks.useEffect)(() => {
|
|
68
|
+
setCurrentRect(trackedAnnotation.object.rect);
|
|
69
|
+
setPreviewObject(null);
|
|
70
|
+
}, [trackedAnnotation]);
|
|
71
|
+
const handlePointerDown = (e) => {
|
|
72
|
+
if (!isSelected) return;
|
|
73
|
+
e.stopPropagation();
|
|
74
|
+
e.preventDefault();
|
|
75
|
+
const target = e.target;
|
|
76
|
+
if (isResizable && target.classList.contains("resize-handle")) {
|
|
77
|
+
setDragState("resizing");
|
|
78
|
+
setResizeDirection(target.dataset.direction);
|
|
79
|
+
} else if (isDraggable) {
|
|
80
|
+
setDragState("dragging");
|
|
81
|
+
} else {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
setStartPos({ x: e.clientX, y: e.clientY });
|
|
85
|
+
setStartRect(currentRect);
|
|
86
|
+
ref.current?.setPointerCapture(e.pointerId);
|
|
87
|
+
};
|
|
88
|
+
const handlePointerMove = (e) => {
|
|
89
|
+
if (dragState === "idle" || !startPos || !startRect) return;
|
|
90
|
+
const dispDelta = { x: e.clientX - startPos.x, y: e.clientY - startPos.y };
|
|
91
|
+
const { x: dx, y: dy } = (0, import_models.restoreOffset)(dispDelta, rotation, scale);
|
|
92
|
+
let newOriginX = startRect.origin.x;
|
|
93
|
+
let newOriginY = startRect.origin.y;
|
|
94
|
+
let newWidth = startRect.size.width;
|
|
95
|
+
let newHeight = startRect.size.height;
|
|
96
|
+
if (dragState === "dragging") {
|
|
97
|
+
newOriginX += dx;
|
|
98
|
+
newOriginY += dy;
|
|
99
|
+
} else if (dragState === "resizing" && resizeDirection) {
|
|
100
|
+
if (resizeDirection.includes("right")) {
|
|
101
|
+
newWidth += dx;
|
|
102
|
+
} else if (resizeDirection.includes("left")) {
|
|
103
|
+
newOriginX += dx;
|
|
104
|
+
newWidth -= dx;
|
|
60
105
|
}
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
67
|
-
"div",
|
|
68
|
-
{
|
|
69
|
-
className: "markup-annotation",
|
|
70
|
-
style: {
|
|
71
|
-
position: "absolute",
|
|
72
|
-
mixBlendMode: "multiply",
|
|
73
|
-
cursor: "pointer",
|
|
74
|
-
outline: isSelected ? "2px solid #007ACC" : "none",
|
|
75
|
-
outlineOffset: isSelected ? "1px" : "0px",
|
|
76
|
-
left: `${trackedAnnotation.object.rect.origin.x * scale}px`,
|
|
77
|
-
top: `${trackedAnnotation.object.rect.origin.y * scale}px`,
|
|
78
|
-
width: `${trackedAnnotation.object.rect.size.width * scale}px`,
|
|
79
|
-
height: `${trackedAnnotation.object.rect.size.height * scale}px`,
|
|
80
|
-
zIndex: 1
|
|
81
|
-
},
|
|
82
|
-
onMouseDown: handleClick
|
|
106
|
+
if (resizeDirection.includes("bottom")) {
|
|
107
|
+
newHeight += dy;
|
|
108
|
+
} else if (resizeDirection.includes("top")) {
|
|
109
|
+
newOriginY += dy;
|
|
110
|
+
newHeight -= dy;
|
|
83
111
|
}
|
|
84
|
-
|
|
85
|
-
|
|
112
|
+
if (newWidth < 1 || newHeight < 1) return;
|
|
113
|
+
}
|
|
114
|
+
const tentativeRect = {
|
|
115
|
+
origin: { x: newOriginX, y: newOriginY },
|
|
116
|
+
size: { width: newWidth, height: newHeight }
|
|
117
|
+
};
|
|
118
|
+
let previewPatch = { rect: tentativeRect };
|
|
119
|
+
if (computeResizePatch) {
|
|
120
|
+
const dir = dragState === "resizing" ? resizeDirection : "bottom-right";
|
|
121
|
+
if (dir) {
|
|
122
|
+
previewPatch = computeResizePatch(trackedAnnotation.object, tentativeRect, dir);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
setCurrentRect(previewPatch.rect || tentativeRect);
|
|
126
|
+
setPreviewObject(previewPatch);
|
|
127
|
+
};
|
|
128
|
+
const handlePointerUp = (e) => {
|
|
129
|
+
if (dragState === "idle") return;
|
|
130
|
+
const usedDirection = resizeDirection || "bottom-right";
|
|
131
|
+
setDragState("idle");
|
|
132
|
+
setResizeDirection(null);
|
|
133
|
+
ref.current?.releasePointerCapture(e.pointerId);
|
|
134
|
+
if (annotationProvides && trackedAnnotation) {
|
|
135
|
+
let patch = { rect: currentRect };
|
|
136
|
+
if (computeResizePatch && usedDirection) {
|
|
137
|
+
patch = computeResizePatch(trackedAnnotation.object, currentRect, usedDirection);
|
|
138
|
+
}
|
|
139
|
+
annotationProvides.updateAnnotation(pageIndex, trackedAnnotation.localId, patch);
|
|
140
|
+
}
|
|
141
|
+
setStartPos(null);
|
|
142
|
+
setStartRect(null);
|
|
143
|
+
setPreviewObject(null);
|
|
144
|
+
};
|
|
145
|
+
const currentObject = previewObject ? { ...trackedAnnotation.object, ...previewObject } : trackedAnnotation.object;
|
|
146
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
147
|
+
"div",
|
|
148
|
+
{
|
|
149
|
+
ref,
|
|
150
|
+
onPointerDown: handlePointerDown,
|
|
151
|
+
onPointerMove: handlePointerMove,
|
|
152
|
+
onPointerUp: handlePointerUp,
|
|
153
|
+
style: {
|
|
154
|
+
position: "absolute",
|
|
155
|
+
outline: isSelected ? "1px solid #007ACC" : "none",
|
|
156
|
+
outlineOffset: isSelected ? `${outlineOffset}px` : "0px",
|
|
157
|
+
left: `${currentRect.origin.x * scale}px`,
|
|
158
|
+
top: `${currentRect.origin.y * scale}px`,
|
|
159
|
+
width: `${currentRect.size.width * scale}px`,
|
|
160
|
+
height: `${currentRect.size.height * scale}px`,
|
|
161
|
+
pointerEvents: isSelected ? "auto" : "none",
|
|
162
|
+
cursor: isSelected && isDraggable ? "move" : "default",
|
|
163
|
+
...style
|
|
164
|
+
},
|
|
165
|
+
...props,
|
|
166
|
+
children: [
|
|
167
|
+
typeof children === "function" ? children(currentObject) : children,
|
|
168
|
+
isSelected && isResizable && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
169
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
170
|
+
"div",
|
|
171
|
+
{
|
|
172
|
+
className: "resize-handle",
|
|
173
|
+
"data-direction": "top-left",
|
|
174
|
+
style: {
|
|
175
|
+
position: "absolute",
|
|
176
|
+
top: -7 - outlineOffset,
|
|
177
|
+
left: -7 - outlineOffset,
|
|
178
|
+
width: 13,
|
|
179
|
+
height: 13,
|
|
180
|
+
background: "blue",
|
|
181
|
+
borderRadius: "50%",
|
|
182
|
+
cursor: rotation % 2 ? "nesw-resize" : "nwse-resize"
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
187
|
+
"div",
|
|
188
|
+
{
|
|
189
|
+
className: "resize-handle",
|
|
190
|
+
"data-direction": "top-right",
|
|
191
|
+
style: {
|
|
192
|
+
position: "absolute",
|
|
193
|
+
top: -7 - outlineOffset,
|
|
194
|
+
right: -7 - outlineOffset,
|
|
195
|
+
width: 13,
|
|
196
|
+
height: 13,
|
|
197
|
+
background: "blue",
|
|
198
|
+
borderRadius: "50%",
|
|
199
|
+
cursor: rotation % 2 ? "nwse-resize" : "nesw-resize"
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
),
|
|
203
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
204
|
+
"div",
|
|
205
|
+
{
|
|
206
|
+
className: "resize-handle",
|
|
207
|
+
"data-direction": "bottom-left",
|
|
208
|
+
style: {
|
|
209
|
+
position: "absolute",
|
|
210
|
+
bottom: -7 - outlineOffset,
|
|
211
|
+
left: -7 - outlineOffset,
|
|
212
|
+
width: 13,
|
|
213
|
+
height: 13,
|
|
214
|
+
background: "blue",
|
|
215
|
+
borderRadius: "50%",
|
|
216
|
+
cursor: rotation % 2 ? "nwse-resize" : "nesw-resize"
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
),
|
|
220
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
221
|
+
"div",
|
|
222
|
+
{
|
|
223
|
+
className: "resize-handle",
|
|
224
|
+
"data-direction": "bottom-right",
|
|
225
|
+
style: {
|
|
226
|
+
position: "absolute",
|
|
227
|
+
bottom: -7 - outlineOffset,
|
|
228
|
+
right: -7 - outlineOffset,
|
|
229
|
+
width: 13,
|
|
230
|
+
height: 13,
|
|
231
|
+
background: "blue",
|
|
232
|
+
borderRadius: "50%",
|
|
233
|
+
cursor: rotation % 2 ? "nesw-resize" : "nwse-resize"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
)
|
|
237
|
+
] })
|
|
238
|
+
]
|
|
239
|
+
}
|
|
240
|
+
);
|
|
86
241
|
}
|
|
87
242
|
|
|
88
243
|
// src/preact/components/text-markup/highlight.tsx
|
|
89
244
|
var import_jsx_runtime2 = require("preact/jsx-runtime");
|
|
90
|
-
function Highlight({
|
|
245
|
+
function Highlight({
|
|
246
|
+
color = "#FFFF00",
|
|
247
|
+
opacity = 0.5,
|
|
248
|
+
rects,
|
|
249
|
+
rect,
|
|
250
|
+
scale,
|
|
251
|
+
onClick,
|
|
252
|
+
style,
|
|
253
|
+
...props
|
|
254
|
+
}) {
|
|
91
255
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: rects.map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
92
256
|
"div",
|
|
93
257
|
{
|
|
258
|
+
onMouseDown: onClick,
|
|
94
259
|
style: {
|
|
95
260
|
position: "absolute",
|
|
96
|
-
left: b.origin.x * scale,
|
|
97
|
-
top: b.origin.y * scale,
|
|
261
|
+
left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,
|
|
262
|
+
top: (rect ? b.origin.y - rect.origin.y : b.origin.y) * scale,
|
|
98
263
|
width: b.size.width * scale,
|
|
99
264
|
height: b.size.height * scale,
|
|
100
265
|
background: color,
|
|
101
266
|
opacity,
|
|
102
|
-
pointerEvents: "none"
|
|
103
|
-
|
|
267
|
+
pointerEvents: onClick ? "auto" : "none",
|
|
268
|
+
cursor: onClick ? "pointer" : "default",
|
|
269
|
+
zIndex: onClick ? 1 : null,
|
|
270
|
+
...style
|
|
271
|
+
},
|
|
272
|
+
...props
|
|
104
273
|
},
|
|
105
274
|
i
|
|
106
275
|
)) });
|
|
@@ -108,21 +277,49 @@ function Highlight({ color = "#FFFF00", opacity = 0.5, rects, scale }) {
|
|
|
108
277
|
|
|
109
278
|
// src/preact/components/text-markup/underline.tsx
|
|
110
279
|
var import_jsx_runtime3 = require("preact/jsx-runtime");
|
|
111
|
-
function Underline({
|
|
280
|
+
function Underline({
|
|
281
|
+
color = "#FFFF00",
|
|
282
|
+
opacity = 0.5,
|
|
283
|
+
rects,
|
|
284
|
+
rect,
|
|
285
|
+
scale,
|
|
286
|
+
onClick,
|
|
287
|
+
style,
|
|
288
|
+
...props
|
|
289
|
+
}) {
|
|
112
290
|
const thickness = 2 * scale;
|
|
113
291
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: rects.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
114
292
|
"div",
|
|
115
293
|
{
|
|
294
|
+
onMouseDown: onClick,
|
|
116
295
|
style: {
|
|
117
296
|
position: "absolute",
|
|
118
|
-
left: r.origin.x * scale,
|
|
119
|
-
top: (r.origin.y
|
|
297
|
+
left: (rect ? r.origin.x - rect.origin.x : r.origin.x) * scale,
|
|
298
|
+
top: (rect ? r.origin.y - rect.origin.y : r.origin.y) * scale,
|
|
120
299
|
width: r.size.width * scale,
|
|
121
|
-
height:
|
|
122
|
-
background:
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
300
|
+
height: r.size.height * scale,
|
|
301
|
+
background: "transparent",
|
|
302
|
+
pointerEvents: onClick ? "auto" : "none",
|
|
303
|
+
cursor: onClick ? "pointer" : "default",
|
|
304
|
+
zIndex: onClick ? 1 : 0,
|
|
305
|
+
...style
|
|
306
|
+
},
|
|
307
|
+
...props,
|
|
308
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
309
|
+
"div",
|
|
310
|
+
{
|
|
311
|
+
style: {
|
|
312
|
+
position: "absolute",
|
|
313
|
+
left: 0,
|
|
314
|
+
bottom: 0,
|
|
315
|
+
width: "100%",
|
|
316
|
+
height: thickness,
|
|
317
|
+
background: color,
|
|
318
|
+
opacity,
|
|
319
|
+
pointerEvents: "none"
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
)
|
|
126
323
|
},
|
|
127
324
|
i
|
|
128
325
|
)) });
|
|
@@ -130,21 +327,50 @@ function Underline({ color = "#FFFF00", opacity = 0.5, rects, scale }) {
|
|
|
130
327
|
|
|
131
328
|
// src/preact/components/text-markup/strikeout.tsx
|
|
132
329
|
var import_jsx_runtime4 = require("preact/jsx-runtime");
|
|
133
|
-
function Strikeout({
|
|
330
|
+
function Strikeout({
|
|
331
|
+
color = "#FFFF00",
|
|
332
|
+
opacity = 0.5,
|
|
333
|
+
rects,
|
|
334
|
+
rect,
|
|
335
|
+
scale,
|
|
336
|
+
onClick,
|
|
337
|
+
style,
|
|
338
|
+
...props
|
|
339
|
+
}) {
|
|
134
340
|
const thickness = 2 * scale;
|
|
135
341
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: rects.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
136
342
|
"div",
|
|
137
343
|
{
|
|
344
|
+
onMouseDown: onClick,
|
|
138
345
|
style: {
|
|
139
346
|
position: "absolute",
|
|
140
|
-
left: r.origin.x * scale,
|
|
141
|
-
top: (r.origin.y
|
|
347
|
+
left: (rect ? r.origin.x - rect.origin.x : r.origin.x) * scale,
|
|
348
|
+
top: (rect ? r.origin.y - rect.origin.y : r.origin.y) * scale,
|
|
142
349
|
width: r.size.width * scale,
|
|
143
|
-
height:
|
|
144
|
-
background:
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
350
|
+
height: r.size.height * scale,
|
|
351
|
+
background: "transparent",
|
|
352
|
+
pointerEvents: onClick ? "auto" : "none",
|
|
353
|
+
cursor: onClick ? "pointer" : "default",
|
|
354
|
+
zIndex: onClick ? 1 : 0,
|
|
355
|
+
...style
|
|
356
|
+
},
|
|
357
|
+
...props,
|
|
358
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
359
|
+
"div",
|
|
360
|
+
{
|
|
361
|
+
style: {
|
|
362
|
+
position: "absolute",
|
|
363
|
+
left: 0,
|
|
364
|
+
top: "50%",
|
|
365
|
+
width: "100%",
|
|
366
|
+
height: thickness,
|
|
367
|
+
background: color,
|
|
368
|
+
opacity,
|
|
369
|
+
transform: "translateY(-50%)",
|
|
370
|
+
pointerEvents: "none"
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
)
|
|
148
374
|
},
|
|
149
375
|
i
|
|
150
376
|
)) });
|
|
@@ -152,7 +378,16 @@ function Strikeout({ color = "#FFFF00", opacity = 0.5, rects, scale }) {
|
|
|
152
378
|
|
|
153
379
|
// src/preact/components/text-markup/squiggly.tsx
|
|
154
380
|
var import_jsx_runtime5 = require("preact/jsx-runtime");
|
|
155
|
-
function Squiggly({
|
|
381
|
+
function Squiggly({
|
|
382
|
+
color = "#FFFF00",
|
|
383
|
+
opacity = 0.5,
|
|
384
|
+
rects,
|
|
385
|
+
rect,
|
|
386
|
+
scale,
|
|
387
|
+
onClick,
|
|
388
|
+
style,
|
|
389
|
+
...props
|
|
390
|
+
}) {
|
|
156
391
|
const amplitude = 2 * scale;
|
|
157
392
|
const period = 6 * scale;
|
|
158
393
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${period}" height="${amplitude * 2}" viewBox="0 0 ${period} ${amplitude * 2}">
|
|
@@ -163,31 +398,160 @@ function Squiggly({ color = "#FFFF00", opacity = 0.5, rects, scale }) {
|
|
|
163
398
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: rects.map((r, i) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
164
399
|
"div",
|
|
165
400
|
{
|
|
401
|
+
onMouseDown: onClick,
|
|
166
402
|
style: {
|
|
167
403
|
position: "absolute",
|
|
168
|
-
left: r.origin.x * scale,
|
|
169
|
-
top: (r.origin.y
|
|
404
|
+
left: (rect ? r.origin.x - rect.origin.x : r.origin.x) * scale,
|
|
405
|
+
top: (rect ? r.origin.y - rect.origin.y : r.origin.y) * scale,
|
|
170
406
|
width: r.size.width * scale,
|
|
171
|
-
height:
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
407
|
+
height: r.size.height * scale,
|
|
408
|
+
background: "transparent",
|
|
409
|
+
pointerEvents: onClick ? "auto" : "none",
|
|
410
|
+
cursor: onClick ? "pointer" : "default",
|
|
411
|
+
zIndex: onClick ? 1 : 0,
|
|
412
|
+
...style
|
|
413
|
+
},
|
|
414
|
+
...props,
|
|
415
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
416
|
+
"div",
|
|
417
|
+
{
|
|
418
|
+
style: {
|
|
419
|
+
position: "absolute",
|
|
420
|
+
left: 0,
|
|
421
|
+
bottom: 0,
|
|
422
|
+
width: "100%",
|
|
423
|
+
height: amplitude * 2,
|
|
424
|
+
backgroundImage: svgDataUri,
|
|
425
|
+
backgroundRepeat: "repeat-x",
|
|
426
|
+
backgroundSize: `${period}px ${amplitude * 2}px`,
|
|
427
|
+
opacity,
|
|
428
|
+
pointerEvents: "none"
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
)
|
|
178
432
|
},
|
|
179
433
|
i
|
|
180
434
|
)) });
|
|
181
435
|
}
|
|
182
436
|
|
|
183
|
-
// src/preact/components/annotations.tsx
|
|
437
|
+
// src/preact/components/annotations/ink.tsx
|
|
438
|
+
var import_hooks3 = require("preact/hooks");
|
|
184
439
|
var import_jsx_runtime6 = require("preact/jsx-runtime");
|
|
185
|
-
function
|
|
440
|
+
function Ink({
|
|
441
|
+
color = "#000000",
|
|
442
|
+
opacity = 1,
|
|
443
|
+
strokeWidth,
|
|
444
|
+
inkList,
|
|
445
|
+
rect,
|
|
446
|
+
scale,
|
|
447
|
+
onClick
|
|
448
|
+
}) {
|
|
449
|
+
const paths = (0, import_hooks3.useMemo)(() => {
|
|
450
|
+
return inkList.map(({ points }) => {
|
|
451
|
+
let d = "";
|
|
452
|
+
points.forEach(({ x, y }, i) => {
|
|
453
|
+
const lx = x - rect.origin.x;
|
|
454
|
+
const ly = y - rect.origin.y;
|
|
455
|
+
d += (i === 0 ? "M" : "L") + lx + " " + ly + " ";
|
|
456
|
+
});
|
|
457
|
+
return d.trim();
|
|
458
|
+
});
|
|
459
|
+
}, [inkList, rect]);
|
|
460
|
+
const width = rect.size.width * scale;
|
|
461
|
+
const height = rect.size.height * scale;
|
|
462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
463
|
+
"svg",
|
|
464
|
+
{
|
|
465
|
+
style: {
|
|
466
|
+
position: "absolute",
|
|
467
|
+
width,
|
|
468
|
+
height,
|
|
469
|
+
pointerEvents: "none",
|
|
470
|
+
zIndex: 2
|
|
471
|
+
},
|
|
472
|
+
width,
|
|
473
|
+
height,
|
|
474
|
+
viewBox: `0 0 ${rect.size.width} ${rect.size.height}`,
|
|
475
|
+
children: paths.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
476
|
+
"path",
|
|
477
|
+
{
|
|
478
|
+
d,
|
|
479
|
+
fill: "none",
|
|
480
|
+
stroke: color,
|
|
481
|
+
strokeWidth,
|
|
482
|
+
strokeLinecap: "round",
|
|
483
|
+
strokeLinejoin: "round",
|
|
484
|
+
opacity,
|
|
485
|
+
pointerEvents: "visibleStroke",
|
|
486
|
+
onMouseDown: onClick,
|
|
487
|
+
style: {
|
|
488
|
+
cursor: "pointer"
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
i
|
|
492
|
+
))
|
|
493
|
+
}
|
|
494
|
+
);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
// src/preact/components/annotations.tsx
|
|
498
|
+
var import_preact3 = require("@embedpdf/plugin-selection/preact");
|
|
499
|
+
|
|
500
|
+
// src/shared/resize-ink.ts
|
|
501
|
+
var import_models2 = require("@embedpdf/models");
|
|
502
|
+
function resizeInkAnnotation(original, newRect, direction, uniform = false) {
|
|
503
|
+
if (original.type !== import_models2.PdfAnnotationSubtype.INK) {
|
|
504
|
+
throw new Error("resizeInkAnnotation: original is not an ink annotation");
|
|
505
|
+
}
|
|
506
|
+
const oldRect = original.rect;
|
|
507
|
+
let scaleX = newRect.size.width / oldRect.size.width;
|
|
508
|
+
let scaleY = newRect.size.height / oldRect.size.height;
|
|
509
|
+
const minSize = 10;
|
|
510
|
+
if (newRect.size.width < minSize || newRect.size.height < minSize) {
|
|
511
|
+
scaleX = Math.max(scaleX, minSize / oldRect.size.width);
|
|
512
|
+
scaleY = Math.max(scaleY, minSize / oldRect.size.height);
|
|
513
|
+
newRect = {
|
|
514
|
+
origin: newRect.origin,
|
|
515
|
+
size: {
|
|
516
|
+
width: oldRect.size.width * scaleX,
|
|
517
|
+
height: oldRect.size.height * scaleY
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
if (uniform) {
|
|
522
|
+
const minScale = Math.min(scaleX, scaleY);
|
|
523
|
+
scaleX = minScale;
|
|
524
|
+
scaleY = minScale;
|
|
525
|
+
newRect.size = {
|
|
526
|
+
width: oldRect.size.width * minScale,
|
|
527
|
+
height: oldRect.size.height * minScale
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
const newInkList = original.inkList.map((stroke) => ({
|
|
531
|
+
points: stroke.points.map((p) => ({
|
|
532
|
+
x: newRect.origin.x + (p.x - oldRect.origin.x) * scaleX,
|
|
533
|
+
y: newRect.origin.y + (p.y - oldRect.origin.y) * scaleY
|
|
534
|
+
}))
|
|
535
|
+
}));
|
|
536
|
+
const avgScale = (scaleX + scaleY) / 2;
|
|
537
|
+
const newStrokeWidth = original.strokeWidth * avgScale;
|
|
538
|
+
return {
|
|
539
|
+
rect: newRect,
|
|
540
|
+
inkList: newInkList,
|
|
541
|
+
strokeWidth: newStrokeWidth
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// src/preact/components/annotations.tsx
|
|
546
|
+
var import_jsx_runtime7 = require("preact/jsx-runtime");
|
|
547
|
+
function Annotations(annotationsProps) {
|
|
548
|
+
const { pageIndex, scale } = annotationsProps;
|
|
186
549
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
187
|
-
const
|
|
188
|
-
const
|
|
189
|
-
const
|
|
190
|
-
(0,
|
|
550
|
+
const { provides: selectionProvides } = (0, import_preact3.useSelectionCapability)();
|
|
551
|
+
const [annotations, setAnnotations] = (0, import_hooks5.useState)([]);
|
|
552
|
+
const { register } = (0, import_preact2.usePointerHandlers)({ pageIndex });
|
|
553
|
+
const [selectionState, setSelectionState] = (0, import_hooks5.useState)(null);
|
|
554
|
+
(0, import_hooks5.useEffect)(() => {
|
|
191
555
|
if (annotationProvides) {
|
|
192
556
|
annotationProvides.onStateChange((state) => {
|
|
193
557
|
setAnnotations((0, import_plugin_annotation2.getAnnotationsByPageIndex)(state, pageIndex));
|
|
@@ -195,7 +559,7 @@ function Annotations({ pageIndex, scale }) {
|
|
|
195
559
|
});
|
|
196
560
|
}
|
|
197
561
|
}, [annotationProvides]);
|
|
198
|
-
const handlers = (0,
|
|
562
|
+
const handlers = (0, import_hooks5.useMemo)(
|
|
199
563
|
() => ({
|
|
200
564
|
onPointerDown: (_, pe) => {
|
|
201
565
|
if (pe.target === pe.currentTarget && annotationProvides) {
|
|
@@ -205,87 +569,137 @@ function Annotations({ pageIndex, scale }) {
|
|
|
205
569
|
}),
|
|
206
570
|
[annotationProvides]
|
|
207
571
|
);
|
|
208
|
-
(0,
|
|
572
|
+
const handleClick = (0, import_hooks5.useCallback)(
|
|
573
|
+
(e, annotation) => {
|
|
574
|
+
e.stopPropagation();
|
|
575
|
+
if (annotationProvides && selectionProvides) {
|
|
576
|
+
annotationProvides.selectAnnotation(pageIndex, annotation.localId);
|
|
577
|
+
selectionProvides.clear();
|
|
578
|
+
}
|
|
579
|
+
},
|
|
580
|
+
[annotationProvides, selectionProvides, pageIndex]
|
|
581
|
+
);
|
|
582
|
+
(0, import_hooks5.useEffect)(() => {
|
|
209
583
|
return register(handlers);
|
|
210
584
|
}, [register, handlers]);
|
|
211
|
-
return /* @__PURE__ */ (0,
|
|
585
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_jsx_runtime7.Fragment, { children: annotations.map((annotation) => {
|
|
212
586
|
const isSelected = selectionState?.localId === annotation.localId;
|
|
213
587
|
switch (annotation.object.type) {
|
|
214
|
-
case
|
|
215
|
-
return /* @__PURE__ */ (0,
|
|
216
|
-
|
|
588
|
+
case import_models3.PdfAnnotationSubtype.UNDERLINE:
|
|
589
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
590
|
+
AnnotationContainer,
|
|
217
591
|
{
|
|
218
592
|
trackedAnnotation: annotation,
|
|
219
|
-
scale,
|
|
220
593
|
isSelected,
|
|
221
|
-
|
|
222
|
-
|
|
594
|
+
isDraggable: false,
|
|
595
|
+
isResizable: false,
|
|
596
|
+
style: { mixBlendMode: "multiply" },
|
|
597
|
+
...annotationsProps,
|
|
598
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
223
599
|
Underline,
|
|
224
600
|
{
|
|
601
|
+
rect: annotation.object.rect,
|
|
225
602
|
color: annotation.object.color,
|
|
226
603
|
opacity: annotation.object.opacity,
|
|
227
604
|
rects: annotation.object.segmentRects,
|
|
228
|
-
scale
|
|
605
|
+
scale,
|
|
606
|
+
onClick: (e) => handleClick(e, annotation)
|
|
229
607
|
}
|
|
230
608
|
)
|
|
231
609
|
},
|
|
232
610
|
annotation.localId
|
|
233
611
|
);
|
|
234
|
-
case
|
|
235
|
-
return /* @__PURE__ */ (0,
|
|
236
|
-
|
|
612
|
+
case import_models3.PdfAnnotationSubtype.STRIKEOUT:
|
|
613
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
614
|
+
AnnotationContainer,
|
|
237
615
|
{
|
|
238
616
|
trackedAnnotation: annotation,
|
|
239
|
-
scale,
|
|
240
617
|
isSelected,
|
|
241
|
-
|
|
242
|
-
|
|
618
|
+
isDraggable: false,
|
|
619
|
+
isResizable: false,
|
|
620
|
+
style: { mixBlendMode: "multiply" },
|
|
621
|
+
...annotationsProps,
|
|
622
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
243
623
|
Strikeout,
|
|
244
624
|
{
|
|
625
|
+
rect: annotation.object.rect,
|
|
245
626
|
color: annotation.object.color,
|
|
246
627
|
opacity: annotation.object.opacity,
|
|
247
628
|
rects: annotation.object.segmentRects,
|
|
248
|
-
scale
|
|
629
|
+
scale,
|
|
630
|
+
onClick: (e) => handleClick(e, annotation)
|
|
249
631
|
}
|
|
250
632
|
)
|
|
251
633
|
},
|
|
252
634
|
annotation.localId
|
|
253
635
|
);
|
|
254
|
-
case
|
|
255
|
-
return /* @__PURE__ */ (0,
|
|
256
|
-
|
|
636
|
+
case import_models3.PdfAnnotationSubtype.SQUIGGLY:
|
|
637
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
638
|
+
AnnotationContainer,
|
|
257
639
|
{
|
|
258
640
|
trackedAnnotation: annotation,
|
|
259
|
-
scale,
|
|
260
641
|
isSelected,
|
|
261
|
-
|
|
262
|
-
|
|
642
|
+
isDraggable: false,
|
|
643
|
+
isResizable: false,
|
|
644
|
+
style: { mixBlendMode: "multiply" },
|
|
645
|
+
...annotationsProps,
|
|
646
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
263
647
|
Squiggly,
|
|
264
648
|
{
|
|
265
649
|
color: annotation.object.color,
|
|
266
650
|
opacity: annotation.object.opacity,
|
|
267
651
|
rects: annotation.object.segmentRects,
|
|
268
|
-
|
|
652
|
+
rect: annotation.object.rect,
|
|
653
|
+
scale,
|
|
654
|
+
onClick: (e) => handleClick(e, annotation)
|
|
269
655
|
}
|
|
270
656
|
)
|
|
271
657
|
},
|
|
272
658
|
annotation.localId
|
|
273
659
|
);
|
|
274
|
-
case
|
|
275
|
-
return /* @__PURE__ */ (0,
|
|
276
|
-
|
|
660
|
+
case import_models3.PdfAnnotationSubtype.HIGHLIGHT:
|
|
661
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
662
|
+
AnnotationContainer,
|
|
277
663
|
{
|
|
278
664
|
trackedAnnotation: annotation,
|
|
279
|
-
scale,
|
|
280
665
|
isSelected,
|
|
281
|
-
|
|
282
|
-
|
|
666
|
+
isDraggable: false,
|
|
667
|
+
isResizable: false,
|
|
668
|
+
style: { mixBlendMode: "multiply" },
|
|
669
|
+
...annotationsProps,
|
|
670
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
283
671
|
Highlight,
|
|
284
672
|
{
|
|
285
673
|
color: annotation.object.color,
|
|
286
674
|
opacity: annotation.object.opacity,
|
|
287
675
|
rects: annotation.object.segmentRects,
|
|
288
|
-
scale
|
|
676
|
+
scale,
|
|
677
|
+
rect: annotation.object.rect,
|
|
678
|
+
onClick: (e) => handleClick(e, annotation)
|
|
679
|
+
}
|
|
680
|
+
)
|
|
681
|
+
},
|
|
682
|
+
annotation.localId
|
|
683
|
+
);
|
|
684
|
+
case import_models3.PdfAnnotationSubtype.INK:
|
|
685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
686
|
+
AnnotationContainer,
|
|
687
|
+
{
|
|
688
|
+
isSelected,
|
|
689
|
+
trackedAnnotation: annotation,
|
|
690
|
+
outlineOffset: 6,
|
|
691
|
+
computeResizePatch: resizeInkAnnotation,
|
|
692
|
+
...annotationsProps,
|
|
693
|
+
children: (obj) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
694
|
+
Ink,
|
|
695
|
+
{
|
|
696
|
+
color: obj.color,
|
|
697
|
+
opacity: obj.opacity,
|
|
698
|
+
strokeWidth: obj.strokeWidth,
|
|
699
|
+
inkList: obj.inkList,
|
|
700
|
+
rect: obj.rect,
|
|
701
|
+
scale,
|
|
702
|
+
onClick: (e) => handleClick(e, annotation)
|
|
289
703
|
}
|
|
290
704
|
)
|
|
291
705
|
},
|
|
@@ -298,66 +712,113 @@ function Annotations({ pageIndex, scale }) {
|
|
|
298
712
|
}
|
|
299
713
|
|
|
300
714
|
// src/preact/components/text-markup.tsx
|
|
301
|
-
var
|
|
715
|
+
var import_models4 = require("@embedpdf/models");
|
|
302
716
|
var import_preact4 = require("@embedpdf/plugin-selection/preact");
|
|
303
|
-
var
|
|
304
|
-
var
|
|
717
|
+
var import_hooks6 = require("preact/hooks");
|
|
718
|
+
var import_jsx_runtime8 = require("preact/jsx-runtime");
|
|
305
719
|
function TextMarkup({ pageIndex, scale }) {
|
|
306
720
|
const { provides: selectionProvides } = (0, import_preact4.useSelectionCapability)();
|
|
307
721
|
const { provides: annotationProvides } = useAnnotationCapability();
|
|
308
|
-
const [rects, setRects] = (0,
|
|
309
|
-
const [
|
|
310
|
-
(0,
|
|
722
|
+
const [rects, setRects] = (0, import_hooks6.useState)([]);
|
|
723
|
+
const [boundingRect, setBoundingRect] = (0, import_hooks6.useState)(null);
|
|
724
|
+
const [activeTool, setActiveTool] = (0, import_hooks6.useState)({ mode: null, defaults: null });
|
|
725
|
+
(0, import_hooks6.useEffect)(() => {
|
|
311
726
|
if (!selectionProvides) return;
|
|
312
727
|
const off = selectionProvides.onSelectionChange(() => {
|
|
313
728
|
setRects(selectionProvides.getHighlightRectsForPage(pageIndex));
|
|
729
|
+
setBoundingRect(selectionProvides.getBoundingRectForPage(pageIndex));
|
|
314
730
|
});
|
|
315
731
|
return off;
|
|
316
732
|
}, [selectionProvides, pageIndex]);
|
|
317
|
-
(0,
|
|
733
|
+
(0, import_hooks6.useEffect)(() => {
|
|
318
734
|
if (!annotationProvides) return;
|
|
319
735
|
const off = annotationProvides.onActiveToolChange(setActiveTool);
|
|
320
736
|
return off;
|
|
321
737
|
}, [annotationProvides]);
|
|
738
|
+
if (!boundingRect) return null;
|
|
322
739
|
switch (activeTool.mode) {
|
|
323
|
-
case
|
|
324
|
-
return /* @__PURE__ */ (0,
|
|
325
|
-
|
|
740
|
+
case import_models4.PdfAnnotationSubtype.UNDERLINE:
|
|
741
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
742
|
+
"div",
|
|
326
743
|
{
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
744
|
+
style: {
|
|
745
|
+
mixBlendMode: "multiply",
|
|
746
|
+
pointerEvents: "none",
|
|
747
|
+
position: "absolute",
|
|
748
|
+
inset: 0
|
|
749
|
+
},
|
|
750
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
751
|
+
Underline,
|
|
752
|
+
{
|
|
753
|
+
color: activeTool.defaults?.color,
|
|
754
|
+
opacity: activeTool.defaults?.opacity,
|
|
755
|
+
rects,
|
|
756
|
+
scale
|
|
757
|
+
}
|
|
758
|
+
)
|
|
331
759
|
}
|
|
332
760
|
);
|
|
333
|
-
case
|
|
334
|
-
return /* @__PURE__ */ (0,
|
|
335
|
-
|
|
761
|
+
case import_models4.PdfAnnotationSubtype.HIGHLIGHT:
|
|
762
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
763
|
+
"div",
|
|
336
764
|
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
765
|
+
style: {
|
|
766
|
+
mixBlendMode: "multiply",
|
|
767
|
+
pointerEvents: "none",
|
|
768
|
+
position: "absolute",
|
|
769
|
+
inset: 0
|
|
770
|
+
},
|
|
771
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
772
|
+
Highlight,
|
|
773
|
+
{
|
|
774
|
+
color: activeTool.defaults?.color,
|
|
775
|
+
opacity: activeTool.defaults?.opacity,
|
|
776
|
+
rects,
|
|
777
|
+
scale
|
|
778
|
+
}
|
|
779
|
+
)
|
|
341
780
|
}
|
|
342
781
|
);
|
|
343
|
-
case
|
|
344
|
-
return /* @__PURE__ */ (0,
|
|
345
|
-
|
|
782
|
+
case import_models4.PdfAnnotationSubtype.STRIKEOUT:
|
|
783
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
784
|
+
"div",
|
|
346
785
|
{
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
786
|
+
style: {
|
|
787
|
+
mixBlendMode: "multiply",
|
|
788
|
+
pointerEvents: "none",
|
|
789
|
+
position: "absolute",
|
|
790
|
+
inset: 0
|
|
791
|
+
},
|
|
792
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
793
|
+
Strikeout,
|
|
794
|
+
{
|
|
795
|
+
color: activeTool.defaults?.color,
|
|
796
|
+
opacity: activeTool.defaults?.opacity,
|
|
797
|
+
rects,
|
|
798
|
+
scale
|
|
799
|
+
}
|
|
800
|
+
)
|
|
351
801
|
}
|
|
352
802
|
);
|
|
353
|
-
case
|
|
354
|
-
return /* @__PURE__ */ (0,
|
|
355
|
-
|
|
803
|
+
case import_models4.PdfAnnotationSubtype.SQUIGGLY:
|
|
804
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
805
|
+
"div",
|
|
356
806
|
{
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
807
|
+
style: {
|
|
808
|
+
mixBlendMode: "multiply",
|
|
809
|
+
pointerEvents: "none",
|
|
810
|
+
position: "absolute",
|
|
811
|
+
inset: 0
|
|
812
|
+
},
|
|
813
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
814
|
+
Squiggly,
|
|
815
|
+
{
|
|
816
|
+
color: activeTool.defaults?.color,
|
|
817
|
+
opacity: activeTool.defaults?.opacity,
|
|
818
|
+
rects,
|
|
819
|
+
scale
|
|
820
|
+
}
|
|
821
|
+
)
|
|
361
822
|
}
|
|
362
823
|
);
|
|
363
824
|
default:
|
|
@@ -365,10 +826,195 @@ function TextMarkup({ pageIndex, scale }) {
|
|
|
365
826
|
}
|
|
366
827
|
}
|
|
367
828
|
|
|
829
|
+
// src/preact/components/annotations/ink-paint.tsx
|
|
830
|
+
var import_hooks8 = require("preact/hooks");
|
|
831
|
+
var import_preact5 = require("@embedpdf/plugin-interaction-manager/preact");
|
|
832
|
+
var import_models5 = require("@embedpdf/models");
|
|
833
|
+
var import_jsx_runtime9 = require("preact/jsx-runtime");
|
|
834
|
+
var MAX_STROKE_WIDTH = 30;
|
|
835
|
+
var InkPaint = ({ pageIndex, scale, pageWidth, pageHeight }) => {
|
|
836
|
+
const { provides: annotationProvides } = useAnnotationCapability();
|
|
837
|
+
const [activeTool, setActiveTool] = (0, import_hooks8.useState)({ mode: null, defaults: null });
|
|
838
|
+
(0, import_hooks8.useEffect)(() => {
|
|
839
|
+
if (!annotationProvides) return;
|
|
840
|
+
const off = annotationProvides.onActiveToolChange(setActiveTool);
|
|
841
|
+
return off;
|
|
842
|
+
}, [annotationProvides]);
|
|
843
|
+
if (activeTool.mode !== import_models5.PdfAnnotationSubtype.INK) return null;
|
|
844
|
+
const toolColor = activeTool.defaults?.color ?? "#000000";
|
|
845
|
+
const toolOpacity = activeTool.defaults?.opacity ?? 1;
|
|
846
|
+
const toolStrokeWidth = activeTool.defaults?.strokeWidth ?? 2;
|
|
847
|
+
const { register } = (0, import_preact5.usePointerHandlers)({ modeId: "ink", pageIndex });
|
|
848
|
+
const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
|
|
849
|
+
const [currentStrokes, setCurrentStrokes] = (0, import_hooks8.useState)([]);
|
|
850
|
+
const [isDrawing, setIsDrawing] = (0, import_hooks8.useState)(false);
|
|
851
|
+
const timerRef = (0, import_hooks8.useRef)(null);
|
|
852
|
+
const pageWidthPDF = pageWidth / scale;
|
|
853
|
+
const pageHeightPDF = pageHeight / scale;
|
|
854
|
+
const handlers = (0, import_hooks8.useMemo)(
|
|
855
|
+
() => ({
|
|
856
|
+
onPointerDown: (pos, evt) => {
|
|
857
|
+
const curX = clamp(pos.x, 0, pageWidthPDF);
|
|
858
|
+
const curY = clamp(pos.y, 0, pageHeightPDF);
|
|
859
|
+
setIsDrawing(true);
|
|
860
|
+
if (timerRef.current) {
|
|
861
|
+
clearTimeout(timerRef.current);
|
|
862
|
+
timerRef.current = null;
|
|
863
|
+
setCurrentStrokes((prev) => [...prev, { points: [{ x: curX, y: curY }] }]);
|
|
864
|
+
} else {
|
|
865
|
+
setCurrentStrokes([{ points: [{ x: curX, y: curY }] }]);
|
|
866
|
+
}
|
|
867
|
+
evt.target?.setPointerCapture?.(evt.pointerId);
|
|
868
|
+
},
|
|
869
|
+
onPointerMove: (pos) => {
|
|
870
|
+
if (!isDrawing) return;
|
|
871
|
+
const curX = clamp(pos.x, 0, pageWidthPDF);
|
|
872
|
+
const curY = clamp(pos.y, 0, pageHeightPDF);
|
|
873
|
+
setCurrentStrokes((prev) => {
|
|
874
|
+
if (!prev.length) return prev;
|
|
875
|
+
const last = prev[prev.length - 1];
|
|
876
|
+
const newLast = { points: [...last.points, { x: curX, y: curY }] };
|
|
877
|
+
return [...prev.slice(0, -1), newLast];
|
|
878
|
+
});
|
|
879
|
+
},
|
|
880
|
+
onPointerUp: (_, evt) => {
|
|
881
|
+
setIsDrawing(false);
|
|
882
|
+
evt.target?.releasePointerCapture?.(evt.pointerId);
|
|
883
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
884
|
+
timerRef.current = setTimeout(() => {
|
|
885
|
+
if (currentStrokes.length && annotationProvides) {
|
|
886
|
+
const allPoints2 = currentStrokes.flatMap((s) => s.points);
|
|
887
|
+
if (!allPoints2.length) return;
|
|
888
|
+
const minX2 = Math.min(...allPoints2.map((p) => p.x));
|
|
889
|
+
const minY2 = Math.min(...allPoints2.map((p) => p.y));
|
|
890
|
+
const maxX2 = Math.max(...allPoints2.map((p) => p.x));
|
|
891
|
+
const maxY2 = Math.max(...allPoints2.map((p) => p.y));
|
|
892
|
+
const halfStroke2 = MAX_STROKE_WIDTH / 2;
|
|
893
|
+
const rectMinX = minX2 - halfStroke2;
|
|
894
|
+
const rectMinY = minY2 - halfStroke2;
|
|
895
|
+
const rectMaxX = maxX2 + halfStroke2;
|
|
896
|
+
const rectMaxY = maxY2 + halfStroke2;
|
|
897
|
+
if (rectMaxX - rectMinX < 1 || rectMaxY - rectMinY < 1) return;
|
|
898
|
+
const rect = {
|
|
899
|
+
origin: { x: rectMinX, y: rectMinY },
|
|
900
|
+
size: { width: rectMaxX - rectMinX, height: rectMaxY - rectMinY }
|
|
901
|
+
};
|
|
902
|
+
const anno = {
|
|
903
|
+
type: import_models5.PdfAnnotationSubtype.INK,
|
|
904
|
+
rect,
|
|
905
|
+
inkList: currentStrokes,
|
|
906
|
+
color: toolColor,
|
|
907
|
+
opacity: toolOpacity,
|
|
908
|
+
strokeWidth: toolStrokeWidth,
|
|
909
|
+
pageIndex,
|
|
910
|
+
id: Date.now() + Math.random()
|
|
911
|
+
};
|
|
912
|
+
annotationProvides.createAnnotation(pageIndex, anno);
|
|
913
|
+
annotationProvides.setAnnotationMode(null);
|
|
914
|
+
annotationProvides.selectAnnotation(pageIndex, anno.id);
|
|
915
|
+
}
|
|
916
|
+
setCurrentStrokes([]);
|
|
917
|
+
timerRef.current = null;
|
|
918
|
+
}, 3e3);
|
|
919
|
+
},
|
|
920
|
+
onPointerCancel: (_, evt) => {
|
|
921
|
+
setIsDrawing(false);
|
|
922
|
+
evt.target?.releasePointerCapture?.(evt.pointerId);
|
|
923
|
+
setCurrentStrokes([]);
|
|
924
|
+
if (timerRef.current) {
|
|
925
|
+
clearTimeout(timerRef.current);
|
|
926
|
+
timerRef.current = null;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}),
|
|
930
|
+
[
|
|
931
|
+
pageWidthPDF,
|
|
932
|
+
pageHeightPDF,
|
|
933
|
+
currentStrokes,
|
|
934
|
+
annotationProvides,
|
|
935
|
+
pageIndex,
|
|
936
|
+
toolColor,
|
|
937
|
+
toolOpacity,
|
|
938
|
+
toolStrokeWidth,
|
|
939
|
+
isDrawing
|
|
940
|
+
]
|
|
941
|
+
);
|
|
942
|
+
(0, import_hooks8.useEffect)(() => {
|
|
943
|
+
if (!register) return;
|
|
944
|
+
return register(handlers);
|
|
945
|
+
}, [register, handlers]);
|
|
946
|
+
(0, import_hooks8.useEffect)(() => {
|
|
947
|
+
return () => {
|
|
948
|
+
if (timerRef.current) clearTimeout(timerRef.current);
|
|
949
|
+
};
|
|
950
|
+
}, []);
|
|
951
|
+
if (!currentStrokes.length) return null;
|
|
952
|
+
const allPoints = currentStrokes.flatMap((s) => s.points);
|
|
953
|
+
if (!allPoints.length) return null;
|
|
954
|
+
const minX = Math.min(...allPoints.map((p) => p.x));
|
|
955
|
+
const minY = Math.min(...allPoints.map((p) => p.y));
|
|
956
|
+
const maxX = Math.max(...allPoints.map((p) => p.x));
|
|
957
|
+
const maxY = Math.max(...allPoints.map((p) => p.y));
|
|
958
|
+
const halfStroke = MAX_STROKE_WIDTH / 2;
|
|
959
|
+
const svgMinX = minX - halfStroke;
|
|
960
|
+
const svgMinY = minY - halfStroke;
|
|
961
|
+
const svgMaxX = maxX + halfStroke;
|
|
962
|
+
const svgMaxY = maxY + halfStroke;
|
|
963
|
+
const dw = svgMaxX - svgMinX;
|
|
964
|
+
const dh = svgMaxY - svgMinY;
|
|
965
|
+
const paths = currentStrokes.map(({ points }) => {
|
|
966
|
+
let d = "";
|
|
967
|
+
points.forEach(({ x, y }, i) => {
|
|
968
|
+
const lx = x - svgMinX;
|
|
969
|
+
const ly = y - svgMinY;
|
|
970
|
+
d += (i === 0 ? "M" : "L") + lx + " " + ly + " ";
|
|
971
|
+
});
|
|
972
|
+
return d.trim();
|
|
973
|
+
});
|
|
974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
975
|
+
"svg",
|
|
976
|
+
{
|
|
977
|
+
style: {
|
|
978
|
+
position: "absolute",
|
|
979
|
+
left: svgMinX * scale,
|
|
980
|
+
top: svgMinY * scale,
|
|
981
|
+
width: dw * scale,
|
|
982
|
+
height: dh * scale,
|
|
983
|
+
pointerEvents: "none",
|
|
984
|
+
zIndex: 2
|
|
985
|
+
},
|
|
986
|
+
width: dw * scale,
|
|
987
|
+
height: dh * scale,
|
|
988
|
+
viewBox: `0 0 ${dw} ${dh}`,
|
|
989
|
+
children: paths.map((d, i) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
990
|
+
"path",
|
|
991
|
+
{
|
|
992
|
+
d,
|
|
993
|
+
fill: "none",
|
|
994
|
+
stroke: toolColor,
|
|
995
|
+
strokeWidth: toolStrokeWidth,
|
|
996
|
+
strokeLinecap: "round",
|
|
997
|
+
strokeLinejoin: "round",
|
|
998
|
+
opacity: toolOpacity
|
|
999
|
+
},
|
|
1000
|
+
i
|
|
1001
|
+
))
|
|
1002
|
+
}
|
|
1003
|
+
);
|
|
1004
|
+
};
|
|
1005
|
+
|
|
368
1006
|
// src/preact/components/annotation-layer.tsx
|
|
369
|
-
var
|
|
370
|
-
function AnnotationLayer({
|
|
371
|
-
|
|
1007
|
+
var import_jsx_runtime10 = require("preact/jsx-runtime");
|
|
1008
|
+
function AnnotationLayer({
|
|
1009
|
+
pageIndex,
|
|
1010
|
+
scale,
|
|
1011
|
+
pageWidth,
|
|
1012
|
+
pageHeight,
|
|
1013
|
+
rotation,
|
|
1014
|
+
style,
|
|
1015
|
+
...props
|
|
1016
|
+
}) {
|
|
1017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
372
1018
|
"div",
|
|
373
1019
|
{
|
|
374
1020
|
style: {
|
|
@@ -376,8 +1022,9 @@ function AnnotationLayer({ pageIndex, scale, style, ...props }) {
|
|
|
376
1022
|
},
|
|
377
1023
|
...props,
|
|
378
1024
|
children: [
|
|
379
|
-
/* @__PURE__ */ (0,
|
|
380
|
-
/* @__PURE__ */ (0,
|
|
1025
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(Annotations, { pageIndex, scale, rotation }),
|
|
1026
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(TextMarkup, { pageIndex, scale }),
|
|
1027
|
+
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(InkPaint, { pageIndex, scale, pageWidth, pageHeight })
|
|
381
1028
|
]
|
|
382
1029
|
}
|
|
383
1030
|
);
|