@embedpdf/plugin-annotation 1.0.14 → 1.0.16

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 (52) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +24 -7
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/annotation-plugin.d.ts +1 -0
  6. package/dist/lib/helpers.d.ts +1 -0
  7. package/dist/lib/types.d.ts +6 -3
  8. package/dist/preact/adapter.d.ts +2 -0
  9. package/dist/preact/index.cjs +1 -1
  10. package/dist/preact/index.cjs.map +1 -1
  11. package/dist/preact/index.js +321 -48
  12. package/dist/preact/index.js.map +1 -1
  13. package/dist/react/adapter.d.ts +2 -2
  14. package/dist/react/index.cjs +1 -1
  15. package/dist/react/index.cjs.map +1 -1
  16. package/dist/react/index.js +321 -48
  17. package/dist/react/index.js.map +1 -1
  18. package/dist/shared-preact/components/annotation-container.d.ts +2 -1
  19. package/dist/shared-preact/components/annotations/circle.d.ts +5 -5
  20. package/dist/shared-preact/components/annotations/free-text.d.ts +2 -2
  21. package/dist/shared-preact/components/annotations/ink.d.ts +5 -5
  22. package/dist/shared-preact/components/annotations/line.d.ts +2 -2
  23. package/dist/shared-preact/components/annotations/polygon.d.ts +2 -2
  24. package/dist/shared-preact/components/annotations/polyline.d.ts +2 -2
  25. package/dist/shared-preact/components/annotations/square.d.ts +5 -5
  26. package/dist/shared-preact/components/annotations/stamp-paint.d.ts +8 -0
  27. package/dist/shared-preact/components/annotations/stamp.d.ts +12 -0
  28. package/dist/shared-preact/components/counter-rotate-container.d.ts +2 -1
  29. package/dist/shared-preact/components/render-annotation.d.ts +1 -1
  30. package/dist/shared-preact/components/text-markup/highlight.d.ts +2 -2
  31. package/dist/shared-preact/components/text-markup/squiggly.d.ts +2 -2
  32. package/dist/shared-preact/components/text-markup/strikeout.d.ts +2 -2
  33. package/dist/shared-preact/components/text-markup/underline.d.ts +2 -2
  34. package/dist/shared-preact/hooks/use-drag-resize.d.ts +10 -3
  35. package/dist/shared-react/components/annotation-container.d.ts +2 -1
  36. package/dist/shared-react/components/annotations/circle.d.ts +5 -5
  37. package/dist/shared-react/components/annotations/free-text.d.ts +2 -2
  38. package/dist/shared-react/components/annotations/ink.d.ts +5 -5
  39. package/dist/shared-react/components/annotations/line.d.ts +2 -2
  40. package/dist/shared-react/components/annotations/polygon.d.ts +2 -2
  41. package/dist/shared-react/components/annotations/polyline.d.ts +2 -2
  42. package/dist/shared-react/components/annotations/square.d.ts +5 -5
  43. package/dist/shared-react/components/annotations/stamp-paint.d.ts +8 -0
  44. package/dist/shared-react/components/annotations/stamp.d.ts +12 -0
  45. package/dist/shared-react/components/counter-rotate-container.d.ts +2 -1
  46. package/dist/shared-react/components/render-annotation.d.ts +1 -1
  47. package/dist/shared-react/components/text-markup/highlight.d.ts +2 -2
  48. package/dist/shared-react/components/text-markup/squiggly.d.ts +2 -2
  49. package/dist/shared-react/components/text-markup/strikeout.d.ts +2 -2
  50. package/dist/shared-react/components/text-markup/underline.d.ts +2 -2
  51. package/dist/shared-react/hooks/use-drag-resize.d.ts +10 -3
  52. package/package.json +14 -9
@@ -1,7 +1,7 @@
1
1
  import { usePlugin, useCapability } from "@embedpdf/core/preact";
2
- import { AnnotationPlugin, patching, getAnnotationsByPageIndex, getSelectedAnnotationByPageIndex, isInk, isSquare, isCircle, isUnderline, isStrikeout, isSquiggly, isHighlight, isLine, isPolyline, isPolygon, isFreeText } from "@embedpdf/plugin-annotation";
2
+ import { AnnotationPlugin, patching, getAnnotationsByPageIndex, getSelectedAnnotationByPageIndex, isInk, isSquare, isCircle, isUnderline, isStrikeout, isSquiggly, isHighlight, isLine, isPolyline, isPolygon, isFreeText, isStamp } from "@embedpdf/plugin-annotation";
3
3
  import { jsx, jsxs, Fragment as Fragment$1 } from "preact/jsx-runtime";
4
- import { restoreOffset, rectEquals, PdfAnnotationBorderStyle, PdfAnnotationSubtype, expandRect, rectFromPoints, textAlignmentToCss, standardFontCss, PdfVerticalAlignment, blendModeToCss, PdfBlendMode } from "@embedpdf/models";
4
+ import { restoreOffset, rectEquals, PdfAnnotationBorderStyle, PdfAnnotationSubtype, expandRect, rectFromPoints, textAlignmentToCss, standardFontCss, PdfVerticalAlignment, ignore, PdfErrorCode, blendModeToCss, PdfBlendMode } from "@embedpdf/models";
5
5
  import { usePointerHandlers } from "@embedpdf/plugin-interaction-manager/preact";
6
6
  import { useSelectionCapability } from "@embedpdf/plugin-selection/preact";
7
7
  import { Fragment } from "preact";
@@ -54,7 +54,8 @@ function CounterRotate({ children, ...props }) {
54
54
  };
55
55
  const menuWrapperProps = {
56
56
  style: menuWrapperStyle,
57
- onPointerDown: (e) => e.stopPropagation()
57
+ onPointerDown: (e) => e.stopPropagation(),
58
+ onTouchStart: (e) => e.stopPropagation()
58
59
  };
59
60
  return /* @__PURE__ */ jsx(Fragment, { children: children({
60
61
  menuWrapperProps,
@@ -151,6 +152,7 @@ function useDragResize({
151
152
  isResizable,
152
153
  computePatch,
153
154
  computeVertices,
155
+ lockAspectRatio = false,
154
156
  currentRect,
155
157
  setCurrentRect,
156
158
  setCurrentVertices,
@@ -185,6 +187,23 @@ function useDragResize({
185
187
  oy += dy;
186
188
  h -= dy;
187
189
  }
190
+ if (lockAspectRatio && startRect.current) {
191
+ const ratio = startRect.current.size.width / startRect.current.size.height;
192
+ const anchorRight = ox + w;
193
+ const anchorBottom = oy + h;
194
+ const horizontalPrimary = dir.current.includes("left") || dir.current.includes("right");
195
+ if (horizontalPrimary) {
196
+ h = w / ratio;
197
+ } else {
198
+ w = h * ratio;
199
+ }
200
+ if (dir.current.includes("left")) {
201
+ ox = anchorRight - w;
202
+ }
203
+ if (dir.current.includes("top")) {
204
+ oy = anchorBottom - h;
205
+ }
206
+ }
188
207
  }
189
208
  if (w < 1 || h < 1) return currentRect;
190
209
  w = clamp(w, 1, pageW);
@@ -193,20 +212,16 @@ function useDragResize({
193
212
  oy = clamp(oy, 0, pageH - h);
194
213
  return { origin: { x: ox, y: oy }, size: { width: w, height: h } };
195
214
  };
196
- const onPointerDown = (e) => {
197
- if (!isSelected || !isDraggable) return;
198
- e.stopPropagation();
199
- e.preventDefault();
200
- drag.current = "dragging";
201
- startPos.current = { x: e.clientX, y: e.clientY };
215
+ const beginDrag = (kind, clientX, clientY) => {
216
+ drag.current = kind;
217
+ startPos.current = { x: clientX, y: clientY };
202
218
  startRect.current = currentRect;
203
- e.currentTarget.setPointerCapture(e.pointerId);
204
219
  };
205
- const onPointerMove = (e) => {
220
+ const handleMove = (clientX, clientY) => {
206
221
  if (drag.current === "idle" || !startPos.current) return;
207
222
  const disp = {
208
- x: e.clientX - startPos.current.x,
209
- y: e.clientY - startPos.current.y
223
+ x: clientX - startPos.current.x,
224
+ y: clientY - startPos.current.y
210
225
  };
211
226
  const { x, y } = restoreOffset(disp, rotation, scale);
212
227
  const nextRect = applyDelta(x, y);
@@ -221,7 +236,7 @@ function useDragResize({
221
236
  setCurrentRect(patch.rect ?? nextRect);
222
237
  setPreviewObject(patch);
223
238
  };
224
- const onPointerUp = () => {
239
+ const finishDragInternal = () => {
225
240
  if (drag.current === "idle") return;
226
241
  const usedDir = dir.current || "bottom-right";
227
242
  drag.current = "idle";
@@ -238,16 +253,45 @@ function useDragResize({
238
253
  dir.current = "none";
239
254
  setPreviewObject(null);
240
255
  };
256
+ const onPointerDown = (e) => {
257
+ if (!isSelected || !isDraggable) return;
258
+ e.stopPropagation();
259
+ e.preventDefault();
260
+ beginDrag("dragging", e.clientX, e.clientY);
261
+ e.currentTarget.setPointerCapture(e.pointerId);
262
+ };
263
+ const onPointerMove = (e) => handleMove(e.clientX, e.clientY);
264
+ const onPointerUp = (e) => {
265
+ finishDragInternal();
266
+ if ((e == null ? void 0 : e.currentTarget) && e.pointerId !== void 0) {
267
+ try {
268
+ e.currentTarget.releasePointerCapture(e.pointerId);
269
+ } catch {
270
+ }
271
+ }
272
+ };
241
273
  const startResize = (direction) => (e) => {
242
274
  if (!isSelected || !isResizable) return;
243
275
  e.stopPropagation();
244
276
  e.preventDefault();
245
- drag.current = "resizing";
246
277
  dir.current = direction;
247
- startPos.current = { x: e.clientX, y: e.clientY };
248
- startRect.current = currentRect;
278
+ beginDrag("resizing", e.clientX, e.clientY);
249
279
  e.currentTarget.setPointerCapture(e.pointerId);
250
280
  };
281
+ const onTouchStart = (e) => {
282
+ if (!isSelected || !isDraggable) return;
283
+ e.stopPropagation();
284
+ e.preventDefault();
285
+ const t = e.touches[0];
286
+ if (!t) return;
287
+ beginDrag("dragging", t.clientX, t.clientY);
288
+ };
289
+ const onTouchMove = (e) => {
290
+ const t = e.touches[0];
291
+ if (!t) return;
292
+ handleMove(t.clientX, t.clientY);
293
+ };
294
+ const onTouchEnd = () => finishDragInternal();
251
295
  useEffect(() => {
252
296
  drag.current = "idle";
253
297
  dir.current = "none";
@@ -258,7 +302,14 @@ function useDragResize({
258
302
  rootHandlers: {
259
303
  onPointerDown,
260
304
  onPointerMove,
261
- onPointerUp
305
+ onPointerUp,
306
+ onPointerCancel: () => onPointerUp(),
307
+ onLostPointerCapture: () => onPointerUp(),
308
+ /* mobile touch fallback */
309
+ onTouchStart,
310
+ onTouchMove,
311
+ onTouchEnd,
312
+ onTouchCancel: onTouchEnd
262
313
  },
263
314
  startResize
264
315
  };
@@ -336,6 +387,7 @@ function AnnotationContainer({
336
387
  isSelected = false,
337
388
  isDraggable = true,
338
389
  isResizable = true,
390
+ lockAspectRatio = false,
339
391
  computeVertices,
340
392
  computePatch,
341
393
  selectionMenu,
@@ -357,6 +409,7 @@ function AnnotationContainer({
357
409
  isSelected,
358
410
  isDraggable,
359
411
  isResizable,
412
+ lockAspectRatio,
360
413
  computePatch,
361
414
  computeVertices,
362
415
  currentRect,
@@ -388,6 +441,7 @@ function AnnotationContainer({
388
441
  width: `${currentRect.size.width * scale}px`,
389
442
  height: `${currentRect.size.height * scale}px`,
390
443
  pointerEvents: isSelected ? "auto" : "none",
444
+ touchAction: isSelected ? "auto" : "none",
391
445
  cursor: isSelected && isDraggable ? "move" : "default",
392
446
  ...isSelected && {
393
447
  zIndex: 3
@@ -468,7 +522,8 @@ function Highlight({
468
522
  return /* @__PURE__ */ jsx(Fragment$1, { children: rects.map((b, i) => /* @__PURE__ */ jsx(
469
523
  "div",
470
524
  {
471
- onMouseDown: onClick,
525
+ onPointerDown: onClick,
526
+ onTouchStart: onClick,
472
527
  style: {
473
528
  position: "absolute",
474
529
  left: (rect ? b.origin.x - rect.origin.x : b.origin.x) * scale,
@@ -501,7 +556,8 @@ function Underline({
501
556
  return /* @__PURE__ */ jsx(Fragment$1, { children: rects.map((r, i) => /* @__PURE__ */ jsx(
502
557
  "div",
503
558
  {
504
- onMouseDown: onClick,
559
+ onPointerDown: onClick,
560
+ onTouchStart: onClick,
505
561
  style: {
506
562
  position: "absolute",
507
563
  left: (rect ? r.origin.x - rect.origin.x : r.origin.x) * scale,
@@ -548,7 +604,8 @@ function Strikeout({
548
604
  return /* @__PURE__ */ jsx(Fragment$1, { children: rects.map((r, i) => /* @__PURE__ */ jsx(
549
605
  "div",
550
606
  {
551
- onMouseDown: onClick,
607
+ onPointerDown: onClick,
608
+ onTouchStart: onClick,
552
609
  style: {
553
610
  position: "absolute",
554
611
  left: (rect ? r.origin.x - rect.origin.x : r.origin.x) * scale,
@@ -602,7 +659,8 @@ function Squiggly({
602
659
  return /* @__PURE__ */ jsx(Fragment$1, { children: rects.map((r, i) => /* @__PURE__ */ jsx(
603
660
  "div",
604
661
  {
605
- onMouseDown: onClick,
662
+ onPointerDown: onClick,
663
+ onTouchStart: onClick,
606
664
  style: {
607
665
  position: "absolute",
608
666
  left: (rect ? r.origin.x - rect.origin.x : r.origin.x) * scale,
@@ -638,14 +696,14 @@ function Squiggly({
638
696
  )) });
639
697
  }
640
698
  function Ink({
699
+ isSelected,
641
700
  color = "#000000",
642
701
  opacity = 1,
643
702
  strokeWidth,
644
703
  inkList,
645
704
  rect,
646
705
  scale,
647
- onClick,
648
- cursor
706
+ onClick
649
707
  }) {
650
708
  const paths = useMemo(() => {
651
709
  return inkList.map(({ points }) => {
@@ -680,10 +738,11 @@ function Ink({
680
738
  d,
681
739
  fill: "none",
682
740
  opacity,
683
- onMouseDown: onClick,
741
+ onPointerDown: onClick,
742
+ onTouchStart: onClick,
684
743
  style: {
685
- cursor,
686
- pointerEvents: "visibleStroke",
744
+ cursor: isSelected ? "move" : "pointer",
745
+ pointerEvents: isSelected ? "none" : "visibleStroke",
687
746
  stroke: color,
688
747
  strokeWidth,
689
748
  strokeLinecap: "round",
@@ -696,6 +755,7 @@ function Ink({
696
755
  );
697
756
  }
698
757
  function Square({
758
+ isSelected,
699
759
  color = "#000000",
700
760
  strokeColor,
701
761
  opacity = 1,
@@ -704,8 +764,7 @@ function Square({
704
764
  strokeDashArray,
705
765
  rect,
706
766
  scale,
707
- onClick,
708
- cursor
767
+ onClick
709
768
  }) {
710
769
  const { width, height, x, y } = useMemo(() => {
711
770
  const outerW = rect.size.width;
@@ -743,10 +802,11 @@ function Square({
743
802
  height,
744
803
  fill: color,
745
804
  opacity,
746
- onMouseDown: onClick,
805
+ onPointerDown: onClick,
806
+ onTouchStart: onClick,
747
807
  style: {
748
- cursor,
749
- pointerEvents: color === "transparent" ? "visibleStroke" : "visible",
808
+ cursor: isSelected ? "move" : "pointer",
809
+ pointerEvents: isSelected ? "none" : color === "transparent" ? "visibleStroke" : "visible",
750
810
  stroke: strokeColor ?? color,
751
811
  strokeWidth,
752
812
  ...strokeStyle === PdfAnnotationBorderStyle.DASHED && {
@@ -768,7 +828,7 @@ function Circle({
768
828
  rect,
769
829
  scale,
770
830
  onClick,
771
- cursor
831
+ isSelected
772
832
  }) {
773
833
  const { width, height, cx, cy, rx, ry } = useMemo(() => {
774
834
  const outerW = rect.size.width;
@@ -809,10 +869,11 @@ function Circle({
809
869
  ry,
810
870
  fill: color,
811
871
  opacity,
812
- onMouseDown: onClick,
872
+ onPointerDown: onClick,
873
+ onTouchStart: onClick,
813
874
  style: {
814
- cursor,
815
- pointerEvents: color === "transparent" ? "visibleStroke" : "visible",
875
+ cursor: isSelected ? "move" : "pointer",
876
+ pointerEvents: isSelected ? "none" : color === "transparent" ? "visibleStroke" : "visible",
816
877
  stroke: strokeColor ?? color,
817
878
  strokeWidth,
818
879
  ...strokeStyle === PdfAnnotationBorderStyle.DASHED && {
@@ -920,7 +981,8 @@ function Line({
920
981
  x2,
921
982
  y2,
922
983
  opacity,
923
- onMouseDown: onClick,
984
+ onPointerDown: onClick,
985
+ onTouchStart: onClick,
924
986
  style: {
925
987
  cursor: isSelected ? "move" : "pointer",
926
988
  pointerEvents: "visibleStroke",
@@ -938,7 +1000,8 @@ function Line({
938
1000
  {
939
1001
  d: endings.start.d,
940
1002
  transform: endings.start.transform,
941
- onMouseDown: onClick,
1003
+ onPointerDown: onClick,
1004
+ onTouchStart: onClick,
942
1005
  stroke: strokeColor,
943
1006
  style: {
944
1007
  cursor: isSelected ? "move" : "pointer",
@@ -958,7 +1021,8 @@ function Line({
958
1021
  d: endings.end.d,
959
1022
  transform: endings.end.transform,
960
1023
  stroke: strokeColor,
961
- onMouseDown: onClick,
1024
+ onPointerDown: onClick,
1025
+ onTouchStart: onClick,
962
1026
  style: {
963
1027
  cursor: isSelected ? "move" : "pointer",
964
1028
  strokeWidth,
@@ -1039,7 +1103,8 @@ function Polyline({
1039
1103
  "path",
1040
1104
  {
1041
1105
  d: pathData,
1042
- onMouseDown: onClick,
1106
+ onPointerDown: onClick,
1107
+ onTouchStart: onClick,
1043
1108
  opacity,
1044
1109
  style: {
1045
1110
  fill: "none",
@@ -1059,7 +1124,8 @@ function Polyline({
1059
1124
  transform: endings.start.transform,
1060
1125
  stroke: strokeColor,
1061
1126
  fill: endings.start.filled ? color : "none",
1062
- onMouseDown: onClick,
1127
+ onPointerDown: onClick,
1128
+ onTouchStart: onClick,
1063
1129
  style: {
1064
1130
  cursor: isSelected ? "move" : "pointer",
1065
1131
  strokeWidth,
@@ -1075,11 +1141,12 @@ function Polyline({
1075
1141
  transform: endings.end.transform,
1076
1142
  stroke: strokeColor,
1077
1143
  fill: endings.end.filled ? color : "none",
1078
- onMouseDown: onClick,
1144
+ onPointerDown: onClick,
1145
+ onTouchStart: onClick,
1079
1146
  style: {
1080
1147
  cursor: isSelected ? "move" : "pointer",
1081
1148
  strokeWidth,
1082
- pointerEvents: endings.end.filled ? "visible" : "visibleStroke",
1149
+ pointerEvents: isSelected ? "none" : endings.end.filled ? "visible" : "visibleStroke",
1083
1150
  strokeLinecap: "butt"
1084
1151
  }
1085
1152
  }
@@ -1130,14 +1197,15 @@ function Polygon({
1130
1197
  "path",
1131
1198
  {
1132
1199
  d: pathData,
1133
- onMouseDown: onClick,
1200
+ onPointerDown: onClick,
1201
+ onTouchStart: onClick,
1134
1202
  opacity,
1135
1203
  style: {
1136
1204
  fill: color,
1137
1205
  stroke: strokeColor ?? color,
1138
1206
  strokeWidth,
1139
1207
  cursor: isSelected ? "move" : "pointer",
1140
- pointerEvents: color === "transparent" ? "visibleStroke" : "visible",
1208
+ pointerEvents: isSelected ? "none" : color === "transparent" ? "visibleStroke" : "visible",
1141
1209
  strokeLinecap: "butt",
1142
1210
  strokeLinejoin: "miter",
1143
1211
  ...strokeStyle === PdfAnnotationBorderStyle.DASHED && {
@@ -1241,6 +1309,7 @@ function FreeText({
1241
1309
  zIndex: 2
1242
1310
  },
1243
1311
  onPointerDown: onClick,
1312
+ onTouchStart: onClick,
1244
1313
  children: /* @__PURE__ */ jsx(
1245
1314
  "span",
1246
1315
  {
@@ -1270,6 +1339,87 @@ function FreeText({
1270
1339
  }
1271
1340
  );
1272
1341
  }
1342
+ function RenderAnnotation({
1343
+ pageIndex,
1344
+ annotation,
1345
+ scaleFactor = 1,
1346
+ style,
1347
+ ...props
1348
+ }) {
1349
+ const { provides: annotationProvides } = useAnnotationCapability();
1350
+ const [imageUrl, setImageUrl] = useState(null);
1351
+ const urlRef = useRef(null);
1352
+ const { width, height } = annotation.rect.size;
1353
+ useEffect(() => {
1354
+ if (annotationProvides) {
1355
+ const task = annotationProvides.renderAnnotation({
1356
+ pageIndex,
1357
+ annotation,
1358
+ scaleFactor,
1359
+ dpr: window.devicePixelRatio
1360
+ });
1361
+ task.wait((blob) => {
1362
+ const url = URL.createObjectURL(blob);
1363
+ setImageUrl(url);
1364
+ urlRef.current = url;
1365
+ }, ignore);
1366
+ return () => {
1367
+ if (urlRef.current) {
1368
+ URL.revokeObjectURL(urlRef.current);
1369
+ urlRef.current = null;
1370
+ } else {
1371
+ task.abort({
1372
+ code: PdfErrorCode.Cancelled,
1373
+ message: "canceled render task"
1374
+ });
1375
+ }
1376
+ };
1377
+ }
1378
+ }, [pageIndex, scaleFactor, annotationProvides, annotation.id, width, height]);
1379
+ const handleImageLoad = () => {
1380
+ if (urlRef.current) {
1381
+ URL.revokeObjectURL(urlRef.current);
1382
+ urlRef.current = null;
1383
+ }
1384
+ };
1385
+ return /* @__PURE__ */ jsx(Fragment, { children: imageUrl && /* @__PURE__ */ jsx(
1386
+ "img",
1387
+ {
1388
+ src: imageUrl,
1389
+ onLoad: handleImageLoad,
1390
+ ...props,
1391
+ style: {
1392
+ width: "100%",
1393
+ height: "100%",
1394
+ ...style || {}
1395
+ }
1396
+ }
1397
+ ) });
1398
+ }
1399
+ function Stamp({ isSelected, annotation, pageIndex, scale, onClick }) {
1400
+ return /* @__PURE__ */ jsx(
1401
+ "div",
1402
+ {
1403
+ style: {
1404
+ position: "absolute",
1405
+ width: "100%",
1406
+ height: "100%",
1407
+ zIndex: 2,
1408
+ pointerEvents: isSelected ? "none" : "auto"
1409
+ },
1410
+ onPointerDown: onClick,
1411
+ onTouchStart: onClick,
1412
+ children: annotation.pdfId !== void 0 && /* @__PURE__ */ jsx(
1413
+ RenderAnnotation,
1414
+ {
1415
+ pageIndex,
1416
+ annotation: { ...annotation.object, id: annotation.pdfId },
1417
+ scaleFactor: scale
1418
+ }
1419
+ )
1420
+ }
1421
+ );
1422
+ }
1273
1423
  function Annotations(annotationsProps) {
1274
1424
  const { pageIndex, scale, selectionMenu } = annotationsProps;
1275
1425
  const { provides: annotationProvides } = useAnnotationCapability();
@@ -1331,7 +1481,7 @@ function Annotations(annotationsProps) {
1331
1481
  children: (obj) => /* @__PURE__ */ jsx(
1332
1482
  Ink,
1333
1483
  {
1334
- cursor: isSelected ? "move" : "pointer",
1484
+ isSelected,
1335
1485
  color: obj.color,
1336
1486
  opacity: obj.opacity,
1337
1487
  strokeWidth: obj.strokeWidth,
@@ -1361,7 +1511,7 @@ function Annotations(annotationsProps) {
1361
1511
  children: (obj) => /* @__PURE__ */ jsx(
1362
1512
  Square,
1363
1513
  {
1364
- cursor: isSelected ? "move" : "pointer",
1514
+ isSelected,
1365
1515
  rect: obj.rect,
1366
1516
  color: obj.color,
1367
1517
  opacity: obj.opacity,
@@ -1393,7 +1543,7 @@ function Annotations(annotationsProps) {
1393
1543
  children: (obj) => /* @__PURE__ */ jsx(
1394
1544
  Circle,
1395
1545
  {
1396
- cursor: isSelected ? "move" : "pointer",
1546
+ isSelected,
1397
1547
  rect: obj.rect,
1398
1548
  color: obj.color,
1399
1549
  opacity: obj.opacity,
@@ -1665,6 +1815,34 @@ function Annotations(annotationsProps) {
1665
1815
  annotation.localId
1666
1816
  );
1667
1817
  }
1818
+ if (isStamp(annotation)) {
1819
+ return /* @__PURE__ */ jsx(
1820
+ AnnotationContainer,
1821
+ {
1822
+ trackedAnnotation: annotation,
1823
+ isSelected,
1824
+ isDraggable: true,
1825
+ isResizable: true,
1826
+ selectionMenu,
1827
+ lockAspectRatio: true,
1828
+ style: {
1829
+ mixBlendMode: blendModeToCss(annotation.object.blendMode ?? PdfBlendMode.Normal)
1830
+ },
1831
+ ...annotationsProps,
1832
+ children: (_object) => /* @__PURE__ */ jsx(
1833
+ Stamp,
1834
+ {
1835
+ isSelected,
1836
+ annotation,
1837
+ pageIndex,
1838
+ scale,
1839
+ onClick: (e) => handleClick(e, annotation)
1840
+ }
1841
+ )
1842
+ },
1843
+ annotation.localId
1844
+ );
1845
+ }
1668
1846
  return null;
1669
1847
  }) });
1670
1848
  }
@@ -2788,6 +2966,92 @@ const FreeTextPaint = ({
2788
2966
  }
2789
2967
  );
2790
2968
  };
2969
+ const StampPaint = ({ pageIndex, scale, pageWidth, pageHeight }) => {
2970
+ const { provides: annotationProvides } = useAnnotationCapability();
2971
+ const inputRef = useRef(null);
2972
+ const canvasRef = useRef(null);
2973
+ const [activeTool, setActiveTool] = useState({ variantKey: null, defaults: null });
2974
+ useEffect(() => {
2975
+ if (!annotationProvides) return;
2976
+ return annotationProvides.onActiveToolChange(setActiveTool);
2977
+ }, [annotationProvides]);
2978
+ if (!activeTool.defaults) return null;
2979
+ if (activeTool.defaults.subtype !== PdfAnnotationSubtype.STAMP) return null;
2980
+ const { register } = usePointerHandlers({ modeId: "stamp", pageIndex });
2981
+ const pageWidthPDF = pageWidth / scale;
2982
+ const pageHeightPDF = pageHeight / scale;
2983
+ const clamp = (v, min, max) => Math.max(min, Math.min(max, v));
2984
+ const [start, setStart] = useState(null);
2985
+ const handlers = useMemo(
2986
+ () => ({
2987
+ onPointerDown: (pos, evt) => {
2988
+ var _a;
2989
+ const x = clamp(pos.x, 0, pageWidthPDF);
2990
+ const y = clamp(pos.y, 0, pageHeightPDF);
2991
+ setStart({ x, y });
2992
+ (_a = inputRef.current) == null ? void 0 : _a.click();
2993
+ }
2994
+ }),
2995
+ [pageWidthPDF, pageHeightPDF]
2996
+ );
2997
+ useEffect(() => register ? register(handlers) : void 0, [register, handlers]);
2998
+ const onChange = async (e) => {
2999
+ var _a;
3000
+ if (!annotationProvides || !start) return;
3001
+ const file = (_a = e.currentTarget.files) == null ? void 0 : _a[0];
3002
+ if (!file) return;
3003
+ const img = await new Promise((res, rej) => {
3004
+ const i = new Image();
3005
+ i.onload = () => res(i);
3006
+ i.onerror = rej;
3007
+ i.src = URL.createObjectURL(file);
3008
+ });
3009
+ const imgW = img.naturalWidth;
3010
+ const imgH = img.naturalHeight;
3011
+ const maxW = pageWidthPDF;
3012
+ const maxH = pageHeightPDF;
3013
+ const scaleFactor = Math.min(1, maxW / imgW, maxH / imgH);
3014
+ const pdfW = imgW * scaleFactor;
3015
+ const pdfH = imgH * scaleFactor;
3016
+ const posX = clamp(start.x, 0, maxW - pdfW);
3017
+ const posY = clamp(start.y, 0, maxH - pdfH);
3018
+ const rect = {
3019
+ origin: { x: posX, y: posY },
3020
+ size: { width: pdfW, height: pdfH }
3021
+ };
3022
+ const canvas = canvasRef.current;
3023
+ if (!canvas) return;
3024
+ canvas.width = pdfW;
3025
+ canvas.height = pdfH;
3026
+ const ctx = canvas.getContext("2d");
3027
+ ctx.drawImage(img, 0, 0, pdfW, pdfH);
3028
+ const imageData = ctx.getImageData(0, 0, pdfW, pdfH);
3029
+ const anno = {
3030
+ type: PdfAnnotationSubtype.STAMP,
3031
+ flags: ["print"],
3032
+ pageIndex,
3033
+ id: Date.now() + Math.random(),
3034
+ rect
3035
+ };
3036
+ annotationProvides.createAnnotation(pageIndex, anno, { imageData });
3037
+ annotationProvides.setActiveVariant(null);
3038
+ annotationProvides.selectAnnotation(pageIndex, anno.id);
3039
+ setStart(null);
3040
+ };
3041
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
3042
+ /* @__PURE__ */ jsx("canvas", { style: { display: "none" }, ref: canvasRef }),
3043
+ /* @__PURE__ */ jsx(
3044
+ "input",
3045
+ {
3046
+ ref: inputRef,
3047
+ type: "file",
3048
+ accept: "image/png,image/jpeg",
3049
+ style: { display: "none" },
3050
+ onChange
3051
+ }
3052
+ )
3053
+ ] });
3054
+ };
2791
3055
  function AnnotationLayer({
2792
3056
  pageIndex,
2793
3057
  scale,
@@ -2872,6 +3136,15 @@ function AnnotationLayer({
2872
3136
  pageWidth,
2873
3137
  pageHeight
2874
3138
  }
3139
+ ),
3140
+ /* @__PURE__ */ jsx(
3141
+ StampPaint,
3142
+ {
3143
+ pageIndex,
3144
+ scale,
3145
+ pageWidth,
3146
+ pageHeight
3147
+ }
2875
3148
  )
2876
3149
  ]
2877
3150
  }