@embedpdf/plugin-annotation 2.13.0 → 2.14.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 (40) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +449 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/handlers/callout-free-text.handler.d.ts +3 -0
  6. package/dist/lib/handlers/index.d.ts +1 -0
  7. package/dist/lib/handlers/types.d.ts +7 -1
  8. package/dist/lib/patching/patch-utils.d.ts +38 -1
  9. package/dist/lib/patching/patches/callout-freetext.patch.d.ts +3 -0
  10. package/dist/lib/patching/patches/index.d.ts +1 -0
  11. package/dist/lib/tools/default-tools.d.ts +35 -0
  12. package/dist/preact/index.cjs +1 -1
  13. package/dist/preact/index.cjs.map +1 -1
  14. package/dist/preact/index.js +395 -14
  15. package/dist/preact/index.js.map +1 -1
  16. package/dist/react/index.cjs +1 -1
  17. package/dist/react/index.cjs.map +1 -1
  18. package/dist/react/index.js +395 -14
  19. package/dist/react/index.js.map +1 -1
  20. package/dist/shared/components/annotations/callout-free-text-preview.d.ts +15 -0
  21. package/dist/shared/components/annotations/callout-free-text.d.ts +15 -0
  22. package/dist/shared-preact/components/annotations/callout-free-text-preview.d.ts +15 -0
  23. package/dist/shared-preact/components/annotations/callout-free-text.d.ts +15 -0
  24. package/dist/shared-react/components/annotations/callout-free-text-preview.d.ts +15 -0
  25. package/dist/shared-react/components/annotations/callout-free-text.d.ts +15 -0
  26. package/dist/svelte/components/annotations/CalloutFreeText.svelte.d.ts +15 -0
  27. package/dist/svelte/components/annotations/CalloutFreeTextPreview.svelte.d.ts +10 -0
  28. package/dist/svelte/components/renderers/CalloutFreeTextRenderer.svelte.d.ts +5 -0
  29. package/dist/svelte/index.cjs +1 -1
  30. package/dist/svelte/index.cjs.map +1 -1
  31. package/dist/svelte/index.js +497 -86
  32. package/dist/svelte/index.js.map +1 -1
  33. package/dist/vue/components/annotations/callout-free-text-preview.vue.d.ts +10 -0
  34. package/dist/vue/components/annotations/callout-free-text.vue.d.ts +25 -0
  35. package/dist/vue/components/renderers/callout-free-text-renderer.vue.d.ts +6 -0
  36. package/dist/vue/index.cjs +1 -1
  37. package/dist/vue/index.cjs.map +1 -1
  38. package/dist/vue/index.js +544 -170
  39. package/dist/vue/index.js.map +1 -1
  40. package/package.json +12 -12
package/dist/index.js CHANGED
@@ -737,6 +737,109 @@ function compensateRotatedVertexEdit(original, vertices, tightRect) {
737
737
  if (Math.abs(qx) < 1e-8 && Math.abs(qy) < 1e-8) return vertices;
738
738
  return vertices.map((v) => ({ x: v.x + qx, y: v.y + qy }));
739
739
  }
740
+ function computeTextBoxFromRD(rect, rd) {
741
+ if (!rd) return rect;
742
+ return {
743
+ origin: { x: rect.origin.x + rd.left, y: rect.origin.y + rd.top },
744
+ size: {
745
+ width: Math.max(0, rect.size.width - rd.left - rd.right),
746
+ height: Math.max(0, rect.size.height - rd.top - rd.bottom)
747
+ }
748
+ };
749
+ }
750
+ function computeRDFromTextBox(overallRect, textBox) {
751
+ return {
752
+ left: textBox.origin.x - overallRect.origin.x,
753
+ top: textBox.origin.y - overallRect.origin.y,
754
+ right: overallRect.origin.x + overallRect.size.width - (textBox.origin.x + textBox.size.width),
755
+ bottom: overallRect.origin.y + overallRect.size.height - (textBox.origin.y + textBox.size.height)
756
+ };
757
+ }
758
+ function computeCalloutConnectionPoint(knee, textBox) {
759
+ const cx = textBox.origin.x + textBox.size.width / 2;
760
+ const cy = textBox.origin.y + textBox.size.height / 2;
761
+ const dx = knee.x - cx;
762
+ const dy = knee.y - cy;
763
+ if (Math.abs(dx) >= Math.abs(dy)) {
764
+ return dx > 0 ? { x: textBox.origin.x + textBox.size.width, y: cy } : { x: textBox.origin.x, y: cy };
765
+ }
766
+ return dy > 0 ? { x: cx, y: textBox.origin.y + textBox.size.height } : { x: cx, y: textBox.origin.y };
767
+ }
768
+ function computeCalloutOverallRect(textBox, calloutLine, lineEnding, strokeWidth) {
769
+ const linePoints = [...calloutLine];
770
+ if (lineEnding && calloutLine.length >= 2) {
771
+ const handler = LINE_ENDING_HANDLERS[lineEnding];
772
+ if (handler) {
773
+ const angle = Math.atan2(
774
+ calloutLine[1].y - calloutLine[0].y,
775
+ calloutLine[1].x - calloutLine[0].x
776
+ );
777
+ const localPts = handler.getLocalPoints(strokeWidth);
778
+ const rotationAngle = handler.getRotation(angle + Math.PI);
779
+ const transformed = localPts.map(
780
+ (p) => rotateAndTranslatePoint(p, rotationAngle, calloutLine[0])
781
+ );
782
+ linePoints.push(...transformed);
783
+ }
784
+ }
785
+ const lineBbox = expandRect(rectFromPoints(linePoints), strokeWidth);
786
+ const tbRight = textBox.origin.x + textBox.size.width;
787
+ const tbBottom = textBox.origin.y + textBox.size.height;
788
+ const lnRight = lineBbox.origin.x + lineBbox.size.width;
789
+ const lnBottom = lineBbox.origin.y + lineBbox.size.height;
790
+ const minX = Math.min(textBox.origin.x, lineBbox.origin.x);
791
+ const minY = Math.min(textBox.origin.y, lineBbox.origin.y);
792
+ const maxX = Math.max(tbRight, lnRight);
793
+ const maxY = Math.max(tbBottom, lnBottom);
794
+ return {
795
+ origin: { x: minX, y: minY },
796
+ size: { width: maxX - minX, height: maxY - minY }
797
+ };
798
+ }
799
+ const calloutVertexConfig = {
800
+ extractVertices: (a) => {
801
+ const textBox = computeTextBoxFromRD(a.rect, a.rectangleDifferences);
802
+ const cl = a.calloutLine;
803
+ if (!cl || cl.length < 3) {
804
+ return [
805
+ { x: a.rect.origin.x, y: a.rect.origin.y },
806
+ { x: a.rect.origin.x, y: a.rect.origin.y },
807
+ { x: textBox.origin.x, y: textBox.origin.y },
808
+ { x: textBox.origin.x + textBox.size.width, y: textBox.origin.y + textBox.size.height }
809
+ ];
810
+ }
811
+ return [
812
+ cl[0],
813
+ cl[1],
814
+ { x: textBox.origin.x, y: textBox.origin.y },
815
+ { x: textBox.origin.x + textBox.size.width, y: textBox.origin.y + textBox.size.height }
816
+ ];
817
+ },
818
+ transformAnnotation: (a, vertices) => {
819
+ if (vertices.length < 4) return {};
820
+ const [arrowTip, knee, tbTL, tbBR] = vertices;
821
+ const textBox = {
822
+ origin: { x: Math.min(tbTL.x, tbBR.x), y: Math.min(tbTL.y, tbBR.y) },
823
+ size: {
824
+ width: Math.abs(tbBR.x - tbTL.x),
825
+ height: Math.abs(tbBR.y - tbTL.y)
826
+ }
827
+ };
828
+ const connectionPoint = computeCalloutConnectionPoint(knee, textBox);
829
+ const calloutLine = [arrowTip, knee, connectionPoint];
830
+ const overallRect = computeCalloutOverallRect(
831
+ textBox,
832
+ calloutLine,
833
+ a.lineEnding,
834
+ a.strokeWidth ?? 1
835
+ );
836
+ return {
837
+ calloutLine,
838
+ rect: overallRect,
839
+ rectangleDifferences: computeRDFromTextBox(overallRect, textBox)
840
+ };
841
+ }
842
+ };
740
843
  function createEnding(ending, strokeWidth, rad, px, py) {
741
844
  if (!ending) return null;
742
845
  const handler = LINE_ENDING_HANDLERS[ending];
@@ -1874,6 +1977,80 @@ const patchFreeText = (orig, ctx) => {
1874
1977
  return ctx.changes;
1875
1978
  }
1876
1979
  };
1980
+ function rebuildFromVertices(orig, arrowTip, knee, tbTL, tbBR) {
1981
+ const textBox = {
1982
+ origin: { x: Math.min(tbTL.x, tbBR.x), y: Math.min(tbTL.y, tbBR.y) },
1983
+ size: {
1984
+ width: Math.abs(tbBR.x - tbTL.x),
1985
+ height: Math.abs(tbBR.y - tbTL.y)
1986
+ }
1987
+ };
1988
+ const connectionPoint = computeCalloutConnectionPoint(knee, textBox);
1989
+ const calloutLine = [arrowTip, knee, connectionPoint];
1990
+ const overallRect = computeCalloutOverallRect(
1991
+ textBox,
1992
+ calloutLine,
1993
+ orig.lineEnding,
1994
+ orig.strokeWidth ?? 1
1995
+ );
1996
+ return {
1997
+ calloutLine,
1998
+ rect: overallRect,
1999
+ rectangleDifferences: computeRDFromTextBox(overallRect, textBox)
2000
+ };
2001
+ }
2002
+ const patchCalloutFreeText = (orig, ctx) => {
2003
+ var _a, _b;
2004
+ switch (ctx.type) {
2005
+ case "vertex-edit": {
2006
+ if (!ctx.changes.calloutLine) return ctx.changes;
2007
+ const verts = ctx.changes.calloutLine;
2008
+ if (verts.length < 4) return ctx.changes;
2009
+ return rebuildFromVertices(orig, verts[0], verts[1], verts[2], verts[3]);
2010
+ }
2011
+ case "move": {
2012
+ if (!ctx.changes.rect) return ctx.changes;
2013
+ const { dx, dy, rects } = baseMoveChanges(orig, ctx.changes.rect);
2014
+ const movedLine = (_a = orig.calloutLine) == null ? void 0 : _a.map((p) => ({ x: p.x + dx, y: p.y + dy }));
2015
+ return {
2016
+ ...rects,
2017
+ ...movedLine && { calloutLine: movedLine }
2018
+ };
2019
+ }
2020
+ case "rotate": {
2021
+ const result = baseRotateChanges(orig, ctx);
2022
+ if (!result) return ctx.changes;
2023
+ const { dx, dy } = rotateOrbitDelta(orig, result);
2024
+ const movedLine = (_b = orig.calloutLine) == null ? void 0 : _b.map((p) => ({ x: p.x + dx, y: p.y + dy }));
2025
+ return {
2026
+ ...result,
2027
+ ...movedLine && { calloutLine: movedLine }
2028
+ };
2029
+ }
2030
+ case "property-update": {
2031
+ if (ctx.changes.lineEnding !== void 0 || ctx.changes.strokeWidth !== void 0) {
2032
+ const merged = { ...orig, ...ctx.changes };
2033
+ if (merged.calloutLine && merged.calloutLine.length >= 3) {
2034
+ const textBox = computeTextBoxFromRD(orig.rect, orig.rectangleDifferences);
2035
+ const overallRect = computeCalloutOverallRect(
2036
+ textBox,
2037
+ merged.calloutLine,
2038
+ merged.lineEnding,
2039
+ merged.strokeWidth ?? 1
2040
+ );
2041
+ return {
2042
+ ...ctx.changes,
2043
+ rect: overallRect,
2044
+ rectangleDifferences: computeRDFromTextBox(overallRect, textBox)
2045
+ };
2046
+ }
2047
+ }
2048
+ return ctx.changes;
2049
+ }
2050
+ default:
2051
+ return ctx.changes;
2052
+ }
2053
+ };
1877
2054
  const patchStamp = (orig, ctx) => {
1878
2055
  switch (ctx.type) {
1879
2056
  case "move":
@@ -1901,11 +2078,17 @@ const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.definePropert
1901
2078
  calculateAABBFromVertices,
1902
2079
  calculateRotatedRectAABB,
1903
2080
  calculateRotatedRectAABBAroundPoint,
2081
+ calloutVertexConfig,
1904
2082
  clampAnnotationToPage,
1905
2083
  compensateRotatedVertexEdit,
2084
+ computeCalloutConnectionPoint,
2085
+ computeCalloutOverallRect,
2086
+ computeRDFromTextBox,
2087
+ computeTextBoxFromRD,
1906
2088
  createEnding,
1907
2089
  getRectCenter,
1908
2090
  lineRectWithEndings,
2091
+ patchCalloutFreeText,
1909
2092
  patchCircle,
1910
2093
  patchFreeText,
1911
2094
  patchInk,
@@ -2138,6 +2321,232 @@ const freeTextHandlerFactory = {
2138
2321
  };
2139
2322
  }
2140
2323
  };
2324
+ const CLICK_THRESHOLD = 5;
2325
+ const DEFAULT_TB_WIDTH = 150;
2326
+ const DEFAULT_TB_HEIGHT = 40;
2327
+ const calloutFreeTextHandlerFactory = {
2328
+ annotationType: PdfAnnotationSubtype.FREETEXT,
2329
+ create(context) {
2330
+ const { onCommit, onPreview, getTool, pageSize, pageIndex } = context;
2331
+ const [getPhase, setPhase] = useState("arrow");
2332
+ const [getArrowTip, setArrowTip] = useState(null);
2333
+ const [getKnee, setKnee] = useState(null);
2334
+ const [getDownPos, setDownPos] = useState(null);
2335
+ const [getTextBoxStart, setTextBoxStart] = useState(null);
2336
+ const [getDragging, setDragging] = useState(false);
2337
+ const clampToPage = (pos) => ({
2338
+ x: clamp(pos.x, 0, pageSize.width),
2339
+ y: clamp(pos.y, 0, pageSize.height)
2340
+ });
2341
+ const clampTextBox = (tb) => ({
2342
+ origin: {
2343
+ x: clamp(tb.origin.x, 0, pageSize.width - tb.size.width),
2344
+ y: clamp(tb.origin.y, 0, pageSize.height - tb.size.height)
2345
+ },
2346
+ size: tb.size
2347
+ });
2348
+ const getDefaults = () => {
2349
+ const tool = getTool();
2350
+ if (!tool) return null;
2351
+ return {
2352
+ ...tool.defaults,
2353
+ fontColor: tool.defaults.fontColor ?? "#000000",
2354
+ opacity: tool.defaults.opacity ?? 1,
2355
+ fontSize: tool.defaults.fontSize ?? 12,
2356
+ fontFamily: tool.defaults.fontFamily ?? PdfStandardFont.Helvetica,
2357
+ color: tool.defaults.color ?? tool.defaults.backgroundColor ?? "transparent",
2358
+ textAlign: tool.defaults.textAlign ?? PdfTextAlignment.Left,
2359
+ verticalAlign: tool.defaults.verticalAlign ?? PdfVerticalAlignment.Top,
2360
+ contents: tool.defaults.contents ?? "Insert text",
2361
+ flags: tool.defaults.flags ?? ["print"],
2362
+ lineEnding: tool.defaults.lineEnding ?? PdfAnnotationLineEnding.OpenArrow,
2363
+ strokeColor: tool.defaults.strokeColor ?? "#000000",
2364
+ strokeWidth: tool.defaults.strokeWidth ?? 1
2365
+ };
2366
+ };
2367
+ const isClick = (a, b) => Math.abs(a.x - b.x) < CLICK_THRESHOLD && Math.abs(a.y - b.y) < CLICK_THRESHOLD;
2368
+ const buildPreview = (cursor) => {
2369
+ const defaults = getDefaults();
2370
+ if (!defaults) return null;
2371
+ const arrowTip = getArrowTip();
2372
+ const knee = getKnee();
2373
+ const phase = getPhase();
2374
+ if (phase === "knee" && arrowTip) {
2375
+ const calloutLine = [arrowTip, cursor];
2376
+ const minX = Math.min(arrowTip.x, cursor.x);
2377
+ const minY = Math.min(arrowTip.y, cursor.y);
2378
+ const w = Math.abs(arrowTip.x - cursor.x);
2379
+ const h = Math.abs(arrowTip.y - cursor.y);
2380
+ const bounds = {
2381
+ origin: { x: minX, y: minY },
2382
+ size: { width: Math.max(w, 1), height: Math.max(h, 1) }
2383
+ };
2384
+ return {
2385
+ type: PdfAnnotationSubtype.FREETEXT,
2386
+ bounds,
2387
+ data: {
2388
+ ...defaults,
2389
+ rect: bounds,
2390
+ calloutLine
2391
+ }
2392
+ };
2393
+ }
2394
+ if (phase === "textbox" && arrowTip && knee) {
2395
+ const tbStart = getTextBoxStart();
2396
+ let textBox;
2397
+ if (getDragging() && tbStart) {
2398
+ textBox = {
2399
+ origin: { x: Math.min(tbStart.x, cursor.x), y: Math.min(tbStart.y, cursor.y) },
2400
+ size: {
2401
+ width: Math.max(Math.abs(cursor.x - tbStart.x), 20),
2402
+ height: Math.max(Math.abs(cursor.y - tbStart.y), 14)
2403
+ }
2404
+ };
2405
+ } else {
2406
+ textBox = {
2407
+ origin: { x: cursor.x - DEFAULT_TB_WIDTH / 2, y: cursor.y - DEFAULT_TB_HEIGHT / 2 },
2408
+ size: { width: DEFAULT_TB_WIDTH, height: DEFAULT_TB_HEIGHT }
2409
+ };
2410
+ }
2411
+ textBox = clampTextBox(textBox);
2412
+ const connectionPoint = computeCalloutConnectionPoint(knee, textBox);
2413
+ const calloutLine = [arrowTip, knee, connectionPoint];
2414
+ const overallRect = computeCalloutOverallRect(
2415
+ textBox,
2416
+ calloutLine,
2417
+ defaults.lineEnding,
2418
+ defaults.strokeWidth
2419
+ );
2420
+ return {
2421
+ type: PdfAnnotationSubtype.FREETEXT,
2422
+ bounds: overallRect,
2423
+ data: {
2424
+ ...defaults,
2425
+ rect: overallRect,
2426
+ calloutLine,
2427
+ textBox
2428
+ }
2429
+ };
2430
+ }
2431
+ return null;
2432
+ };
2433
+ const commitCallout = (tb) => {
2434
+ const defaults = getDefaults();
2435
+ const arrowTip = getArrowTip();
2436
+ const knee = getKnee();
2437
+ if (!defaults || !arrowTip || !knee) return;
2438
+ const textBox = clampTextBox(tb);
2439
+ const connectionPoint = computeCalloutConnectionPoint(knee, textBox);
2440
+ const calloutLine = [arrowTip, knee, connectionPoint];
2441
+ const overallRect = computeCalloutOverallRect(
2442
+ textBox,
2443
+ calloutLine,
2444
+ defaults.lineEnding,
2445
+ defaults.strokeWidth
2446
+ );
2447
+ const rd = computeRDFromTextBox(overallRect, textBox);
2448
+ const anno = {
2449
+ ...defaults,
2450
+ type: PdfAnnotationSubtype.FREETEXT,
2451
+ intent: "FreeTextCallout",
2452
+ rect: overallRect,
2453
+ rectangleDifferences: rd,
2454
+ calloutLine,
2455
+ pageIndex,
2456
+ id: uuidV4(),
2457
+ created: /* @__PURE__ */ new Date()
2458
+ };
2459
+ onCommit(anno);
2460
+ resetState();
2461
+ };
2462
+ const resetState = () => {
2463
+ setPhase("arrow");
2464
+ setArrowTip(null);
2465
+ setKnee(null);
2466
+ setDownPos(null);
2467
+ setTextBoxStart(null);
2468
+ setDragging(false);
2469
+ onPreview(null);
2470
+ };
2471
+ return {
2472
+ onPointerDown: (pos, evt) => {
2473
+ var _a, _b;
2474
+ const clampedPos = clampToPage(pos);
2475
+ const phase = getPhase();
2476
+ if (phase === "arrow" || phase === "knee") {
2477
+ setDownPos(clampedPos);
2478
+ (_a = evt.setPointerCapture) == null ? void 0 : _a.call(evt);
2479
+ } else if (phase === "textbox") {
2480
+ setTextBoxStart(clampedPos);
2481
+ setDragging(true);
2482
+ (_b = evt.setPointerCapture) == null ? void 0 : _b.call(evt);
2483
+ }
2484
+ },
2485
+ onPointerMove: (pos) => {
2486
+ const clampedPos = clampToPage(pos);
2487
+ const phase = getPhase();
2488
+ if (phase === "textbox" && getDragging()) {
2489
+ onPreview(buildPreview(clampedPos));
2490
+ } else if (phase === "knee" || phase === "textbox") {
2491
+ onPreview(buildPreview(clampedPos));
2492
+ }
2493
+ },
2494
+ onPointerUp: (pos, evt) => {
2495
+ var _a, _b, _c, _d;
2496
+ const clampedPos = clampToPage(pos);
2497
+ const phase = getPhase();
2498
+ const downPos = getDownPos();
2499
+ if (phase === "arrow" && downPos && isClick(downPos, clampedPos)) {
2500
+ setArrowTip(clampedPos);
2501
+ setPhase("knee");
2502
+ setDownPos(null);
2503
+ (_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
2504
+ return;
2505
+ }
2506
+ if (phase === "knee" && downPos && isClick(downPos, clampedPos)) {
2507
+ setKnee(clampedPos);
2508
+ setPhase("textbox");
2509
+ setDownPos(null);
2510
+ (_b = evt.releasePointerCapture) == null ? void 0 : _b.call(evt);
2511
+ return;
2512
+ }
2513
+ if (phase === "textbox" && getDragging()) {
2514
+ const tbStart = getTextBoxStart();
2515
+ if (tbStart) {
2516
+ const minX = Math.min(tbStart.x, clampedPos.x);
2517
+ const minY = Math.min(tbStart.y, clampedPos.y);
2518
+ const w = Math.abs(clampedPos.x - tbStart.x);
2519
+ const h = Math.abs(clampedPos.y - tbStart.y);
2520
+ if (w > 5 || h > 5) {
2521
+ const textBox = {
2522
+ origin: { x: minX, y: minY },
2523
+ size: { width: Math.max(w, 20), height: Math.max(h, 14) }
2524
+ };
2525
+ commitCallout(textBox);
2526
+ } else {
2527
+ commitCallout({
2528
+ origin: {
2529
+ x: tbStart.x - DEFAULT_TB_WIDTH / 2,
2530
+ y: tbStart.y - DEFAULT_TB_HEIGHT / 2
2531
+ },
2532
+ size: { width: DEFAULT_TB_WIDTH, height: DEFAULT_TB_HEIGHT }
2533
+ });
2534
+ }
2535
+ }
2536
+ (_c = evt.releasePointerCapture) == null ? void 0 : _c.call(evt);
2537
+ return;
2538
+ }
2539
+ setDownPos(null);
2540
+ (_d = evt.releasePointerCapture) == null ? void 0 : _d.call(evt);
2541
+ },
2542
+ onPointerCancel: (_, evt) => {
2543
+ var _a;
2544
+ resetState();
2545
+ (_a = evt.releasePointerCapture) == null ? void 0 : _a.call(evt);
2546
+ }
2547
+ };
2548
+ }
2549
+ };
2141
2550
  const lineHandlerFactory = {
2142
2551
  annotationType: PdfAnnotationSubtype.LINE,
2143
2552
  create(context) {
@@ -3665,7 +4074,7 @@ const freeTextTools = [
3665
4074
  name: "Free Text",
3666
4075
  labelKey: "annotation.freeText",
3667
4076
  categories: ["annotation", "markup"],
3668
- matchScore: (a) => a.type === PdfAnnotationSubtype.FREETEXT ? 1 : 0,
4077
+ matchScore: (a) => a.type === PdfAnnotationSubtype.FREETEXT && a.intent !== "FreeTextCallout" ? 1 : 0,
3669
4078
  interaction: {
3670
4079
  exclusive: false,
3671
4080
  cursor: "crosshair",
@@ -3705,6 +4114,44 @@ const freeTextTools = [
3705
4114
  pointerHandler: freeTextHandlerFactory
3706
4115
  }
3707
4116
  ];
4117
+ const calloutFreeTextTools = [
4118
+ {
4119
+ id: "freeTextCallout",
4120
+ name: "Callout",
4121
+ labelKey: "annotation.callout",
4122
+ categories: ["annotation", "markup"],
4123
+ matchScore: (a) => a.type === PdfAnnotationSubtype.FREETEXT && a.intent === "FreeTextCallout" ? 10 : 0,
4124
+ interaction: {
4125
+ exclusive: false,
4126
+ cursor: "crosshair",
4127
+ isDraggable: true,
4128
+ isResizable: false,
4129
+ isRotatable: false
4130
+ },
4131
+ defaults: {
4132
+ type: PdfAnnotationSubtype.FREETEXT,
4133
+ intent: "FreeTextCallout",
4134
+ contents: "Insert text",
4135
+ fontSize: 14,
4136
+ fontColor: "#E44234",
4137
+ fontFamily: PdfStandardFont.Helvetica,
4138
+ textAlign: PdfTextAlignment.Left,
4139
+ verticalAlign: PdfVerticalAlignment.Top,
4140
+ color: "transparent",
4141
+ opacity: 1,
4142
+ lineEnding: PdfAnnotationLineEnding.OpenArrow,
4143
+ strokeColor: "#E44234",
4144
+ strokeWidth: 1
4145
+ },
4146
+ behavior: {
4147
+ insertUpright: true,
4148
+ editAfterCreate: true,
4149
+ selectAfterCreate: true
4150
+ },
4151
+ transform: patchCalloutFreeText,
4152
+ pointerHandler: calloutFreeTextHandlerFactory
4153
+ }
4154
+ ];
3708
4155
  const stampTools = [
3709
4156
  {
3710
4157
  id: "stamp",
@@ -3771,6 +4218,7 @@ const defaultTools = [
3771
4218
  ...polygonTools,
3772
4219
  ...textCommentTools,
3773
4220
  ...freeTextTools,
4221
+ ...calloutFreeTextTools,
3774
4222
  ...stampTools,
3775
4223
  ...linkTools
3776
4224
  ];