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