@embedpdf/plugin-annotation 2.7.0 → 2.9.0

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 (134) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +1131 -203
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/annotation-plugin.d.ts +2 -0
  6. package/dist/lib/geometry/cloudy-border.d.ts +90 -0
  7. package/dist/lib/geometry/index.d.ts +1 -0
  8. package/dist/lib/handlers/index.d.ts +4 -0
  9. package/dist/lib/handlers/insert-text.handler.d.ts +8 -0
  10. package/dist/lib/handlers/replace-text.handler.d.ts +9 -0
  11. package/dist/lib/handlers/selection-utils.d.ts +7 -0
  12. package/dist/lib/handlers/text-markup.handler.d.ts +7 -0
  13. package/dist/lib/handlers/text.handler.d.ts +3 -0
  14. package/dist/lib/handlers/types.d.ts +14 -1
  15. package/dist/lib/helpers.d.ts +2 -1
  16. package/dist/lib/selectors.d.ts +6 -1
  17. package/dist/lib/tools/default-tools.d.ts +141 -45
  18. package/dist/lib/tools/tools-utils.d.ts +2 -0
  19. package/dist/lib/tools/types.d.ts +34 -1
  20. package/dist/lib/types.d.ts +1 -0
  21. package/dist/preact/index.cjs +1 -1
  22. package/dist/preact/index.cjs.map +1 -1
  23. package/dist/preact/index.js +621 -274
  24. package/dist/preact/index.js.map +1 -1
  25. package/dist/react/index.cjs +1 -1
  26. package/dist/react/index.cjs.map +1 -1
  27. package/dist/react/index.js +621 -274
  28. package/dist/react/index.js.map +1 -1
  29. package/dist/shared/annotation-bounds.d.ts +14 -0
  30. package/dist/shared/components/annotation-container.d.ts +4 -2
  31. package/dist/shared/components/annotations/caret.d.ts +24 -0
  32. package/dist/shared/components/annotations/circle.d.ts +8 -4
  33. package/dist/shared/components/annotations/free-text.d.ts +2 -2
  34. package/dist/shared/components/annotations/ink.d.ts +2 -2
  35. package/dist/shared/components/annotations/line.d.ts +2 -2
  36. package/dist/shared/components/annotations/link.d.ts +2 -2
  37. package/dist/shared/components/annotations/polygon.d.ts +5 -3
  38. package/dist/shared/components/annotations/polyline.d.ts +8 -4
  39. package/dist/shared/components/annotations/square.d.ts +8 -4
  40. package/dist/shared/components/annotations/stamp.d.ts +2 -2
  41. package/dist/shared/components/annotations/text.d.ts +14 -0
  42. package/dist/shared/components/text-markup/highlight.d.ts +2 -2
  43. package/dist/shared/components/text-markup/squiggly.d.ts +2 -2
  44. package/dist/shared/components/text-markup/strikeout.d.ts +2 -2
  45. package/dist/shared/components/text-markup/underline.d.ts +2 -2
  46. package/dist/shared/components/types.d.ts +8 -4
  47. package/dist/shared-preact/annotation-bounds.d.ts +14 -0
  48. package/dist/shared-preact/components/annotation-container.d.ts +4 -2
  49. package/dist/shared-preact/components/annotations/caret.d.ts +24 -0
  50. package/dist/shared-preact/components/annotations/circle.d.ts +8 -4
  51. package/dist/shared-preact/components/annotations/free-text.d.ts +2 -2
  52. package/dist/shared-preact/components/annotations/ink.d.ts +2 -2
  53. package/dist/shared-preact/components/annotations/line.d.ts +2 -2
  54. package/dist/shared-preact/components/annotations/link.d.ts +2 -2
  55. package/dist/shared-preact/components/annotations/polygon.d.ts +5 -3
  56. package/dist/shared-preact/components/annotations/polyline.d.ts +8 -4
  57. package/dist/shared-preact/components/annotations/square.d.ts +8 -4
  58. package/dist/shared-preact/components/annotations/stamp.d.ts +2 -2
  59. package/dist/shared-preact/components/annotations/text.d.ts +14 -0
  60. package/dist/shared-preact/components/text-markup/highlight.d.ts +2 -2
  61. package/dist/shared-preact/components/text-markup/squiggly.d.ts +2 -2
  62. package/dist/shared-preact/components/text-markup/strikeout.d.ts +2 -2
  63. package/dist/shared-preact/components/text-markup/underline.d.ts +2 -2
  64. package/dist/shared-preact/components/types.d.ts +8 -4
  65. package/dist/shared-react/annotation-bounds.d.ts +14 -0
  66. package/dist/shared-react/components/annotation-container.d.ts +4 -2
  67. package/dist/shared-react/components/annotations/caret.d.ts +24 -0
  68. package/dist/shared-react/components/annotations/circle.d.ts +8 -4
  69. package/dist/shared-react/components/annotations/free-text.d.ts +2 -2
  70. package/dist/shared-react/components/annotations/ink.d.ts +2 -2
  71. package/dist/shared-react/components/annotations/line.d.ts +2 -2
  72. package/dist/shared-react/components/annotations/link.d.ts +2 -2
  73. package/dist/shared-react/components/annotations/polygon.d.ts +5 -3
  74. package/dist/shared-react/components/annotations/polyline.d.ts +8 -4
  75. package/dist/shared-react/components/annotations/square.d.ts +8 -4
  76. package/dist/shared-react/components/annotations/stamp.d.ts +2 -2
  77. package/dist/shared-react/components/annotations/text.d.ts +14 -0
  78. package/dist/shared-react/components/text-markup/highlight.d.ts +2 -2
  79. package/dist/shared-react/components/text-markup/squiggly.d.ts +2 -2
  80. package/dist/shared-react/components/text-markup/strikeout.d.ts +2 -2
  81. package/dist/shared-react/components/text-markup/underline.d.ts +2 -2
  82. package/dist/shared-react/components/types.d.ts +8 -4
  83. package/dist/shared-vue/annotation-bounds.d.ts +14 -0
  84. package/dist/svelte/components/annotations/Caret.svelte.d.ts +13 -0
  85. package/dist/svelte/components/annotations/Circle.svelte.d.ts +4 -2
  86. package/dist/svelte/components/annotations/FreeText.svelte.d.ts +1 -1
  87. package/dist/svelte/components/annotations/Ink.svelte.d.ts +1 -1
  88. package/dist/svelte/components/annotations/Line.svelte.d.ts +1 -1
  89. package/dist/svelte/components/annotations/Link.svelte.d.ts +1 -1
  90. package/dist/svelte/components/annotations/Polygon.svelte.d.ts +2 -1
  91. package/dist/svelte/components/annotations/Polyline.svelte.d.ts +4 -2
  92. package/dist/svelte/components/annotations/Square.svelte.d.ts +4 -2
  93. package/dist/svelte/components/annotations/Stamp.svelte.d.ts +1 -1
  94. package/dist/svelte/components/annotations/Text.svelte.d.ts +10 -0
  95. package/dist/svelte/components/annotations/index.d.ts +1 -0
  96. package/dist/svelte/components/renderers/CaretRenderer.svelte.d.ts +5 -0
  97. package/dist/svelte/components/renderers/TextRenderer.svelte.d.ts +5 -0
  98. package/dist/svelte/components/text-markup/Highlight.svelte.d.ts +1 -1
  99. package/dist/svelte/components/text-markup/Squiggly.svelte.d.ts +1 -1
  100. package/dist/svelte/components/text-markup/Strikeout.svelte.d.ts +1 -1
  101. package/dist/svelte/components/text-markup/Underline.svelte.d.ts +1 -1
  102. package/dist/svelte/components/types.d.ts +2 -1
  103. package/dist/svelte/context/types.d.ts +7 -3
  104. package/dist/svelte/index.cjs +1 -1
  105. package/dist/svelte/index.cjs.map +1 -1
  106. package/dist/svelte/index.js +831 -416
  107. package/dist/svelte/index.js.map +1 -1
  108. package/dist/vue/components/annotation-container.vue.d.ts +9 -8
  109. package/dist/vue/components/annotation-layer.vue.d.ts +1 -1
  110. package/dist/vue/components/annotations/caret.vue.d.ts +24 -0
  111. package/dist/vue/components/annotations/circle.vue.d.ts +7 -3
  112. package/dist/vue/components/annotations/free-text.vue.d.ts +2 -2
  113. package/dist/vue/components/annotations/index.d.ts +1 -0
  114. package/dist/vue/components/annotations/ink.vue.d.ts +2 -2
  115. package/dist/vue/components/annotations/line.vue.d.ts +2 -2
  116. package/dist/vue/components/annotations/link.vue.d.ts +2 -2
  117. package/dist/vue/components/annotations/polygon.vue.d.ts +4 -2
  118. package/dist/vue/components/annotations/polyline.vue.d.ts +8 -3
  119. package/dist/vue/components/annotations/square.vue.d.ts +7 -3
  120. package/dist/vue/components/annotations/stamp.vue.d.ts +2 -2
  121. package/dist/vue/components/annotations/text.vue.d.ts +14 -0
  122. package/dist/vue/components/annotations.vue.d.ts +9 -10
  123. package/dist/vue/components/renderers/caret-renderer.vue.d.ts +6 -0
  124. package/dist/vue/components/renderers/text-renderer.vue.d.ts +6 -0
  125. package/dist/vue/components/text-markup/highlight.vue.d.ts +2 -2
  126. package/dist/vue/components/text-markup/squiggly.vue.d.ts +2 -2
  127. package/dist/vue/components/text-markup/strikeout.vue.d.ts +2 -2
  128. package/dist/vue/components/text-markup/underline.vue.d.ts +2 -2
  129. package/dist/vue/context/types.d.ts +7 -3
  130. package/dist/vue/index.cjs +1 -1
  131. package/dist/vue/index.cjs.map +1 -1
  132. package/dist/vue/index.js +778 -354
  133. package/dist/vue/index.js.map +1 -1
  134. package/package.json +10 -10
package/dist/index.js CHANGED
@@ -156,8 +156,11 @@ function isLink(a) {
156
156
  function isRedact(a) {
157
157
  return a.object.type === PdfAnnotationSubtype.REDACT;
158
158
  }
159
+ function isCaret(a) {
160
+ return a.object.type === PdfAnnotationSubtype.CARET;
161
+ }
159
162
  function isSidebarAnnotation(a) {
160
- return isTextMarkup(a) || isInk(a) || isSquare(a) || isCircle(a) || isPolygon(a) || isLine(a) || isPolyline(a) || isFreeText(a) || isStamp(a) || isRedact(a);
163
+ return isText(a) && !a.object.inReplyToId || isTextMarkup(a) || isInk(a) || isSquare(a) || isCircle(a) || isPolygon(a) || isLine(a) || isPolyline(a) || isFreeText(a) || isStamp(a) || isRedact(a) || isCaret(a);
161
164
  }
162
165
  const getAnnotationsByPageIndex = (s, page) => (s.pages[page] ?? []).map((uid) => s.byUid[uid]);
163
166
  const getAnnotations = (s) => {
@@ -199,19 +202,33 @@ const getSidebarAnnotationsWithRepliesGroupedByPage = (s) => {
199
202
  }
200
203
  }
201
204
  }
205
+ const membersByLeader = {};
206
+ const consumedAsGroupMember = /* @__PURE__ */ new Set();
207
+ for (const uidList of Object.values(s.pages)) {
208
+ for (const uid of uidList) {
209
+ const ta = s.byUid[uid];
210
+ if (ta && ta.object.inReplyToId && ta.object.replyType === PdfAnnotationReplyType.Group && ta.object.type !== PdfAnnotationSubtype.LINK && isSidebarAnnotation(ta)) {
211
+ const leaderId = ta.object.inReplyToId;
212
+ (membersByLeader[leaderId] || (membersByLeader[leaderId] = [])).push(ta);
213
+ consumedAsGroupMember.add(ta.object.id);
214
+ }
215
+ }
216
+ }
202
217
  const out = {};
203
218
  for (const [pageStr, uidList] of Object.entries(s.pages)) {
204
219
  const page = Number(pageStr);
205
220
  const pageAnnotations = [];
206
221
  for (const uid of uidList) {
207
222
  const ta = s.byUid[uid];
208
- if (ta && isSidebarAnnotation(ta)) {
209
- pageAnnotations.push({
210
- page,
211
- annotation: ta,
212
- replies: repliesByParent[ta.object.id] ?? []
213
- });
214
- }
223
+ if (!ta || !isSidebarAnnotation(ta)) continue;
224
+ if (consumedAsGroupMember.has(ta.object.id)) continue;
225
+ const members = membersByLeader[ta.object.id];
226
+ pageAnnotations.push({
227
+ page,
228
+ annotation: ta,
229
+ replies: repliesByParent[ta.object.id] ?? [],
230
+ ...members && members.length > 0 ? { groupMembers: members } : {}
231
+ });
215
232
  }
216
233
  if (pageAnnotations.length > 0) {
217
234
  out[page] = pageAnnotations;
@@ -323,6 +340,62 @@ const getSelectionGroupingAction = (s) => {
323
340
  }
324
341
  return selected.length >= 2 ? "group" : "disabled";
325
342
  };
343
+ const inkTools = [
344
+ {
345
+ id: "ink",
346
+ name: "Pen",
347
+ matchScore: (a) => a.type === PdfAnnotationSubtype.INK && a.intent !== "InkHighlight" ? 5 : 0,
348
+ interaction: {
349
+ exclusive: false,
350
+ cursor: "crosshair",
351
+ isDraggable: true,
352
+ isResizable: true,
353
+ lockAspectRatio: false
354
+ },
355
+ defaults: {
356
+ type: PdfAnnotationSubtype.INK,
357
+ strokeColor: "#E44234",
358
+ color: "#E44234",
359
+ // deprecated alias
360
+ opacity: 1,
361
+ strokeWidth: 6
362
+ },
363
+ behavior: {
364
+ commitDelay: 800
365
+ }
366
+ },
367
+ {
368
+ id: "inkHighlighter",
369
+ name: "Ink Highlighter",
370
+ matchScore: (a) => a.type === PdfAnnotationSubtype.INK && a.intent === "InkHighlight" ? 10 : 0,
371
+ interaction: {
372
+ exclusive: false,
373
+ cursor: "crosshair",
374
+ isDraggable: true,
375
+ isResizable: true,
376
+ lockAspectRatio: false,
377
+ lockGroupAspectRatio: (a) => {
378
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
379
+ return r2 >= 6 && r2 <= 84;
380
+ }
381
+ },
382
+ defaults: {
383
+ type: PdfAnnotationSubtype.INK,
384
+ intent: "InkHighlight",
385
+ strokeColor: "#FFCD45",
386
+ color: "#FFCD45",
387
+ // deprecated alias
388
+ opacity: 1,
389
+ strokeWidth: 14,
390
+ blendMode: PdfBlendMode.Multiply
391
+ },
392
+ behavior: {
393
+ commitDelay: 800,
394
+ smartLineRecognition: true,
395
+ smartLineThreshold: 0.15
396
+ }
397
+ }
398
+ ];
326
399
  const defaultTools = [
327
400
  // Text Markup Tools
328
401
  {
@@ -334,6 +407,7 @@ const defaultTools = [
334
407
  textSelection: true,
335
408
  isDraggable: false,
336
409
  isResizable: false,
410
+ isRotatable: false,
337
411
  // Text markup annotations are anchored to text and should not move/resize in groups
338
412
  isGroupDraggable: false,
339
413
  isGroupResizable: false
@@ -356,6 +430,7 @@ const defaultTools = [
356
430
  textSelection: true,
357
431
  isDraggable: false,
358
432
  isResizable: false,
433
+ isRotatable: false,
359
434
  isGroupDraggable: false,
360
435
  isGroupResizable: false
361
436
  },
@@ -376,6 +451,7 @@ const defaultTools = [
376
451
  textSelection: true,
377
452
  isDraggable: false,
378
453
  isResizable: false,
454
+ isRotatable: false,
379
455
  isGroupDraggable: false,
380
456
  isGroupResizable: false
381
457
  },
@@ -396,6 +472,7 @@ const defaultTools = [
396
472
  textSelection: true,
397
473
  isDraggable: false,
398
474
  isResizable: false,
475
+ isRotatable: false,
399
476
  isGroupDraggable: false,
400
477
  isGroupResizable: false
401
478
  },
@@ -407,53 +484,61 @@ const defaultTools = [
407
484
  opacity: 1
408
485
  }
409
486
  },
410
- // Drawing Tools
487
+ // Insert Text (Caret with intent Insert)
411
488
  {
412
- id: "ink",
413
- name: "Pen",
414
- matchScore: (a) => a.type === PdfAnnotationSubtype.INK && a.intent !== "InkHighlight" ? 5 : 0,
489
+ id: "insertText",
490
+ name: "Insert Text",
491
+ matchScore: (a) => {
492
+ var _a;
493
+ if (a.type !== PdfAnnotationSubtype.CARET) return 0;
494
+ return ((_a = a.intent) == null ? void 0 : _a.includes("Insert")) ? 2 : 1;
495
+ },
415
496
  interaction: {
416
497
  exclusive: false,
417
- cursor: "crosshair",
418
- isDraggable: true,
419
- isResizable: true,
420
- lockAspectRatio: false
498
+ textSelection: true,
499
+ showSelectionRects: true,
500
+ isDraggable: false,
501
+ isResizable: false,
502
+ isRotatable: false,
503
+ isGroupDraggable: false,
504
+ isGroupResizable: false
421
505
  },
422
506
  defaults: {
423
- type: PdfAnnotationSubtype.INK,
507
+ type: PdfAnnotationSubtype.CARET,
424
508
  strokeColor: "#E44234",
425
- color: "#E44234",
426
- // deprecated alias
427
509
  opacity: 1,
428
- strokeWidth: 6
510
+ intent: "Insert"
429
511
  }
430
512
  },
513
+ // Replace Text (StrikeOut + Caret group)
431
514
  {
432
- id: "inkHighlighter",
433
- name: "Ink Highlighter",
434
- matchScore: (a) => a.type === PdfAnnotationSubtype.INK && a.intent === "InkHighlight" ? 10 : 0,
515
+ id: "replaceText",
516
+ name: "Replace Text",
517
+ matchScore: (a) => {
518
+ var _a, _b;
519
+ if (a.type === PdfAnnotationSubtype.STRIKEOUT && ((_a = a.intent) == null ? void 0 : _a.includes("StrikeOutTextEdit")))
520
+ return 2;
521
+ if (a.type === PdfAnnotationSubtype.CARET && ((_b = a.intent) == null ? void 0 : _b.includes("Replace"))) return 2;
522
+ return 0;
523
+ },
435
524
  interaction: {
436
525
  exclusive: false,
437
- cursor: "crosshair",
438
- isDraggable: true,
439
- isResizable: true,
440
- lockAspectRatio: false,
441
- lockGroupAspectRatio: (a) => {
442
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
443
- return r >= 6 && r <= 84;
444
- }
526
+ textSelection: true,
527
+ isDraggable: false,
528
+ isResizable: false,
529
+ isRotatable: false,
530
+ isGroupDraggable: false,
531
+ isGroupResizable: false
445
532
  },
446
533
  defaults: {
447
- type: PdfAnnotationSubtype.INK,
448
- intent: "InkHighlight",
449
- strokeColor: "#FFCD45",
450
- color: "#FFCD45",
451
- // deprecated alias
534
+ type: PdfAnnotationSubtype.STRIKEOUT,
535
+ strokeColor: "#E44234",
452
536
  opacity: 1,
453
- strokeWidth: 14,
454
- blendMode: PdfBlendMode.Multiply
537
+ intent: "StrikeOutTextEdit"
455
538
  }
456
539
  },
540
+ // Drawing Tools
541
+ ...inkTools,
457
542
  // Shape Tools
458
543
  {
459
544
  id: "circle",
@@ -466,8 +551,8 @@ const defaultTools = [
466
551
  isResizable: true,
467
552
  lockAspectRatio: false,
468
553
  lockGroupAspectRatio: (a) => {
469
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
470
- return r >= 6 && r <= 84;
554
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
555
+ return r2 >= 6 && r2 <= 84;
471
556
  }
472
557
  },
473
558
  defaults: {
@@ -494,8 +579,8 @@ const defaultTools = [
494
579
  isResizable: true,
495
580
  lockAspectRatio: false,
496
581
  lockGroupAspectRatio: (a) => {
497
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
498
- return r >= 6 && r <= 84;
582
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
583
+ return r2 >= 6 && r2 <= 84;
499
584
  }
500
585
  },
501
586
  defaults: {
@@ -525,8 +610,8 @@ const defaultTools = [
525
610
  isGroupResizable: true,
526
611
  // Scales proportionally in a group
527
612
  lockGroupAspectRatio: (a) => {
528
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
529
- return r >= 6 && r <= 84;
613
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
614
+ return r2 >= 6 && r2 <= 84;
530
615
  }
531
616
  },
532
617
  defaults: {
@@ -556,8 +641,8 @@ const defaultTools = [
556
641
  isGroupResizable: true,
557
642
  // Scales proportionally in a group
558
643
  lockGroupAspectRatio: (a) => {
559
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
560
- return r >= 6 && r <= 84;
644
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
645
+ return r2 >= 6 && r2 <= 84;
561
646
  }
562
647
  },
563
648
  defaults: {
@@ -592,8 +677,8 @@ const defaultTools = [
592
677
  isGroupResizable: true,
593
678
  // Scales proportionally in a group
594
679
  lockGroupAspectRatio: (a) => {
595
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
596
- return r >= 6 && r <= 84;
680
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
681
+ return r2 >= 6 && r2 <= 84;
597
682
  }
598
683
  },
599
684
  defaults: {
@@ -618,8 +703,8 @@ const defaultTools = [
618
703
  isGroupResizable: true,
619
704
  // Scales proportionally in a group
620
705
  lockGroupAspectRatio: (a) => {
621
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
622
- return r >= 6 && r <= 84;
706
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
707
+ return r2 >= 6 && r2 <= 84;
623
708
  }
624
709
  },
625
710
  defaults: {
@@ -631,6 +716,26 @@ const defaultTools = [
631
716
  }
632
717
  },
633
718
  // Text & Stamp
719
+ {
720
+ id: "textComment",
721
+ name: "Comment",
722
+ matchScore: (a) => a.type === PdfAnnotationSubtype.TEXT && !a.inReplyToId ? 1 : 0,
723
+ interaction: {
724
+ exclusive: false,
725
+ cursor: "crosshair",
726
+ isDraggable: true,
727
+ isResizable: false,
728
+ isRotatable: false
729
+ },
730
+ defaults: {
731
+ type: PdfAnnotationSubtype.TEXT,
732
+ strokeColor: "#FFCD45",
733
+ opacity: 1
734
+ },
735
+ behavior: {
736
+ selectAfterCreate: true
737
+ }
738
+ },
634
739
  {
635
740
  id: "freeText",
636
741
  name: "Free Text",
@@ -642,8 +747,8 @@ const defaultTools = [
642
747
  isResizable: true,
643
748
  lockAspectRatio: false,
644
749
  lockGroupAspectRatio: (a) => {
645
- const r = ((a.rotation ?? 0) % 90 + 90) % 90;
646
- return r >= 6 && r <= 84;
750
+ const r2 = ((a.rotation ?? 0) % 90 + 90) % 90;
751
+ return r2 >= 6 && r2 <= 84;
647
752
  }
648
753
  },
649
754
  defaults: {
@@ -952,7 +1057,7 @@ const reducer = (state, action) => {
952
1057
  },
953
1058
  byUid: {
954
1059
  ...docState.byUid,
955
- [uid]: { commitState: "new", object: annotation }
1060
+ [uid]: { commitState: "new", object: annotation, dictMode: true }
956
1061
  },
957
1062
  hasPendingChanges: true
958
1063
  }
@@ -1086,6 +1191,18 @@ function useState(initialValue) {
1086
1191
  };
1087
1192
  return [getValue, setValue];
1088
1193
  }
1194
+ function isLineLike(points, threshold) {
1195
+ if (points.length < 3) return true;
1196
+ const A = points[0];
1197
+ const B = points[points.length - 1];
1198
+ const len = Math.hypot(B.x - A.x, B.y - A.y);
1199
+ if (len < 5) return false;
1200
+ const maxDev = points.reduce((max, P) => {
1201
+ const d = Math.abs((B.x - A.x) * (A.y - P.y) - (A.x - P.x) * (B.y - A.y)) / len;
1202
+ return Math.max(max, d);
1203
+ }, 0);
1204
+ return maxDev / len < threshold;
1205
+ }
1089
1206
  const inkHandlerFactory = {
1090
1207
  annotationType: PdfAnnotationSubtype.INK,
1091
1208
  create(context) {
@@ -1121,7 +1238,8 @@ const inkHandlerFactory = {
1121
1238
  data: {
1122
1239
  ...defaults,
1123
1240
  rect: bounds,
1124
- inkList: strokes
1241
+ inkList: strokes,
1242
+ blendMode: defaults.blendMode
1125
1243
  }
1126
1244
  };
1127
1245
  };
@@ -1149,6 +1267,37 @@ const inkHandlerFactory = {
1149
1267
  var _a;
1150
1268
  setIsDrawing(false);
1151
1269
  (_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
1270
+ const tool = getTool();
1271
+ const behavior = tool == null ? void 0 : tool.behavior;
1272
+ if (behavior == null ? void 0 : behavior.smartLineRecognition) {
1273
+ const threshold = behavior.smartLineThreshold ?? 0.15;
1274
+ const strokes = getStrokes();
1275
+ const last = strokes[strokes.length - 1];
1276
+ if (last && last.points.length > 1 && isLineLike(last.points, threshold)) {
1277
+ const first = last.points[0];
1278
+ const end = last.points[last.points.length - 1];
1279
+ const dx = end.x - first.x;
1280
+ const dy = end.y - first.y;
1281
+ const angleDeg = Math.atan2(Math.abs(dy), Math.abs(dx)) * (180 / Math.PI);
1282
+ const snapAngleDeg = behavior.snapAngleDeg ?? 15;
1283
+ if (angleDeg <= snapAngleDeg) {
1284
+ const avgY = last.points.reduce((sum, p) => sum + p.y, 0) / last.points.length;
1285
+ last.points = [
1286
+ { x: first.x, y: avgY },
1287
+ { x: end.x, y: avgY }
1288
+ ];
1289
+ } else if (angleDeg >= 90 - snapAngleDeg) {
1290
+ const avgX = last.points.reduce((sum, p) => sum + p.x, 0) / last.points.length;
1291
+ last.points = [
1292
+ { x: avgX, y: first.y },
1293
+ { x: avgX, y: end.y }
1294
+ ];
1295
+ }
1296
+ setStrokes([...strokes]);
1297
+ onPreview(getPreview());
1298
+ }
1299
+ }
1300
+ const commitDelay = (behavior == null ? void 0 : behavior.commitDelay) ?? 800;
1152
1301
  if (timerRef.current) clearTimeout(timerRef.current);
1153
1302
  timerRef.current = setTimeout(() => {
1154
1303
  const strokes = getStrokes();
@@ -1169,7 +1318,7 @@ const inkHandlerFactory = {
1169
1318
  }
1170
1319
  setStrokes([]);
1171
1320
  onPreview(null);
1172
- }, 800);
1321
+ }, commitDelay);
1173
1322
  },
1174
1323
  onPointerCancel: (_, evt) => {
1175
1324
  var _a;
@@ -1182,45 +1331,6 @@ const inkHandlerFactory = {
1182
1331
  };
1183
1332
  }
1184
1333
  };
1185
- function useClickDetector({
1186
- threshold = 5,
1187
- getTool,
1188
- onClickDetected
1189
- }) {
1190
- const [getStartPos, setStartPos] = useState(null);
1191
- const [getHasMoved, setHasMoved] = useState(false);
1192
- return {
1193
- onStart: (pos) => {
1194
- setStartPos(pos);
1195
- setHasMoved(false);
1196
- },
1197
- onMove: (pos) => {
1198
- const start = getStartPos();
1199
- if (!start || getHasMoved()) return;
1200
- const distance = Math.sqrt(Math.pow(pos.x - start.x, 2) + Math.pow(pos.y - start.y, 2));
1201
- if (distance > threshold) {
1202
- setHasMoved(true);
1203
- }
1204
- },
1205
- onEnd: (pos) => {
1206
- var _a;
1207
- const start = getStartPos();
1208
- if (start && !getHasMoved()) {
1209
- const tool = getTool();
1210
- if (tool && "clickBehavior" in tool && ((_a = tool.clickBehavior) == null ? void 0 : _a.enabled)) {
1211
- onClickDetected(pos, tool);
1212
- }
1213
- }
1214
- setStartPos(null);
1215
- setHasMoved(false);
1216
- },
1217
- hasMoved: getHasMoved,
1218
- reset: () => {
1219
- setStartPos(null);
1220
- setHasMoved(false);
1221
- }
1222
- };
1223
- }
1224
1334
  function createArrowHandler(isClosed) {
1225
1335
  const calculateGeometry = (sw) => {
1226
1336
  const len = sw * 9;
@@ -1280,14 +1390,14 @@ const LINE_ENDING_HANDLERS = {
1280
1390
  },
1281
1391
  [PdfAnnotationLineEnding.Circle]: {
1282
1392
  getSvgPath: (sw) => {
1283
- const r = sw * 5 / 2;
1284
- return `M ${r} 0 A ${r} ${r} 0 1 1 ${-r} 0 A ${r} ${r} 0 1 1 ${r} 0`;
1393
+ const r2 = sw * 5 / 2;
1394
+ return `M ${r2} 0 A ${r2} ${r2} 0 1 1 ${-r2} 0 A ${r2} ${r2} 0 1 1 ${r2} 0`;
1285
1395
  },
1286
1396
  getLocalPoints: (sw) => {
1287
- const r = sw * 5 / 2;
1397
+ const r2 = sw * 5 / 2;
1288
1398
  return [
1289
- { x: -r, y: -r },
1290
- { x: r, y: r }
1399
+ { x: -r2, y: -r2 },
1400
+ { x: r2, y: r2 }
1291
1401
  ];
1292
1402
  },
1293
1403
  getRotation: () => 0,
@@ -1429,7 +1539,7 @@ function createEnding(ending, strokeWidth, rad, px, py) {
1429
1539
  if (!ending) return null;
1430
1540
  const handler = LINE_ENDING_HANDLERS[ending];
1431
1541
  if (!handler) return null;
1432
- const toDeg = (r) => r * 180 / Math.PI;
1542
+ const toDeg = (r2) => r2 * 180 / Math.PI;
1433
1543
  const rotationAngle = handler.getRotation(rad);
1434
1544
  return {
1435
1545
  d: handler.getSvgPath(strokeWidth),
@@ -1601,6 +1711,75 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
1601
1711
  rotatePointAroundCenter: rotatePointAround,
1602
1712
  rotateVertices
1603
1713
  }, Symbol.toStringTag, { value: "Module" }));
1714
+ const COMMENT_SIZE = 24;
1715
+ const textHandlerFactory = {
1716
+ annotationType: PdfAnnotationSubtype.TEXT,
1717
+ create(context) {
1718
+ const { onCommit, getTool, pageSize } = context;
1719
+ return {
1720
+ onPointerDown: (pos) => {
1721
+ const tool = getTool();
1722
+ if (!tool) return;
1723
+ const rect = {
1724
+ origin: { x: pos.x - COMMENT_SIZE / 2, y: pos.y - COMMENT_SIZE / 2 },
1725
+ size: { width: COMMENT_SIZE, height: COMMENT_SIZE }
1726
+ };
1727
+ let anno = {
1728
+ ...tool.defaults,
1729
+ rect,
1730
+ type: PdfAnnotationSubtype.TEXT,
1731
+ icon: tool.defaults.icon ?? PdfAnnotationIcon.Comment,
1732
+ contents: tool.defaults.contents ?? "",
1733
+ flags: tool.defaults.flags ?? ["print", "noRotate", "noZoom"],
1734
+ pageIndex: context.pageIndex,
1735
+ id: uuidV4(),
1736
+ created: /* @__PURE__ */ new Date()
1737
+ };
1738
+ anno = clampAnnotationToPage(anno, pageSize);
1739
+ onCommit(anno);
1740
+ }
1741
+ };
1742
+ }
1743
+ };
1744
+ function useClickDetector({
1745
+ threshold = 5,
1746
+ getTool,
1747
+ onClickDetected
1748
+ }) {
1749
+ const [getStartPos, setStartPos] = useState(null);
1750
+ const [getHasMoved, setHasMoved] = useState(false);
1751
+ return {
1752
+ onStart: (pos) => {
1753
+ setStartPos(pos);
1754
+ setHasMoved(false);
1755
+ },
1756
+ onMove: (pos) => {
1757
+ const start = getStartPos();
1758
+ if (!start || getHasMoved()) return;
1759
+ const distance2 = Math.sqrt(Math.pow(pos.x - start.x, 2) + Math.pow(pos.y - start.y, 2));
1760
+ if (distance2 > threshold) {
1761
+ setHasMoved(true);
1762
+ }
1763
+ },
1764
+ onEnd: (pos) => {
1765
+ var _a;
1766
+ const start = getStartPos();
1767
+ if (start && !getHasMoved()) {
1768
+ const tool = getTool();
1769
+ if (tool && "clickBehavior" in tool && ((_a = tool.clickBehavior) == null ? void 0 : _a.enabled)) {
1770
+ onClickDetected(pos, tool);
1771
+ }
1772
+ }
1773
+ setStartPos(null);
1774
+ setHasMoved(false);
1775
+ },
1776
+ hasMoved: getHasMoved,
1777
+ reset: () => {
1778
+ setStartPos(null);
1779
+ setHasMoved(false);
1780
+ }
1781
+ };
1782
+ }
1604
1783
  const freeTextHandlerFactory = {
1605
1784
  annotationType: PdfAnnotationSubtype.FREETEXT,
1606
1785
  create(context) {
@@ -2003,6 +2182,554 @@ const polylineHandlerFactory = {
2003
2182
  };
2004
2183
  }
2005
2184
  };
2185
+ function convertAABBRectToUnrotatedSpace(newAABBRect, originalAABBRect, originalUnrotatedRect, rotationDegrees) {
2186
+ const theta = rotationDegrees * Math.PI / 180;
2187
+ const A = Math.abs(Math.cos(theta));
2188
+ const B = Math.abs(Math.sin(theta));
2189
+ const det = A * A - B * B;
2190
+ const newAABBw = newAABBRect.size.width;
2191
+ const newAABBh = newAABBRect.size.height;
2192
+ let newWidth;
2193
+ let newHeight;
2194
+ if (Math.abs(det) > 1e-6) {
2195
+ newWidth = (A * newAABBw - B * newAABBh) / det;
2196
+ newHeight = (A * newAABBh - B * newAABBw) / det;
2197
+ newWidth = Math.max(newWidth, 1);
2198
+ newHeight = Math.max(newHeight, 1);
2199
+ } else {
2200
+ const origArea = originalAABBRect.size.width * originalAABBRect.size.height;
2201
+ const newArea = newAABBw * newAABBh;
2202
+ const uniformScale = origArea > 0 ? Math.sqrt(newArea / origArea) : 1;
2203
+ newWidth = originalUnrotatedRect.size.width * uniformScale;
2204
+ newHeight = originalUnrotatedRect.size.height * uniformScale;
2205
+ }
2206
+ const newCenterX = newAABBRect.origin.x + newAABBw / 2;
2207
+ const newCenterY = newAABBRect.origin.y + newAABBh / 2;
2208
+ return {
2209
+ origin: { x: newCenterX - newWidth / 2, y: newCenterY - newHeight / 2 },
2210
+ size: { width: newWidth, height: newHeight }
2211
+ };
2212
+ }
2213
+ const ANGLE_180 = Math.PI;
2214
+ const ANGLE_90 = Math.PI / 2;
2215
+ const ANGLE_34 = 34 * Math.PI / 180;
2216
+ const ANGLE_30 = 30 * Math.PI / 180;
2217
+ const ANGLE_12 = 12 * Math.PI / 180;
2218
+ class PathBuilder {
2219
+ constructor() {
2220
+ this.parts = [];
2221
+ this.bbox = {
2222
+ minX: Infinity,
2223
+ minY: Infinity,
2224
+ maxX: -Infinity,
2225
+ maxY: -Infinity
2226
+ };
2227
+ this.started = false;
2228
+ }
2229
+ moveTo(x, y) {
2230
+ const sy = -y;
2231
+ this.updateBBox(x, sy);
2232
+ this.parts.push(`M ${r(x)} ${r(sy)}`);
2233
+ this.started = true;
2234
+ }
2235
+ curveTo(x1, y1, x2, y2, x3, y3) {
2236
+ const sy1 = -y1;
2237
+ const sy2 = -y2;
2238
+ const sy3 = -y3;
2239
+ this.updateBBox(x1, sy1);
2240
+ this.updateBBox(x2, sy2);
2241
+ this.updateBBox(x3, sy3);
2242
+ this.parts.push(`C ${r(x1)} ${r(sy1)}, ${r(x2)} ${r(sy2)}, ${r(x3)} ${r(sy3)}`);
2243
+ }
2244
+ close() {
2245
+ if (this.started) {
2246
+ this.parts.push("Z");
2247
+ }
2248
+ }
2249
+ build(lineWidth) {
2250
+ const d = lineWidth > 0 ? lineWidth / 2 : 0;
2251
+ return {
2252
+ path: this.parts.join(" "),
2253
+ bbox: {
2254
+ minX: this.bbox.minX - d,
2255
+ minY: this.bbox.minY - d,
2256
+ maxX: this.bbox.maxX + d,
2257
+ maxY: this.bbox.maxY + d
2258
+ }
2259
+ };
2260
+ }
2261
+ updateBBox(x, y) {
2262
+ if (x < this.bbox.minX) this.bbox.minX = x;
2263
+ if (y < this.bbox.minY) this.bbox.minY = y;
2264
+ if (x > this.bbox.maxX) this.bbox.maxX = x;
2265
+ if (y > this.bbox.maxY) this.bbox.maxY = y;
2266
+ }
2267
+ }
2268
+ function r(n) {
2269
+ return Number(n.toFixed(4)).toString();
2270
+ }
2271
+ function distance(a, b) {
2272
+ const dx = b.x - a.x;
2273
+ const dy = b.y - a.y;
2274
+ return Math.sqrt(dx * dx + dy * dy);
2275
+ }
2276
+ function cosine(dx, hypot) {
2277
+ return hypot === 0 ? 0 : dx / hypot;
2278
+ }
2279
+ function sine(dy, hypot) {
2280
+ return hypot === 0 ? 0 : dy / hypot;
2281
+ }
2282
+ function polygonDirection(pts) {
2283
+ let a = 0;
2284
+ const len = pts.length;
2285
+ for (let i = 0; i < len; i++) {
2286
+ const j = (i + 1) % len;
2287
+ a += pts[i].x * pts[j].y - pts[i].y * pts[j].x;
2288
+ }
2289
+ return a;
2290
+ }
2291
+ function ensurePositiveWinding(pts) {
2292
+ if (polygonDirection(pts) < 0) {
2293
+ pts.reverse();
2294
+ }
2295
+ }
2296
+ function removeZeroLengthSegments(polygon) {
2297
+ if (polygon.length <= 2) return polygon;
2298
+ const tolerance = 0.5;
2299
+ const result = [polygon[0]];
2300
+ for (let i = 1; i < polygon.length; i++) {
2301
+ const prev = result[result.length - 1];
2302
+ const cur = polygon[i];
2303
+ if (Math.abs(cur.x - prev.x) >= tolerance || Math.abs(cur.y - prev.y) >= tolerance) {
2304
+ result.push(cur);
2305
+ }
2306
+ }
2307
+ return result;
2308
+ }
2309
+ function arcSegment(startAng, endAng, cx, cy, rx, ry, out, addMoveTo) {
2310
+ const cosA = Math.cos(startAng);
2311
+ const sinA = Math.sin(startAng);
2312
+ const cosB = Math.cos(endAng);
2313
+ const sinB = Math.sin(endAng);
2314
+ const denom = Math.sin((endAng - startAng) / 2);
2315
+ if (denom === 0) {
2316
+ if (addMoveTo) {
2317
+ out.moveTo(cx + rx * cosA, cy + ry * sinA);
2318
+ }
2319
+ return;
2320
+ }
2321
+ const bcp = 4 / 3 * (1 - Math.cos((endAng - startAng) / 2)) / denom;
2322
+ const p1x = cx + rx * (cosA - bcp * sinA);
2323
+ const p1y = cy + ry * (sinA + bcp * cosA);
2324
+ const p2x = cx + rx * (cosB + bcp * sinB);
2325
+ const p2y = cy + ry * (sinB - bcp * cosB);
2326
+ const p3x = cx + rx * cosB;
2327
+ const p3y = cy + ry * sinB;
2328
+ if (addMoveTo) {
2329
+ out.moveTo(cx + rx * cosA, cy + ry * sinA);
2330
+ }
2331
+ out.curveTo(p1x, p1y, p2x, p2y, p3x, p3y);
2332
+ }
2333
+ function arcSegmentToArray(startAng, endAng, cx, cy, rx, ry) {
2334
+ const cosA = Math.cos(startAng);
2335
+ const sinA = Math.sin(startAng);
2336
+ const cosB = Math.cos(endAng);
2337
+ const sinB = Math.sin(endAng);
2338
+ const denom = Math.sin((endAng - startAng) / 2);
2339
+ if (denom === 0) return [];
2340
+ const bcp = 4 / 3 * (1 - Math.cos((endAng - startAng) / 2)) / denom;
2341
+ return [
2342
+ { x: cx + rx * (cosA - bcp * sinA), y: cy + ry * (sinA + bcp * cosA) },
2343
+ { x: cx + rx * (cosB + bcp * sinB), y: cy + ry * (sinB - bcp * cosB) },
2344
+ { x: cx + rx * cosB, y: cy + ry * sinB }
2345
+ ];
2346
+ }
2347
+ function getArc(startAng, endAng, rx, ry, cx, cy, out, addMoveTo) {
2348
+ const angleIncr = ANGLE_90;
2349
+ let angleTodo = endAng - startAng;
2350
+ while (angleTodo < 0) angleTodo += 2 * Math.PI;
2351
+ const sweep = angleTodo;
2352
+ let angleDone = 0;
2353
+ if (addMoveTo) {
2354
+ out.moveTo(cx + rx * Math.cos(startAng), cy + ry * Math.sin(startAng));
2355
+ }
2356
+ while (angleTodo > angleIncr) {
2357
+ arcSegment(startAng + angleDone, startAng + angleDone + angleIncr, cx, cy, rx, ry, out, false);
2358
+ angleDone += angleIncr;
2359
+ angleTodo -= angleIncr;
2360
+ }
2361
+ if (angleTodo > 0) {
2362
+ arcSegment(startAng + angleDone, startAng + sweep, cx, cy, rx, ry, out, false);
2363
+ }
2364
+ }
2365
+ function addCornerCurl(anglePrev, angleCur, radius, cx, cy, alpha, alphaPrev, out, addMoveTo) {
2366
+ let a = anglePrev + ANGLE_180 + alphaPrev;
2367
+ const b = anglePrev + ANGLE_180 + alphaPrev - 22 * Math.PI / 180;
2368
+ arcSegment(a, b, cx, cy, radius, radius, out, addMoveTo);
2369
+ a = b;
2370
+ const bEnd = angleCur - alpha;
2371
+ getArc(a, bEnd, radius, radius, cx, cy, out, false);
2372
+ }
2373
+ function addFirstIntermediateCurl(angleCur, r2, alpha, cx, cy, out) {
2374
+ const a = angleCur + ANGLE_180;
2375
+ arcSegment(a + alpha, a + alpha - ANGLE_30, cx, cy, r2, r2, out, false);
2376
+ arcSegment(a + alpha - ANGLE_30, a + ANGLE_90, cx, cy, r2, r2, out, false);
2377
+ arcSegment(a + ANGLE_90, a + ANGLE_180 - ANGLE_34, cx, cy, r2, r2, out, false);
2378
+ }
2379
+ function getIntermediateCurlTemplate(angleCur, r2) {
2380
+ const pts = [];
2381
+ const a = angleCur + ANGLE_180;
2382
+ pts.push(...arcSegmentToArray(a + ANGLE_34, a + ANGLE_12, 0, 0, r2, r2));
2383
+ pts.push(...arcSegmentToArray(a + ANGLE_12, a + ANGLE_90, 0, 0, r2, r2));
2384
+ pts.push(...arcSegmentToArray(a + ANGLE_90, a + ANGLE_180 - ANGLE_34, 0, 0, r2, r2));
2385
+ return pts;
2386
+ }
2387
+ function outputCurlTemplate(template, x, y, out) {
2388
+ for (let i = 0; i + 2 < template.length; i += 3) {
2389
+ const a = template[i];
2390
+ const b = template[i + 1];
2391
+ const c = template[i + 2];
2392
+ out.curveTo(a.x + x, a.y + y, b.x + x, b.y + y, c.x + x, c.y + y);
2393
+ }
2394
+ }
2395
+ function computeParamsPolygon(idealRadius, k, length) {
2396
+ if (length === 0) return { n: -1, adjustedRadius: idealRadius };
2397
+ const cornerSpace = 2 * k * idealRadius;
2398
+ const remaining = length - cornerSpace;
2399
+ if (remaining <= 0) {
2400
+ return { n: 0, adjustedRadius: idealRadius };
2401
+ }
2402
+ const idealAdvance = 2 * k * idealRadius;
2403
+ const n = Math.max(1, Math.ceil(remaining / idealAdvance));
2404
+ const adjustedRadius = remaining / (n * 2 * k);
2405
+ return { n, adjustedRadius };
2406
+ }
2407
+ function cloudyPolygonImpl(vertices, isEllipse, intensity, lineWidth, out) {
2408
+ let polygon = removeZeroLengthSegments(vertices);
2409
+ ensurePositiveWinding(polygon);
2410
+ const numPoints = polygon.length;
2411
+ if (numPoints < 2) return;
2412
+ if (intensity <= 0) {
2413
+ out.moveTo(polygon[0].x, polygon[0].y);
2414
+ for (let i = 1; i < numPoints; i++) {
2415
+ out.curveTo(
2416
+ polygon[i].x,
2417
+ polygon[i].y,
2418
+ polygon[i].x,
2419
+ polygon[i].y,
2420
+ polygon[i].x,
2421
+ polygon[i].y
2422
+ );
2423
+ }
2424
+ return;
2425
+ }
2426
+ let idealRadius = isEllipse ? getEllipseCloudRadius(intensity, lineWidth) : getPolygonCloudRadius(intensity, lineWidth);
2427
+ if (idealRadius < 0.5) idealRadius = 0.5;
2428
+ const k = Math.cos(ANGLE_34);
2429
+ const edgeAlphas = [];
2430
+ for (let j = 0; j + 1 < numPoints; j++) {
2431
+ const len = distance(polygon[j], polygon[j + 1]);
2432
+ if (len <= 0 || len >= 2 * k * idealRadius) {
2433
+ edgeAlphas.push(ANGLE_34);
2434
+ } else {
2435
+ edgeAlphas.push(Math.acos(Math.min(1, len / (2 * idealRadius))));
2436
+ }
2437
+ }
2438
+ let anglePrev = 0;
2439
+ let outputStarted = false;
2440
+ for (let j = 0; j + 1 < numPoints; j++) {
2441
+ const pt = polygon[j];
2442
+ const ptNext = polygon[j + 1];
2443
+ const len = distance(pt, ptNext);
2444
+ if (len === 0) continue;
2445
+ const params = computeParamsPolygon(idealRadius, k, len);
2446
+ if (params.n < 0) {
2447
+ if (!outputStarted) {
2448
+ out.moveTo(pt.x, pt.y);
2449
+ outputStarted = true;
2450
+ }
2451
+ continue;
2452
+ }
2453
+ const edgeRadius = Math.max(0.5, params.adjustedRadius);
2454
+ const intermAdvance = 2 * k * edgeRadius;
2455
+ const firstAdvance = k * idealRadius + k * edgeRadius;
2456
+ let angleCur = Math.atan2(ptNext.y - pt.y, ptNext.x - pt.x);
2457
+ if (j === 0) {
2458
+ const ptPrev = polygon[numPoints - 2];
2459
+ anglePrev = Math.atan2(pt.y - ptPrev.y, pt.x - ptPrev.x);
2460
+ }
2461
+ const cos = cosine(ptNext.x - pt.x, len);
2462
+ const sin = sine(ptNext.y - pt.y, len);
2463
+ let x = pt.x;
2464
+ let y = pt.y;
2465
+ const alpha = edgeAlphas[j];
2466
+ const prevEdgeIdx = j === 0 ? numPoints - 2 : j - 1;
2467
+ const alphaPrevEdge = edgeAlphas[prevEdgeIdx] ?? ANGLE_34;
2468
+ addCornerCurl(
2469
+ anglePrev,
2470
+ angleCur,
2471
+ idealRadius,
2472
+ pt.x,
2473
+ pt.y,
2474
+ alpha,
2475
+ alphaPrevEdge,
2476
+ out,
2477
+ !outputStarted
2478
+ );
2479
+ outputStarted = true;
2480
+ if (params.n === 0) {
2481
+ x += len * cos;
2482
+ y += len * sin;
2483
+ } else {
2484
+ x += firstAdvance * cos;
2485
+ y += firstAdvance * sin;
2486
+ let numInterm = params.n;
2487
+ if (params.n >= 1) {
2488
+ addFirstIntermediateCurl(angleCur, edgeRadius, ANGLE_34, x, y, out);
2489
+ x += intermAdvance * cos;
2490
+ y += intermAdvance * sin;
2491
+ numInterm = params.n - 1;
2492
+ }
2493
+ const template = getIntermediateCurlTemplate(angleCur, edgeRadius);
2494
+ for (let i = 0; i < numInterm; i++) {
2495
+ outputCurlTemplate(template, x, y, out);
2496
+ x += intermAdvance * cos;
2497
+ y += intermAdvance * sin;
2498
+ }
2499
+ }
2500
+ anglePrev = angleCur;
2501
+ }
2502
+ }
2503
+ function flattenEllipse(left, bottom, right, top) {
2504
+ const cx = (left + right) / 2;
2505
+ const cy = (bottom + top) / 2;
2506
+ const rx = (right - left) / 2;
2507
+ const ry = (top - bottom) / 2;
2508
+ if (rx <= 0 || ry <= 0) return [];
2509
+ const numSegments = Math.max(32, Math.ceil(Math.max(rx, ry) * 2));
2510
+ const points = [];
2511
+ for (let i = 0; i <= numSegments; i++) {
2512
+ const angle = 2 * Math.PI * i / numSegments;
2513
+ points.push({
2514
+ x: cx + rx * Math.cos(angle),
2515
+ y: cy + ry * Math.sin(angle)
2516
+ });
2517
+ }
2518
+ return points;
2519
+ }
2520
+ function getEllipseCloudRadius(intensity, lineWidth) {
2521
+ return 4.75 * intensity + 0.5 * lineWidth;
2522
+ }
2523
+ function getPolygonCloudRadius(intensity, lineWidth) {
2524
+ return 4 * intensity + 0.5 * lineWidth;
2525
+ }
2526
+ function cloudyEllipseImpl(left, bottom, right, top, intensity, lineWidth, out) {
2527
+ if (intensity <= 0) {
2528
+ const rx = Math.abs(right - left) / 2;
2529
+ const ry = Math.abs(top - bottom) / 2;
2530
+ const cx = (left + right) / 2;
2531
+ const cy = (bottom + top) / 2;
2532
+ getArc(0, 2 * Math.PI, rx, ry, cx, cy, out, true);
2533
+ return;
2534
+ }
2535
+ const width = right - left;
2536
+ const height = top - bottom;
2537
+ let cloudRadius = getEllipseCloudRadius(intensity, lineWidth);
2538
+ const threshold1 = 0.5 * cloudRadius;
2539
+ if (width < threshold1 && height < threshold1) {
2540
+ const rx = Math.abs(right - left) / 2;
2541
+ const ry = Math.abs(top - bottom) / 2;
2542
+ const cx = (left + right) / 2;
2543
+ const cy = (bottom + top) / 2;
2544
+ getArc(0, 2 * Math.PI, rx, ry, cx, cy, out, true);
2545
+ return;
2546
+ }
2547
+ const threshold2 = 5;
2548
+ if (width < threshold2 && height > 20 || width > 20 && height < threshold2) {
2549
+ cloudyPolygonImpl(
2550
+ [
2551
+ { x: left, y: bottom },
2552
+ { x: right, y: bottom },
2553
+ { x: right, y: top },
2554
+ { x: left, y: top },
2555
+ { x: left, y: bottom }
2556
+ ],
2557
+ true,
2558
+ intensity,
2559
+ lineWidth,
2560
+ out
2561
+ );
2562
+ return;
2563
+ }
2564
+ const radiusAdj = Math.sin(ANGLE_12) * cloudRadius - 1.5;
2565
+ let adjLeft = left;
2566
+ let adjRight = right;
2567
+ let adjBottom = bottom;
2568
+ let adjTop = top;
2569
+ if (width > 2 * radiusAdj) {
2570
+ adjLeft += radiusAdj;
2571
+ adjRight -= radiusAdj;
2572
+ } else {
2573
+ const mid = (left + right) / 2;
2574
+ adjLeft = mid - 0.1;
2575
+ adjRight = mid + 0.1;
2576
+ }
2577
+ if (height > 2 * radiusAdj) {
2578
+ adjBottom += radiusAdj;
2579
+ adjTop -= radiusAdj;
2580
+ } else {
2581
+ const mid = (top + bottom) / 2;
2582
+ adjTop = mid + 0.1;
2583
+ adjBottom = mid - 0.1;
2584
+ }
2585
+ const flatPolygon = flattenEllipse(adjLeft, adjBottom, adjRight, adjTop);
2586
+ const numFlatPts = flatPolygon.length;
2587
+ if (numFlatPts < 2) return;
2588
+ let totLen = 0;
2589
+ for (let i = 1; i < numFlatPts; i++) {
2590
+ totLen += distance(flatPolygon[i - 1], flatPolygon[i]);
2591
+ }
2592
+ const k = Math.cos(ANGLE_34);
2593
+ let curlAdvance = 2 * k * cloudRadius;
2594
+ let n = Math.ceil(totLen / curlAdvance);
2595
+ if (n < 2) {
2596
+ const rx = Math.abs(right - left) / 2;
2597
+ const ry = Math.abs(top - bottom) / 2;
2598
+ const cx = (left + right) / 2;
2599
+ const cy = (bottom + top) / 2;
2600
+ getArc(0, 2 * Math.PI, rx, ry, cx, cy, out, true);
2601
+ return;
2602
+ }
2603
+ curlAdvance = totLen / n;
2604
+ cloudRadius = curlAdvance / (2 * k);
2605
+ if (cloudRadius < 0.5) {
2606
+ cloudRadius = 0.5;
2607
+ curlAdvance = 2 * k * cloudRadius;
2608
+ } else if (cloudRadius < 3) {
2609
+ const rx = Math.abs(right - left) / 2;
2610
+ const ry = Math.abs(top - bottom) / 2;
2611
+ const cx = (left + right) / 2;
2612
+ const cy = (bottom + top) / 2;
2613
+ getArc(0, 2 * Math.PI, rx, ry, cx, cy, out, true);
2614
+ return;
2615
+ }
2616
+ const centerPoints = [];
2617
+ let lengthRemain = 0;
2618
+ const comparisonToler = lineWidth * 0.1;
2619
+ for (let i = 0; i + 1 < numFlatPts; i++) {
2620
+ const p1 = flatPolygon[i];
2621
+ const p2 = flatPolygon[i + 1];
2622
+ const segDx = p2.x - p1.x;
2623
+ const segDy = p2.y - p1.y;
2624
+ const segLen = distance(p1, p2);
2625
+ if (segLen === 0) continue;
2626
+ let lengthTodo = segLen + lengthRemain;
2627
+ if (lengthTodo >= curlAdvance - comparisonToler || i === numFlatPts - 2) {
2628
+ const cos = cosine(segDx, segLen);
2629
+ const sin = sine(segDy, segLen);
2630
+ let d = curlAdvance - lengthRemain;
2631
+ while (lengthTodo >= curlAdvance - comparisonToler) {
2632
+ centerPoints.push({ x: p1.x + d * cos, y: p1.y + d * sin });
2633
+ lengthTodo -= curlAdvance;
2634
+ d += curlAdvance;
2635
+ }
2636
+ lengthRemain = Math.max(0, lengthTodo);
2637
+ } else {
2638
+ lengthRemain += segLen;
2639
+ }
2640
+ }
2641
+ const cpLen = centerPoints.length;
2642
+ let epAnglePrev = 0;
2643
+ let epAlphaPrev = 0;
2644
+ for (let i = 0; i < cpLen; i++) {
2645
+ const idxNext = (i + 1) % cpLen;
2646
+ const pt = centerPoints[i];
2647
+ const ptNext = centerPoints[idxNext];
2648
+ if (i === 0) {
2649
+ const ptPrev = centerPoints[cpLen - 1];
2650
+ epAnglePrev = Math.atan2(pt.y - ptPrev.y, pt.x - ptPrev.x);
2651
+ epAlphaPrev = computeParamsEllipse(ptPrev, pt, cloudRadius, curlAdvance);
2652
+ }
2653
+ const angleCur = Math.atan2(ptNext.y - pt.y, ptNext.x - pt.x);
2654
+ const alpha = computeParamsEllipse(pt, ptNext, cloudRadius, curlAdvance);
2655
+ addCornerCurl(epAnglePrev, angleCur, cloudRadius, pt.x, pt.y, alpha, epAlphaPrev, out, i === 0);
2656
+ epAnglePrev = angleCur;
2657
+ epAlphaPrev = alpha;
2658
+ }
2659
+ }
2660
+ function computeParamsEllipse(pt, ptNext, r2, curlAdv) {
2661
+ const len = distance(pt, ptNext);
2662
+ if (len === 0) return ANGLE_34;
2663
+ const e = len - curlAdv;
2664
+ const arg = (curlAdv / 2 + e / 2) / r2;
2665
+ return arg < -1 || arg > 1 ? 0 : Math.acos(arg);
2666
+ }
2667
+ function getCloudyBorderExtent(intensity, lineWidth, isEllipse) {
2668
+ const cloudRadius = isEllipse ? getEllipseCloudRadius(intensity, lineWidth) : getPolygonCloudRadius(intensity, lineWidth);
2669
+ return cloudRadius + lineWidth / 2;
2670
+ }
2671
+ function generateCloudyRectanglePath(rect, rd, intensity, lineWidth) {
2672
+ const out = new PathBuilder();
2673
+ let left = 0;
2674
+ let top = 0;
2675
+ let right = rect.width;
2676
+ let bottom = rect.height;
2677
+ if (rd) {
2678
+ left += rd.left;
2679
+ top += rd.top;
2680
+ right -= rd.right;
2681
+ bottom -= rd.bottom;
2682
+ } else {
2683
+ left += lineWidth / 2;
2684
+ top += lineWidth / 2;
2685
+ right -= lineWidth / 2;
2686
+ bottom -= lineWidth / 2;
2687
+ }
2688
+ const polygon = [
2689
+ { x: left, y: -top },
2690
+ { x: right, y: -top },
2691
+ { x: right, y: -bottom },
2692
+ { x: left, y: -bottom },
2693
+ { x: left, y: -top }
2694
+ ];
2695
+ cloudyPolygonImpl(polygon, false, intensity, lineWidth, out);
2696
+ out.close();
2697
+ return out.build(lineWidth);
2698
+ }
2699
+ function generateCloudyEllipsePath(rect, rd, intensity, lineWidth) {
2700
+ const out = new PathBuilder();
2701
+ let left = 0;
2702
+ let top = 0;
2703
+ let right = rect.width;
2704
+ let bottom = rect.height;
2705
+ if (rd) {
2706
+ left += rd.left;
2707
+ top += rd.top;
2708
+ right -= rd.right;
2709
+ bottom -= rd.bottom;
2710
+ }
2711
+ cloudyEllipseImpl(left, -bottom, right, -top, intensity, lineWidth, out);
2712
+ out.close();
2713
+ return out.build(lineWidth);
2714
+ }
2715
+ function generateCloudyPolygonPath(vertices, rectOrigin, intensity, lineWidth) {
2716
+ const out = new PathBuilder();
2717
+ if (vertices.length < 3) {
2718
+ return out.build(lineWidth);
2719
+ }
2720
+ const localPts = vertices.map((v) => ({
2721
+ x: v.x - rectOrigin.x,
2722
+ y: -(v.y - rectOrigin.y)
2723
+ }));
2724
+ const first = localPts[0];
2725
+ const last = localPts[localPts.length - 1];
2726
+ if (first.x !== last.x || first.y !== last.y) {
2727
+ localPts.push({ x: first.x, y: first.y });
2728
+ }
2729
+ cloudyPolygonImpl(localPts, false, intensity, lineWidth, out);
2730
+ out.close();
2731
+ return out.build(lineWidth);
2732
+ }
2006
2733
  const HANDLE_SIZE_PX = 14;
2007
2734
  const polygonHandlerFactory = {
2008
2735
  annotationType: PdfAnnotationSubtype.POLYGON,
@@ -2041,7 +2768,9 @@ const polygonHandlerFactory = {
2041
2768
  if (vertices.length < 3) return;
2042
2769
  const defaults = getDefaults();
2043
2770
  if (!defaults) return;
2044
- const rect = expandRect(rectFromPoints(vertices), defaults.strokeWidth / 2);
2771
+ const intensity = defaults.cloudyBorderIntensity ?? 0;
2772
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, defaults.strokeWidth, false) : defaults.strokeWidth / 2;
2773
+ const rect = expandRect(rectFromPoints(vertices), pad);
2045
2774
  const anno = {
2046
2775
  ...defaults,
2047
2776
  vertices,
@@ -2049,7 +2778,10 @@ const polygonHandlerFactory = {
2049
2778
  type: PdfAnnotationSubtype.POLYGON,
2050
2779
  pageIndex: context.pageIndex,
2051
2780
  id: uuidV4(),
2052
- created: /* @__PURE__ */ new Date()
2781
+ created: /* @__PURE__ */ new Date(),
2782
+ ...intensity > 0 && {
2783
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
2784
+ }
2053
2785
  };
2054
2786
  onCommit(anno);
2055
2787
  setVertices([]);
@@ -2062,8 +2794,10 @@ const polygonHandlerFactory = {
2062
2794
  if (vertices.length === 0 || !currentPos) return null;
2063
2795
  const defaults = getDefaults();
2064
2796
  if (!defaults) return null;
2797
+ const intensity = defaults.cloudyBorderIntensity ?? 0;
2798
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, defaults.strokeWidth, false) : defaults.strokeWidth / 2;
2065
2799
  const allPoints = [...vertices, currentPos];
2066
- const bounds = expandRect(rectFromPoints(allPoints), defaults.strokeWidth / 2);
2800
+ const bounds = expandRect(rectFromPoints(allPoints), pad);
2067
2801
  return {
2068
2802
  type: PdfAnnotationSubtype.POLYGON,
2069
2803
  bounds,
@@ -2149,10 +2883,11 @@ const squareHandlerFactory = {
2149
2883
  const x = clamp(pos.x - halfWidth, 0, pageSize.width - width);
2150
2884
  const y = clamp(pos.y - halfHeight, 0, pageSize.height - height);
2151
2885
  const strokeWidth = defaults.strokeWidth;
2152
- const halfStroke = strokeWidth / 2;
2886
+ const intensity = defaults.cloudyBorderIntensity ?? 0;
2887
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, strokeWidth, false) : strokeWidth / 2;
2153
2888
  const rect = {
2154
- origin: { x: x - halfStroke, y: y - halfStroke },
2155
- size: { width: width + strokeWidth, height: height + strokeWidth }
2889
+ origin: { x: x - pad, y: y - pad },
2890
+ size: { width: width + 2 * pad, height: height + 2 * pad }
2156
2891
  };
2157
2892
  const anno = {
2158
2893
  ...defaults,
@@ -2160,7 +2895,10 @@ const squareHandlerFactory = {
2160
2895
  created: /* @__PURE__ */ new Date(),
2161
2896
  id: uuidV4(),
2162
2897
  pageIndex,
2163
- rect
2898
+ rect,
2899
+ ...intensity > 0 && {
2900
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
2901
+ }
2164
2902
  };
2165
2903
  onCommit(anno);
2166
2904
  }
@@ -2175,17 +2913,21 @@ const squareHandlerFactory = {
2175
2913
  const defaults = getDefaults();
2176
2914
  if (!defaults) return null;
2177
2915
  const strokeWidth = defaults.strokeWidth;
2178
- const halfStroke = strokeWidth / 2;
2916
+ const intensity = defaults.cloudyBorderIntensity ?? 0;
2917
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, strokeWidth, false) : strokeWidth / 2;
2179
2918
  const rect = {
2180
- origin: { x: minX - halfStroke, y: minY - halfStroke },
2181
- size: { width: width + strokeWidth, height: height + strokeWidth }
2919
+ origin: { x: minX - pad, y: minY - pad },
2920
+ size: { width: width + 2 * pad, height: height + 2 * pad }
2182
2921
  };
2183
2922
  return {
2184
2923
  type: PdfAnnotationSubtype.SQUARE,
2185
2924
  bounds: rect,
2186
2925
  data: {
2187
2926
  rect,
2188
- ...defaults
2927
+ ...defaults,
2928
+ ...intensity > 0 && {
2929
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
2930
+ }
2189
2931
  }
2190
2932
  };
2191
2933
  };
@@ -2219,13 +2961,18 @@ const squareHandlerFactory = {
2219
2961
  if (!defaults2) return;
2220
2962
  const preview = getPreview(clampedPos);
2221
2963
  if (preview) {
2964
+ const intensity = defaults2.cloudyBorderIntensity ?? 0;
2965
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, defaults2.strokeWidth, false) : void 0;
2222
2966
  const anno = {
2223
2967
  ...defaults2,
2224
2968
  type: PdfAnnotationSubtype.SQUARE,
2225
2969
  created: /* @__PURE__ */ new Date(),
2226
2970
  id: uuidV4(),
2227
2971
  pageIndex,
2228
- rect: preview.data.rect
2972
+ rect: preview.data.rect,
2973
+ ...pad !== void 0 && {
2974
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
2975
+ }
2229
2976
  };
2230
2977
  onCommit(anno);
2231
2978
  }
@@ -2349,10 +3096,11 @@ const circleHandlerFactory = {
2349
3096
  const x = clamp(pos.x - halfWidth, 0, pageSize.width - width);
2350
3097
  const y = clamp(pos.y - halfHeight, 0, pageSize.height - height);
2351
3098
  const strokeWidth = defaults.strokeWidth;
2352
- const halfStroke = strokeWidth / 2;
3099
+ const intensity = defaults.cloudyBorderIntensity ?? 0;
3100
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, strokeWidth, true) : strokeWidth / 2;
2353
3101
  const rect = {
2354
- origin: { x: x - halfStroke, y: y - halfStroke },
2355
- size: { width: width + strokeWidth, height: height + strokeWidth }
3102
+ origin: { x: x - pad, y: y - pad },
3103
+ size: { width: width + 2 * pad, height: height + 2 * pad }
2356
3104
  };
2357
3105
  const anno = {
2358
3106
  ...defaults,
@@ -2360,7 +3108,10 @@ const circleHandlerFactory = {
2360
3108
  created: /* @__PURE__ */ new Date(),
2361
3109
  id: uuidV4(),
2362
3110
  pageIndex,
2363
- rect
3111
+ rect,
3112
+ ...intensity > 0 && {
3113
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
3114
+ }
2364
3115
  };
2365
3116
  onCommit(anno);
2366
3117
  }
@@ -2375,17 +3126,21 @@ const circleHandlerFactory = {
2375
3126
  const defaults = getDefaults();
2376
3127
  if (!defaults) return null;
2377
3128
  const strokeWidth = defaults.strokeWidth;
2378
- const halfStroke = strokeWidth / 2;
3129
+ const intensity = defaults.cloudyBorderIntensity ?? 0;
3130
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, strokeWidth, true) : strokeWidth / 2;
2379
3131
  const rect = {
2380
- origin: { x: minX - halfStroke, y: minY - halfStroke },
2381
- size: { width: width + strokeWidth, height: height + strokeWidth }
3132
+ origin: { x: minX - pad, y: minY - pad },
3133
+ size: { width: width + 2 * pad, height: height + 2 * pad }
2382
3134
  };
2383
3135
  return {
2384
3136
  type: PdfAnnotationSubtype.CIRCLE,
2385
3137
  bounds: rect,
2386
3138
  data: {
2387
3139
  rect,
2388
- ...defaults
3140
+ ...defaults,
3141
+ ...intensity > 0 && {
3142
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
3143
+ }
2389
3144
  }
2390
3145
  };
2391
3146
  };
@@ -2419,6 +3174,8 @@ const circleHandlerFactory = {
2419
3174
  if (!defaults2) return;
2420
3175
  const preview = getPreview(clampedPos);
2421
3176
  if (preview) {
3177
+ const intensity = defaults2.cloudyBorderIntensity ?? 0;
3178
+ const pad = intensity > 0 ? getCloudyBorderExtent(intensity, defaults2.strokeWidth, true) : void 0;
2422
3179
  const anno = {
2423
3180
  ...defaults2,
2424
3181
  type: PdfAnnotationSubtype.CIRCLE,
@@ -2426,7 +3183,10 @@ const circleHandlerFactory = {
2426
3183
  created: /* @__PURE__ */ new Date(),
2427
3184
  id: uuidV4(),
2428
3185
  pageIndex,
2429
- rect: preview.data.rect
3186
+ rect: preview.data.rect,
3187
+ ...pad !== void 0 && {
3188
+ rectangleDifferences: { left: pad, top: pad, right: pad, bottom: pad }
3189
+ }
2430
3190
  };
2431
3191
  onCommit(anno);
2432
3192
  }
@@ -2453,6 +3213,135 @@ const circleHandlerFactory = {
2453
3213
  };
2454
3214
  }
2455
3215
  };
3216
+ const textMarkupSelectionHandler = {
3217
+ toolId: "__textMarkup__",
3218
+ handle(context, selections, getText) {
3219
+ const tool = context.getTool();
3220
+ if (!tool) return;
3221
+ for (const selection of selections) {
3222
+ const id = uuidV4();
3223
+ getText().then((text) => {
3224
+ var _a;
3225
+ context.createAnnotation(selection.pageIndex, {
3226
+ ...tool.defaults,
3227
+ rect: selection.rect,
3228
+ segmentRects: selection.segmentRects,
3229
+ pageIndex: selection.pageIndex,
3230
+ created: /* @__PURE__ */ new Date(),
3231
+ id,
3232
+ ...text != null && { custom: { text } }
3233
+ });
3234
+ if ((_a = tool.behavior) == null ? void 0 : _a.selectAfterCreate) {
3235
+ context.selectAnnotation(selection.pageIndex, id);
3236
+ }
3237
+ });
3238
+ }
3239
+ }
3240
+ };
3241
+ function computeCaretRect(lastSegRect) {
3242
+ const lineHeight = lastSegRect.size.height;
3243
+ const height = lineHeight / 2;
3244
+ const width = height;
3245
+ const lineEndX = lastSegRect.origin.x + lastSegRect.size.width;
3246
+ return {
3247
+ origin: {
3248
+ x: lineEndX - width / 2,
3249
+ y: lastSegRect.origin.y + lineHeight / 2
3250
+ },
3251
+ size: { width, height }
3252
+ };
3253
+ }
3254
+ const insertTextSelectionHandler = {
3255
+ toolId: "insertText",
3256
+ handle(context, selections, getText) {
3257
+ const tool = context.getTool();
3258
+ if (!tool) return;
3259
+ const getDefaults = () => ({
3260
+ strokeColor: tool.defaults.strokeColor ?? "#E44234",
3261
+ opacity: tool.defaults.opacity ?? 1,
3262
+ flags: tool.defaults.flags ?? ["print"]
3263
+ });
3264
+ for (const selection of selections) {
3265
+ const lastSegRect = selection.segmentRects[selection.segmentRects.length - 1];
3266
+ if (!lastSegRect) continue;
3267
+ const caretRect = computeCaretRect(lastSegRect);
3268
+ const caretId = uuidV4();
3269
+ const defaults = getDefaults();
3270
+ getText().then((text) => {
3271
+ var _a;
3272
+ context.createAnnotation(selection.pageIndex, {
3273
+ type: PdfAnnotationSubtype.CARET,
3274
+ id: caretId,
3275
+ pageIndex: selection.pageIndex,
3276
+ rect: caretRect,
3277
+ strokeColor: defaults.strokeColor,
3278
+ opacity: defaults.opacity,
3279
+ intent: "Insert",
3280
+ rectangleDifferences: { left: 0.5, top: 0.5, right: 0.5, bottom: 0.5 },
3281
+ created: /* @__PURE__ */ new Date(),
3282
+ flags: defaults.flags,
3283
+ ...text != null && { custom: { text } }
3284
+ });
3285
+ if ((_a = tool.behavior) == null ? void 0 : _a.selectAfterCreate) {
3286
+ context.selectAnnotation(selection.pageIndex, caretId);
3287
+ }
3288
+ });
3289
+ }
3290
+ }
3291
+ };
3292
+ const replaceTextSelectionHandler = {
3293
+ toolId: "replaceText",
3294
+ handle(context, selections, getText) {
3295
+ const tool = context.getTool();
3296
+ if (!tool) return;
3297
+ const getDefaults = () => ({
3298
+ strokeColor: tool.defaults.strokeColor ?? "#E44234",
3299
+ opacity: tool.defaults.opacity ?? 1,
3300
+ flags: tool.defaults.flags ?? ["print"]
3301
+ });
3302
+ for (const selection of selections) {
3303
+ const lastSegRect = selection.segmentRects[selection.segmentRects.length - 1];
3304
+ if (!lastSegRect) continue;
3305
+ const caretRect = computeCaretRect(lastSegRect);
3306
+ const caretId = uuidV4();
3307
+ const strikeoutId = uuidV4();
3308
+ const defaults = getDefaults();
3309
+ getText().then((text) => {
3310
+ var _a;
3311
+ context.createAnnotation(selection.pageIndex, {
3312
+ type: PdfAnnotationSubtype.CARET,
3313
+ id: caretId,
3314
+ pageIndex: selection.pageIndex,
3315
+ rect: caretRect,
3316
+ strokeColor: defaults.strokeColor,
3317
+ opacity: defaults.opacity,
3318
+ intent: "Replace",
3319
+ rectangleDifferences: { left: 0.5, top: 0.5, right: 0.5, bottom: 0.5 },
3320
+ created: /* @__PURE__ */ new Date(),
3321
+ flags: defaults.flags
3322
+ });
3323
+ context.createAnnotation(selection.pageIndex, {
3324
+ type: PdfAnnotationSubtype.STRIKEOUT,
3325
+ id: strikeoutId,
3326
+ pageIndex: selection.pageIndex,
3327
+ rect: selection.rect,
3328
+ segmentRects: selection.segmentRects,
3329
+ strokeColor: defaults.strokeColor,
3330
+ opacity: defaults.opacity,
3331
+ intent: "StrikeOutTextEdit",
3332
+ inReplyToId: caretId,
3333
+ replyType: PdfAnnotationReplyType.Group,
3334
+ created: /* @__PURE__ */ new Date(),
3335
+ flags: defaults.flags,
3336
+ ...text != null && { custom: { text } }
3337
+ });
3338
+ if ((_a = tool.behavior) == null ? void 0 : _a.selectAfterCreate) {
3339
+ context.selectAnnotation(selection.pageIndex, caretId);
3340
+ }
3341
+ });
3342
+ }
3343
+ }
3344
+ };
2456
3345
  const patchInk = (original, ctx) => {
2457
3346
  switch (ctx.type) {
2458
3347
  case "vertex-edit":
@@ -2469,23 +3358,29 @@ const patchInk = (original, ctx) => {
2469
3358
  }
2470
3359
  case "resize": {
2471
3360
  if (!ctx.changes.rect) return ctx.changes;
2472
- const { oldRect, resolvedRect, rects } = baseResizeScaling(
3361
+ const { scaleX, scaleY, oldRect, resolvedRect, rects } = baseResizeScaling(
2473
3362
  original,
2474
3363
  ctx.changes.rect,
2475
3364
  ctx.metadata
2476
3365
  );
2477
- const inset = (r, pad) => ({
2478
- origin: { x: r.origin.x + pad, y: r.origin.y + pad },
3366
+ const inset = (r2, pad) => ({
3367
+ origin: { x: r2.origin.x + pad, y: r2.origin.y + pad },
2479
3368
  size: {
2480
- width: Math.max(1, r.size.width - pad * 2),
2481
- height: Math.max(1, r.size.height - pad * 2)
3369
+ width: Math.max(1, r2.size.width - pad * 2),
3370
+ height: Math.max(1, r2.size.height - pad * 2)
2482
3371
  }
2483
3372
  });
2484
- const strokeScale = Math.min(
2485
- resolvedRect.size.width / oldRect.size.width,
2486
- resolvedRect.size.height / oldRect.size.height
3373
+ const resizeEpsilon = 1e-3;
3374
+ const widthChanged = Math.abs(scaleX - 1) > resizeEpsilon;
3375
+ const heightChanged = Math.abs(scaleY - 1) > resizeEpsilon;
3376
+ const strokeScale = widthChanged && !heightChanged ? scaleX : !widthChanged && heightChanged ? scaleY : Math.min(scaleX, scaleY);
3377
+ const rawStrokeWidth = Math.max(1, original.strokeWidth * strokeScale);
3378
+ const maxStrokeWidth = Math.max(
3379
+ 1,
3380
+ Math.min(resolvedRect.size.width, resolvedRect.size.height)
2487
3381
  );
2488
- const newStrokeWidth = Math.max(1, Math.round(original.strokeWidth * strokeScale));
3382
+ const clampedStrokeWidth = Math.min(rawStrokeWidth, maxStrokeWidth);
3383
+ const newStrokeWidth = Number(clampedStrokeWidth.toFixed(1));
2489
3384
  const innerOld = inset(oldRect, original.strokeWidth / 2);
2490
3385
  const innerNew = inset(resolvedRect, newStrokeWidth / 2);
2491
3386
  const sx = innerNew.size.width / Math.max(innerOld.size.width, 1e-6);
@@ -2695,11 +3590,17 @@ const patchPolyline = (orig, ctx) => {
2695
3590
  return ctx.changes;
2696
3591
  }
2697
3592
  };
3593
+ function getPolygonPad(intensity, strokeWidth) {
3594
+ if ((intensity ?? 0) > 0) {
3595
+ return getCloudyBorderExtent(intensity, strokeWidth, false);
3596
+ }
3597
+ return strokeWidth / 2;
3598
+ }
2698
3599
  const patchPolygon = (orig, ctx) => {
2699
3600
  switch (ctx.type) {
2700
3601
  case "vertex-edit":
2701
3602
  if (ctx.changes.vertices && ctx.changes.vertices.length) {
2702
- const pad = orig.strokeWidth / 2;
3603
+ const pad = getPolygonPad(orig.cloudyBorderIntensity, orig.strokeWidth);
2703
3604
  const rawVertices = ctx.changes.vertices;
2704
3605
  const rawRect = expandRect(rectFromPoints(rawVertices), pad);
2705
3606
  const compensated = compensateRotatedVertexEdit(orig, rawVertices, rawRect);
@@ -2743,15 +3644,30 @@ const patchPolygon = (orig, ctx) => {
2743
3644
  };
2744
3645
  }
2745
3646
  case "property-update": {
2746
- const needsRectUpdate = ctx.changes.strokeWidth !== void 0 || ctx.changes.rotation !== void 0;
3647
+ const cloudyChanged = ctx.changes.cloudyBorderIntensity !== void 0;
3648
+ const needsRectUpdate = ctx.changes.strokeWidth !== void 0 || ctx.changes.rotation !== void 0 || cloudyChanged;
2747
3649
  if (!needsRectUpdate) return ctx.changes;
2748
3650
  const merged = { ...orig, ...ctx.changes };
2749
- const pad = merged.strokeWidth / 2;
3651
+ const pad = getPolygonPad(merged.cloudyBorderIntensity, merged.strokeWidth);
2750
3652
  const tightRect = expandRect(rectFromPoints(merged.vertices), pad);
3653
+ let patch = ctx.changes;
3654
+ const hasCloudy = (orig.cloudyBorderIntensity ?? 0) > 0;
3655
+ if (cloudyChanged || ctx.changes.strokeWidth !== void 0 && hasCloudy) {
3656
+ const intensity = merged.cloudyBorderIntensity ?? 0;
3657
+ if (intensity > 0) {
3658
+ const extent = getCloudyBorderExtent(intensity, merged.strokeWidth, false);
3659
+ patch = {
3660
+ ...patch,
3661
+ rectangleDifferences: { left: extent, top: extent, right: extent, bottom: extent }
3662
+ };
3663
+ } else {
3664
+ patch = { ...patch, rectangleDifferences: void 0 };
3665
+ }
3666
+ }
2751
3667
  const effectiveRotation = ctx.changes.rotation ?? orig.rotation ?? 0;
2752
3668
  if (orig.unrotatedRect || ctx.changes.rotation !== void 0) {
2753
3669
  return {
2754
- ...ctx.changes,
3670
+ ...patch,
2755
3671
  unrotatedRect: tightRect,
2756
3672
  rect: calculateRotatedRectAABBAroundPoint(
2757
3673
  tightRect,
@@ -2760,7 +3676,7 @@ const patchPolygon = (orig, ctx) => {
2760
3676
  )
2761
3677
  };
2762
3678
  }
2763
- return { ...ctx.changes, rect: tightRect };
3679
+ return { ...patch, rect: tightRect };
2764
3680
  }
2765
3681
  default:
2766
3682
  return ctx.changes;
@@ -2776,11 +3692,29 @@ const patchCircle = (orig, ctx) => {
2776
3692
  return baseResizeScaling(orig, ctx.changes.rect, ctx.metadata).rects;
2777
3693
  case "rotate":
2778
3694
  return baseRotateChanges(orig, ctx) ?? ctx.changes;
2779
- case "property-update":
3695
+ case "property-update": {
3696
+ let patch = ctx.changes;
3697
+ const cloudyChanged = ctx.changes.cloudyBorderIntensity !== void 0;
3698
+ const strokeChanged = ctx.changes.strokeWidth !== void 0;
3699
+ const hasCloudy = (orig.cloudyBorderIntensity ?? 0) > 0;
3700
+ if (cloudyChanged || strokeChanged && hasCloudy) {
3701
+ const merged = { ...orig, ...ctx.changes };
3702
+ const intensity = merged.cloudyBorderIntensity ?? 0;
3703
+ if (intensity > 0) {
3704
+ const extent = getCloudyBorderExtent(intensity, merged.strokeWidth, true);
3705
+ patch = {
3706
+ ...patch,
3707
+ rectangleDifferences: { left: extent, top: extent, right: extent, bottom: extent }
3708
+ };
3709
+ } else {
3710
+ patch = { ...patch, rectangleDifferences: void 0 };
3711
+ }
3712
+ }
2780
3713
  if (ctx.changes.rotation !== void 0) {
2781
- return { ...ctx.changes, ...basePropertyRotationChanges(orig, ctx.changes.rotation) };
3714
+ patch = { ...patch, ...basePropertyRotationChanges(orig, ctx.changes.rotation) };
2782
3715
  }
2783
- return ctx.changes;
3716
+ return patch;
3717
+ }
2784
3718
  default:
2785
3719
  return ctx.changes;
2786
3720
  }
@@ -2795,11 +3729,29 @@ const patchSquare = (orig, ctx) => {
2795
3729
  return baseResizeScaling(orig, ctx.changes.rect, ctx.metadata).rects;
2796
3730
  case "rotate":
2797
3731
  return baseRotateChanges(orig, ctx) ?? ctx.changes;
2798
- case "property-update":
3732
+ case "property-update": {
3733
+ let patch = ctx.changes;
3734
+ const cloudyChanged = ctx.changes.cloudyBorderIntensity !== void 0;
3735
+ const strokeChanged = ctx.changes.strokeWidth !== void 0;
3736
+ const hasCloudy = (orig.cloudyBorderIntensity ?? 0) > 0;
3737
+ if (cloudyChanged || strokeChanged && hasCloudy) {
3738
+ const merged = { ...orig, ...ctx.changes };
3739
+ const intensity = merged.cloudyBorderIntensity ?? 0;
3740
+ if (intensity > 0) {
3741
+ const extent = getCloudyBorderExtent(intensity, merged.strokeWidth, false);
3742
+ patch = {
3743
+ ...patch,
3744
+ rectangleDifferences: { left: extent, top: extent, right: extent, bottom: extent }
3745
+ };
3746
+ } else {
3747
+ patch = { ...patch, rectangleDifferences: void 0 };
3748
+ }
3749
+ }
2799
3750
  if (ctx.changes.rotation !== void 0) {
2800
- return { ...ctx.changes, ...basePropertyRotationChanges(orig, ctx.changes.rotation) };
3751
+ patch = { ...patch, ...basePropertyRotationChanges(orig, ctx.changes.rotation) };
2801
3752
  }
2802
- return ctx.changes;
3753
+ return patch;
3754
+ }
2803
3755
  default:
2804
3756
  return ctx.changes;
2805
3757
  }
@@ -2842,34 +3794,6 @@ const patchStamp = (orig, ctx) => {
2842
3794
  return ctx.changes;
2843
3795
  }
2844
3796
  };
2845
- function convertAABBRectToUnrotatedSpace(newAABBRect, originalAABBRect, originalUnrotatedRect, rotationDegrees) {
2846
- const theta = rotationDegrees * Math.PI / 180;
2847
- const A = Math.abs(Math.cos(theta));
2848
- const B = Math.abs(Math.sin(theta));
2849
- const det = A * A - B * B;
2850
- const newAABBw = newAABBRect.size.width;
2851
- const newAABBh = newAABBRect.size.height;
2852
- let newWidth;
2853
- let newHeight;
2854
- if (Math.abs(det) > 1e-6) {
2855
- newWidth = (A * newAABBw - B * newAABBh) / det;
2856
- newHeight = (A * newAABBh - B * newAABBw) / det;
2857
- newWidth = Math.max(newWidth, 1);
2858
- newHeight = Math.max(newHeight, 1);
2859
- } else {
2860
- const origArea = originalAABBRect.size.width * originalAABBRect.size.height;
2861
- const newArea = newAABBw * newAABBh;
2862
- const uniformScale = origArea > 0 ? Math.sqrt(newArea / origArea) : 1;
2863
- newWidth = originalUnrotatedRect.size.width * uniformScale;
2864
- newHeight = originalUnrotatedRect.size.height * uniformScale;
2865
- }
2866
- const newCenterX = newAABBRect.origin.x + newAABBw / 2;
2867
- const newCenterY = newAABBRect.origin.y + newAABBh / 2;
2868
- return {
2869
- origin: { x: newCenterX - newWidth / 2, y: newCenterY - newHeight / 2 },
2870
- size: { width: newWidth, height: newHeight }
2871
- };
2872
- }
2873
3797
  const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
2874
3798
  constructor(id, registry, config) {
2875
3799
  var _a, _b, _c;
@@ -2881,6 +3805,7 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
2881
3805
  this.importQueue = /* @__PURE__ */ new Map();
2882
3806
  this.commitInProgress = /* @__PURE__ */ new Map();
2883
3807
  this.handlerFactories = /* @__PURE__ */ new Map();
3808
+ this.selectionHandlerFactories = /* @__PURE__ */ new Map();
2884
3809
  this.activeTool$ = createBehaviorEmitter();
2885
3810
  this.events$ = createBehaviorEmitter();
2886
3811
  this.toolsChange$ = createBehaviorEmitter();
@@ -2897,6 +3822,7 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
2897
3822
  this.history = ((_b = registry.getPlugin("history")) == null ? void 0 : _b.provides()) ?? null;
2898
3823
  this.interactionManager = ((_c = registry.getPlugin("interaction-manager")) == null ? void 0 : _c.provides()) ?? null;
2899
3824
  this.registerHandlerFactories();
3825
+ this.registerSelectionHandlerFactories();
2900
3826
  this.registerBuiltInPatches();
2901
3827
  }
2902
3828
  // ─────────────────────────────────────────────────────────
@@ -2922,7 +3848,7 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
2922
3848
  for (const tool of this.state.tools) {
2923
3849
  if (tool.interaction.textSelection) {
2924
3850
  this.selection.enableForMode(tool.interaction.mode ?? tool.id, {
2925
- showSelectionRects: false,
3851
+ showSelectionRects: tool.interaction.showSelectionRects ?? false,
2926
3852
  enableSelection: true,
2927
3853
  enableMarquee: false
2928
3854
  });
@@ -2951,6 +3877,11 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
2951
3877
  this.handlerFactories.set(PdfAnnotationSubtype.LINE, lineHandlerFactory);
2952
3878
  this.handlerFactories.set(PdfAnnotationSubtype.INK, inkHandlerFactory);
2953
3879
  this.handlerFactories.set(PdfAnnotationSubtype.FREETEXT, freeTextHandlerFactory);
3880
+ this.handlerFactories.set(PdfAnnotationSubtype.TEXT, textHandlerFactory);
3881
+ }
3882
+ registerSelectionHandlerFactories() {
3883
+ this.selectionHandlerFactories.set("insertText", insertTextSelectionHandler);
3884
+ this.selectionHandlerFactories.set("replaceText", replaceTextSelectionHandler);
2954
3885
  }
2955
3886
  registerBuiltInPatches() {
2956
3887
  this.patchRegistry.register(PdfAnnotationSubtype.INK, patchInk);
@@ -2984,7 +3915,7 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
2984
3915
  if (modeId !== "pointerMode") return;
2985
3916
  const docState = this.state.documents[documentId];
2986
3917
  if (!docState) return;
2987
- const pageAnnotations = (docState.pages[pageIndex] ?? []).map((uid) => docState.byUid[uid]).filter((ta) => ta !== void 0).filter((ta) => !isLink(ta));
3918
+ const pageAnnotations = (docState.pages[pageIndex] ?? []).map((uid) => docState.byUid[uid]).filter((ta) => ta !== void 0).filter((ta) => isSidebarAnnotation(ta));
2988
3919
  const selectedIds = pageAnnotations.filter((ta) => rectsIntersect(rect, ta.object.rect)).map((ta) => ta.object.id);
2989
3920
  if (selectedIds.length > 0) {
2990
3921
  const expandedIds = /* @__PURE__ */ new Set();
@@ -3002,44 +3933,32 @@ const _AnnotationPlugin = class _AnnotationPlugin extends BasePlugin {
3002
3933
  }
3003
3934
  });
3004
3935
  (_c = this.selection) == null ? void 0 : _c.onEndSelection(({ documentId }) => {
3005
- var _a2, _b2, _c2;
3006
- if (!this.checkPermission(documentId, PdfPermissionFlag.ModifyAnnotations)) {
3007
- return;
3008
- }
3936
+ var _a2, _b2, _c2, _d;
3937
+ if (!this.checkPermission(documentId, PdfPermissionFlag.ModifyAnnotations)) return;
3009
3938
  const activeTool = this.getActiveTool(documentId);
3010
3939
  if (!activeTool || !activeTool.interaction.textSelection) return;
3011
3940
  const formattedSelection = (_a2 = this.selection) == null ? void 0 : _a2.getFormattedSelection();
3012
3941
  const selectionText = (_b2 = this.selection) == null ? void 0 : _b2.getSelectedText();
3013
3942
  if (!formattedSelection || !selectionText) return;
3014
- for (const selection of formattedSelection) {
3015
- selectionText.wait((text) => {
3016
- var _a3, _b3;
3017
- const annotationId = uuidV4();
3018
- this.createAnnotation(
3019
- selection.pageIndex,
3020
- {
3021
- ...activeTool.defaults,
3022
- rect: selection.rect,
3023
- segmentRects: selection.segmentRects,
3024
- pageIndex: selection.pageIndex,
3025
- created: /* @__PURE__ */ new Date(),
3026
- id: annotationId,
3027
- custom: {
3028
- text: text.join("\n")
3029
- }
3030
- },
3031
- void 0,
3032
- documentId
3033
- );
3034
- if ((_a3 = activeTool.behavior) == null ? void 0 : _a3.deactivateToolAfterCreate) {
3035
- this.setActiveTool(null, documentId);
3036
- }
3037
- if ((_b3 = activeTool.behavior) == null ? void 0 : _b3.selectAfterCreate) {
3038
- this.selectAnnotation(selection.pageIndex, annotationId, documentId);
3039
- }
3040
- }, ignore);
3943
+ const getText = () => new Promise((resolve) => {
3944
+ selectionText.wait(
3945
+ (text) => resolve(text.join("\n")),
3946
+ () => resolve(void 0)
3947
+ );
3948
+ });
3949
+ const context = {
3950
+ toolId: activeTool.id,
3951
+ documentId,
3952
+ getTool: () => this.getActiveTool(documentId) ?? null,
3953
+ createAnnotation: (pageIndex, annotation) => this.createAnnotation(pageIndex, annotation, void 0, documentId),
3954
+ selectAnnotation: (pageIndex, id) => this.selectAnnotation(pageIndex, id, documentId)
3955
+ };
3956
+ const handler = this.selectionHandlerFactories.get(activeTool.id) ?? textMarkupSelectionHandler;
3957
+ handler.handle(context, formattedSelection, getText);
3958
+ if ((_c2 = activeTool.behavior) == null ? void 0 : _c2.deactivateToolAfterCreate) {
3959
+ this.setActiveTool(null, documentId);
3041
3960
  }
3042
- (_c2 = this.selection) == null ? void 0 : _c2.clear();
3961
+ (_d = this.selection) == null ? void 0 : _d.clear();
3043
3962
  });
3044
3963
  }
3045
3964
  registerInteractionForTool(tool) {
@@ -4867,6 +5786,8 @@ const isPolylineTool = createToolPredicate("polyline");
4867
5786
  const isPolygonTool = createToolPredicate("polygon");
4868
5787
  const isFreeTextTool = createToolPredicate("freeText");
4869
5788
  const isStampTool = createToolPredicate("stamp");
5789
+ const isInsertTextTool = createToolPredicate("insertText");
5790
+ const isReplaceTextTool = createToolPredicate("replaceText");
4870
5791
  const AnnotationPluginPackage = {
4871
5792
  manifest,
4872
5793
  create: (registry, config) => new AnnotationPlugin(ANNOTATION_PLUGIN_ID, registry, config),
@@ -4881,10 +5802,14 @@ export {
4881
5802
  calculateRotatedRectAABBAroundPoint2 as calculateRotatedRectAABBAroundPoint,
4882
5803
  convertAABBRectToUnrotatedSpace,
4883
5804
  createToolPredicate,
5805
+ generateCloudyEllipsePath,
5806
+ generateCloudyPolygonPath,
5807
+ generateCloudyRectanglePath,
4884
5808
  getAnnotationByUid,
4885
5809
  getAnnotations,
4886
5810
  getAnnotationsByPageIndex,
4887
5811
  getAttachedLinks,
5812
+ getCloudyBorderExtent,
4888
5813
  getGroupLeaderId,
4889
5814
  getGroupMembers,
4890
5815
  getIRTChildIds,
@@ -4906,6 +5831,7 @@ export {
4906
5831
  initialDocumentState,
4907
5832
  initialState,
4908
5833
  isAnnotationSelected,
5834
+ isCaret,
4909
5835
  isCircle,
4910
5836
  isCircleTool,
4911
5837
  isFreeText,
@@ -4916,6 +5842,7 @@ export {
4916
5842
  isInk,
4917
5843
  isInkHighlighterTool,
4918
5844
  isInkTool,
5845
+ isInsertTextTool,
4919
5846
  isLine,
4920
5847
  isLineTool,
4921
5848
  isLink,
@@ -4924,6 +5851,7 @@ export {
4924
5851
  isPolyline,
4925
5852
  isPolylineTool,
4926
5853
  isRedact,
5854
+ isReplaceTextTool,
4927
5855
  isSidebarAnnotation,
4928
5856
  isSquare,
4929
5857
  isSquareTool,