@embedpdf/plugin-annotation 2.13.0 → 2.14.1

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 (53) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.cjs.map +1 -1
  3. package/dist/index.js +522 -7
  4. package/dist/index.js.map +1 -1
  5. package/dist/lib/annotation-plugin.d.ts +25 -0
  6. package/dist/lib/handlers/callout-free-text.handler.d.ts +3 -0
  7. package/dist/lib/handlers/index.d.ts +1 -0
  8. package/dist/lib/handlers/types.d.ts +7 -1
  9. package/dist/lib/helpers.d.ts +8 -0
  10. package/dist/lib/patching/patch-utils.d.ts +38 -1
  11. package/dist/lib/patching/patches/callout-freetext.patch.d.ts +3 -0
  12. package/dist/lib/patching/patches/index.d.ts +1 -0
  13. package/dist/lib/tools/default-tools.d.ts +35 -0
  14. package/dist/lib/types.d.ts +21 -2
  15. package/dist/preact/index.cjs +1 -1
  16. package/dist/preact/index.cjs.map +1 -1
  17. package/dist/preact/index.js +422 -32
  18. package/dist/preact/index.js.map +1 -1
  19. package/dist/react/index.cjs +1 -1
  20. package/dist/react/index.cjs.map +1 -1
  21. package/dist/react/index.js +422 -32
  22. package/dist/react/index.js.map +1 -1
  23. package/dist/shared/components/annotation-container.d.ts +13 -1
  24. package/dist/shared/components/annotations/callout-free-text-preview.d.ts +15 -0
  25. package/dist/shared/components/annotations/callout-free-text.d.ts +15 -0
  26. package/dist/shared/components/types.d.ts +12 -0
  27. package/dist/shared-preact/components/annotation-container.d.ts +13 -1
  28. package/dist/shared-preact/components/annotations/callout-free-text-preview.d.ts +15 -0
  29. package/dist/shared-preact/components/annotations/callout-free-text.d.ts +15 -0
  30. package/dist/shared-preact/components/types.d.ts +12 -0
  31. package/dist/shared-react/components/annotation-container.d.ts +13 -1
  32. package/dist/shared-react/components/annotations/callout-free-text-preview.d.ts +15 -0
  33. package/dist/shared-react/components/annotations/callout-free-text.d.ts +15 -0
  34. package/dist/shared-react/components/types.d.ts +12 -0
  35. package/dist/svelte/components/annotations/CalloutFreeText.svelte.d.ts +15 -0
  36. package/dist/svelte/components/annotations/CalloutFreeTextPreview.svelte.d.ts +10 -0
  37. package/dist/svelte/components/renderers/CalloutFreeTextRenderer.svelte.d.ts +5 -0
  38. package/dist/svelte/components/types.d.ts +12 -0
  39. package/dist/svelte/index.cjs +1 -1
  40. package/dist/svelte/index.cjs.map +1 -1
  41. package/dist/svelte/index.js +528 -106
  42. package/dist/svelte/index.js.map +1 -1
  43. package/dist/svelte/types.d.ts +12 -0
  44. package/dist/vue/components/annotation-container.vue.d.ts +12 -0
  45. package/dist/vue/components/annotations/callout-free-text-preview.vue.d.ts +10 -0
  46. package/dist/vue/components/annotations/callout-free-text.vue.d.ts +25 -0
  47. package/dist/vue/components/renderers/callout-free-text-renderer.vue.d.ts +6 -0
  48. package/dist/vue/index.cjs +1 -1
  49. package/dist/vue/index.cjs.map +1 -1
  50. package/dist/vue/index.js +601 -211
  51. package/dist/vue/index.js.map +1 -1
  52. package/dist/vue/types.d.ts +12 -0
  53. package/package.json +12 -12
@@ -1,5 +1,5 @@
1
1
  import { createPluginPackage } from "@embedpdf/core";
2
- import { AnnotationPlugin, initialDocumentState, generateCloudyRectanglePath, generateCloudyEllipsePath, patching, generateCloudyPolygonPath, LockModeType, getAnnotationsByPageIndex, getSelectedAnnotationIds, resolveInteractionProp, getAnnotationCategories, hasLockedFlag, isCategoryLocked, AnnotationPluginPackage as AnnotationPluginPackage$1 } from "@embedpdf/plugin-annotation";
2
+ import { AnnotationPlugin, initialDocumentState, generateCloudyRectanglePath, generateCloudyEllipsePath, patching, generateCloudyPolygonPath, LockModeType, getAnnotationsByPageIndex, getSelectedAnnotationIds, resolveInteractionProp, hasNoViewFlag, hasHiddenFlag, AnnotationPluginPackage as AnnotationPluginPackage$1 } from "@embedpdf/plugin-annotation";
3
3
  export * from "@embedpdf/plugin-annotation";
4
4
  import { jsx, jsxs, Fragment } from "preact/jsx-runtime";
5
5
  import { createContext, Fragment as Fragment$1 } from "preact";
@@ -161,6 +161,8 @@ function AnnotationContainer({
161
161
  blendMode,
162
162
  vertexConfig,
163
163
  selectionMenu,
164
+ structurallyLocked = false,
165
+ contentLocked = false,
164
166
  outlineOffset = 1,
165
167
  onDoubleClick,
166
168
  onSelect,
@@ -681,7 +683,9 @@ function AnnotationContainer({
681
683
  context: {
682
684
  type: "annotation",
683
685
  annotation: trackedAnnotation,
684
- pageIndex
686
+ pageIndex,
687
+ structurallyLocked,
688
+ contentLocked
685
689
  },
686
690
  selected: isSelected,
687
691
  placement: {
@@ -1275,7 +1279,7 @@ function createRenderer(entry) {
1275
1279
  renderLocked: entry.renderLocked ? (props) => entry.renderLocked(props) : void 0
1276
1280
  };
1277
1281
  }
1278
- const MIN_HIT_AREA_SCREEN_PX$5 = 20;
1282
+ const MIN_HIT_AREA_SCREEN_PX$6 = 20;
1279
1283
  function Ink({
1280
1284
  isSelected,
1281
1285
  strokeColor,
@@ -1301,7 +1305,7 @@ function Ink({
1301
1305
  }, [inkList, rect]);
1302
1306
  const width = rect.size.width * scale;
1303
1307
  const height = rect.size.height * scale;
1304
- const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$5 / scale);
1308
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$6 / scale);
1305
1309
  return /* @__PURE__ */ jsxs(
1306
1310
  "svg",
1307
1311
  {
@@ -1354,7 +1358,7 @@ function Ink({
1354
1358
  }
1355
1359
  );
1356
1360
  }
1357
- const MIN_HIT_AREA_SCREEN_PX$4 = 20;
1361
+ const MIN_HIT_AREA_SCREEN_PX$5 = 20;
1358
1362
  function Square({
1359
1363
  isSelected,
1360
1364
  color = "#000000",
@@ -1394,7 +1398,7 @@ function Square({
1394
1398
  }, [isCloudy, rect, rectangleDifferences, cloudyBorderIntensity, strokeWidth]);
1395
1399
  const svgWidth = rect.size.width * scale;
1396
1400
  const svgHeight = rect.size.height * scale;
1397
- const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$4 / scale);
1401
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$5 / scale);
1398
1402
  return /* @__PURE__ */ jsxs(
1399
1403
  "svg",
1400
1404
  {
@@ -1476,7 +1480,7 @@ function Square({
1476
1480
  }
1477
1481
  );
1478
1482
  }
1479
- const MIN_HIT_AREA_SCREEN_PX$3 = 20;
1483
+ const MIN_HIT_AREA_SCREEN_PX$4 = 20;
1480
1484
  function Circle({
1481
1485
  color = "#000000",
1482
1486
  strokeColor,
@@ -1518,7 +1522,7 @@ function Circle({
1518
1522
  }, [isCloudy, rect, rectangleDifferences, cloudyBorderIntensity, strokeWidth]);
1519
1523
  const svgWidth = width * scale;
1520
1524
  const svgHeight = height * scale;
1521
- const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$3 / scale);
1525
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$4 / scale);
1522
1526
  return /* @__PURE__ */ jsxs(
1523
1527
  "svg",
1524
1528
  {
@@ -1600,7 +1604,7 @@ function Circle({
1600
1604
  }
1601
1605
  );
1602
1606
  }
1603
- const MIN_HIT_AREA_SCREEN_PX$2 = 20;
1607
+ const MIN_HIT_AREA_SCREEN_PX$3 = 20;
1604
1608
  function Line({
1605
1609
  color = "transparent",
1606
1610
  opacity = 1,
@@ -1633,7 +1637,7 @@ function Line({
1633
1637
  }, [lineEndings, strokeWidth, x1, y1, x2, y2]);
1634
1638
  const width = rect.size.width * scale;
1635
1639
  const height = rect.size.height * scale;
1636
- const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$2 / scale);
1640
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$3 / scale);
1637
1641
  return /* @__PURE__ */ jsxs(
1638
1642
  "svg",
1639
1643
  {
@@ -1757,7 +1761,7 @@ function Line({
1757
1761
  }
1758
1762
  );
1759
1763
  }
1760
- const MIN_HIT_AREA_SCREEN_PX$1 = 20;
1764
+ const MIN_HIT_AREA_SCREEN_PX$2 = 20;
1761
1765
  function Polyline({
1762
1766
  rect,
1763
1767
  vertices,
@@ -1805,7 +1809,7 @@ function Polyline({
1805
1809
  }, [localPts, lineEndings, strokeWidth]);
1806
1810
  const width = rect.size.width * scale;
1807
1811
  const height = rect.size.height * scale;
1808
- const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$1 / scale);
1812
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$2 / scale);
1809
1813
  return /* @__PURE__ */ jsxs(
1810
1814
  "svg",
1811
1815
  {
@@ -1927,7 +1931,7 @@ function Polyline({
1927
1931
  }
1928
1932
  );
1929
1933
  }
1930
- const MIN_HIT_AREA_SCREEN_PX = 20;
1934
+ const MIN_HIT_AREA_SCREEN_PX$1 = 20;
1931
1935
  function Polygon({
1932
1936
  rect,
1933
1937
  vertices,
@@ -1964,7 +1968,7 @@ function Polygon({
1964
1968
  const isPreviewing = currentVertex && vertices.length > 0;
1965
1969
  const width = rect.size.width * scale;
1966
1970
  const height = rect.size.height * scale;
1967
- const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX / scale);
1971
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX$1 / scale);
1968
1972
  return /* @__PURE__ */ jsxs(
1969
1973
  "svg",
1970
1974
  {
@@ -2204,6 +2208,339 @@ function FreeText({
2204
2208
  }
2205
2209
  );
2206
2210
  }
2211
+ const MIN_HIT_AREA_SCREEN_PX = 20;
2212
+ function CalloutFreeText({
2213
+ documentId,
2214
+ isSelected,
2215
+ isEditing,
2216
+ annotation,
2217
+ pageIndex,
2218
+ scale,
2219
+ onClick,
2220
+ appearanceActive = false
2221
+ }) {
2222
+ const editorRef = useRef(null);
2223
+ const editingRef = useRef(false);
2224
+ const { provides: annotationCapability } = useAnnotationCapability();
2225
+ const annotationProvides = (annotationCapability == null ? void 0 : annotationCapability.forDocument(documentId)) ?? null;
2226
+ const obj = annotation.object;
2227
+ const rect = obj.rect;
2228
+ const rd = obj.rectangleDifferences;
2229
+ const calloutLine = obj.calloutLine;
2230
+ const strokeWidth = obj.strokeWidth ?? 1;
2231
+ const strokeColor = obj.strokeColor ?? "#000000";
2232
+ const textBox = useMemo(() => patching.computeTextBoxFromRD(rect, rd), [rect, rd]);
2233
+ const textBoxRelative = useMemo(
2234
+ () => ({
2235
+ left: (textBox.origin.x - rect.origin.x + strokeWidth / 2) * scale,
2236
+ top: (textBox.origin.y - rect.origin.y + strokeWidth / 2) * scale,
2237
+ width: (textBox.size.width - strokeWidth) * scale,
2238
+ height: (textBox.size.height - strokeWidth) * scale
2239
+ }),
2240
+ [textBox, rect, scale, strokeWidth]
2241
+ );
2242
+ const lineCoords = useMemo(() => {
2243
+ if (!calloutLine || calloutLine.length < 3) return null;
2244
+ return calloutLine.map((p) => ({
2245
+ x: p.x - rect.origin.x,
2246
+ y: p.y - rect.origin.y
2247
+ }));
2248
+ }, [calloutLine, rect]);
2249
+ const ending = useMemo(() => {
2250
+ if (!lineCoords || lineCoords.length < 2) return null;
2251
+ const angle = Math.atan2(lineCoords[1].y - lineCoords[0].y, lineCoords[1].x - lineCoords[0].x);
2252
+ return patching.createEnding(
2253
+ obj.lineEnding,
2254
+ strokeWidth,
2255
+ angle + Math.PI,
2256
+ lineCoords[0].x,
2257
+ lineCoords[0].y
2258
+ );
2259
+ }, [lineCoords, obj.lineEnding, strokeWidth]);
2260
+ const visualLineCoords = useMemo(() => {
2261
+ if (!lineCoords || lineCoords.length < 2) return lineCoords;
2262
+ const pts = lineCoords.map((p) => ({ ...p }));
2263
+ const last = pts.length - 1;
2264
+ const prev = last - 1;
2265
+ const dx = pts[last].x - pts[prev].x;
2266
+ const dy = pts[last].y - pts[prev].y;
2267
+ const len = Math.sqrt(dx * dx + dy * dy);
2268
+ if (len > 0) {
2269
+ const halfBw = strokeWidth / 2;
2270
+ pts[last].x += dx / len * halfBw;
2271
+ pts[last].y += dy / len * halfBw;
2272
+ }
2273
+ return pts;
2274
+ }, [lineCoords, strokeWidth]);
2275
+ const { adjustedFontPx, wrapperStyle } = useIOSZoomPrevention(obj.fontSize * scale, isEditing);
2276
+ useEffect(() => {
2277
+ var _a;
2278
+ if (isEditing && editorRef.current) {
2279
+ editingRef.current = true;
2280
+ const editor = editorRef.current;
2281
+ editor.focus();
2282
+ const tool = annotationProvides == null ? void 0 : annotationProvides.findToolForAnnotation(obj);
2283
+ const isDefaultContent = ((_a = tool == null ? void 0 : tool.defaults) == null ? void 0 : _a.contents) != null && obj.contents === tool.defaults.contents;
2284
+ const selection = window.getSelection();
2285
+ if (selection) {
2286
+ const range = document.createRange();
2287
+ range.selectNodeContents(editor);
2288
+ if (!isDefaultContent) {
2289
+ range.collapse(false);
2290
+ }
2291
+ selection.removeAllRanges();
2292
+ selection.addRange(range);
2293
+ }
2294
+ }
2295
+ }, [isEditing]);
2296
+ const handleBlur = () => {
2297
+ if (!editingRef.current) return;
2298
+ editingRef.current = false;
2299
+ if (!annotationProvides) return;
2300
+ if (!editorRef.current) return;
2301
+ annotationProvides.updateAnnotation(pageIndex, obj.id, {
2302
+ contents: editorRef.current.innerText.replace(/\u00A0/g, " ")
2303
+ });
2304
+ };
2305
+ const width = rect.size.width * scale;
2306
+ const height = rect.size.height * scale;
2307
+ const hitStrokeWidth = Math.max(strokeWidth, MIN_HIT_AREA_SCREEN_PX / scale);
2308
+ return /* @__PURE__ */ jsxs(
2309
+ "div",
2310
+ {
2311
+ style: {
2312
+ position: "absolute",
2313
+ width,
2314
+ height,
2315
+ cursor: isSelected && !isEditing ? "move" : "default",
2316
+ pointerEvents: "none",
2317
+ zIndex: 2,
2318
+ opacity: appearanceActive ? 0 : 1
2319
+ },
2320
+ children: [
2321
+ /* @__PURE__ */ jsxs(
2322
+ "svg",
2323
+ {
2324
+ style: {
2325
+ position: "absolute",
2326
+ width,
2327
+ height,
2328
+ pointerEvents: "none",
2329
+ overflow: "visible"
2330
+ },
2331
+ width,
2332
+ height,
2333
+ viewBox: `0 0 ${rect.size.width} ${rect.size.height}`,
2334
+ children: [
2335
+ lineCoords && /* @__PURE__ */ jsxs(Fragment, { children: [
2336
+ /* @__PURE__ */ jsx(
2337
+ "polyline",
2338
+ {
2339
+ points: lineCoords.map((p) => `${p.x},${p.y}`).join(" "),
2340
+ fill: "none",
2341
+ stroke: "transparent",
2342
+ strokeWidth: hitStrokeWidth,
2343
+ onPointerDown: onClick ? (e) => onClick(e) : void 0,
2344
+ style: {
2345
+ cursor: isSelected ? "move" : onClick ? "pointer" : "default",
2346
+ pointerEvents: !onClick ? "none" : isSelected ? "none" : "visibleStroke"
2347
+ }
2348
+ }
2349
+ ),
2350
+ ending && /* @__PURE__ */ jsx(
2351
+ "path",
2352
+ {
2353
+ d: ending.d,
2354
+ transform: ending.transform,
2355
+ fill: "transparent",
2356
+ stroke: "transparent",
2357
+ strokeWidth: hitStrokeWidth,
2358
+ onPointerDown: onClick ? (e) => onClick(e) : void 0,
2359
+ style: {
2360
+ cursor: isSelected ? "move" : onClick ? "pointer" : "default",
2361
+ pointerEvents: !onClick ? "none" : isSelected ? "none" : ending.filled ? "visible" : "visibleStroke"
2362
+ }
2363
+ }
2364
+ )
2365
+ ] }),
2366
+ !appearanceActive && /* @__PURE__ */ jsxs(Fragment, { children: [
2367
+ visualLineCoords && /* @__PURE__ */ jsxs(Fragment, { children: [
2368
+ /* @__PURE__ */ jsx(
2369
+ "polyline",
2370
+ {
2371
+ points: visualLineCoords.map((p) => `${p.x},${p.y}`).join(" "),
2372
+ fill: "none",
2373
+ stroke: strokeColor,
2374
+ strokeWidth,
2375
+ opacity: obj.opacity,
2376
+ style: { pointerEvents: "none" }
2377
+ }
2378
+ ),
2379
+ ending && /* @__PURE__ */ jsx(
2380
+ "path",
2381
+ {
2382
+ d: ending.d,
2383
+ transform: ending.transform,
2384
+ stroke: strokeColor,
2385
+ fill: ending.filled ? obj.color ?? "transparent" : "none",
2386
+ strokeWidth,
2387
+ opacity: obj.opacity,
2388
+ style: { pointerEvents: "none" }
2389
+ }
2390
+ )
2391
+ ] }),
2392
+ /* @__PURE__ */ jsx(
2393
+ "rect",
2394
+ {
2395
+ x: textBox.origin.x - rect.origin.x + strokeWidth / 2,
2396
+ y: textBox.origin.y - rect.origin.y + strokeWidth / 2,
2397
+ width: textBox.size.width - strokeWidth,
2398
+ height: textBox.size.height - strokeWidth,
2399
+ fill: obj.color ?? obj.backgroundColor ?? "transparent",
2400
+ stroke: strokeColor,
2401
+ strokeWidth,
2402
+ opacity: obj.opacity,
2403
+ style: { pointerEvents: "none" }
2404
+ }
2405
+ )
2406
+ ] })
2407
+ ]
2408
+ }
2409
+ ),
2410
+ /* @__PURE__ */ jsx(
2411
+ "div",
2412
+ {
2413
+ onPointerDown: onClick ? (e) => onClick(e) : void 0,
2414
+ style: {
2415
+ position: "absolute",
2416
+ left: (textBox.origin.x - rect.origin.x) * scale,
2417
+ top: (textBox.origin.y - rect.origin.y) * scale,
2418
+ width: textBox.size.width * scale,
2419
+ height: textBox.size.height * scale,
2420
+ cursor: isSelected && !isEditing ? "move" : onClick ? "pointer" : "default",
2421
+ pointerEvents: !onClick ? "none" : isSelected && !isEditing ? "none" : "auto"
2422
+ }
2423
+ }
2424
+ ),
2425
+ /* @__PURE__ */ jsx(
2426
+ "span",
2427
+ {
2428
+ ref: editorRef,
2429
+ onBlur: handleBlur,
2430
+ tabIndex: 0,
2431
+ style: {
2432
+ position: "absolute",
2433
+ left: textBoxRelative.left,
2434
+ top: textBoxRelative.top,
2435
+ width: textBoxRelative.width,
2436
+ height: textBoxRelative.height,
2437
+ color: obj.fontColor,
2438
+ fontSize: adjustedFontPx,
2439
+ ...standardFontCssProperties(obj.fontFamily),
2440
+ textAlign: textAlignmentToCss(obj.textAlign),
2441
+ flexDirection: "column",
2442
+ justifyContent: obj.verticalAlign === PdfVerticalAlignment.Top ? "flex-start" : obj.verticalAlign === PdfVerticalAlignment.Middle ? "center" : "flex-end",
2443
+ display: "flex",
2444
+ padding: strokeWidth * scale / 2 + 2 * scale,
2445
+ opacity: obj.opacity,
2446
+ lineHeight: "1.18",
2447
+ overflow: "hidden",
2448
+ cursor: isEditing ? "text" : "default",
2449
+ outline: "none",
2450
+ pointerEvents: isEditing ? "auto" : "none",
2451
+ ...wrapperStyle
2452
+ },
2453
+ contentEditable: isEditing,
2454
+ ...suppressContentEditableWarningProps,
2455
+ children: obj.contents
2456
+ }
2457
+ )
2458
+ ]
2459
+ }
2460
+ );
2461
+ }
2462
+ function CalloutFreeTextPreview({
2463
+ calloutLine,
2464
+ textBox,
2465
+ bounds,
2466
+ scale,
2467
+ strokeColor,
2468
+ strokeWidth,
2469
+ color,
2470
+ backgroundColor,
2471
+ opacity,
2472
+ lineEnding
2473
+ }) {
2474
+ if (!calloutLine || calloutLine.length < 2) return /* @__PURE__ */ jsx(Fragment$1, {});
2475
+ const sw = strokeWidth ?? 1;
2476
+ const sc = strokeColor ?? "#000000";
2477
+ const op = opacity ?? 1;
2478
+ const w = bounds.size.width;
2479
+ const h = bounds.size.height;
2480
+ const ox = bounds.origin.x;
2481
+ const oy = bounds.origin.y;
2482
+ const lineCoords = calloutLine.map((p) => ({ x: p.x - ox, y: p.y - oy }));
2483
+ const angle = Math.atan2(lineCoords[1].y - lineCoords[0].y, lineCoords[1].x - lineCoords[0].x);
2484
+ const ending = patching.createEnding(
2485
+ lineEnding,
2486
+ sw,
2487
+ angle + Math.PI,
2488
+ lineCoords[0].x,
2489
+ lineCoords[0].y
2490
+ );
2491
+ const halfSw = sw / 2;
2492
+ return /* @__PURE__ */ jsxs(
2493
+ "svg",
2494
+ {
2495
+ style: {
2496
+ position: "absolute",
2497
+ width: w * scale,
2498
+ height: h * scale,
2499
+ pointerEvents: "none",
2500
+ overflow: "visible"
2501
+ },
2502
+ width: w * scale,
2503
+ height: h * scale,
2504
+ viewBox: `0 0 ${w} ${h}`,
2505
+ children: [
2506
+ /* @__PURE__ */ jsx(
2507
+ "polyline",
2508
+ {
2509
+ points: lineCoords.map((p) => `${p.x},${p.y}`).join(" "),
2510
+ fill: "none",
2511
+ stroke: sc,
2512
+ strokeWidth: sw,
2513
+ opacity: op
2514
+ }
2515
+ ),
2516
+ ending && /* @__PURE__ */ jsx(
2517
+ "path",
2518
+ {
2519
+ d: ending.d,
2520
+ transform: ending.transform,
2521
+ stroke: sc,
2522
+ fill: ending.filled ? color ?? "transparent" : "none",
2523
+ strokeWidth: sw,
2524
+ opacity: op
2525
+ }
2526
+ ),
2527
+ textBox && /* @__PURE__ */ jsx(
2528
+ "rect",
2529
+ {
2530
+ x: textBox.origin.x - ox + halfSw,
2531
+ y: textBox.origin.y - oy + halfSw,
2532
+ width: textBox.size.width - sw,
2533
+ height: textBox.size.height - sw,
2534
+ fill: color ?? backgroundColor ?? "transparent",
2535
+ stroke: sc,
2536
+ strokeWidth: sw,
2537
+ opacity: op
2538
+ }
2539
+ )
2540
+ ]
2541
+ }
2542
+ );
2543
+ }
2207
2544
  function RenderAnnotation({
2208
2545
  documentId,
2209
2546
  pageIndex,
@@ -2896,11 +3233,59 @@ const builtInRenderers = [
2896
3233
  ),
2897
3234
  interactionDefaults: { isDraggable: false, isResizable: false, isRotatable: false }
2898
3235
  }),
3236
+ // --- Callout FreeText (must appear before regular FreeText to match first) ---
3237
+ createRenderer({
3238
+ id: "freeTextCallout",
3239
+ matches: (a) => a.type === PdfAnnotationSubtype.FREETEXT && a.intent === "FreeTextCallout",
3240
+ matchesPreview: (p) => p.type === PdfAnnotationSubtype.FREETEXT && !!p.data.calloutLine,
3241
+ render: ({
3242
+ annotation,
3243
+ currentObject,
3244
+ isSelected,
3245
+ isEditing,
3246
+ scale,
3247
+ pageIndex,
3248
+ documentId,
3249
+ onClick,
3250
+ appearanceActive
3251
+ }) => /* @__PURE__ */ jsx(
3252
+ CalloutFreeText,
3253
+ {
3254
+ documentId,
3255
+ isSelected,
3256
+ isEditing,
3257
+ annotation: { ...annotation, object: currentObject },
3258
+ pageIndex,
3259
+ scale,
3260
+ onClick,
3261
+ appearanceActive
3262
+ }
3263
+ ),
3264
+ renderPreview: ({ data, bounds, scale }) => /* @__PURE__ */ jsx(
3265
+ CalloutFreeTextPreview,
3266
+ {
3267
+ calloutLine: data.calloutLine,
3268
+ textBox: data.textBox,
3269
+ bounds,
3270
+ scale,
3271
+ strokeColor: data.strokeColor,
3272
+ strokeWidth: data.strokeWidth,
3273
+ color: data.color,
3274
+ backgroundColor: data.backgroundColor,
3275
+ opacity: data.opacity,
3276
+ lineEnding: data.lineEnding
3277
+ }
3278
+ ),
3279
+ vertexConfig: patching.calloutVertexConfig,
3280
+ interactionDefaults: { isDraggable: true, isResizable: false, isRotatable: false },
3281
+ isDraggable: (toolDraggable, { isEditing }) => toolDraggable && !isEditing,
3282
+ onDoubleClick: (id, setEditingId) => setEditingId(id)
3283
+ }),
2899
3284
  // --- FreeText ---
2900
3285
  createRenderer({
2901
3286
  id: "freeText",
2902
- matches: (a) => a.type === PdfAnnotationSubtype.FREETEXT,
2903
- matchesPreview: (p) => p.type === PdfAnnotationSubtype.FREETEXT,
3287
+ matches: (a) => a.type === PdfAnnotationSubtype.FREETEXT && a.intent !== "FreeTextCallout",
3288
+ matchesPreview: (p) => p.type === PdfAnnotationSubtype.FREETEXT && !p.data.calloutLine,
2904
3289
  render: ({
2905
3290
  annotation,
2906
3291
  currentObject,
@@ -3039,7 +3424,7 @@ function Annotations(annotationsProps) {
3039
3424
  const [allSelectedIds, setAllSelectedIds] = useState([]);
3040
3425
  const [editingId, setEditingId] = useState(null);
3041
3426
  const [appearanceMap, setAppearanceMap] = useState({});
3042
- const [lockedMode, setLockedMode] = useState({ type: LockModeType.None });
3427
+ const [, setLockedMode] = useState({ type: LockModeType.None });
3043
3428
  const prevScaleRef = useRef(scale);
3044
3429
  const annotationProvides = useMemo(
3045
3430
  () => annotationCapability ? annotationCapability.forDocument(documentId) : null,
@@ -3229,35 +3614,38 @@ function Annotations(annotationsProps) {
3229
3614
  var _a, _b, _c;
3230
3615
  const renderer = resolveRenderer(annotation);
3231
3616
  if (!renderer) return null;
3617
+ if (hasNoViewFlag(annotation.object)) return null;
3618
+ if (hasHiddenFlag(annotation.object)) return null;
3232
3619
  const tool = (annotationProvides == null ? void 0 : annotationProvides.findToolForAnnotation(annotation.object)) ?? null;
3233
- const categories = getAnnotationCategories(tool);
3234
- const locked = hasLockedFlag(annotation.object) || isCategoryLocked(categories, lockedMode);
3235
- if (locked && renderer.hiddenWhenLocked) return null;
3236
- const hasRenderLocked = locked && !!renderer.renderLocked;
3237
- const isSelected = locked ? false : allSelectedIds.includes(annotation.object.id);
3238
- const isEditing = locked ? false : editingId === annotation.object.id;
3620
+ const nonInteractive = annotationProvides ? !annotationProvides.isAnnotationInteractive(annotation.object) : false;
3621
+ const structurallyLocked = annotationProvides ? annotationProvides.isAnnotationStructurallyLocked(annotation.object) : false;
3622
+ const contentLocked = annotationProvides ? annotationProvides.isAnnotationContentLocked(annotation.object) : false;
3623
+ if (nonInteractive && renderer.hiddenWhenLocked) return null;
3624
+ const hasRenderLocked = nonInteractive && !!renderer.renderLocked;
3625
+ const isSelected = nonInteractive ? false : allSelectedIds.includes(annotation.object.id);
3626
+ const isEditing = nonInteractive ? false : editingId === annotation.object.id;
3239
3627
  const defaults = renderer.interactionDefaults;
3240
3628
  const resolvedDraggable = resolveInteractionProp(
3241
3629
  tool == null ? void 0 : tool.interaction.isDraggable,
3242
3630
  annotation.object,
3243
3631
  (defaults == null ? void 0 : defaults.isDraggable) ?? true
3244
3632
  );
3245
- const finalDraggable = locked ? false : renderer.isDraggable ? renderer.isDraggable(resolvedDraggable, { isEditing }) : resolvedDraggable;
3633
+ const finalDraggable = structurallyLocked ? false : renderer.isDraggable ? renderer.isDraggable(resolvedDraggable, { isEditing }) : resolvedDraggable;
3246
3634
  const useAP = ((_a = tool == null ? void 0 : tool.behavior) == null ? void 0 : _a.useAppearanceStream) ?? renderer.useAppearanceStream ?? true;
3247
3635
  const appearance = hasRenderLocked ? void 0 : useAP ? getAppearanceForAnnotation(annotation) : void 0;
3248
3636
  const noopSelect = (e) => {
3249
3637
  e.stopPropagation();
3250
3638
  };
3251
- const onSelect = locked ? noopSelect : renderer.selectOverride ? (e) => renderer.selectOverride(e, annotation, selectHelpers) : (e) => handleClick(e, annotation);
3639
+ const onSelect = nonInteractive ? noopSelect : renderer.selectOverride ? (e) => renderer.selectOverride(e, annotation, selectHelpers) : (e) => handleClick(e, annotation);
3252
3640
  return /* @__PURE__ */ jsx(
3253
3641
  AnnotationContainer,
3254
3642
  {
3255
3643
  trackedAnnotation: annotation,
3256
3644
  isSelected,
3257
3645
  isEditing,
3258
- isMultiSelected: locked ? false : isMultiSelected,
3646
+ isMultiSelected: nonInteractive ? false : isMultiSelected,
3259
3647
  isDraggable: finalDraggable,
3260
- isResizable: locked ? false : resolveInteractionProp(
3648
+ isResizable: structurallyLocked ? false : resolveInteractionProp(
3261
3649
  tool == null ? void 0 : tool.interaction.isResizable,
3262
3650
  annotation.object,
3263
3651
  (defaults == null ? void 0 : defaults.isResizable) ?? false
@@ -3267,15 +3655,17 @@ function Annotations(annotationsProps) {
3267
3655
  annotation.object,
3268
3656
  (defaults == null ? void 0 : defaults.lockAspectRatio) ?? false
3269
3657
  ),
3270
- isRotatable: locked ? false : resolveInteractionProp(
3658
+ isRotatable: structurallyLocked ? false : resolveInteractionProp(
3271
3659
  tool == null ? void 0 : tool.interaction.isRotatable,
3272
3660
  annotation.object,
3273
3661
  (defaults == null ? void 0 : defaults.isRotatable) ?? false
3274
3662
  ),
3275
- vertexConfig: locked ? void 0 : renderer.vertexConfig,
3276
- selectionMenu: locked ? void 0 : ((_b = renderer.hideSelectionMenu) == null ? void 0 : _b.call(renderer, annotation.object)) ? void 0 : selectionMenu,
3663
+ vertexConfig: structurallyLocked ? void 0 : renderer.vertexConfig,
3664
+ selectionMenu: nonInteractive ? void 0 : ((_b = renderer.hideSelectionMenu) == null ? void 0 : _b.call(renderer, annotation.object)) ? void 0 : selectionMenu,
3665
+ structurallyLocked,
3666
+ contentLocked,
3277
3667
  onSelect,
3278
- onDoubleClick: locked ? void 0 : renderer.onDoubleClick ? (e) => {
3668
+ onDoubleClick: nonInteractive || contentLocked ? void 0 : renderer.onDoubleClick ? (e) => {
3279
3669
  e.stopPropagation();
3280
3670
  renderer.onDoubleClick(annotation.object.id, setEditingId);
3281
3671
  } : void 0,
@@ -3308,7 +3698,7 @@ function Annotations(annotationsProps) {
3308
3698
  scale,
3309
3699
  pageIndex,
3310
3700
  documentId,
3311
- onClick: locked ? void 0 : onSelect,
3701
+ onClick: nonInteractive ? void 0 : onSelect,
3312
3702
  appearanceActive
3313
3703
  });
3314
3704
  }