@embedpdf/plugin-annotation 1.0.10 → 1.0.12

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