@embedpdf/plugin-annotation 3.0.0-next.10 → 3.0.0-next.12
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.
- package/dist/authoring-BhtyfsMx.d.cts +37 -0
- package/dist/authoring-R4ezdnXd.d.ts +37 -0
- package/dist/authoring.cjs +16 -0
- package/dist/authoring.d.cts +2 -0
- package/dist/authoring.d.ts +2 -0
- package/dist/authoring.js +3 -0
- package/dist/{capability-BRf0HrOi.js → capability-Bh_1PL5v.js} +266 -280
- package/dist/capability-Bh_1PL5v.js.map +1 -0
- package/dist/{capability-Cl9x8oLS.cjs → capability-R7dgogJs.cjs} +332 -364
- package/dist/capability-R7dgogJs.cjs.map +1 -0
- package/dist/contract/host.cjs +3 -0
- package/dist/contract/host.d.cts +2 -0
- package/dist/contract/host.d.ts +2 -0
- package/dist/contract/host.js +2 -0
- package/dist/contract.cjs +10 -0
- package/dist/contract.cjs.map +1 -0
- package/dist/contract.d.cts +10 -0
- package/dist/contract.d.ts +10 -0
- package/dist/contract.js +8 -0
- package/dist/contract.js.map +1 -0
- package/dist/index.cjs +25 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -47
- package/dist/index.d.ts +5 -47
- package/dist/index.js +15 -15
- package/dist/index.js.map +1 -1
- package/dist/internal.cjs +4 -2
- package/dist/internal.d.cts +2 -1
- package/dist/internal.d.ts +2 -1
- package/dist/internal.js +3 -1
- package/dist/seam-6pJeKOOJ.cjs +296 -0
- package/dist/seam-6pJeKOOJ.cjs.map +1 -0
- package/dist/seam-C4L_7rDt.js +225 -0
- package/dist/seam-C4L_7rDt.js.map +1 -0
- package/dist/{types-Due7UgzE.d.cts → types-BAPdbfPT.d.cts} +89 -18
- package/dist/{types-DITX_3CG.d.ts → types-BgetZ4BK.d.ts} +88 -17
- package/dist/types-BvB1vUKb.js +20 -0
- package/dist/types-BvB1vUKb.js.map +1 -0
- package/dist/types-Dlhdw2k_.cjs +31 -0
- package/dist/types-Dlhdw2k_.cjs.map +1 -0
- package/package.json +21 -7
- package/dist/capability-BRf0HrOi.js.map +0 -1
- package/dist/capability-Cl9x8oLS.cjs.map +0 -1
|
@@ -1,238 +1,13 @@
|
|
|
1
|
+
const require_seam = require("./seam-6pJeKOOJ.cjs");
|
|
2
|
+
const require_types = require("./types-Dlhdw2k_.cjs");
|
|
1
3
|
let _embedpdf_core = require("@embedpdf/core");
|
|
2
|
-
let
|
|
4
|
+
let _embedpdf_plugin_actions_contract = require("@embedpdf/plugin-actions/contract");
|
|
5
|
+
let _embedpdf_plugin_interaction_contract = require("@embedpdf/plugin-interaction/contract");
|
|
3
6
|
let _embedpdf_engine_core_runtime = require("@embedpdf/engine-core/runtime");
|
|
4
|
-
let
|
|
7
|
+
let _embedpdf_core_acrojs = require("@embedpdf/core-acrojs");
|
|
8
|
+
let _embedpdf_plugin_selection_contract = require("@embedpdf/plugin-selection/contract");
|
|
5
9
|
let _embedpdf_core_annotation = require("@embedpdf/core-annotation");
|
|
6
10
|
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
11
|
//#region src/repository/props.ts
|
|
237
12
|
/**
|
|
238
13
|
* GENERIC per-key prop lowerings — the 1:1 mappings from the flat props
|
|
@@ -251,15 +26,15 @@ const borderSlice = (style) => ({
|
|
|
251
26
|
* the old projections did (a fresh draft may not carry `text` yet). */
|
|
252
27
|
const textOf = (a) => a.text ?? _embedpdf_core_annotation.initialTextStyle;
|
|
253
28
|
const GENERIC_PROPS = {
|
|
254
|
-
color: (a) => ({ color: cssToColor(a.style.color) }),
|
|
29
|
+
color: (a) => ({ color: require_seam.cssToColor(a.style.color) }),
|
|
255
30
|
opacity: (a) => ({ opacity: a.style.opacity }),
|
|
256
31
|
blendMode: (a) => ({ blendMode: a.style.blendMode }),
|
|
257
|
-
interiorColor: (a) => ({ interiorColor: a.style.interiorColor ? cssToColor(a.style.interiorColor) : null }),
|
|
32
|
+
interiorColor: (a) => ({ interiorColor: a.style.interiorColor ? require_seam.cssToColor(a.style.interiorColor) : null }),
|
|
258
33
|
strokeWidth: (a) => ({ strokeWidth: a.style.strokeWidth }),
|
|
259
34
|
border: (a) => borderSlice(a.style),
|
|
260
35
|
fontFamily: (a) => ({ fontFamily: textOf(a).fontFamily }),
|
|
261
36
|
fontSize: (a) => ({ fontSize: textOf(a).fontSize }),
|
|
262
|
-
fontColor: (a) => ({ fontColor: cssToColor(textOf(a).fontColor) }),
|
|
37
|
+
fontColor: (a) => ({ fontColor: require_seam.cssToColor(textOf(a).fontColor) }),
|
|
263
38
|
textAlign: (a) => ({ textAlign: textOf(a).textAlign }),
|
|
264
39
|
icon: (a) => a.icon !== void 0 ? { icon: a.icon } : {},
|
|
265
40
|
link: () => ({})
|
|
@@ -270,7 +45,7 @@ const GENERIC_PROPS = {
|
|
|
270
45
|
* `/Rect`(+`unrotatedRect`+`rotation`), total (nulls state the clears). */
|
|
271
46
|
const boxEmit = (a, crop) => {
|
|
272
47
|
const g = a.geom;
|
|
273
|
-
return boxGeomFields(g.rect, (0, _embedpdf_core_annotation.geomRotation)(a.geom), crop);
|
|
48
|
+
return require_seam.boxGeomFields(g.rect, (0, _embedpdf_core_annotation.geomRotation)(a.geom), crop);
|
|
274
49
|
};
|
|
275
50
|
//#endregion
|
|
276
51
|
//#region src/repository/kinds/shape.ts
|
|
@@ -298,7 +73,7 @@ function cloudyExtras(a) {
|
|
|
298
73
|
}
|
|
299
74
|
const ingest = (dto, crop, ellipse) => {
|
|
300
75
|
const d = dto;
|
|
301
|
-
return { geom: boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, ellipse) };
|
|
76
|
+
return { geom: require_seam.boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, ellipse) };
|
|
302
77
|
};
|
|
303
78
|
const projection = (ellipse) => ({
|
|
304
79
|
ingest: (dto, crop) => ingest(dto, crop, ellipse),
|
|
@@ -322,7 +97,7 @@ const circle = projection(true);
|
|
|
322
97
|
* omission would preserve a stale advisory angle. */
|
|
323
98
|
const advisoryRotation = (g) => {
|
|
324
99
|
const rot = (0, _embedpdf_core_annotation.geomRotation)(g);
|
|
325
|
-
return { rotation: rot ? toPdfRotation(rot) : null };
|
|
100
|
+
return { rotation: rot ? require_seam.toPdfRotation(rot) : null };
|
|
326
101
|
};
|
|
327
102
|
/** `/BE` intensity for a closed poly (polygon): the curls are generated from
|
|
328
103
|
* /Vertices + /BE alone — per ISO 32000 no /RD applies — and the /Rect
|
|
@@ -367,7 +142,7 @@ const line = {
|
|
|
367
142
|
a: (0, _embedpdf_core_annotation.pdfToContentPoint)(d.linePoints.start, crop),
|
|
368
143
|
b: (0, _embedpdf_core_annotation.pdfToContentPoint)(d.linePoints.end, crop),
|
|
369
144
|
ends: d.lineEndings,
|
|
370
|
-
...rotFromDTO(d.rotation)
|
|
145
|
+
...require_seam.rotFromDTO(d.rotation)
|
|
371
146
|
} };
|
|
372
147
|
},
|
|
373
148
|
geometry: (a, crop) => {
|
|
@@ -392,7 +167,7 @@ const polyProjection = (closed) => ({
|
|
|
392
167
|
points: d.vertices.map((p) => (0, _embedpdf_core_annotation.pdfToContentPoint)(p, crop)),
|
|
393
168
|
closed,
|
|
394
169
|
..."lineEndings" in d ? { ends: d.lineEndings } : {},
|
|
395
|
-
...rotFromDTO(d.rotation)
|
|
170
|
+
...require_seam.rotFromDTO(d.rotation)
|
|
396
171
|
} };
|
|
397
172
|
},
|
|
398
173
|
geometry: (a, crop) => {
|
|
@@ -415,7 +190,7 @@ const ink = {
|
|
|
415
190
|
geom: {
|
|
416
191
|
t: "ink",
|
|
417
192
|
strokes: d.inkList.map((stroke) => stroke.map((p) => (0, _embedpdf_core_annotation.pdfToContentPoint)(p, crop))),
|
|
418
|
-
...rotFromDTO(d.rotation)
|
|
193
|
+
...require_seam.rotFromDTO(d.rotation)
|
|
419
194
|
},
|
|
420
195
|
...d.intent ? { intent: d.intent } : {}
|
|
421
196
|
};
|
|
@@ -440,7 +215,7 @@ function textFromDTO(dto) {
|
|
|
440
215
|
return {
|
|
441
216
|
fontFamily: dto.fontFamily,
|
|
442
217
|
fontSize: dto.fontSize,
|
|
443
|
-
fontColor: colorToCss(dto.fontColor ?? dto.color),
|
|
218
|
+
fontColor: require_seam.colorToCss(dto.fontColor ?? dto.color),
|
|
444
219
|
textAlign: dto.textAlign
|
|
445
220
|
};
|
|
446
221
|
}
|
|
@@ -484,7 +259,7 @@ function calloutFields(a, crop) {
|
|
|
484
259
|
calloutLine,
|
|
485
260
|
lineEnding: g.callout.ending,
|
|
486
261
|
...rot ? {
|
|
487
|
-
rotation: toPdfRotation(rot),
|
|
262
|
+
rotation: require_seam.toPdfRotation(rot),
|
|
488
263
|
unrotatedRect: (0, _embedpdf_core_annotation.contentToPdfRect)(g.rect, crop)
|
|
489
264
|
} : {
|
|
490
265
|
rotation: null,
|
|
@@ -497,11 +272,11 @@ const freeText = {
|
|
|
497
272
|
const d = dto;
|
|
498
273
|
if (d.intent === "free-text-callout" && d.calloutLine && d.calloutLine.length >= 2) {
|
|
499
274
|
const cl = d.calloutLine;
|
|
500
|
-
const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;
|
|
275
|
+
const rot = d.rotation ? require_seam.fromPdfRotation(d.rotation) : 0;
|
|
501
276
|
return {
|
|
502
277
|
geom: {
|
|
503
278
|
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),
|
|
279
|
+
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
280
|
callout: {
|
|
506
281
|
tip: (0, _embedpdf_core_annotation.pdfToContentPoint)(cl[0], crop),
|
|
507
282
|
knee: cl.length === 3 ? (0, _embedpdf_core_annotation.pdfToContentPoint)(cl[1], crop) : void 0,
|
|
@@ -512,7 +287,7 @@ const freeText = {
|
|
|
512
287
|
text: textFromDTO(d)
|
|
513
288
|
};
|
|
514
289
|
}
|
|
515
|
-
const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;
|
|
290
|
+
const rot = d.rotation ? require_seam.fromPdfRotation(d.rotation) : 0;
|
|
516
291
|
return {
|
|
517
292
|
geom: {
|
|
518
293
|
t: "text",
|
|
@@ -615,7 +390,7 @@ const strikeout = markupProjection("strikeout");
|
|
|
615
390
|
const caret = {
|
|
616
391
|
ingest: (dto, crop) => {
|
|
617
392
|
const d = dto;
|
|
618
|
-
const rot = d.rotation ? fromPdfRotation(d.rotation) : 0;
|
|
393
|
+
const rot = d.rotation ? require_seam.fromPdfRotation(d.rotation) : 0;
|
|
619
394
|
return {
|
|
620
395
|
geom: {
|
|
621
396
|
t: "caret",
|
|
@@ -625,7 +400,7 @@ const caret = {
|
|
|
625
400
|
...d.intent ? { intent: d.intent } : {}
|
|
626
401
|
};
|
|
627
402
|
},
|
|
628
|
-
geometry: (a, crop) => a.geom.t === "caret" ? boxGeomFields(a.geom.rect, a.geom.rot ?? 0, crop) : null,
|
|
403
|
+
geometry: (a, crop) => a.geom.t === "caret" ? require_seam.boxGeomFields(a.geom.rect, a.geom.rot ?? 0, crop) : null,
|
|
629
404
|
draftExtras: (a) => ({
|
|
630
405
|
rectDifferences: {
|
|
631
406
|
left: .5,
|
|
@@ -652,7 +427,7 @@ const redact = {
|
|
|
652
427
|
text: {
|
|
653
428
|
fontFamily: d.fontFamily,
|
|
654
429
|
fontSize: d.fontSize,
|
|
655
|
-
fontColor: colorToCss(d.fontColor),
|
|
430
|
+
fontColor: require_seam.colorToCss(d.fontColor),
|
|
656
431
|
textAlign: d.textAlign
|
|
657
432
|
},
|
|
658
433
|
...d.overlayText ? { label: {
|
|
@@ -693,7 +468,7 @@ const fileAttachment = iconProjection("file-attachment");
|
|
|
693
468
|
const stamp = {
|
|
694
469
|
ingest: (dto, crop) => {
|
|
695
470
|
const d = dto;
|
|
696
|
-
return { geom: boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, false) };
|
|
471
|
+
return { geom: require_seam.boxGeomFromDTO(d, d.rotation, d.unrotatedRect, crop, false) };
|
|
697
472
|
},
|
|
698
473
|
geometry: (a, crop) => boxEmit(a, crop),
|
|
699
474
|
createable: false
|
|
@@ -712,10 +487,10 @@ const link = {
|
|
|
712
487
|
},
|
|
713
488
|
geometry: rectGeometry,
|
|
714
489
|
prop: { link: (a) => {
|
|
715
|
-
const target = writableTarget(a.link);
|
|
490
|
+
const target = require_seam.writableTarget(a.link);
|
|
716
491
|
return target ? { target } : a.link == null ? { target: null } : {};
|
|
717
492
|
} },
|
|
718
|
-
draftExtras: (a) => ({ target: writableTarget(a.link) })
|
|
493
|
+
draftExtras: (a) => ({ target: require_seam.writableTarget(a.link) })
|
|
719
494
|
};
|
|
720
495
|
/** One PDF `widget` subtype → per-family CLIENT kinds (radios have no font). */
|
|
721
496
|
const WIDGET_KIND_BY_FAMILY = {
|
|
@@ -736,7 +511,7 @@ function widgetTextFromDTO(dto) {
|
|
|
736
511
|
return {
|
|
737
512
|
fontFamily: dto.fontFamily ?? "helvetica",
|
|
738
513
|
fontSize: dto.fontSize ?? 0,
|
|
739
|
-
fontColor: dto.fontColor ? colorToCss(dto.fontColor) : "#000000",
|
|
514
|
+
fontColor: dto.fontColor ? require_seam.colorToCss(dto.fontColor) : "#000000",
|
|
740
515
|
textAlign: dto.textAlign
|
|
741
516
|
};
|
|
742
517
|
}
|
|
@@ -744,7 +519,7 @@ const widget = {
|
|
|
744
519
|
ingest: (dto, crop) => {
|
|
745
520
|
const d = dto;
|
|
746
521
|
return {
|
|
747
|
-
geom: boxGeomFromDTO(d, void 0, void 0, crop, false),
|
|
522
|
+
geom: require_seam.boxGeomFromDTO(d, void 0, void 0, crop, false),
|
|
748
523
|
...WIDGET_TEXT_KINDS.has(widgetKindOf(d.fieldFamily)) ? { text: widgetTextFromDTO(d) } : {}
|
|
749
524
|
};
|
|
750
525
|
},
|
|
@@ -825,16 +600,16 @@ function fromDTO(dto, crop, source = "baked") {
|
|
|
825
600
|
const slice = projectionOf(dto.subtype).ingest(dto, crop);
|
|
826
601
|
const strippedRect = !(dto.subtype === "free-text" && dto.intent === "free-text-callout") && "unrotatedRect" in dto && "rotation" in dto && dto.rotation ? dto.unrotatedRect : void 0;
|
|
827
602
|
return {
|
|
828
|
-
id: refKey(dto.ref),
|
|
603
|
+
id: require_seam.refKey(dto.ref),
|
|
829
604
|
ref: dto.ref,
|
|
830
605
|
pon: dto.pageObjectNumber,
|
|
831
606
|
subtype: dto.subtype === "widget" ? widgetKindOf(dto.fieldFamily) : dto.subtype,
|
|
832
607
|
flags: dto.flags,
|
|
833
608
|
source,
|
|
834
609
|
data: dto,
|
|
835
|
-
...dto.inReplyTo ? { irt: refKey(dto.inReplyTo) } : {},
|
|
836
|
-
...dto.replyType === "group" && dto.inReplyTo ? { group: refKey(dto.inReplyTo) } : {},
|
|
837
|
-
style: styleFromDTO(dto),
|
|
610
|
+
...dto.inReplyTo ? { irt: require_seam.refKey(dto.inReplyTo) } : {},
|
|
611
|
+
...dto.replyType === "group" && dto.inReplyTo ? { group: require_seam.refKey(dto.inReplyTo) } : {},
|
|
612
|
+
style: require_seam.styleFromDTO(dto),
|
|
838
613
|
...slice,
|
|
839
614
|
apBox: (0, _embedpdf_core_annotation.pdfToContentRect)(strippedRect ?? dto.rect, crop),
|
|
840
615
|
...strippedRect ? { apRot: (0, _embedpdf_core_annotation.geomRotation)(slice.geom) } : {}
|
|
@@ -909,6 +684,46 @@ function toCreateDraft(a, crop) {
|
|
|
909
684
|
};
|
|
910
685
|
}
|
|
911
686
|
//#endregion
|
|
687
|
+
//#region src/hover-feed.ts
|
|
688
|
+
/**
|
|
689
|
+
* The annotation plane's E/X trigger feed — a thin adapter from the ONE
|
|
690
|
+
* pointer-driven hover seam (the `hoverAt` diff) onto the shared hover pump.
|
|
691
|
+
*
|
|
692
|
+
* Anti-cascade is structural and lives in the CALLER's seam placement:
|
|
693
|
+
* reducer-side hover clears (session-hide, remove, reload) never pass
|
|
694
|
+
* through `hoverAt`, so an effect-induced hover loss can never masquerade as
|
|
695
|
+
* a cursor exit. This module only decides WHO is hoverable here:
|
|
696
|
+
*
|
|
697
|
+
* - Drafts (no engine ref) can't carry /AA — skipped.
|
|
698
|
+
* - Widgets and links belong to their own event planes (fill controls /
|
|
699
|
+
* LinkLayer anchors own their pixels). When they ARE hit-testable on this
|
|
700
|
+
* plane, an authoring tool owns them — firing hover actions while editing
|
|
701
|
+
* would be wrong — so they are skipped unconditionally.
|
|
702
|
+
* - Tree-less annotations are FREE: no target, no dispatch, and per-event
|
|
703
|
+
* flags keep a lone /E or /X from dispatching its inert twin.
|
|
704
|
+
*/
|
|
705
|
+
function createAnnotationHoverFeed(actions, annotOf) {
|
|
706
|
+
const pump = (0, _embedpdf_plugin_actions_contract.createHoverPump)(actions.dispatch);
|
|
707
|
+
const targetOf = (id) => {
|
|
708
|
+
if (!id) return null;
|
|
709
|
+
const annot = annotOf(id);
|
|
710
|
+
if (!annot?.ref) return null;
|
|
711
|
+
if (annot.subtype.startsWith("widget") || annot.subtype === "link") return null;
|
|
712
|
+
const enter = Boolean(annot.data?.actions?.cursorEnter?.root);
|
|
713
|
+
const exit = Boolean(annot.data?.actions?.cursorExit?.root);
|
|
714
|
+
if (!enter && !exit) return null;
|
|
715
|
+
return {
|
|
716
|
+
ref: annot.ref,
|
|
717
|
+
pon: annot.pon,
|
|
718
|
+
events: {
|
|
719
|
+
enter,
|
|
720
|
+
exit
|
|
721
|
+
}
|
|
722
|
+
};
|
|
723
|
+
};
|
|
724
|
+
return { hover: (id) => pump.hover(targetOf(id)) };
|
|
725
|
+
}
|
|
726
|
+
//#endregion
|
|
912
727
|
//#region src/text-item.ts
|
|
913
728
|
/**
|
|
914
729
|
* The free-text presentation projection: the core's geometry-only `textBoxes`
|
|
@@ -960,6 +775,15 @@ function buildTextItems(m, pon, view) {
|
|
|
960
775
|
//#endregion
|
|
961
776
|
//#region src/tools.ts
|
|
962
777
|
/**
|
|
778
|
+
* The tool `armStamp` activates — and the only tool an armed payload survives
|
|
779
|
+
* onto (plus the legacy `annotation-stamp` tag, honoured for embedder configs
|
|
780
|
+
* written before the tags were unified). Placement consults the armed payload
|
|
781
|
+
* BEFORE the active tool's own `source` spec, so a payload must not outlive
|
|
782
|
+
* its tool onto a sibling stamp preset: an `image` preset's click has to open
|
|
783
|
+
* its own picker, not silently place whatever the stamp panel last armed.
|
|
784
|
+
*/
|
|
785
|
+
const ARMED_STAMP_TOOL_ID = "stamp";
|
|
786
|
+
/**
|
|
963
787
|
* The creation properties each known authoring kind actually consumes. This is
|
|
964
788
|
* deliberately separate from the flat internal patch vocabulary: it gives tool
|
|
965
789
|
* configuration precise compile-time and runtime validation while mixed-selection
|
|
@@ -1293,7 +1117,7 @@ const DEFAULT_TOOLS = [
|
|
|
1293
1117
|
}
|
|
1294
1118
|
},
|
|
1295
1119
|
{
|
|
1296
|
-
id:
|
|
1120
|
+
id: ARMED_STAMP_TOOL_ID,
|
|
1297
1121
|
subtype: "stamp",
|
|
1298
1122
|
cursor: "copy",
|
|
1299
1123
|
enables: ["annotation-place", "annotation-edit"],
|
|
@@ -1475,7 +1299,7 @@ const isIconPlaceKind = (subtype) => subtype === "text" || subtype === "file-att
|
|
|
1475
1299
|
function iconPlacementDraft(subtype, geom, defaults, flags, file) {
|
|
1476
1300
|
const shared = {
|
|
1477
1301
|
...geom,
|
|
1478
|
-
color: cssToColor(defaults.color),
|
|
1302
|
+
color: require_seam.cssToColor(defaults.color),
|
|
1479
1303
|
opacity: defaults.opacity,
|
|
1480
1304
|
flags: {
|
|
1481
1305
|
print: true,
|
|
@@ -1522,6 +1346,8 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1522
1346
|
* slot. See {@link FilePickerProvider}. */
|
|
1523
1347
|
let filePickerProvider = null;
|
|
1524
1348
|
const model = () => ctx.getState().model;
|
|
1349
|
+
const actionsForHover = ctx.tryGet(_embedpdf_plugin_actions_contract.ActionsToken);
|
|
1350
|
+
const hoverFeed = actionsForHover ? createAnnotationHoverFeed(actionsForHover, (id) => model().byId[id] ?? null) : null;
|
|
1525
1351
|
const chromeSettings = () => ctx.getState().chrome;
|
|
1526
1352
|
/**
|
|
1527
1353
|
* Ids on a page whose Behavior is currently ENGAGED (form widgets under a
|
|
@@ -1674,11 +1500,21 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1674
1500
|
if (!(0, _embedpdf_core_annotation.viewable)(a.flags, false)) continue;
|
|
1675
1501
|
const target = a.link ?? (a.data?.subtype === "link" ? a.data.target ?? null : null);
|
|
1676
1502
|
if (target == null || a.geom.t !== "rect") continue;
|
|
1503
|
+
const activate = a.data?.actions?.activate;
|
|
1504
|
+
const ref = a.ref ?? a.data?.ref ?? void 0;
|
|
1505
|
+
const hoverEnter = Boolean(a.data?.actions?.cursorEnter?.root);
|
|
1506
|
+
const hoverExit = Boolean(a.data?.actions?.cursorExit?.root);
|
|
1677
1507
|
v.push({
|
|
1678
1508
|
id,
|
|
1679
1509
|
rect: a.geom.rect,
|
|
1680
1510
|
target,
|
|
1681
|
-
attached: a.group !== void 0
|
|
1511
|
+
attached: a.group !== void 0,
|
|
1512
|
+
...activate ? { activate } : {},
|
|
1513
|
+
...ref ? { ref } : {},
|
|
1514
|
+
...hoverEnter || hoverExit ? { hoverEvents: {
|
|
1515
|
+
enter: hoverEnter,
|
|
1516
|
+
exit: hoverExit
|
|
1517
|
+
} } : {}
|
|
1682
1518
|
});
|
|
1683
1519
|
}
|
|
1684
1520
|
linkItemsCache.set(pon, {
|
|
@@ -1739,6 +1575,14 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1739
1575
|
* rendered, never synced, and dies with the tool.
|
|
1740
1576
|
*/
|
|
1741
1577
|
let armedStamp = null;
|
|
1578
|
+
/** Fixed bytes as a provider: the same image at every size. */
|
|
1579
|
+
const fixedPreview = (bytes, mimeType) => {
|
|
1580
|
+
const preview = {
|
|
1581
|
+
bytes,
|
|
1582
|
+
...mimeType ? { mimeType } : {}
|
|
1583
|
+
};
|
|
1584
|
+
return async () => preview;
|
|
1585
|
+
};
|
|
1742
1586
|
/**
|
|
1743
1587
|
* The desired stamp size (PDF points) from sniffed bytes: the image's
|
|
1744
1588
|
* INTRINSIC pixel dimensions taken 1:1 as points (the v2 rule — keep the
|
|
@@ -1767,23 +1611,21 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1767
1611
|
const meta = (0, _embedpdf_engine_core_runtime.sniffBinaryMetadata)(resolved.bytes);
|
|
1768
1612
|
if (!meta) throw new Error("[annotation] stamp source must be PNG, JPEG, or single-page PDF bytes");
|
|
1769
1613
|
let preview = null;
|
|
1770
|
-
if (input.preview)
|
|
1614
|
+
if (typeof input.preview === "function") preview = input.preview;
|
|
1615
|
+
else if (input.preview) {
|
|
1771
1616
|
const p = await (0, _embedpdf_engine_core_runtime.resolveBinarySource)(input.preview);
|
|
1772
|
-
preview =
|
|
1773
|
-
|
|
1774
|
-
mimeType: p.mimeType
|
|
1775
|
-
};
|
|
1776
|
-
} else if (meta.mimeType !== "application/pdf") preview = {
|
|
1777
|
-
bytes: new Uint8Array(resolved.bytes),
|
|
1778
|
-
mimeType: meta.mimeType
|
|
1779
|
-
};
|
|
1617
|
+
preview = fixedPreview(new Uint8Array(p.bytes), p.mimeType);
|
|
1618
|
+
} else if (meta.mimeType !== "application/pdf") preview = fixedPreview(new Uint8Array(resolved.bytes), meta.mimeType);
|
|
1780
1619
|
armedStamp = {
|
|
1781
1620
|
source: input.source,
|
|
1782
1621
|
...desiredStampSize(meta, input.targetWidth, input.intrinsicSize),
|
|
1783
|
-
preview
|
|
1622
|
+
preview,
|
|
1623
|
+
previewCache: /* @__PURE__ */ new Map(),
|
|
1624
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
1625
|
+
...input.subject !== void 0 ? { subject: input.subject } : {}
|
|
1784
1626
|
};
|
|
1785
1627
|
ctx.dispatch({ type: "STAMP_ARM_CHANGED" });
|
|
1786
|
-
ctx.tryGet(
|
|
1628
|
+
ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken)?.activateTool(ARMED_STAMP_TOOL_ID);
|
|
1787
1629
|
};
|
|
1788
1630
|
const disarmStamp = () => {
|
|
1789
1631
|
if (!armedStamp) return;
|
|
@@ -1910,42 +1752,66 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1910
1752
|
* emits the repository's box rotation fields — the engine bakes the tilted
|
|
1911
1753
|
* /AP exactly as an interactively rotated stamp round-trips, and the fit uses
|
|
1912
1754
|
* the ROTATED footprint. Returns false when the page/document isn't ready. */
|
|
1913
|
-
const createStampAt = (pon, point, source, desired, rotCW = 0) => {
|
|
1755
|
+
const createStampAt = (pon, point, source, desired, rotCW = 0, identity = {}) => {
|
|
1914
1756
|
const doc = ctx.doc;
|
|
1915
1757
|
const crop = cropOf(pon);
|
|
1916
|
-
if (!doc || !crop) return
|
|
1758
|
+
if (!doc || !crop) return null;
|
|
1917
1759
|
const box = (0, _embedpdf_core_annotation.fitStampBox)(point, desired, {
|
|
1918
1760
|
width: crop.right - crop.left,
|
|
1919
1761
|
height: crop.top - crop.bottom
|
|
1920
1762
|
}, rotCW);
|
|
1921
|
-
doc.page(pon).annotations.create({
|
|
1763
|
+
return doc.page(pon).annotations.create({
|
|
1922
1764
|
subtype: "stamp",
|
|
1923
|
-
...boxGeomFields(box, rotCW, crop),
|
|
1765
|
+
...require_seam.boxGeomFields(box, rotCW, crop),
|
|
1924
1766
|
source,
|
|
1925
|
-
fit: "contain"
|
|
1767
|
+
fit: "contain",
|
|
1768
|
+
...identity.name !== void 0 ? { name: identity.name } : {},
|
|
1769
|
+
...identity.subject !== void 0 ? { subject: identity.subject } : {}
|
|
1926
1770
|
}).then((res) => {
|
|
1927
1771
|
syncDTO(res.created, "baked");
|
|
1928
1772
|
apply({
|
|
1929
1773
|
t: "select",
|
|
1930
|
-
ids: [refKey(res.created.ref)]
|
|
1774
|
+
ids: [require_seam.refKey(res.created.ref)]
|
|
1931
1775
|
});
|
|
1932
|
-
|
|
1776
|
+
return res.created.ref;
|
|
1777
|
+
});
|
|
1778
|
+
};
|
|
1779
|
+
/** The click path's fire-and-forget wrapper: a rejected placement is logged,
|
|
1780
|
+
* never thrown into the gesture. */
|
|
1781
|
+
const createStampAtSync = (pon, point, source, desired, rotCW = 0, identity = {}) => {
|
|
1782
|
+
const placed = createStampAt(pon, point, source, desired, rotCW, identity);
|
|
1783
|
+
if (!placed) return false;
|
|
1784
|
+
placed.catch((err) => console.error("[annotation] stamp placement failed:", err));
|
|
1933
1785
|
return true;
|
|
1934
1786
|
};
|
|
1787
|
+
/** Programmatic placement — the same law as a click, awaited. */
|
|
1788
|
+
const placeStamp = async (input, placement) => {
|
|
1789
|
+
const meta = (0, _embedpdf_engine_core_runtime.sniffBinaryMetadata)((await (0, _embedpdf_engine_core_runtime.resolveBinarySource)(input.source)).bytes);
|
|
1790
|
+
if (!meta) throw new Error("[annotation] stamp source must be PNG, JPEG, or single-page PDF bytes");
|
|
1791
|
+
const placed = createStampAt(placement.pageObjectNumber, placement.at, input.source, desiredStampSize(meta, placement.targetWidth ?? input.targetWidth, input.intrinsicSize), placement.rotation ?? 0, {
|
|
1792
|
+
...input.name !== void 0 ? { name: input.name } : {},
|
|
1793
|
+
...input.subject !== void 0 ? { subject: input.subject } : {}
|
|
1794
|
+
});
|
|
1795
|
+
if (!placed) throw new Error(`[annotation] cannot place a stamp on page ${placement.pageObjectNumber}: document or page not ready`);
|
|
1796
|
+
return placed;
|
|
1797
|
+
};
|
|
1935
1798
|
/** The active tool's upright counter-rotation for a click at `displayRotation`
|
|
1936
1799
|
* (0 when the tool doesn't ask for upright, or the display isn't rotated). */
|
|
1937
1800
|
const uprightRotFor = (displayRotation) => {
|
|
1938
1801
|
if (!displayRotation) return 0;
|
|
1939
|
-
const ix = ctx.tryGet(
|
|
1802
|
+
const ix = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
|
|
1940
1803
|
return (ix ? registry.get(ix.activeToolId()) : void 0)?.upright ? (0, _embedpdf_core_annotation.uprightRotation)(displayRotation) : 0;
|
|
1941
1804
|
};
|
|
1942
1805
|
const placeArmedStamp = (pon, point, displayRotation) => {
|
|
1943
1806
|
const armed = armedStamp;
|
|
1944
1807
|
if (!armed) return false;
|
|
1945
|
-
return
|
|
1808
|
+
return createStampAtSync(pon, point, armed.source, {
|
|
1946
1809
|
width: armed.width,
|
|
1947
1810
|
height: armed.height
|
|
1948
|
-
}, uprightRotFor(displayRotation)
|
|
1811
|
+
}, uprightRotFor(displayRotation), {
|
|
1812
|
+
...armed.name !== void 0 ? { name: armed.name } : {},
|
|
1813
|
+
...armed.subject !== void 0 ? { subject: armed.subject } : {}
|
|
1814
|
+
});
|
|
1949
1815
|
};
|
|
1950
1816
|
/** Sniff a stamp source (rejecting non-image bytes) and place it at its
|
|
1951
1817
|
* intrinsic size (fit to the page in {@link createStampAt}); `targetWidth`
|
|
@@ -1956,7 +1822,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1956
1822
|
console.error("[annotation] stamp source must be PNG, JPEG, or single-page PDF bytes");
|
|
1957
1823
|
return;
|
|
1958
1824
|
}
|
|
1959
|
-
|
|
1825
|
+
createStampAtSync(pon, point, source, desiredStampSize(meta, targetWidth), rotCW);
|
|
1960
1826
|
};
|
|
1961
1827
|
/**
|
|
1962
1828
|
* Click-to-place: resolve the ACTIVE tool's source spec. Fixed `bytes` place
|
|
@@ -1965,7 +1831,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1965
1831
|
* document changed while the picker was open (the intent expired).
|
|
1966
1832
|
*/
|
|
1967
1833
|
const requestStampAt = (pon, point, displayRotation) => {
|
|
1968
|
-
const ix = ctx.tryGet(
|
|
1834
|
+
const ix = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
|
|
1969
1835
|
const tool = ix ? registry.get(ix.activeToolId()) : void 0;
|
|
1970
1836
|
const spec = tool?.source;
|
|
1971
1837
|
if (!spec) return false;
|
|
@@ -1998,7 +1864,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
1998
1864
|
provider(req).then((picked) => {
|
|
1999
1865
|
if (!picked) return;
|
|
2000
1866
|
if (ctx.doc !== docAtClick) return;
|
|
2001
|
-
if (ctx.tryGet(
|
|
1867
|
+
if (ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken)?.activeToolId() !== tool.id) return;
|
|
2002
1868
|
place(picked);
|
|
2003
1869
|
}, (err) => console.error("[annotation] file-picker provider failed:", err));
|
|
2004
1870
|
return true;
|
|
@@ -2015,12 +1881,12 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2015
1881
|
width: crop.right - crop.left,
|
|
2016
1882
|
height: crop.top - crop.bottom
|
|
2017
1883
|
}, rotCW);
|
|
2018
|
-
const draft = iconPlacementDraft(tool.subtype, boxGeomFields(box, rotCW, crop), (0, _embedpdf_core_annotation.defaultsFor)(model(), tool.preset), tool.flags, file);
|
|
1884
|
+
const draft = iconPlacementDraft(tool.subtype, require_seam.boxGeomFields(box, rotCW, crop), (0, _embedpdf_core_annotation.defaultsFor)(model(), tool.preset), tool.flags, file);
|
|
2019
1885
|
doc.page(pon).annotations.create(draft).then((res) => {
|
|
2020
1886
|
syncDTO(res.created, "baked");
|
|
2021
1887
|
apply({
|
|
2022
1888
|
t: "select",
|
|
2023
|
-
ids: [refKey(res.created.ref)]
|
|
1889
|
+
ids: [require_seam.refKey(res.created.ref)]
|
|
2024
1890
|
});
|
|
2025
1891
|
}, (err) => console.error("[annotation] icon placement failed:", err));
|
|
2026
1892
|
return true;
|
|
@@ -2038,7 +1904,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2038
1904
|
*/
|
|
2039
1905
|
const placeAt = (pon, point, displayRotation) => {
|
|
2040
1906
|
if (placeArmedStamp(pon, point, displayRotation)) return true;
|
|
2041
|
-
const ix = ctx.tryGet(
|
|
1907
|
+
const ix = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken);
|
|
2042
1908
|
const tool = ix ? registry.get(ix.activeToolId()) : void 0;
|
|
2043
1909
|
if (!tool) return false;
|
|
2044
1910
|
if (tool.subtype === "stamp") return requestStampAt(pon, point, displayRotation);
|
|
@@ -2049,7 +1915,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2049
1915
|
};
|
|
2050
1916
|
/** The page a ref lives on: from the loaded model first (covers obj/nm refs
|
|
2051
1917
|
* 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);
|
|
1918
|
+
const ponForRef = (ref) => model().byId[require_seam.refKey(ref)]?.pon ?? (ref.kind === "index" ? ref.pageObjectNumber : null);
|
|
2053
1919
|
/**
|
|
2054
1920
|
* Re-sync one annotation into the model from the authoritative engine DTO,
|
|
2055
1921
|
* with the render `source` the caller decides: `'vector'` when WE authored or
|
|
@@ -2228,10 +2094,10 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2228
2094
|
});
|
|
2229
2095
|
const byMember = /* @__PURE__ */ new Map();
|
|
2230
2096
|
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);
|
|
2097
|
+
byMember.set(require_seam.refKey(t.root.ref), t);
|
|
2098
|
+
for (const r of t.replies) byMember.set(require_seam.refKey(r.ref), t);
|
|
2099
|
+
for (const g of t.groupedParts) byMember.set(require_seam.refKey(g.ref), t);
|
|
2100
|
+
for (const s of t.review.statusRefs) byMember.set(require_seam.refKey(s), t);
|
|
2235
2101
|
}
|
|
2236
2102
|
return {
|
|
2237
2103
|
threads,
|
|
@@ -2253,7 +2119,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2253
2119
|
return threadsMemo;
|
|
2254
2120
|
};
|
|
2255
2121
|
const threadOf = (ref) => {
|
|
2256
|
-
const t = threadsIndex().byMember.get(refKey(ref));
|
|
2122
|
+
const t = threadsIndex().byMember.get(require_seam.refKey(ref));
|
|
2257
2123
|
if (!t) throw new Error("[annotation] no comment thread contains this ref");
|
|
2258
2124
|
return t;
|
|
2259
2125
|
};
|
|
@@ -2273,7 +2139,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2273
2139
|
await doc.page(ref.pageObjectNumber).annotations.delete(ref);
|
|
2274
2140
|
apply({
|
|
2275
2141
|
t: "remove",
|
|
2276
|
-
ids: [refKey(ref)]
|
|
2142
|
+
ids: [require_seam.refKey(ref)]
|
|
2277
2143
|
});
|
|
2278
2144
|
};
|
|
2279
2145
|
const REPLY_FLAGS = {
|
|
@@ -2289,7 +2155,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2289
2155
|
/** Coarse authority mirror (doc.annotate.modify) — B3 replaces this with
|
|
2290
2156
|
* the collab-scope mirrors; the FLAG split is already the real rule. */
|
|
2291
2157
|
const mutationTarget = (ref) => {
|
|
2292
|
-
const d = model().byId[refKey(ref)]?.data;
|
|
2158
|
+
const d = model().byId[require_seam.refKey(ref)]?.data;
|
|
2293
2159
|
return {
|
|
2294
2160
|
...d?.userId !== void 0 ? { userId: d.userId } : {},
|
|
2295
2161
|
...d?.groupId !== void 0 ? { groupId: d.groupId } : {}
|
|
@@ -2322,7 +2188,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2322
2188
|
};
|
|
2323
2189
|
const allowsMutation = (action, ref) => ctx.doc?.security.allowsAnnotationMutation(action, mutationTarget(ref)) ?? false;
|
|
2324
2190
|
const deletableOne = (ref) => {
|
|
2325
|
-
const a = model().byId[refKey(ref)];
|
|
2191
|
+
const a = model().byId[require_seam.refKey(ref)];
|
|
2326
2192
|
return !!a && (0, _embedpdf_core_annotation.annotDeletable)(a);
|
|
2327
2193
|
};
|
|
2328
2194
|
const threadMemberRefs = (t) => [
|
|
@@ -2333,7 +2199,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2333
2199
|
];
|
|
2334
2200
|
const comments = {
|
|
2335
2201
|
threads: () => threadsIndex().threads,
|
|
2336
|
-
thread: (ref) => threadsIndex().byMember.get(refKey(ref)) ?? null,
|
|
2202
|
+
thread: (ref) => threadsIndex().byMember.get(require_seam.refKey(ref)) ?? null,
|
|
2337
2203
|
hydration: () => ctx.getState().hydration,
|
|
2338
2204
|
rehydrate,
|
|
2339
2205
|
reply: async (ref, text) => {
|
|
@@ -2348,7 +2214,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2348
2214
|
})).ref;
|
|
2349
2215
|
},
|
|
2350
2216
|
edit: async (ref, text) => {
|
|
2351
|
-
const subtype = model().byId[refKey(ref)]?.data?.subtype;
|
|
2217
|
+
const subtype = model().byId[require_seam.refKey(ref)]?.data?.subtype;
|
|
2352
2218
|
if (!subtype) throw new Error("[annotation] cannot edit an uncommitted annotation");
|
|
2353
2219
|
await updateOne(ref, {
|
|
2354
2220
|
subtype,
|
|
@@ -2411,13 +2277,13 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2411
2277
|
};
|
|
2412
2278
|
},
|
|
2413
2279
|
permissionsFor: (ref) => {
|
|
2414
|
-
model().byId[refKey(ref)]?.flags;
|
|
2415
|
-
const t = threadsIndex().byMember.get(refKey(ref)) ?? null;
|
|
2280
|
+
model().byId[require_seam.refKey(ref)]?.flags;
|
|
2281
|
+
const t = threadsIndex().byMember.get(require_seam.refKey(ref)) ?? null;
|
|
2416
2282
|
return {
|
|
2417
2283
|
canReply: allowsCreate(),
|
|
2418
2284
|
canSetStatus: allowsCreate(),
|
|
2419
2285
|
canEditText: (() => {
|
|
2420
|
-
const a = model().byId[refKey(ref)];
|
|
2286
|
+
const a = model().byId[require_seam.refKey(ref)];
|
|
2421
2287
|
return !!a && (0, _embedpdf_core_annotation.annotContentsEditable)(a);
|
|
2422
2288
|
})(),
|
|
2423
2289
|
canDelete: deletableOne(ref),
|
|
@@ -2463,7 +2329,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2463
2329
|
const crop = cropOf(a.pon);
|
|
2464
2330
|
if (!crop) return;
|
|
2465
2331
|
const page = doc.page(a.pon);
|
|
2466
|
-
const target = writableTarget(desired);
|
|
2332
|
+
const target = require_seam.writableTarget(desired);
|
|
2467
2333
|
const rects = desired == null ? [] : linkChildRects(a).map((r) => (0, _embedpdf_core_annotation.contentToPdfRect)(r, crop));
|
|
2468
2334
|
const current = (0, _embedpdf_core_annotation.linkChildrenOf)(model(), id);
|
|
2469
2335
|
try {
|
|
@@ -2561,7 +2427,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2561
2427
|
apply({
|
|
2562
2428
|
t: "created",
|
|
2563
2429
|
tempId: fx.primary,
|
|
2564
|
-
id: refKey(primaryResult.created.ref),
|
|
2430
|
+
id: require_seam.refKey(primaryResult.created.ref),
|
|
2565
2431
|
ref: primaryResult.created.ref
|
|
2566
2432
|
});
|
|
2567
2433
|
syncDTO(primaryResult.created, "vector");
|
|
@@ -2580,7 +2446,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2580
2446
|
apply({
|
|
2581
2447
|
t: "created",
|
|
2582
2448
|
tempId,
|
|
2583
|
-
id: refKey(result.created.ref),
|
|
2449
|
+
id: require_seam.refKey(result.created.ref),
|
|
2584
2450
|
ref: result.created.ref
|
|
2585
2451
|
});
|
|
2586
2452
|
syncDTO(result.created, "vector");
|
|
@@ -2589,7 +2455,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2589
2455
|
const removeIds = ids.filter((id) => !committed.some((c) => c.tempId === id));
|
|
2590
2456
|
for (const part of [...committed].reverse()) try {
|
|
2591
2457
|
await doc.page(primary.pon).annotations.delete(part.ref);
|
|
2592
|
-
removeIds.push(refKey(part.ref));
|
|
2458
|
+
removeIds.push(require_seam.refKey(part.ref));
|
|
2593
2459
|
} catch {}
|
|
2594
2460
|
if (removeIds.length) apply({
|
|
2595
2461
|
t: "remove",
|
|
@@ -2607,7 +2473,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2607
2473
|
apply({
|
|
2608
2474
|
t: "created",
|
|
2609
2475
|
tempId: fx.id,
|
|
2610
|
-
id: refKey(res.created.ref),
|
|
2476
|
+
id: require_seam.refKey(res.created.ref),
|
|
2611
2477
|
ref: res.created.ref
|
|
2612
2478
|
});
|
|
2613
2479
|
syncDTO(res.created, "vector");
|
|
@@ -2637,8 +2503,62 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2637
2503
|
});
|
|
2638
2504
|
});
|
|
2639
2505
|
} else if (fx.fx === "syncLink") scheduleLinkSync(fx.id, { target: fx.target });
|
|
2640
|
-
else
|
|
2506
|
+
else {
|
|
2507
|
+
require_seam.refKey(fx.ref);
|
|
2508
|
+
doc.page(fx.ref.pageObjectNumber).annotations.delete(fx.ref).then(() => {}, () => {});
|
|
2509
|
+
}
|
|
2641
2510
|
}
|
|
2511
|
+
const reloadPageNow = async (pon) => {
|
|
2512
|
+
const doc = ctx.doc;
|
|
2513
|
+
const crop = cropOf(pon);
|
|
2514
|
+
if (!doc || !crop) return;
|
|
2515
|
+
try {
|
|
2516
|
+
const snap = await doc.page(pon).annotations.list();
|
|
2517
|
+
const m = model();
|
|
2518
|
+
const stale = m.order.filter((id) => m.byId[id]?.pon === pon);
|
|
2519
|
+
if (stale.length) apply({
|
|
2520
|
+
t: "remove",
|
|
2521
|
+
ids: stale
|
|
2522
|
+
});
|
|
2523
|
+
apply({
|
|
2524
|
+
t: "loaded",
|
|
2525
|
+
annots: snap.annotations.map((d) => ingestDTO(d, crop))
|
|
2526
|
+
});
|
|
2527
|
+
} catch {}
|
|
2528
|
+
};
|
|
2529
|
+
/** Script patch → the engine's per-kind patch vocabulary. Colors cross the
|
|
2530
|
+
* Acrobat-array → engine {r,g,b}/255 boundary here; everything else maps
|
|
2531
|
+
* one-to-one (the VM's validity matrix already scoped keys per kind). */
|
|
2532
|
+
const engineScriptPatch = (subtype, patch) => {
|
|
2533
|
+
const out = { subtype };
|
|
2534
|
+
const toEngineColor = (color) => {
|
|
2535
|
+
const rgb = (0, _embedpdf_core_acrojs.scriptColorToRgb)(color);
|
|
2536
|
+
return rgb ? {
|
|
2537
|
+
r: Math.round(rgb.r * 255),
|
|
2538
|
+
g: Math.round(rgb.g * 255),
|
|
2539
|
+
b: Math.round(rgb.b * 255)
|
|
2540
|
+
} : null;
|
|
2541
|
+
};
|
|
2542
|
+
if (patch.strokeColor) {
|
|
2543
|
+
const color = toEngineColor(patch.strokeColor);
|
|
2544
|
+
if (!color) return /* @__PURE__ */ new Error("transparent stroke colours are not supported");
|
|
2545
|
+
out.color = color;
|
|
2546
|
+
}
|
|
2547
|
+
if (patch.fillColor) out.interiorColor = toEngineColor(patch.fillColor);
|
|
2548
|
+
if (patch.opacity !== void 0) out.opacity = patch.opacity;
|
|
2549
|
+
if (patch.width !== void 0) out.strokeWidth = patch.width;
|
|
2550
|
+
if (patch.borderStyle) out.borderStyle = patch.borderStyle === "D" ? "dashed" : "solid";
|
|
2551
|
+
if (patch.dash) out.dashArray = patch.dash;
|
|
2552
|
+
if (patch.rect) out.rect = {
|
|
2553
|
+
left: patch.rect[0],
|
|
2554
|
+
bottom: patch.rect[1],
|
|
2555
|
+
right: patch.rect[2],
|
|
2556
|
+
top: patch.rect[3]
|
|
2557
|
+
};
|
|
2558
|
+
if (patch.contents !== void 0) out.contents = patch.contents;
|
|
2559
|
+
if (patch.flags) out.flags = patch.flags;
|
|
2560
|
+
return out;
|
|
2561
|
+
};
|
|
2642
2562
|
return {
|
|
2643
2563
|
create: async (pon, draft) => {
|
|
2644
2564
|
const doc = ctx.doc;
|
|
@@ -2652,6 +2572,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2652
2572
|
return res.created.ref;
|
|
2653
2573
|
},
|
|
2654
2574
|
armStamp,
|
|
2575
|
+
placeStamp,
|
|
2655
2576
|
disarmStamp,
|
|
2656
2577
|
placeArmedStamp,
|
|
2657
2578
|
requestStampAt,
|
|
@@ -2665,7 +2586,20 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2665
2586
|
const g = ctx.getState().toolGhost;
|
|
2666
2587
|
return g && g.pon === pon ? g : null;
|
|
2667
2588
|
},
|
|
2668
|
-
armedStampPreview: () =>
|
|
2589
|
+
armedStampPreview: (devicePixelWidth) => {
|
|
2590
|
+
const armed = armedStamp;
|
|
2591
|
+
if (!armed?.preview) return Promise.resolve(null);
|
|
2592
|
+
const bucket = require_types.previewBucket(devicePixelWidth ?? 0);
|
|
2593
|
+
let pending = armed.previewCache.get(bucket);
|
|
2594
|
+
if (!pending) {
|
|
2595
|
+
pending = armed.preview(bucket).catch((error) => {
|
|
2596
|
+
console.error("[annotation] stamp ghost preview failed:", error);
|
|
2597
|
+
return null;
|
|
2598
|
+
});
|
|
2599
|
+
armed.previewCache.set(bucket, pending);
|
|
2600
|
+
}
|
|
2601
|
+
return pending;
|
|
2602
|
+
},
|
|
2669
2603
|
stampArmEpoch: () => ctx.getState().stampArmEpoch,
|
|
2670
2604
|
setFilePickerProvider: (provider) => {
|
|
2671
2605
|
filePickerProvider = provider;
|
|
@@ -2686,7 +2620,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2686
2620
|
const resolved = buildToolRegistry([...configTools, def]).get(def.id);
|
|
2687
2621
|
if (!resolved) throw new Error(`[annotation] could not resolve tool '${def.id}'`);
|
|
2688
2622
|
registry.set(resolved.id, resolved);
|
|
2689
|
-
const un = ctx.tryGet(
|
|
2623
|
+
const un = ctx.tryGet(_embedpdf_plugin_interaction_contract.InteractionToken)?.registerTool({
|
|
2690
2624
|
id: resolved.id,
|
|
2691
2625
|
cursor: resolved.cursor,
|
|
2692
2626
|
enables: resolved.enables,
|
|
@@ -2720,34 +2654,34 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2720
2654
|
await doc.page(pon).annotations.delete(ref);
|
|
2721
2655
|
apply({
|
|
2722
2656
|
t: "remove",
|
|
2723
|
-
ids: [refKey(ref)]
|
|
2657
|
+
ids: [require_seam.refKey(ref)]
|
|
2724
2658
|
});
|
|
2725
2659
|
},
|
|
2726
2660
|
canRead: () => canRead(),
|
|
2727
2661
|
canCreate: () => allowsCreate(),
|
|
2728
2662
|
canEdit: (ref) => {
|
|
2729
|
-
const a = model().byId[refKey(ref)];
|
|
2663
|
+
const a = model().byId[require_seam.refKey(ref)];
|
|
2730
2664
|
return !!a && (0, _embedpdf_core_annotation.annotTransformable)(a);
|
|
2731
2665
|
},
|
|
2732
2666
|
canDelete: (ref) => {
|
|
2733
|
-
const a = model().byId[refKey(ref)];
|
|
2667
|
+
const a = model().byId[require_seam.refKey(ref)];
|
|
2734
2668
|
return !!a && (0, _embedpdf_core_annotation.annotDeletable)(a);
|
|
2735
2669
|
},
|
|
2736
2670
|
comments,
|
|
2737
2671
|
links: {
|
|
2738
2672
|
of: (ref) => {
|
|
2739
|
-
const a = model().byId[refKey(ref)];
|
|
2673
|
+
const a = model().byId[require_seam.refKey(ref)];
|
|
2740
2674
|
if (!a) return null;
|
|
2741
2675
|
return a.subtype === "link" ? a.link ?? null : (0, _embedpdf_core_annotation.linkOf)(model(), a.id);
|
|
2742
2676
|
},
|
|
2743
|
-
set: (ref, target) => scheduleLinkSync(refKey(ref), { target }),
|
|
2744
|
-
clear: (ref) => scheduleLinkSync(refKey(ref), { target: null })
|
|
2677
|
+
set: (ref, target) => scheduleLinkSync(require_seam.refKey(ref), { target }),
|
|
2678
|
+
clear: (ref) => scheduleLinkSync(require_seam.refKey(ref), { target: null })
|
|
2745
2679
|
},
|
|
2746
2680
|
getSelection: () => {
|
|
2747
2681
|
const m = model();
|
|
2748
2682
|
return m.selected.map((id) => m.byId[id]?.ref).filter((r) => r != null);
|
|
2749
2683
|
},
|
|
2750
|
-
get: (ref) => model().byId[refKey(ref)]?.data ?? null,
|
|
2684
|
+
get: (ref) => model().byId[require_seam.refKey(ref)]?.data ?? null,
|
|
2751
2685
|
list: (pon) => {
|
|
2752
2686
|
const m = model();
|
|
2753
2687
|
return m.order.map((id) => m.byId[id]).filter((a) => a?.pon === pon).map((a) => a?.data).filter((d) => d != null);
|
|
@@ -2779,10 +2713,13 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2779
2713
|
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
2714
|
if (h.t === "annot") id = h.id;
|
|
2781
2715
|
}
|
|
2782
|
-
if (m.hovered !== id)
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2716
|
+
if (m.hovered !== id) {
|
|
2717
|
+
hoverFeed?.hover(id);
|
|
2718
|
+
apply({
|
|
2719
|
+
t: "hover",
|
|
2720
|
+
id
|
|
2721
|
+
});
|
|
2722
|
+
}
|
|
2786
2723
|
},
|
|
2787
2724
|
behaviorFor: (a) => behaviors.find((b) => b.matches(a) && b.engaged()) ?? null,
|
|
2788
2725
|
linkItemsOn: (pon) => memoLinkItems(pon),
|
|
@@ -2866,7 +2803,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2866
2803
|
cancelCreationDraft: () => apply({ t: "cancel" }),
|
|
2867
2804
|
markupFromSelection: (subtype, preset) => {
|
|
2868
2805
|
if (!allowsCreate()) return false;
|
|
2869
|
-
const selection = ctx.tryGet(
|
|
2806
|
+
const selection = ctx.tryGet(_embedpdf_plugin_selection_contract.SelectionToken);
|
|
2870
2807
|
if (!selection || !selection.hasSelection()) return false;
|
|
2871
2808
|
const snapshot = selection.snapshot();
|
|
2872
2809
|
let created = false;
|
|
@@ -2942,7 +2879,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
2942
2879
|
select: (ref, options) => {
|
|
2943
2880
|
apply({
|
|
2944
2881
|
t: "select",
|
|
2945
|
-
ids: [refKey(ref)],
|
|
2882
|
+
ids: [require_seam.refKey(ref)],
|
|
2946
2883
|
add: options?.add
|
|
2947
2884
|
});
|
|
2948
2885
|
},
|
|
@@ -3002,24 +2939,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
3002
2939
|
return subs.length > 0 && subs.every((a) => a.ref != null && allowsMutation("update", a.ref));
|
|
3003
2940
|
},
|
|
3004
2941
|
ensurePage: () => {},
|
|
3005
|
-
reloadPage:
|
|
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
|
-
},
|
|
2942
|
+
reloadPage: (pon) => reloadPageNow(pon),
|
|
3023
2943
|
hydration: () => ctx.getState().hydration,
|
|
3024
2944
|
ensureHydrated: () => {
|
|
3025
2945
|
if (hydrationStarted) return;
|
|
@@ -3038,7 +2958,7 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
3038
2958
|
currentEditing: () => model().editing,
|
|
3039
2959
|
beginTextEdit: (ref) => apply({
|
|
3040
2960
|
t: "beginTextEdit",
|
|
3041
|
-
id: refKey(ref)
|
|
2961
|
+
id: require_seam.refKey(ref)
|
|
3042
2962
|
}),
|
|
3043
2963
|
beginTextEditAt: (pon, point, scale, rotation, zoom) => {
|
|
3044
2964
|
const m = model();
|
|
@@ -3056,10 +2976,10 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
3056
2976
|
setContents: (ref, text) => {
|
|
3057
2977
|
apply({
|
|
3058
2978
|
t: "setText",
|
|
3059
|
-
id: refKey(ref),
|
|
2979
|
+
id: require_seam.refKey(ref),
|
|
3060
2980
|
text
|
|
3061
2981
|
});
|
|
3062
|
-
const key = refKey(ref);
|
|
2982
|
+
const key = require_seam.refKey(ref);
|
|
3063
2983
|
clearTimeout(textTimers.get(key));
|
|
3064
2984
|
textTimers.set(key, setTimeout(() => {
|
|
3065
2985
|
textTimers.delete(key);
|
|
@@ -3085,6 +3005,72 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
3085
3005
|
textTimers.clear();
|
|
3086
3006
|
apply({ t: "endTextEdit" });
|
|
3087
3007
|
},
|
|
3008
|
+
commitScriptEffects: async (entries) => {
|
|
3009
|
+
const doc = ctx.doc;
|
|
3010
|
+
if (!doc) return { results: entries.map((entry) => ({
|
|
3011
|
+
annotObjectNumber: entry.annotObjectNumber,
|
|
3012
|
+
status: "failed",
|
|
3013
|
+
error: "no document"
|
|
3014
|
+
})) };
|
|
3015
|
+
const results = [];
|
|
3016
|
+
const touchedPons = /* @__PURE__ */ new Set();
|
|
3017
|
+
let failed = false;
|
|
3018
|
+
for (const entry of entries) {
|
|
3019
|
+
if (failed) {
|
|
3020
|
+
results.push({
|
|
3021
|
+
annotObjectNumber: entry.annotObjectNumber,
|
|
3022
|
+
status: "skipped"
|
|
3023
|
+
});
|
|
3024
|
+
continue;
|
|
3025
|
+
}
|
|
3026
|
+
const loaded = model().byId[`obj:${entry.annotObjectNumber}`];
|
|
3027
|
+
const pon = loaded?.pon ?? entry.pageObjectNumber;
|
|
3028
|
+
let ref = loaded?.ref ?? null;
|
|
3029
|
+
let subtype = loaded?.subtype;
|
|
3030
|
+
if ((!ref || !subtype) && pon !== void 0) try {
|
|
3031
|
+
const { annotations } = await doc.page(pon).annotations.list();
|
|
3032
|
+
const dto = annotations.find((candidate) => candidate.ref.kind === "objectNumber" && candidate.ref.annotObjectNumber === entry.annotObjectNumber);
|
|
3033
|
+
if (dto) {
|
|
3034
|
+
ref = dto.ref;
|
|
3035
|
+
subtype = dto.subtype;
|
|
3036
|
+
}
|
|
3037
|
+
} catch {}
|
|
3038
|
+
if (pon === void 0 || !ref || !subtype) {
|
|
3039
|
+
results.push({
|
|
3040
|
+
annotObjectNumber: entry.annotObjectNumber,
|
|
3041
|
+
status: "failed",
|
|
3042
|
+
error: "annotation not resolved (page not loaded)"
|
|
3043
|
+
});
|
|
3044
|
+
continue;
|
|
3045
|
+
}
|
|
3046
|
+
const patch = engineScriptPatch(subtype, entry.patch);
|
|
3047
|
+
if (patch instanceof Error) {
|
|
3048
|
+
results.push({
|
|
3049
|
+
annotObjectNumber: entry.annotObjectNumber,
|
|
3050
|
+
status: "failed",
|
|
3051
|
+
error: patch.message
|
|
3052
|
+
});
|
|
3053
|
+
continue;
|
|
3054
|
+
}
|
|
3055
|
+
try {
|
|
3056
|
+
await doc.page(pon).annotations.update(ref, patch);
|
|
3057
|
+
touchedPons.add(pon);
|
|
3058
|
+
results.push({
|
|
3059
|
+
annotObjectNumber: entry.annotObjectNumber,
|
|
3060
|
+
status: "applied"
|
|
3061
|
+
});
|
|
3062
|
+
} catch (error) {
|
|
3063
|
+
failed = true;
|
|
3064
|
+
results.push({
|
|
3065
|
+
annotObjectNumber: entry.annotObjectNumber,
|
|
3066
|
+
status: "failed",
|
|
3067
|
+
error: error instanceof Error ? error.message : String(error)
|
|
3068
|
+
});
|
|
3069
|
+
}
|
|
3070
|
+
}
|
|
3071
|
+
for (const touched of touchedPons) await reloadPageNow(touched);
|
|
3072
|
+
return { results };
|
|
3073
|
+
},
|
|
3088
3074
|
registerBehavior: (b) => {
|
|
3089
3075
|
behaviors.push(b);
|
|
3090
3076
|
return () => {
|
|
@@ -3095,10 +3081,10 @@ function createAnnotationCapability(ctx, config = {}) {
|
|
|
3095
3081
|
};
|
|
3096
3082
|
}
|
|
3097
3083
|
//#endregion
|
|
3098
|
-
Object.defineProperty(exports, "
|
|
3084
|
+
Object.defineProperty(exports, "ARMED_STAMP_TOOL_ID", {
|
|
3099
3085
|
enumerable: true,
|
|
3100
3086
|
get: function() {
|
|
3101
|
-
return
|
|
3087
|
+
return ARMED_STAMP_TOOL_ID;
|
|
3102
3088
|
}
|
|
3103
3089
|
});
|
|
3104
3090
|
Object.defineProperty(exports, "DEFAULT_TOOLS", {
|
|
@@ -3131,18 +3117,6 @@ Object.defineProperty(exports, "isTouchDirect", {
|
|
|
3131
3117
|
return isTouchDirect;
|
|
3132
3118
|
}
|
|
3133
3119
|
});
|
|
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
3120
|
Object.defineProperty(exports, "toCreateDraft", {
|
|
3147
3121
|
enumerable: true,
|
|
3148
3122
|
get: function() {
|
|
@@ -3155,11 +3129,5 @@ Object.defineProperty(exports, "toPatch", {
|
|
|
3155
3129
|
return toPatch;
|
|
3156
3130
|
}
|
|
3157
3131
|
});
|
|
3158
|
-
Object.defineProperty(exports, "widgetAppearanceFromProps", {
|
|
3159
|
-
enumerable: true,
|
|
3160
|
-
get: function() {
|
|
3161
|
-
return widgetAppearanceFromProps;
|
|
3162
|
-
}
|
|
3163
|
-
});
|
|
3164
3132
|
|
|
3165
|
-
//# sourceMappingURL=capability-
|
|
3133
|
+
//# sourceMappingURL=capability-R7dgogJs.cjs.map
|