@embedpdf/plugin-annotation 3.0.0-next.10 → 3.0.0-next.11

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 (43) hide show
  1. package/dist/authoring-BhtyfsMx.d.cts +37 -0
  2. package/dist/authoring-R4ezdnXd.d.ts +37 -0
  3. package/dist/authoring.cjs +16 -0
  4. package/dist/authoring.d.cts +2 -0
  5. package/dist/authoring.d.ts +2 -0
  6. package/dist/authoring.js +3 -0
  7. package/dist/{capability-Cl9x8oLS.cjs → capability-Csb9WMm-.cjs} +256 -348
  8. package/dist/capability-Csb9WMm-.cjs.map +1 -0
  9. package/dist/{capability-BRf0HrOi.js → capability-DBsr2D-L.js} +191 -259
  10. package/dist/capability-DBsr2D-L.js.map +1 -0
  11. package/dist/contract/host.cjs +3 -0
  12. package/dist/contract/host.d.cts +2 -0
  13. package/dist/contract/host.d.ts +2 -0
  14. package/dist/contract/host.js +2 -0
  15. package/dist/contract.cjs +8 -0
  16. package/dist/contract.cjs.map +1 -0
  17. package/dist/contract.d.cts +10 -0
  18. package/dist/contract.d.ts +10 -0
  19. package/dist/contract.js +8 -0
  20. package/dist/contract.js.map +1 -0
  21. package/dist/index.cjs +22 -23
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +4 -46
  24. package/dist/index.d.ts +4 -46
  25. package/dist/index.js +12 -13
  26. package/dist/index.js.map +1 -1
  27. package/dist/internal.cjs +4 -2
  28. package/dist/internal.d.cts +2 -1
  29. package/dist/internal.d.ts +2 -1
  30. package/dist/internal.js +3 -1
  31. package/dist/seam-6pJeKOOJ.cjs +296 -0
  32. package/dist/seam-6pJeKOOJ.cjs.map +1 -0
  33. package/dist/seam-C4L_7rDt.js +225 -0
  34. package/dist/seam-C4L_7rDt.js.map +1 -0
  35. package/dist/types-CwytT-TI.js +13 -0
  36. package/dist/types-CwytT-TI.js.map +1 -0
  37. package/dist/types-DimcLIic.cjs +17 -0
  38. package/dist/types-DimcLIic.cjs.map +1 -0
  39. package/dist/{types-Due7UgzE.d.cts → types-eLTpocXz.d.cts} +37 -9
  40. package/dist/{types-DITX_3CG.d.ts → types-otwv-Cdl.d.ts} +36 -8
  41. package/package.json +21 -7
  42. package/dist/capability-BRf0HrOi.js.map +0 -1
  43. package/dist/capability-Cl9x8oLS.cjs.map +0 -1
@@ -1,238 +1,12 @@
1
+ const require_seam = require("./seam-6pJeKOOJ.cjs");
1
2
  let _embedpdf_core = require("@embedpdf/core");
2
- let _embedpdf_plugin_interaction = require("@embedpdf/plugin-interaction");
3
+ let _embedpdf_plugin_actions_contract = require("@embedpdf/plugin-actions/contract");
4
+ let _embedpdf_plugin_interaction_contract = require("@embedpdf/plugin-interaction/contract");
3
5
  let _embedpdf_engine_core_runtime = require("@embedpdf/engine-core/runtime");
4
- let _embedpdf_plugin_selection = require("@embedpdf/plugin-selection");
6
+ let _embedpdf_core_acrojs = require("@embedpdf/core-acrojs");
7
+ let _embedpdf_plugin_selection_contract = require("@embedpdf/plugin-selection/contract");
5
8
  let _embedpdf_core_annotation = require("@embedpdf/core-annotation");
6
9
  let _embedpdf_core_geometry = require("@embedpdf/core-geometry");
7
- //#region src/types.ts
8
- /**
9
- * The annotation capability token. Typed to the full {@link AnnotationHostCapability}
10
- * here (the package internals + the `/internal` entry use this view). The package
11
- * root re-exports the SAME token narrowed to {@link AnnotationCapability}.
12
- */
13
- const AnnotationToken = (0, _embedpdf_core.createCapabilityToken)("annotation", { hint: `add annotationPlugin() from '@embedpdf/plugin-annotation' to your plugins list` });
14
- //#endregion
15
- //#region src/repository/seam.ts
16
- function refKey(ref) {
17
- return ref.kind === "objectNumber" ? `obj:${ref.annotObjectNumber}` : ref.kind === "nm" ? `nm:${ref.nm}` : `idx:${ref.pageObjectNumber}:${ref.index}`;
18
- }
19
- const h2 = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0");
20
- const colorToCss = (c) => `#${h2(c.r)}${h2(c.g)}${h2(c.b)}`;
21
- function cssToColor(css) {
22
- const s = css.trim();
23
- const m6 = /^#?([0-9a-f]{6})$/i.exec(s);
24
- if (m6) {
25
- const n = parseInt(m6[1], 16);
26
- return {
27
- r: n >> 16 & 255,
28
- g: n >> 8 & 255,
29
- b: n & 255
30
- };
31
- }
32
- const m3 = /^#?([0-9a-f]{3})$/i.exec(s);
33
- if (m3) {
34
- const [a, b, c] = m3[1];
35
- return {
36
- r: parseInt(a + a, 16),
37
- g: parseInt(b + b, 16),
38
- b: parseInt(c + c, 16)
39
- };
40
- }
41
- return {
42
- r: 0,
43
- g: 0,
44
- b: 0
45
- };
46
- }
47
- const toPdfRotation = (rotCW) => (0, _embedpdf_core_annotation.normalizeDeg)(-rotCW);
48
- const fromPdfRotation = (rotPdf) => (0, _embedpdf_core_annotation.normalizeDeg)(-rotPdf);
49
- /** Advisory `rot` for a vertex geom, from a DTO's (PDF-convention) `rotation`.
50
- * Absent → no `rot` key (kept off the geom so unrotated shapes stay clean). */
51
- const rotFromDTO = (rotation) => rotation ? { rot: fromPdfRotation(rotation) } : {};
52
- /**
53
- * Geometry/rotation fields for a BOX kind (square/circle/plain free-text). The
54
- * model's `rect` is the UNROTATED logical box and `rot` the applied tilt, so:
55
- * - rot == 0 → `/Rect` IS the box; the transform pair is stated as `null`
56
- * (TOTAL projection — the engine's tri-state writes preserve omissions, so
57
- * an omitted field would keep a stale rotation instead of flattening it).
58
- * - rot != 0 → `/Rect` is the rotated visual AABB (PDFium clips the baked /AP
59
- * to it), `unrotatedRect` the logical box, `rotation` the PDF angle.
60
- */
61
- function boxGeomFields(rect, rot, crop) {
62
- if (!rot) return {
63
- rect: (0, _embedpdf_core_annotation.contentToPdfRect)(rect, crop),
64
- rotation: null,
65
- unrotatedRect: null
66
- };
67
- return {
68
- rect: (0, _embedpdf_core_annotation.contentToPdfRect)((0, _embedpdf_core_annotation.rotatedAabb)(rect, rot), crop),
69
- unrotatedRect: (0, _embedpdf_core_annotation.contentToPdfRect)(rect, crop),
70
- rotation: toPdfRotation(rot)
71
- };
72
- }
73
- /** A box geom (square/circle/stamp) from its DTO: when rotated, the LOCAL box
74
- * is the stored `unrotatedRect` (the AABB `/Rect` is the rendered envelope)
75
- * and `rot` the converted tilt; unrotated, `/Rect` IS the box. */
76
- function boxGeomFromDTO(dto, rotation, unrotatedRect, crop, ellipse) {
77
- const rot = rotation ? fromPdfRotation(rotation) : 0;
78
- return {
79
- t: "rect",
80
- rect: (0, _embedpdf_core_annotation.pdfToContentRect)(rot && unrotatedRect ? unrotatedRect : dto.rect, crop),
81
- ellipse,
82
- ...rot ? { rot } : {}
83
- };
84
- }
85
- /** Inset a PdfRect by a `/RD` (PDF user space, y-up: all four are non-negative
86
- * insets from the matching `/Rect` edge). Used to recover the callout text box. */
87
- const insetPdfRectByRD = (r, rd) => rd ? {
88
- left: r.left + rd.left,
89
- bottom: r.bottom + rd.bottom,
90
- right: r.right - rd.right,
91
- top: r.top - rd.top
92
- } : r;
93
- /** Engine border fields (`/BS /S`, `/BS /D`, `/BE /I`) → the `Border` union. A
94
- * cloudy effect wins over the underlying border style (which stays solid). */
95
- function borderFromDTO(d) {
96
- if ((d.cloudyIntensity ?? 0) > 0) return {
97
- kind: "cloudy",
98
- intensity: d.cloudyIntensity
99
- };
100
- if (d.borderStyle === "dashed") return {
101
- kind: "dashed",
102
- dash: d.dashArray?.length ? d.dashArray : [3, 3]
103
- };
104
- return { kind: "solid" };
105
- }
106
- /** The writable projection of a `link` value: `goto`/`uri` pass through,
107
- * read-only arms (`javascript`, `named`, `goto-remote`, `launch`,
108
- * `unsupported`) yield `null` — they can be carried, never (re)written. */
109
- function writableTarget(t) {
110
- return t && (t.kind === "goto" || t.kind === "uri") ? t : null;
111
- }
112
- const TEXT_MARKUP = /* @__PURE__ */ new Set([
113
- "highlight",
114
- "underline",
115
- "squiggly",
116
- "strikeout"
117
- ]);
118
- const STROKE_KINDS = /* @__PURE__ */ new Set([
119
- "square",
120
- "circle",
121
- "line",
122
- "polygon",
123
- "polyline",
124
- "ink"
125
- ]);
126
- /** Engine DTO → content-space `Style` (CSS colours, `Border` union). Exported so
127
- * selection-aware UIs can read display values straight off a {@link AnnotationDTO}
128
- * without re-deriving the colour/border mapping. */
129
- function styleFromDTO(dto) {
130
- if (dto.subtype === "widget") return {
131
- color: dto.color ? colorToCss(dto.color) : "#1a1a1a",
132
- interiorColor: dto.interiorColor ? colorToCss(dto.interiorColor) : null,
133
- strokeWidth: dto.strokeWidth,
134
- opacity: 1,
135
- blendMode: dto.blendMode,
136
- border: dto.borderStyle === "dashed" ? {
137
- kind: "dashed",
138
- dash: [3, 3]
139
- } : { kind: "solid" }
140
- };
141
- if (STROKE_KINDS.has(dto.subtype)) {
142
- const d = dto;
143
- return {
144
- color: colorToCss(d.color),
145
- interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,
146
- strokeWidth: d.strokeWidth,
147
- opacity: d.opacity,
148
- blendMode: dto.blendMode,
149
- border: borderFromDTO(d)
150
- };
151
- }
152
- if (TEXT_MARKUP.has(dto.subtype)) {
153
- const d = dto;
154
- return {
155
- color: colorToCss(d.color),
156
- interiorColor: null,
157
- strokeWidth: 0,
158
- opacity: d.opacity,
159
- blendMode: dto.blendMode,
160
- border: { kind: "solid" }
161
- };
162
- }
163
- if (dto.subtype === "caret") {
164
- const d = dto;
165
- return {
166
- color: colorToCss(d.color),
167
- interiorColor: null,
168
- strokeWidth: 1,
169
- opacity: d.opacity,
170
- blendMode: dto.blendMode,
171
- border: { kind: "solid" }
172
- };
173
- }
174
- if (dto.subtype === "free-text") {
175
- const d = dto;
176
- return {
177
- color: colorToCss(d.color),
178
- interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,
179
- strokeWidth: d.strokeWidth,
180
- opacity: d.opacity,
181
- blendMode: dto.blendMode,
182
- border: borderFromDTO(d)
183
- };
184
- }
185
- if (dto.subtype === "redact") {
186
- const d = dto;
187
- return {
188
- color: colorToCss(d.color),
189
- interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,
190
- strokeWidth: 1.5,
191
- opacity: d.opacity,
192
- blendMode: dto.blendMode,
193
- border: { kind: "solid" }
194
- };
195
- }
196
- if (dto.subtype === "text" || dto.subtype === "file-attachment") {
197
- const d = dto;
198
- return {
199
- color: colorToCss(d.color),
200
- interiorColor: null,
201
- strokeWidth: 1,
202
- opacity: d.opacity,
203
- blendMode: dto.blendMode,
204
- border: { kind: "solid" }
205
- };
206
- }
207
- return {
208
- color: "#444444",
209
- interiorColor: null,
210
- strokeWidth: 1,
211
- opacity: 1,
212
- blendMode: dto.blendMode,
213
- border: { kind: "solid" }
214
- };
215
- }
216
- /**
217
- * The flat props vocabulary (CSS colours, house keys) → the engine's widget
218
- * appearance for `doc.forms` authoring — the SAME mapping the widget patch
219
- * lowering uses, exported as a boundary utility so the form plugin can style
220
- * `placeField` from a tool's `currentDefaults` without growing a second CSS
221
- * parser. Absent keys stay absent (the engine writes nothing for them).
222
- */
223
- function widgetAppearanceFromProps(props) {
224
- return {
225
- ...props.color !== void 0 ? { color: cssToColor(props.color) } : {},
226
- ...props.interiorColor !== void 0 ? { interiorColor: props.interiorColor ? cssToColor(props.interiorColor) : null } : {},
227
- ...props.strokeWidth !== void 0 ? { strokeWidth: props.strokeWidth } : {},
228
- ...props.border !== void 0 ? { borderStyle: props.border.kind === "dashed" ? "dashed" : "solid" } : {},
229
- ...props.fontFamily !== void 0 ? { fontFamily: props.fontFamily } : {},
230
- ...props.fontSize !== void 0 ? { fontSize: props.fontSize } : {},
231
- ...props.fontColor !== void 0 ? { fontColor: cssToColor(props.fontColor) } : {},
232
- ...props.textAlign !== void 0 ? { textAlign: props.textAlign } : {}
233
- };
234
- }
235
- //#endregion
236
10
  //#region src/repository/props.ts
237
11
  /**
238
12
  * GENERIC per-key prop lowerings — the 1:1 mappings from the flat props
@@ -251,15 +25,15 @@ const borderSlice = (style) => ({
251
25
  * the old projections did (a fresh draft may not carry `text` yet). */
252
26
  const textOf = (a) => a.text ?? _embedpdf_core_annotation.initialTextStyle;
253
27
  const GENERIC_PROPS = {
254
- color: (a) => ({ color: cssToColor(a.style.color) }),
28
+ color: (a) => ({ color: require_seam.cssToColor(a.style.color) }),
255
29
  opacity: (a) => ({ opacity: a.style.opacity }),
256
30
  blendMode: (a) => ({ blendMode: a.style.blendMode }),
257
- interiorColor: (a) => ({ interiorColor: a.style.interiorColor ? cssToColor(a.style.interiorColor) : null }),
31
+ interiorColor: (a) => ({ interiorColor: a.style.interiorColor ? require_seam.cssToColor(a.style.interiorColor) : null }),
258
32
  strokeWidth: (a) => ({ strokeWidth: a.style.strokeWidth }),
259
33
  border: (a) => borderSlice(a.style),
260
34
  fontFamily: (a) => ({ fontFamily: textOf(a).fontFamily }),
261
35
  fontSize: (a) => ({ fontSize: textOf(a).fontSize }),
262
- fontColor: (a) => ({ fontColor: cssToColor(textOf(a).fontColor) }),
36
+ fontColor: (a) => ({ fontColor: require_seam.cssToColor(textOf(a).fontColor) }),
263
37
  textAlign: (a) => ({ textAlign: textOf(a).textAlign }),
264
38
  icon: (a) => a.icon !== void 0 ? { icon: a.icon } : {},
265
39
  link: () => ({})
@@ -270,7 +44,7 @@ const GENERIC_PROPS = {
270
44
  * `/Rect`(+`unrotatedRect`+`rotation`), total (nulls state the clears). */
271
45
  const boxEmit = (a, crop) => {
272
46
  const g = a.geom;
273
- return boxGeomFields(g.rect, (0, _embedpdf_core_annotation.geomRotation)(a.geom), crop);
47
+ return require_seam.boxGeomFields(g.rect, (0, _embedpdf_core_annotation.geomRotation)(a.geom), crop);
274
48
  };
275
49
  //#endregion
276
50
  //#region src/repository/kinds/shape.ts
@@ -298,7 +72,7 @@ function cloudyExtras(a) {
298
72
  }
299
73
  const ingest = (dto, crop, ellipse) => {
300
74
  const d = dto;
301
- return { geom: boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, ellipse) };
75
+ return { geom: require_seam.boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, ellipse) };
302
76
  };
303
77
  const projection = (ellipse) => ({
304
78
  ingest: (dto, crop) => ingest(dto, crop, ellipse),
@@ -322,7 +96,7 @@ const circle = projection(true);
322
96
  * omission would preserve a stale advisory angle. */
323
97
  const advisoryRotation = (g) => {
324
98
  const rot = (0, _embedpdf_core_annotation.geomRotation)(g);
325
- return { rotation: rot ? toPdfRotation(rot) : null };
99
+ return { rotation: rot ? require_seam.toPdfRotation(rot) : null };
326
100
  };
327
101
  /** `/BE` intensity for a closed poly (polygon): the curls are generated from
328
102
  * /Vertices + /BE alone — per ISO 32000 no /RD applies — and the /Rect
@@ -367,7 +141,7 @@ const line = {
367
141
  a: (0, _embedpdf_core_annotation.pdfToContentPoint)(d.linePoints.start, crop),
368
142
  b: (0, _embedpdf_core_annotation.pdfToContentPoint)(d.linePoints.end, crop),
369
143
  ends: d.lineEndings,
370
- ...rotFromDTO(d.rotation)
144
+ ...require_seam.rotFromDTO(d.rotation)
371
145
  } };
372
146
  },
373
147
  geometry: (a, crop) => {
@@ -392,7 +166,7 @@ const polyProjection = (closed) => ({
392
166
  points: d.vertices.map((p) => (0, _embedpdf_core_annotation.pdfToContentPoint)(p, crop)),
393
167
  closed,
394
168
  ..."lineEndings" in d ? { ends: d.lineEndings } : {},
395
- ...rotFromDTO(d.rotation)
169
+ ...require_seam.rotFromDTO(d.rotation)
396
170
  } };
397
171
  },
398
172
  geometry: (a, crop) => {
@@ -415,7 +189,7 @@ const ink = {
415
189
  geom: {
416
190
  t: "ink",
417
191
  strokes: d.inkList.map((stroke) => stroke.map((p) => (0, _embedpdf_core_annotation.pdfToContentPoint)(p, crop))),
418
- ...rotFromDTO(d.rotation)
192
+ ...require_seam.rotFromDTO(d.rotation)
419
193
  },
420
194
  ...d.intent ? { intent: d.intent } : {}
421
195
  };
@@ -440,7 +214,7 @@ function textFromDTO(dto) {
440
214
  return {
441
215
  fontFamily: dto.fontFamily,
442
216
  fontSize: dto.fontSize,
443
- fontColor: colorToCss(dto.fontColor ?? dto.color),
217
+ fontColor: require_seam.colorToCss(dto.fontColor ?? dto.color),
444
218
  textAlign: dto.textAlign
445
219
  };
446
220
  }
@@ -484,7 +258,7 @@ function calloutFields(a, crop) {
484
258
  calloutLine,
485
259
  lineEnding: g.callout.ending,
486
260
  ...rot ? {
487
- rotation: toPdfRotation(rot),
261
+ rotation: require_seam.toPdfRotation(rot),
488
262
  unrotatedRect: (0, _embedpdf_core_annotation.contentToPdfRect)(g.rect, crop)
489
263
  } : {
490
264
  rotation: null,
@@ -497,11 +271,11 @@ const freeText = {
497
271
  const d = dto;
498
272
  if (d.intent === "free-text-callout" && d.calloutLine && d.calloutLine.length >= 2) {
499
273
  const cl = d.calloutLine;
500
- const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;
274
+ const rot = d.rotation ? require_seam.fromPdfRotation(d.rotation) : 0;
501
275
  return {
502
276
  geom: {
503
277
  t: "text",
504
- rect: rot && d.unrotatedRect ? (0, _embedpdf_core_annotation.pdfToContentRect)(d.unrotatedRect, crop) : (0, _embedpdf_core_annotation.pdfToContentRect)(insetPdfRectByRD(d.rect, d.rectDifferences), crop),
278
+ rect: rot && d.unrotatedRect ? (0, _embedpdf_core_annotation.pdfToContentRect)(d.unrotatedRect, crop) : (0, _embedpdf_core_annotation.pdfToContentRect)(require_seam.insetPdfRectByRD(d.rect, d.rectDifferences), crop),
505
279
  callout: {
506
280
  tip: (0, _embedpdf_core_annotation.pdfToContentPoint)(cl[0], crop),
507
281
  knee: cl.length === 3 ? (0, _embedpdf_core_annotation.pdfToContentPoint)(cl[1], crop) : void 0,
@@ -512,7 +286,7 @@ const freeText = {
512
286
  text: textFromDTO(d)
513
287
  };
514
288
  }
515
- const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;
289
+ const rot = d.rotation ? require_seam.fromPdfRotation(d.rotation) : 0;
516
290
  return {
517
291
  geom: {
518
292
  t: "text",
@@ -615,7 +389,7 @@ const strikeout = markupProjection("strikeout");
615
389
  const caret = {
616
390
  ingest: (dto, crop) => {
617
391
  const d = dto;
618
- const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;
392
+ const rot = d.rotation ? require_seam.fromPdfRotation(d.rotation) : 0;
619
393
  return {
620
394
  geom: {
621
395
  t: "caret",
@@ -625,7 +399,7 @@ const caret = {
625
399
  ...d.intent ? { intent: d.intent } : {}
626
400
  };
627
401
  },
628
- geometry: (a, crop) => a.geom.t === "caret" ? boxGeomFields(a.geom.rect, a.geom.rot ?? 0, crop) : null,
402
+ geometry: (a, crop) => a.geom.t === "caret" ? require_seam.boxGeomFields(a.geom.rect, a.geom.rot ?? 0, crop) : null,
629
403
  draftExtras: (a) => ({
630
404
  rectDifferences: {
631
405
  left: .5,
@@ -652,7 +426,7 @@ const redact = {
652
426
  text: {
653
427
  fontFamily: d.fontFamily,
654
428
  fontSize: d.fontSize,
655
- fontColor: colorToCss(d.fontColor),
429
+ fontColor: require_seam.colorToCss(d.fontColor),
656
430
  textAlign: d.textAlign
657
431
  },
658
432
  ...d.overlayText ? { label: {
@@ -693,7 +467,7 @@ const fileAttachment = iconProjection("file-attachment");
693
467
  const stamp = {
694
468
  ingest: (dto, crop) => {
695
469
  const d = dto;
696
- return { geom: boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, false) };
470
+ return { geom: require_seam.boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, false) };
697
471
  },
698
472
  geometry: (a, crop) => boxEmit(a, crop),
699
473
  createable: false
@@ -712,10 +486,10 @@ const link = {
712
486
  },
713
487
  geometry: rectGeometry,
714
488
  prop: { link: (a) => {
715
- const target = writableTarget(a.link);
489
+ const target = require_seam.writableTarget(a.link);
716
490
  return target ? { target } : a.link == null ? { target: null } : {};
717
491
  } },
718
- draftExtras: (a) => ({ target: writableTarget(a.link) })
492
+ draftExtras: (a) => ({ target: require_seam.writableTarget(a.link) })
719
493
  };
720
494
  /** One PDF `widget` subtype → per-family CLIENT kinds (radios have no font). */
721
495
  const WIDGET_KIND_BY_FAMILY = {
@@ -736,7 +510,7 @@ function widgetTextFromDTO(dto) {
736
510
  return {
737
511
  fontFamily: dto.fontFamily ?? "helvetica",
738
512
  fontSize: dto.fontSize ?? 0,
739
- fontColor: dto.fontColor ? colorToCss(dto.fontColor) : "#000000",
513
+ fontColor: dto.fontColor ? require_seam.colorToCss(dto.fontColor) : "#000000",
740
514
  textAlign: dto.textAlign
741
515
  };
742
516
  }
@@ -744,7 +518,7 @@ const widget = {
744
518
  ingest: (dto, crop) => {
745
519
  const d = dto;
746
520
  return {
747
- geom: boxGeomFromDTO(d, void 0, void 0, crop, false),
521
+ geom: require_seam.boxGeomFromDTO(d, void 0, void 0, crop, false),
748
522
  ...WIDGET_TEXT_KINDS.has(widgetKindOf(d.fieldFamily)) ? { text: widgetTextFromDTO(d) } : {}
749
523
  };
750
524
  },
@@ -825,16 +599,16 @@ function fromDTO(dto, crop, source = "baked") {
825
599
  const slice = projectionOf(dto.subtype).ingest(dto, crop);
826
600
  const strippedRect = !(dto.subtype === "free-text" && dto.intent === "free-text-callout") && "unrotatedRect" in dto && "rotation" in dto && dto.rotation ? dto.unrotatedRect : void 0;
827
601
  return {
828
- id: refKey(dto.ref),
602
+ id: require_seam.refKey(dto.ref),
829
603
  ref: dto.ref,
830
604
  pon: dto.pageObjectNumber,
831
605
  subtype: dto.subtype === "widget" ? widgetKindOf(dto.fieldFamily) : dto.subtype,
832
606
  flags: dto.flags,
833
607
  source,
834
608
  data: dto,
835
- ...dto.inReplyTo ? { irt: refKey(dto.inReplyTo) } : {},
836
- ...dto.replyType === "group" && dto.inReplyTo ? { group: refKey(dto.inReplyTo) } : {},
837
- style: styleFromDTO(dto),
609
+ ...dto.inReplyTo ? { irt: require_seam.refKey(dto.inReplyTo) } : {},
610
+ ...dto.replyType === "group" && dto.inReplyTo ? { group: require_seam.refKey(dto.inReplyTo) } : {},
611
+ style: require_seam.styleFromDTO(dto),
838
612
  ...slice,
839
613
  apBox: (0, _embedpdf_core_annotation.pdfToContentRect)(strippedRect ?? dto.rect, crop),
840
614
  ...strippedRect ? { apRot: (0, _embedpdf_core_annotation.geomRotation)(slice.geom) } : {}
@@ -909,6 +683,46 @@ function toCreateDraft(a, crop) {
909
683
  };
910
684
  }
911
685
  //#endregion
686
+ //#region src/hover-feed.ts
687
+ /**
688
+ * The annotation plane's E/X trigger feed — a thin adapter from the ONE
689
+ * pointer-driven hover seam (the `hoverAt` diff) onto the shared hover pump.
690
+ *
691
+ * Anti-cascade is structural and lives in the CALLER's seam placement:
692
+ * reducer-side hover clears (session-hide, remove, reload) never pass
693
+ * through `hoverAt`, so an effect-induced hover loss can never masquerade as
694
+ * a cursor exit. This module only decides WHO is hoverable here:
695
+ *
696
+ * - Drafts (no engine ref) can't carry /AA — skipped.
697
+ * - Widgets and links belong to their own event planes (fill controls /
698
+ * LinkLayer anchors own their pixels). When they ARE hit-testable on this
699
+ * plane, an authoring tool owns them — firing hover actions while editing
700
+ * would be wrong — so they are skipped unconditionally.
701
+ * - Tree-less annotations are FREE: no target, no dispatch, and per-event
702
+ * flags keep a lone /E or /X from dispatching its inert twin.
703
+ */
704
+ function createAnnotationHoverFeed(actions, annotOf) {
705
+ const pump = (0, _embedpdf_plugin_actions_contract.createHoverPump)(actions.dispatch);
706
+ const targetOf = (id) => {
707
+ if (!id) return null;
708
+ const annot = annotOf(id);
709
+ if (!annot?.ref) return null;
710
+ if (annot.subtype.startsWith("widget") || annot.subtype === "link") return null;
711
+ const enter = Boolean(annot.data?.actions?.cursorEnter?.root);
712
+ const exit = Boolean(annot.data?.actions?.cursorExit?.root);
713
+ if (!enter && !exit) return null;
714
+ return {
715
+ ref: annot.ref,
716
+ pon: annot.pon,
717
+ events: {
718
+ enter,
719
+ exit
720
+ }
721
+ };
722
+ };
723
+ return { hover: (id) => pump.hover(targetOf(id)) };
724
+ }
725
+ //#endregion
912
726
  //#region src/text-item.ts
913
727
  /**
914
728
  * The free-text presentation projection: the core's geometry-only `textBoxes`
@@ -1475,7 +1289,7 @@ const isIconPlaceKind = (subtype) => subtype === "text" || subtype === "file-att
1475
1289
  function iconPlacementDraft(subtype, geom, defaults, flags, file) {
1476
1290
  const shared = {
1477
1291
  ...geom,
1478
- color: cssToColor(defaults.color),
1292
+ color: require_seam.cssToColor(defaults.color),
1479
1293
  opacity: defaults.opacity,
1480
1294
  flags: {
1481
1295
  print: true,
@@ -1522,6 +1336,8 @@ function createAnnotationCapability(ctx, config = {}) {
1522
1336
  * slot. See {@link FilePickerProvider}. */
1523
1337
  let filePickerProvider = null;
1524
1338
  const model = () => ctx.getState().model;
1339
+ const actionsForHover = ctx.tryGet(_embedpdf_plugin_actions_contract.ActionsToken);
1340
+ const hoverFeed = actionsForHover ? createAnnotationHoverFeed(actionsForHover, (id) => model().byId[id] ?? null) : null;
1525
1341
  const chromeSettings = () => ctx.getState().chrome;
1526
1342
  /**
1527
1343
  * Ids on a page whose Behavior is currently ENGAGED (form widgets under a
@@ -1674,11 +1490,21 @@ function createAnnotationCapability(ctx, config = {}) {
1674
1490
  if (!(0, _embedpdf_core_annotation.viewable)(a.flags, false)) continue;
1675
1491
  const target = a.link ?? (a.data?.subtype === "link" ? a.data.target ?? null : null);
1676
1492
  if (target == null || a.geom.t !== "rect") continue;
1493
+ const activate = a.data?.actions?.activate;
1494
+ const ref = a.ref ?? a.data?.ref ?? void 0;
1495
+ const hoverEnter = Boolean(a.data?.actions?.cursorEnter?.root);
1496
+ const hoverExit = Boolean(a.data?.actions?.cursorExit?.root);
1677
1497
  v.push({
1678
1498
  id,
1679
1499
  rect: a.geom.rect,
1680
1500
  target,
1681
- attached: a.group !== void 0
1501
+ attached: a.group !== void 0,
1502
+ ...activate ? { activate } : {},
1503
+ ...ref ? { ref } : {},
1504
+ ...hoverEnter || hoverExit ? { hoverEvents: {
1505
+ enter: hoverEnter,
1506
+ exit: hoverExit
1507
+ } } : {}
1682
1508
  });
1683
1509
  }
1684
1510
  linkItemsCache.set(pon, {
@@ -1783,7 +1609,7 @@ function createAnnotationCapability(ctx, config = {}) {
1783
1609
  preview
1784
1610
  };
1785
1611
  ctx.dispatch({ type: "STAMP_ARM_CHANGED" });
1786
- ctx.tryGet(_embedpdf_plugin_interaction.InteractionToken)?.activateTool("stamp");
1612
+ ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken)?.activateTool("stamp");
1787
1613
  };
1788
1614
  const disarmStamp = () => {
1789
1615
  if (!armedStamp) return;
@@ -1920,14 +1746,14 @@ function createAnnotationCapability(ctx, config = {}) {
1920
1746
  }, rotCW);
1921
1747
  doc.page(pon).annotations.create({
1922
1748
  subtype: "stamp",
1923
- ...boxGeomFields(box, rotCW, crop),
1749
+ ...require_seam.boxGeomFields(box, rotCW, crop),
1924
1750
  source,
1925
1751
  fit: "contain"
1926
1752
  }).then((res) => {
1927
1753
  syncDTO(res.created, "baked");
1928
1754
  apply({
1929
1755
  t: "select",
1930
- ids: [refKey(res.created.ref)]
1756
+ ids: [require_seam.refKey(res.created.ref)]
1931
1757
  });
1932
1758
  }, (err) => console.error("[annotation] stamp placement failed:", err));
1933
1759
  return true;
@@ -1936,7 +1762,7 @@ function createAnnotationCapability(ctx, config = {}) {
1936
1762
  * (0 when the tool doesn't ask for upright, or the display isn't rotated). */
1937
1763
  const uprightRotFor = (displayRotation) => {
1938
1764
  if (!displayRotation) return 0;
1939
- const ix = ctx.tryGet(_embedpdf_plugin_interaction.InteractionToken);
1765
+ const ix = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
1940
1766
  return (ix ? registry.get(ix.activeToolId()) : void 0)?.upright ? (0, _embedpdf_core_annotation.uprightRotation)(displayRotation) : 0;
1941
1767
  };
1942
1768
  const placeArmedStamp = (pon, point, displayRotation) => {
@@ -1965,7 +1791,7 @@ function createAnnotationCapability(ctx, config = {}) {
1965
1791
  * document changed while the picker was open (the intent expired).
1966
1792
  */
1967
1793
  const requestStampAt = (pon, point, displayRotation) => {
1968
- const ix = ctx.tryGet(_embedpdf_plugin_interaction.InteractionToken);
1794
+ const ix = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
1969
1795
  const tool = ix ? registry.get(ix.activeToolId()) : void 0;
1970
1796
  const spec = tool?.source;
1971
1797
  if (!spec) return false;
@@ -1998,7 +1824,7 @@ function createAnnotationCapability(ctx, config = {}) {
1998
1824
  provider(req).then((picked) => {
1999
1825
  if (!picked) return;
2000
1826
  if (ctx.doc !== docAtClick) return;
2001
- if (ctx.tryGet(_embedpdf_plugin_interaction.InteractionToken)?.activeToolId() !== tool.id) return;
1827
+ if (ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken)?.activeToolId() !== tool.id) return;
2002
1828
  place(picked);
2003
1829
  }, (err) => console.error("[annotation] file-picker provider failed:", err));
2004
1830
  return true;
@@ -2015,12 +1841,12 @@ function createAnnotationCapability(ctx, config = {}) {
2015
1841
  width: crop.right - crop.left,
2016
1842
  height: crop.top - crop.bottom
2017
1843
  }, rotCW);
2018
- const draft = iconPlacementDraft(tool.subtype, boxGeomFields(box, rotCW, crop), (0, _embedpdf_core_annotation.defaultsFor)(model(), tool.preset), tool.flags, file);
1844
+ const draft = iconPlacementDraft(tool.subtype, require_seam.boxGeomFields(box, rotCW, crop), (0, _embedpdf_core_annotation.defaultsFor)(model(), tool.preset), tool.flags, file);
2019
1845
  doc.page(pon).annotations.create(draft).then((res) => {
2020
1846
  syncDTO(res.created, "baked");
2021
1847
  apply({
2022
1848
  t: "select",
2023
- ids: [refKey(res.created.ref)]
1849
+ ids: [require_seam.refKey(res.created.ref)]
2024
1850
  });
2025
1851
  }, (err) => console.error("[annotation] icon placement failed:", err));
2026
1852
  return true;
@@ -2038,7 +1864,7 @@ function createAnnotationCapability(ctx, config = {}) {
2038
1864
  */
2039
1865
  const placeAt = (pon, point, displayRotation) => {
2040
1866
  if (placeArmedStamp(pon, point, displayRotation)) return true;
2041
- const ix = ctx.tryGet(_embedpdf_plugin_interaction.InteractionToken);
1867
+ const ix = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
2042
1868
  const tool = ix ? registry.get(ix.activeToolId()) : void 0;
2043
1869
  if (!tool) return false;
2044
1870
  if (tool.subtype === "stamp") return requestStampAt(pon, point, displayRotation);
@@ -2049,7 +1875,7 @@ function createAnnotationCapability(ctx, config = {}) {
2049
1875
  };
2050
1876
  /** The page a ref lives on: from the loaded model first (covers obj/nm refs
2051
1877
  * that don't carry a pon), else the ref itself (index refs do). */
2052
- const ponForRef = (ref) => model().byId[refKey(ref)]?.pon ?? (ref.kind === "index" ? ref.pageObjectNumber : null);
1878
+ const ponForRef = (ref) => model().byId[require_seam.refKey(ref)]?.pon ?? (ref.kind === "index" ? ref.pageObjectNumber : null);
2053
1879
  /**
2054
1880
  * Re-sync one annotation into the model from the authoritative engine DTO,
2055
1881
  * with the render `source` the caller decides: `'vector'` when WE authored or
@@ -2228,10 +2054,10 @@ function createAnnotationCapability(ctx, config = {}) {
2228
2054
  });
2229
2055
  const byMember = /* @__PURE__ */ new Map();
2230
2056
  for (const t of threads) {
2231
- byMember.set(refKey(t.root.ref), t);
2232
- for (const r of t.replies) byMember.set(refKey(r.ref), t);
2233
- for (const g of t.groupedParts) byMember.set(refKey(g.ref), t);
2234
- for (const s of t.review.statusRefs) byMember.set(refKey(s), t);
2057
+ byMember.set(require_seam.refKey(t.root.ref), t);
2058
+ for (const r of t.replies) byMember.set(require_seam.refKey(r.ref), t);
2059
+ for (const g of t.groupedParts) byMember.set(require_seam.refKey(g.ref), t);
2060
+ for (const s of t.review.statusRefs) byMember.set(require_seam.refKey(s), t);
2235
2061
  }
2236
2062
  return {
2237
2063
  threads,
@@ -2253,7 +2079,7 @@ function createAnnotationCapability(ctx, config = {}) {
2253
2079
  return threadsMemo;
2254
2080
  };
2255
2081
  const threadOf = (ref) => {
2256
- const t = threadsIndex().byMember.get(refKey(ref));
2082
+ const t = threadsIndex().byMember.get(require_seam.refKey(ref));
2257
2083
  if (!t) throw new Error("[annotation] no comment thread contains this ref");
2258
2084
  return t;
2259
2085
  };
@@ -2273,7 +2099,7 @@ function createAnnotationCapability(ctx, config = {}) {
2273
2099
  await doc.page(ref.pageObjectNumber).annotations.delete(ref);
2274
2100
  apply({
2275
2101
  t: "remove",
2276
- ids: [refKey(ref)]
2102
+ ids: [require_seam.refKey(ref)]
2277
2103
  });
2278
2104
  };
2279
2105
  const REPLY_FLAGS = {
@@ -2289,7 +2115,7 @@ function createAnnotationCapability(ctx, config = {}) {
2289
2115
  /** Coarse authority mirror (doc.annotate.modify) — B3 replaces this with
2290
2116
  * the collab-scope mirrors; the FLAG split is already the real rule. */
2291
2117
  const mutationTarget = (ref) => {
2292
- const d = model().byId[refKey(ref)]?.data;
2118
+ const d = model().byId[require_seam.refKey(ref)]?.data;
2293
2119
  return {
2294
2120
  ...d?.userId !== void 0 ? { userId: d.userId } : {},
2295
2121
  ...d?.groupId !== void 0 ? { groupId: d.groupId } : {}
@@ -2322,7 +2148,7 @@ function createAnnotationCapability(ctx, config = {}) {
2322
2148
  };
2323
2149
  const allowsMutation = (action, ref) => ctx.doc?.security.allowsAnnotationMutation(action, mutationTarget(ref)) ?? false;
2324
2150
  const deletableOne = (ref) => {
2325
- const a = model().byId[refKey(ref)];
2151
+ const a = model().byId[require_seam.refKey(ref)];
2326
2152
  return !!a && (0, _embedpdf_core_annotation.annotDeletable)(a);
2327
2153
  };
2328
2154
  const threadMemberRefs = (t) => [
@@ -2333,7 +2159,7 @@ function createAnnotationCapability(ctx, config = {}) {
2333
2159
  ];
2334
2160
  const comments = {
2335
2161
  threads: () => threadsIndex().threads,
2336
- thread: (ref) => threadsIndex().byMember.get(refKey(ref)) ?? null,
2162
+ thread: (ref) => threadsIndex().byMember.get(require_seam.refKey(ref)) ?? null,
2337
2163
  hydration: () => ctx.getState().hydration,
2338
2164
  rehydrate,
2339
2165
  reply: async (ref, text) => {
@@ -2348,7 +2174,7 @@ function createAnnotationCapability(ctx, config = {}) {
2348
2174
  })).ref;
2349
2175
  },
2350
2176
  edit: async (ref, text) => {
2351
- const subtype = model().byId[refKey(ref)]?.data?.subtype;
2177
+ const subtype = model().byId[require_seam.refKey(ref)]?.data?.subtype;
2352
2178
  if (!subtype) throw new Error("[annotation] cannot edit an uncommitted annotation");
2353
2179
  await updateOne(ref, {
2354
2180
  subtype,
@@ -2411,13 +2237,13 @@ function createAnnotationCapability(ctx, config = {}) {
2411
2237
  };
2412
2238
  },
2413
2239
  permissionsFor: (ref) => {
2414
- model().byId[refKey(ref)]?.flags;
2415
- const t = threadsIndex().byMember.get(refKey(ref)) ?? null;
2240
+ model().byId[require_seam.refKey(ref)]?.flags;
2241
+ const t = threadsIndex().byMember.get(require_seam.refKey(ref)) ?? null;
2416
2242
  return {
2417
2243
  canReply: allowsCreate(),
2418
2244
  canSetStatus: allowsCreate(),
2419
2245
  canEditText: (() => {
2420
- const a = model().byId[refKey(ref)];
2246
+ const a = model().byId[require_seam.refKey(ref)];
2421
2247
  return !!a && (0, _embedpdf_core_annotation.annotContentsEditable)(a);
2422
2248
  })(),
2423
2249
  canDelete: deletableOne(ref),
@@ -2463,7 +2289,7 @@ function createAnnotationCapability(ctx, config = {}) {
2463
2289
  const crop = cropOf(a.pon);
2464
2290
  if (!crop) return;
2465
2291
  const page = doc.page(a.pon);
2466
- const target = writableTarget(desired);
2292
+ const target = require_seam.writableTarget(desired);
2467
2293
  const rects = desired == null ? [] : linkChildRects(a).map((r) => (0, _embedpdf_core_annotation.contentToPdfRect)(r, crop));
2468
2294
  const current = (0, _embedpdf_core_annotation.linkChildrenOf)(model(), id);
2469
2295
  try {
@@ -2561,7 +2387,7 @@ function createAnnotationCapability(ctx, config = {}) {
2561
2387
  apply({
2562
2388
  t: "created",
2563
2389
  tempId: fx.primary,
2564
- id: refKey(primaryResult.created.ref),
2390
+ id: require_seam.refKey(primaryResult.created.ref),
2565
2391
  ref: primaryResult.created.ref
2566
2392
  });
2567
2393
  syncDTO(primaryResult.created, "vector");
@@ -2580,7 +2406,7 @@ function createAnnotationCapability(ctx, config = {}) {
2580
2406
  apply({
2581
2407
  t: "created",
2582
2408
  tempId,
2583
- id: refKey(result.created.ref),
2409
+ id: require_seam.refKey(result.created.ref),
2584
2410
  ref: result.created.ref
2585
2411
  });
2586
2412
  syncDTO(result.created, "vector");
@@ -2589,7 +2415,7 @@ function createAnnotationCapability(ctx, config = {}) {
2589
2415
  const removeIds = ids.filter((id) => !committed.some((c) => c.tempId === id));
2590
2416
  for (const part of [...committed].reverse()) try {
2591
2417
  await doc.page(primary.pon).annotations.delete(part.ref);
2592
- removeIds.push(refKey(part.ref));
2418
+ removeIds.push(require_seam.refKey(part.ref));
2593
2419
  } catch {}
2594
2420
  if (removeIds.length) apply({
2595
2421
  t: "remove",
@@ -2607,7 +2433,7 @@ function createAnnotationCapability(ctx, config = {}) {
2607
2433
  apply({
2608
2434
  t: "created",
2609
2435
  tempId: fx.id,
2610
- id: refKey(res.created.ref),
2436
+ id: require_seam.refKey(res.created.ref),
2611
2437
  ref: res.created.ref
2612
2438
  });
2613
2439
  syncDTO(res.created, "vector");
@@ -2637,8 +2463,62 @@ function createAnnotationCapability(ctx, config = {}) {
2637
2463
  });
2638
2464
  });
2639
2465
  } else if (fx.fx === "syncLink") scheduleLinkSync(fx.id, { target: fx.target });
2640
- else doc.page(fx.ref.pageObjectNumber).annotations.delete(fx.ref).then(() => {}, () => {});
2466
+ else {
2467
+ require_seam.refKey(fx.ref);
2468
+ doc.page(fx.ref.pageObjectNumber).annotations.delete(fx.ref).then(() => {}, () => {});
2469
+ }
2641
2470
  }
2471
+ const reloadPageNow = async (pon) => {
2472
+ const doc = ctx.doc;
2473
+ const crop = cropOf(pon);
2474
+ if (!doc || !crop) return;
2475
+ try {
2476
+ const snap = await doc.page(pon).annotations.list();
2477
+ const m = model();
2478
+ const stale = m.order.filter((id) => m.byId[id]?.pon === pon);
2479
+ if (stale.length) apply({
2480
+ t: "remove",
2481
+ ids: stale
2482
+ });
2483
+ apply({
2484
+ t: "loaded",
2485
+ annots: snap.annotations.map((d) => ingestDTO(d, crop))
2486
+ });
2487
+ } catch {}
2488
+ };
2489
+ /** Script patch → the engine's per-kind patch vocabulary. Colors cross the
2490
+ * Acrobat-array → engine {r,g,b}/255 boundary here; everything else maps
2491
+ * one-to-one (the VM's validity matrix already scoped keys per kind). */
2492
+ const engineScriptPatch = (subtype, patch) => {
2493
+ const out = { subtype };
2494
+ const toEngineColor = (color) => {
2495
+ const rgb = (0, _embedpdf_core_acrojs.scriptColorToRgb)(color);
2496
+ return rgb ? {
2497
+ r: Math.round(rgb.r * 255),
2498
+ g: Math.round(rgb.g * 255),
2499
+ b: Math.round(rgb.b * 255)
2500
+ } : null;
2501
+ };
2502
+ if (patch.strokeColor) {
2503
+ const color = toEngineColor(patch.strokeColor);
2504
+ if (!color) return /* @__PURE__ */ new Error("transparent stroke colours are not supported");
2505
+ out.color = color;
2506
+ }
2507
+ if (patch.fillColor) out.interiorColor = toEngineColor(patch.fillColor);
2508
+ if (patch.opacity !== void 0) out.opacity = patch.opacity;
2509
+ if (patch.width !== void 0) out.strokeWidth = patch.width;
2510
+ if (patch.borderStyle) out.borderStyle = patch.borderStyle === "D" ? "dashed" : "solid";
2511
+ if (patch.dash) out.dashArray = patch.dash;
2512
+ if (patch.rect) out.rect = {
2513
+ left: patch.rect[0],
2514
+ bottom: patch.rect[1],
2515
+ right: patch.rect[2],
2516
+ top: patch.rect[3]
2517
+ };
2518
+ if (patch.contents !== void 0) out.contents = patch.contents;
2519
+ if (patch.flags) out.flags = patch.flags;
2520
+ return out;
2521
+ };
2642
2522
  return {
2643
2523
  create: async (pon, draft) => {
2644
2524
  const doc = ctx.doc;
@@ -2686,7 +2566,7 @@ function createAnnotationCapability(ctx, config = {}) {
2686
2566
  const resolved = buildToolRegistry([...configTools, def]).get(def.id);
2687
2567
  if (!resolved) throw new Error(`[annotation] could not resolve tool '${def.id}'`);
2688
2568
  registry.set(resolved.id, resolved);
2689
- const un = ctx.tryGet(_embedpdf_plugin_interaction.InteractionToken)?.registerTool({
2569
+ const un = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken)?.registerTool({
2690
2570
  id: resolved.id,
2691
2571
  cursor: resolved.cursor,
2692
2572
  enables: resolved.enables,
@@ -2720,34 +2600,34 @@ function createAnnotationCapability(ctx, config = {}) {
2720
2600
  await doc.page(pon).annotations.delete(ref);
2721
2601
  apply({
2722
2602
  t: "remove",
2723
- ids: [refKey(ref)]
2603
+ ids: [require_seam.refKey(ref)]
2724
2604
  });
2725
2605
  },
2726
2606
  canRead: () => canRead(),
2727
2607
  canCreate: () => allowsCreate(),
2728
2608
  canEdit: (ref) => {
2729
- const a = model().byId[refKey(ref)];
2609
+ const a = model().byId[require_seam.refKey(ref)];
2730
2610
  return !!a && (0, _embedpdf_core_annotation.annotTransformable)(a);
2731
2611
  },
2732
2612
  canDelete: (ref) => {
2733
- const a = model().byId[refKey(ref)];
2613
+ const a = model().byId[require_seam.refKey(ref)];
2734
2614
  return !!a && (0, _embedpdf_core_annotation.annotDeletable)(a);
2735
2615
  },
2736
2616
  comments,
2737
2617
  links: {
2738
2618
  of: (ref) => {
2739
- const a = model().byId[refKey(ref)];
2619
+ const a = model().byId[require_seam.refKey(ref)];
2740
2620
  if (!a) return null;
2741
2621
  return a.subtype === "link" ? a.link ?? null : (0, _embedpdf_core_annotation.linkOf)(model(), a.id);
2742
2622
  },
2743
- set: (ref, target) => scheduleLinkSync(refKey(ref), { target }),
2744
- clear: (ref) => scheduleLinkSync(refKey(ref), { target: null })
2623
+ set: (ref, target) => scheduleLinkSync(require_seam.refKey(ref), { target }),
2624
+ clear: (ref) => scheduleLinkSync(require_seam.refKey(ref), { target: null })
2745
2625
  },
2746
2626
  getSelection: () => {
2747
2627
  const m = model();
2748
2628
  return m.selected.map((id) => m.byId[id]?.ref).filter((r) => r != null);
2749
2629
  },
2750
- get: (ref) => model().byId[refKey(ref)]?.data ?? null,
2630
+ get: (ref) => model().byId[require_seam.refKey(ref)]?.data ?? null,
2751
2631
  list: (pon) => {
2752
2632
  const m = model();
2753
2633
  return m.order.map((id) => m.byId[id]).filter((a) => a?.pon === pon).map((a) => a?.data).filter((d) => d != null);
@@ -2779,10 +2659,13 @@ function createAnnotationCapability(ctx, config = {}) {
2779
2659
  const h = (0, _embedpdf_core_annotation.hitTest)(m, at.pon, at.point, chromeGeomAt(at.scale), m.hitMargin, pageBoxOf(at.pon), inertIdsAt(at.pon), viewEnv(at.zoom, at.rotation));
2780
2660
  if (h.t === "annot") id = h.id;
2781
2661
  }
2782
- if (m.hovered !== id) apply({
2783
- t: "hover",
2784
- id
2785
- });
2662
+ if (m.hovered !== id) {
2663
+ hoverFeed?.hover(id);
2664
+ apply({
2665
+ t: "hover",
2666
+ id
2667
+ });
2668
+ }
2786
2669
  },
2787
2670
  behaviorFor: (a) => behaviors.find((b) => b.matches(a) && b.engaged()) ?? null,
2788
2671
  linkItemsOn: (pon) => memoLinkItems(pon),
@@ -2866,7 +2749,7 @@ function createAnnotationCapability(ctx, config = {}) {
2866
2749
  cancelCreationDraft: () => apply({ t: "cancel" }),
2867
2750
  markupFromSelection: (subtype, preset) => {
2868
2751
  if (!allowsCreate()) return false;
2869
- const selection = ctx.tryGet(_embedpdf_plugin_selection.SelectionToken);
2752
+ const selection = ctx.tryGet(_embedpdf_plugin_selection_contract.SelectionToken);
2870
2753
  if (!selection || !selection.hasSelection()) return false;
2871
2754
  const snapshot = selection.snapshot();
2872
2755
  let created = false;
@@ -2942,7 +2825,7 @@ function createAnnotationCapability(ctx, config = {}) {
2942
2825
  select: (ref, options) => {
2943
2826
  apply({
2944
2827
  t: "select",
2945
- ids: [refKey(ref)],
2828
+ ids: [require_seam.refKey(ref)],
2946
2829
  add: options?.add
2947
2830
  });
2948
2831
  },
@@ -3002,24 +2885,7 @@ function createAnnotationCapability(ctx, config = {}) {
3002
2885
  return subs.length > 0 && subs.every((a) => a.ref != null && allowsMutation("update", a.ref));
3003
2886
  },
3004
2887
  ensurePage: () => {},
3005
- reloadPage: async (pon) => {
3006
- const doc = ctx.doc;
3007
- const crop = cropOf(pon);
3008
- if (!doc || !crop) return;
3009
- try {
3010
- const snap = await doc.page(pon).annotations.list();
3011
- const m = model();
3012
- const stale = m.order.filter((id) => m.byId[id]?.pon === pon);
3013
- if (stale.length) apply({
3014
- t: "remove",
3015
- ids: stale
3016
- });
3017
- apply({
3018
- t: "loaded",
3019
- annots: snap.annotations.map((d) => ingestDTO(d, crop))
3020
- });
3021
- } catch {}
3022
- },
2888
+ reloadPage: (pon) => reloadPageNow(pon),
3023
2889
  hydration: () => ctx.getState().hydration,
3024
2890
  ensureHydrated: () => {
3025
2891
  if (hydrationStarted) return;
@@ -3038,7 +2904,7 @@ function createAnnotationCapability(ctx, config = {}) {
3038
2904
  currentEditing: () => model().editing,
3039
2905
  beginTextEdit: (ref) => apply({
3040
2906
  t: "beginTextEdit",
3041
- id: refKey(ref)
2907
+ id: require_seam.refKey(ref)
3042
2908
  }),
3043
2909
  beginTextEditAt: (pon, point, scale, rotation, zoom) => {
3044
2910
  const m = model();
@@ -3056,10 +2922,10 @@ function createAnnotationCapability(ctx, config = {}) {
3056
2922
  setContents: (ref, text) => {
3057
2923
  apply({
3058
2924
  t: "setText",
3059
- id: refKey(ref),
2925
+ id: require_seam.refKey(ref),
3060
2926
  text
3061
2927
  });
3062
- const key = refKey(ref);
2928
+ const key = require_seam.refKey(ref);
3063
2929
  clearTimeout(textTimers.get(key));
3064
2930
  textTimers.set(key, setTimeout(() => {
3065
2931
  textTimers.delete(key);
@@ -3085,6 +2951,72 @@ function createAnnotationCapability(ctx, config = {}) {
3085
2951
  textTimers.clear();
3086
2952
  apply({ t: "endTextEdit" });
3087
2953
  },
2954
+ commitScriptEffects: async (entries) => {
2955
+ const doc = ctx.doc;
2956
+ if (!doc) return { results: entries.map((entry) => ({
2957
+ annotObjectNumber: entry.annotObjectNumber,
2958
+ status: "failed",
2959
+ error: "no document"
2960
+ })) };
2961
+ const results = [];
2962
+ const touchedPons = /* @__PURE__ */ new Set();
2963
+ let failed = false;
2964
+ for (const entry of entries) {
2965
+ if (failed) {
2966
+ results.push({
2967
+ annotObjectNumber: entry.annotObjectNumber,
2968
+ status: "skipped"
2969
+ });
2970
+ continue;
2971
+ }
2972
+ const loaded = model().byId[`obj:${entry.annotObjectNumber}`];
2973
+ const pon = loaded?.pon ?? entry.pageObjectNumber;
2974
+ let ref = loaded?.ref ?? null;
2975
+ let subtype = loaded?.subtype;
2976
+ if ((!ref || !subtype) && pon !== void 0) try {
2977
+ const { annotations } = await doc.page(pon).annotations.list();
2978
+ const dto = annotations.find((candidate) => candidate.ref.kind === "objectNumber" && candidate.ref.annotObjectNumber === entry.annotObjectNumber);
2979
+ if (dto) {
2980
+ ref = dto.ref;
2981
+ subtype = dto.subtype;
2982
+ }
2983
+ } catch {}
2984
+ if (pon === void 0 || !ref || !subtype) {
2985
+ results.push({
2986
+ annotObjectNumber: entry.annotObjectNumber,
2987
+ status: "failed",
2988
+ error: "annotation not resolved (page not loaded)"
2989
+ });
2990
+ continue;
2991
+ }
2992
+ const patch = engineScriptPatch(subtype, entry.patch);
2993
+ if (patch instanceof Error) {
2994
+ results.push({
2995
+ annotObjectNumber: entry.annotObjectNumber,
2996
+ status: "failed",
2997
+ error: patch.message
2998
+ });
2999
+ continue;
3000
+ }
3001
+ try {
3002
+ await doc.page(pon).annotations.update(ref, patch);
3003
+ touchedPons.add(pon);
3004
+ results.push({
3005
+ annotObjectNumber: entry.annotObjectNumber,
3006
+ status: "applied"
3007
+ });
3008
+ } catch (error) {
3009
+ failed = true;
3010
+ results.push({
3011
+ annotObjectNumber: entry.annotObjectNumber,
3012
+ status: "failed",
3013
+ error: error instanceof Error ? error.message : String(error)
3014
+ });
3015
+ }
3016
+ }
3017
+ for (const touched of touchedPons) await reloadPageNow(touched);
3018
+ return { results };
3019
+ },
3088
3020
  registerBehavior: (b) => {
3089
3021
  behaviors.push(b);
3090
3022
  return () => {
@@ -3095,12 +3027,6 @@ function createAnnotationCapability(ctx, config = {}) {
3095
3027
  };
3096
3028
  }
3097
3029
  //#endregion
3098
- Object.defineProperty(exports, "AnnotationToken", {
3099
- enumerable: true,
3100
- get: function() {
3101
- return AnnotationToken;
3102
- }
3103
- });
3104
3030
  Object.defineProperty(exports, "DEFAULT_TOOLS", {
3105
3031
  enumerable: true,
3106
3032
  get: function() {
@@ -3131,18 +3057,6 @@ Object.defineProperty(exports, "isTouchDirect", {
3131
3057
  return isTouchDirect;
3132
3058
  }
3133
3059
  });
3134
- Object.defineProperty(exports, "refKey", {
3135
- enumerable: true,
3136
- get: function() {
3137
- return refKey;
3138
- }
3139
- });
3140
- Object.defineProperty(exports, "styleFromDTO", {
3141
- enumerable: true,
3142
- get: function() {
3143
- return styleFromDTO;
3144
- }
3145
- });
3146
3060
  Object.defineProperty(exports, "toCreateDraft", {
3147
3061
  enumerable: true,
3148
3062
  get: function() {
@@ -3155,11 +3069,5 @@ Object.defineProperty(exports, "toPatch", {
3155
3069
  return toPatch;
3156
3070
  }
3157
3071
  });
3158
- Object.defineProperty(exports, "widgetAppearanceFromProps", {
3159
- enumerable: true,
3160
- get: function() {
3161
- return widgetAppearanceFromProps;
3162
- }
3163
- });
3164
3072
 
3165
- //# sourceMappingURL=capability-Cl9x8oLS.cjs.map
3073
+ //# sourceMappingURL=capability-Csb9WMm-.cjs.map