@embedpdf/plugin-annotation 3.0.0-next.13 → 3.0.0-next.15
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/README.md +129 -0
- package/dist/authoring.cjs +12 -2
- package/dist/authoring.d.cts +2 -2
- package/dist/authoring.d.ts +2 -2
- package/dist/authoring.js +2 -3
- package/dist/contract/host.cjs +18 -2
- package/dist/contract/host.d.cts +3 -2
- package/dist/contract/host.d.ts +3 -2
- package/dist/contract/host.js +3 -2
- package/dist/contract-BK4LHe9v.d.cts +1127 -0
- package/dist/contract-BOo9iZKo.d.ts +1127 -0
- package/dist/contract-CPzpRG3h.cjs +692 -0
- package/dist/contract-CPzpRG3h.cjs.map +1 -0
- package/dist/contract-b2e_LZvu.js +651 -0
- package/dist/contract-b2e_LZvu.js.map +1 -0
- package/dist/contract.cjs +11 -10
- package/dist/contract.d.cts +2 -3
- package/dist/contract.d.ts +2 -3
- package/dist/contract.js +2 -4
- package/dist/host-contract-BbjhS_Fo.d.ts +310 -0
- package/dist/host-contract-CxrQPcPj.js +52 -0
- package/dist/host-contract-CxrQPcPj.js.map +1 -0
- package/dist/{contract-a4eaQWga.cjs → host-contract-DY9jFPPF.cjs} +36 -16
- package/dist/host-contract-DY9jFPPF.cjs.map +1 -0
- package/dist/host-contract-Nzxwh0XS.d.cts +310 -0
- package/dist/index.cjs +4995 -414
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -17
- package/dist/index.d.ts +12 -17
- package/dist/index.js +4949 -388
- package/dist/index.js.map +1 -1
- package/package.json +11 -14
- package/dist/authoring-BhtyfsMx.d.cts +0 -37
- package/dist/authoring-R4ezdnXd.d.ts +0 -37
- package/dist/capability-B_dkoB1K.js +0 -3041
- package/dist/capability-B_dkoB1K.js.map +0 -1
- package/dist/capability-DVx1NmTe.cjs +0 -3064
- package/dist/capability-DVx1NmTe.cjs.map +0 -1
- package/dist/contract-CgAcfAE7.d.cts +0 -34
- package/dist/contract-CiG2_HBq.d.ts +0 -34
- package/dist/contract-DtXE1hjY.js +0 -32
- package/dist/contract-DtXE1hjY.js.map +0 -1
- package/dist/contract-a4eaQWga.cjs.map +0 -1
- package/dist/internal.cjs +0 -8
- package/dist/internal.d.cts +0 -14
- package/dist/internal.d.ts +0 -14
- package/dist/internal.js +0 -5
- package/dist/seam-6pJeKOOJ.cjs +0 -296
- package/dist/seam-6pJeKOOJ.cjs.map +0 -1
- package/dist/seam-C4L_7rDt.js +0 -225
- package/dist/seam-C4L_7rDt.js.map +0 -1
- package/dist/tools-0NI3b9z8.cjs +0 -536
- package/dist/tools-0NI3b9z8.cjs.map +0 -1
- package/dist/tools-DBEYx3-c.js +0 -513
- package/dist/tools-DBEYx3-c.js.map +0 -1
- package/dist/types-BvB1vUKb.js +0 -20
- package/dist/types-BvB1vUKb.js.map +0 -1
- package/dist/types-D5V0TIwk.d.ts +0 -1200
- package/dist/types-Dlhdw2k_.cjs +0 -31
- package/dist/types-Dlhdw2k_.cjs.map +0 -1
- package/dist/types-ObcPYc3-.d.cts +0 -1200
package/dist/seam-C4L_7rDt.js
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import { contentToPdfPoint, contentToPdfRect, contentToPdfRect as contentToPdfRect$1, normalizeDeg, pdfToContentPoint as pdfToContentPoint$1, pdfToContentRect, pdfToContentRect as pdfToContentRect$1, rotatedAabb } from "@embedpdf/core-annotation";
|
|
2
|
-
//#region src/repository/seam.ts
|
|
3
|
-
function refKey(ref) {
|
|
4
|
-
return ref.kind === "objectNumber" ? `obj:${ref.annotObjectNumber}` : ref.kind === "nm" ? `nm:${ref.nm}` : `idx:${ref.pageObjectNumber}:${ref.index}`;
|
|
5
|
-
}
|
|
6
|
-
const h2 = (n) => Math.max(0, Math.min(255, Math.round(n))).toString(16).padStart(2, "0");
|
|
7
|
-
const colorToCss = (c) => `#${h2(c.r)}${h2(c.g)}${h2(c.b)}`;
|
|
8
|
-
function cssToColor(css) {
|
|
9
|
-
const s = css.trim();
|
|
10
|
-
const m6 = /^#?([0-9a-f]{6})$/i.exec(s);
|
|
11
|
-
if (m6) {
|
|
12
|
-
const n = parseInt(m6[1], 16);
|
|
13
|
-
return {
|
|
14
|
-
r: n >> 16 & 255,
|
|
15
|
-
g: n >> 8 & 255,
|
|
16
|
-
b: n & 255
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
const m3 = /^#?([0-9a-f]{3})$/i.exec(s);
|
|
20
|
-
if (m3) {
|
|
21
|
-
const [a, b, c] = m3[1];
|
|
22
|
-
return {
|
|
23
|
-
r: parseInt(a + a, 16),
|
|
24
|
-
g: parseInt(b + b, 16),
|
|
25
|
-
b: parseInt(c + c, 16)
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
return {
|
|
29
|
-
r: 0,
|
|
30
|
-
g: 0,
|
|
31
|
-
b: 0
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
const toPdfRotation = (rotCW) => normalizeDeg(-rotCW);
|
|
35
|
-
const fromPdfRotation = (rotPdf) => normalizeDeg(-rotPdf);
|
|
36
|
-
/** Advisory `rot` for a vertex geom, from a DTO's (PDF-convention) `rotation`.
|
|
37
|
-
* Absent → no `rot` key (kept off the geom so unrotated shapes stay clean). */
|
|
38
|
-
const rotFromDTO = (rotation) => rotation ? { rot: fromPdfRotation(rotation) } : {};
|
|
39
|
-
/**
|
|
40
|
-
* Geometry/rotation fields for a BOX kind (square/circle/plain free-text). The
|
|
41
|
-
* model's `rect` is the UNROTATED logical box and `rot` the applied tilt, so:
|
|
42
|
-
* - rot == 0 → `/Rect` IS the box; the transform pair is stated as `null`
|
|
43
|
-
* (TOTAL projection — the engine's tri-state writes preserve omissions, so
|
|
44
|
-
* an omitted field would keep a stale rotation instead of flattening it).
|
|
45
|
-
* - rot != 0 → `/Rect` is the rotated visual AABB (PDFium clips the baked /AP
|
|
46
|
-
* to it), `unrotatedRect` the logical box, `rotation` the PDF angle.
|
|
47
|
-
*/
|
|
48
|
-
function boxGeomFields(rect, rot, crop) {
|
|
49
|
-
if (!rot) return {
|
|
50
|
-
rect: contentToPdfRect(rect, crop),
|
|
51
|
-
rotation: null,
|
|
52
|
-
unrotatedRect: null
|
|
53
|
-
};
|
|
54
|
-
return {
|
|
55
|
-
rect: contentToPdfRect(rotatedAabb(rect, rot), crop),
|
|
56
|
-
unrotatedRect: contentToPdfRect(rect, crop),
|
|
57
|
-
rotation: toPdfRotation(rot)
|
|
58
|
-
};
|
|
59
|
-
}
|
|
60
|
-
/** A box geom (square/circle/stamp) from its DTO: when rotated, the LOCAL box
|
|
61
|
-
* is the stored `unrotatedRect` (the AABB `/Rect` is the rendered envelope)
|
|
62
|
-
* and `rot` the converted tilt; unrotated, `/Rect` IS the box. */
|
|
63
|
-
function boxGeomFromDTO(dto, rotation, unrotatedRect, crop, ellipse) {
|
|
64
|
-
const rot = rotation ? fromPdfRotation(rotation) : 0;
|
|
65
|
-
return {
|
|
66
|
-
t: "rect",
|
|
67
|
-
rect: pdfToContentRect(rot && unrotatedRect ? unrotatedRect : dto.rect, crop),
|
|
68
|
-
ellipse,
|
|
69
|
-
...rot ? { rot } : {}
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
/** Inset a PdfRect by a `/RD` (PDF user space, y-up: all four are non-negative
|
|
73
|
-
* insets from the matching `/Rect` edge). Used to recover the callout text box. */
|
|
74
|
-
const insetPdfRectByRD = (r, rd) => rd ? {
|
|
75
|
-
left: r.left + rd.left,
|
|
76
|
-
bottom: r.bottom + rd.bottom,
|
|
77
|
-
right: r.right - rd.right,
|
|
78
|
-
top: r.top - rd.top
|
|
79
|
-
} : r;
|
|
80
|
-
/** Engine border fields (`/BS /S`, `/BS /D`, `/BE /I`) → the `Border` union. A
|
|
81
|
-
* cloudy effect wins over the underlying border style (which stays solid). */
|
|
82
|
-
function borderFromDTO(d) {
|
|
83
|
-
if ((d.cloudyIntensity ?? 0) > 0) return {
|
|
84
|
-
kind: "cloudy",
|
|
85
|
-
intensity: d.cloudyIntensity
|
|
86
|
-
};
|
|
87
|
-
if (d.borderStyle === "dashed") return {
|
|
88
|
-
kind: "dashed",
|
|
89
|
-
dash: d.dashArray?.length ? d.dashArray : [3, 3]
|
|
90
|
-
};
|
|
91
|
-
return { kind: "solid" };
|
|
92
|
-
}
|
|
93
|
-
/** The writable projection of a `link` value: `goto`/`uri` pass through,
|
|
94
|
-
* read-only arms (`javascript`, `named`, `goto-remote`, `launch`,
|
|
95
|
-
* `unsupported`) yield `null` — they can be carried, never (re)written. */
|
|
96
|
-
function writableTarget(t) {
|
|
97
|
-
return t && (t.kind === "goto" || t.kind === "uri") ? t : null;
|
|
98
|
-
}
|
|
99
|
-
const TEXT_MARKUP = /* @__PURE__ */ new Set([
|
|
100
|
-
"highlight",
|
|
101
|
-
"underline",
|
|
102
|
-
"squiggly",
|
|
103
|
-
"strikeout"
|
|
104
|
-
]);
|
|
105
|
-
const STROKE_KINDS = /* @__PURE__ */ new Set([
|
|
106
|
-
"square",
|
|
107
|
-
"circle",
|
|
108
|
-
"line",
|
|
109
|
-
"polygon",
|
|
110
|
-
"polyline",
|
|
111
|
-
"ink"
|
|
112
|
-
]);
|
|
113
|
-
/** Engine DTO → content-space `Style` (CSS colours, `Border` union). Exported so
|
|
114
|
-
* selection-aware UIs can read display values straight off a {@link AnnotationDTO}
|
|
115
|
-
* without re-deriving the colour/border mapping. */
|
|
116
|
-
function styleFromDTO(dto) {
|
|
117
|
-
if (dto.subtype === "widget") return {
|
|
118
|
-
color: dto.color ? colorToCss(dto.color) : "#1a1a1a",
|
|
119
|
-
interiorColor: dto.interiorColor ? colorToCss(dto.interiorColor) : null,
|
|
120
|
-
strokeWidth: dto.strokeWidth,
|
|
121
|
-
opacity: 1,
|
|
122
|
-
blendMode: dto.blendMode,
|
|
123
|
-
border: dto.borderStyle === "dashed" ? {
|
|
124
|
-
kind: "dashed",
|
|
125
|
-
dash: [3, 3]
|
|
126
|
-
} : { kind: "solid" }
|
|
127
|
-
};
|
|
128
|
-
if (STROKE_KINDS.has(dto.subtype)) {
|
|
129
|
-
const d = dto;
|
|
130
|
-
return {
|
|
131
|
-
color: colorToCss(d.color),
|
|
132
|
-
interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,
|
|
133
|
-
strokeWidth: d.strokeWidth,
|
|
134
|
-
opacity: d.opacity,
|
|
135
|
-
blendMode: dto.blendMode,
|
|
136
|
-
border: borderFromDTO(d)
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
if (TEXT_MARKUP.has(dto.subtype)) {
|
|
140
|
-
const d = dto;
|
|
141
|
-
return {
|
|
142
|
-
color: colorToCss(d.color),
|
|
143
|
-
interiorColor: null,
|
|
144
|
-
strokeWidth: 0,
|
|
145
|
-
opacity: d.opacity,
|
|
146
|
-
blendMode: dto.blendMode,
|
|
147
|
-
border: { kind: "solid" }
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
if (dto.subtype === "caret") {
|
|
151
|
-
const d = dto;
|
|
152
|
-
return {
|
|
153
|
-
color: colorToCss(d.color),
|
|
154
|
-
interiorColor: null,
|
|
155
|
-
strokeWidth: 1,
|
|
156
|
-
opacity: d.opacity,
|
|
157
|
-
blendMode: dto.blendMode,
|
|
158
|
-
border: { kind: "solid" }
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
if (dto.subtype === "free-text") {
|
|
162
|
-
const d = dto;
|
|
163
|
-
return {
|
|
164
|
-
color: colorToCss(d.color),
|
|
165
|
-
interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,
|
|
166
|
-
strokeWidth: d.strokeWidth,
|
|
167
|
-
opacity: d.opacity,
|
|
168
|
-
blendMode: dto.blendMode,
|
|
169
|
-
border: borderFromDTO(d)
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
if (dto.subtype === "redact") {
|
|
173
|
-
const d = dto;
|
|
174
|
-
return {
|
|
175
|
-
color: colorToCss(d.color),
|
|
176
|
-
interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,
|
|
177
|
-
strokeWidth: 1.5,
|
|
178
|
-
opacity: d.opacity,
|
|
179
|
-
blendMode: dto.blendMode,
|
|
180
|
-
border: { kind: "solid" }
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
if (dto.subtype === "text" || dto.subtype === "file-attachment") {
|
|
184
|
-
const d = dto;
|
|
185
|
-
return {
|
|
186
|
-
color: colorToCss(d.color),
|
|
187
|
-
interiorColor: null,
|
|
188
|
-
strokeWidth: 1,
|
|
189
|
-
opacity: d.opacity,
|
|
190
|
-
blendMode: dto.blendMode,
|
|
191
|
-
border: { kind: "solid" }
|
|
192
|
-
};
|
|
193
|
-
}
|
|
194
|
-
return {
|
|
195
|
-
color: "#444444",
|
|
196
|
-
interiorColor: null,
|
|
197
|
-
strokeWidth: 1,
|
|
198
|
-
opacity: 1,
|
|
199
|
-
blendMode: dto.blendMode,
|
|
200
|
-
border: { kind: "solid" }
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* The flat props vocabulary (CSS colours, house keys) → the engine's widget
|
|
205
|
-
* appearance for `doc.forms` authoring — the SAME mapping the widget patch
|
|
206
|
-
* lowering uses, exported as a boundary utility so the form plugin can style
|
|
207
|
-
* `placeField` from a tool's `currentDefaults` without growing a second CSS
|
|
208
|
-
* parser. Absent keys stay absent (the engine writes nothing for them).
|
|
209
|
-
*/
|
|
210
|
-
function widgetAppearanceFromProps(props) {
|
|
211
|
-
return {
|
|
212
|
-
...props.color !== void 0 ? { color: cssToColor(props.color) } : {},
|
|
213
|
-
...props.interiorColor !== void 0 ? { interiorColor: props.interiorColor ? cssToColor(props.interiorColor) : null } : {},
|
|
214
|
-
...props.strokeWidth !== void 0 ? { strokeWidth: props.strokeWidth } : {},
|
|
215
|
-
...props.border !== void 0 ? { borderStyle: props.border.kind === "dashed" ? "dashed" : "solid" } : {},
|
|
216
|
-
...props.fontFamily !== void 0 ? { fontFamily: props.fontFamily } : {},
|
|
217
|
-
...props.fontSize !== void 0 ? { fontSize: props.fontSize } : {},
|
|
218
|
-
...props.fontColor !== void 0 ? { fontColor: cssToColor(props.fontColor) } : {},
|
|
219
|
-
...props.textAlign !== void 0 ? { textAlign: props.textAlign } : {}
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
//#endregion
|
|
223
|
-
export { contentToPdfRect$1 as a, insetPdfRectByRD as c, refKey as d, rotFromDTO as f, writableTarget as g, widgetAppearanceFromProps as h, contentToPdfPoint as i, pdfToContentPoint$1 as l, toPdfRotation as m, boxGeomFromDTO as n, cssToColor as o, styleFromDTO as p, colorToCss as r, fromPdfRotation as s, boxGeomFields as t, pdfToContentRect$1 as u };
|
|
224
|
-
|
|
225
|
-
//# sourceMappingURL=seam-C4L_7rDt.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"seam-C4L_7rDt.js","names":[],"sources":["../src/repository/seam.ts"],"sourcesContent":["/**\n * The geometry/colour/rotation SEAM between the engine's PDF-space wire\n * vocabulary and the core's content-space model. Every conversion between the\n * two worlds lives here — kind modules speak through these helpers and never\n * hand-roll a convention flip.\n */\nimport type {\n AnnotationDTO,\n AnnotationRef,\n Color,\n PdfLinkTarget,\n PdfLinkTargetWritable,\n PdfRect,\n PdfRectDifferences,\n StandardFont,\n WidgetAppearance,\n} from '@embedpdf/engine-core/runtime';\nimport {\n contentToPdfRect,\n normalizeDeg,\n pdfToContentRect,\n rotatedAabb,\n type AnnotationPropsPatch,\n type Border,\n type Geom,\n type Rect,\n type Style,\n} from '@embedpdf/core-annotation';\n\n// The content↔PDF bridge, re-exported so kind modules cross the seam through\n// ONE import point and never reach into the core's geometry directly.\nexport {\n contentToPdfPoint,\n contentToPdfRect,\n pdfToContentPoint,\n pdfToContentRect,\n} from '@embedpdf/core-annotation';\n\nexport function refKey(ref: AnnotationRef): string {\n return ref.kind === 'objectNumber'\n ? `obj:${ref.annotObjectNumber}`\n : ref.kind === 'nm'\n ? `nm:${ref.nm}`\n : `idx:${ref.pageObjectNumber}:${ref.index}`;\n}\n\n/* ── colour seam (engine Color ↔ CSS hex) ─────────────────────────────────── */\n\nconst h2 = (n: number) =>\n Math.max(0, Math.min(255, Math.round(n)))\n .toString(16)\n .padStart(2, '0');\nexport const colorToCss = (c: Color): string => `#${h2(c.r)}${h2(c.g)}${h2(c.b)}`;\nexport function cssToColor(css: string): Color {\n const s = css.trim();\n const m6 = /^#?([0-9a-f]{6})$/i.exec(s);\n if (m6) {\n const n = parseInt(m6[1], 16);\n return { r: (n >> 16) & 255, g: (n >> 8) & 255, b: n & 255 };\n }\n const m3 = /^#?([0-9a-f]{3})$/i.exec(s);\n if (m3) {\n const [a, b, c] = m3[1];\n return { r: parseInt(a + a, 16), g: parseInt(b + b, 16), b: parseInt(c + c, 16) };\n }\n return { r: 0, g: 0, b: 0 };\n}\n\n/* ── rotation seam (CW content ↔ PDF convention) ──────────────────────────────\n * The model's `rot` is CLOCKWISE in content space (y-down). PDF user space is\n * y-up, so the y-flip at this boundary turns a CW content tilt into a CCW PDF\n * tilt of the same magnitude — i.e. the stored `/EMBD_Metadata/Rotation` is the\n * NEGATION (mod 360). This is the ONE place the convention is converted; every\n * layer above speaks CW-content and the engine/PDFium speaks the PDF angle.\n */\nexport const toPdfRotation = (rotCW: number): number => normalizeDeg(-rotCW);\nexport const fromPdfRotation = (rotPdf: number): number => normalizeDeg(-rotPdf);\n\n/** Advisory `rot` for a vertex geom, from a DTO's (PDF-convention) `rotation`.\n * Absent → no `rot` key (kept off the geom so unrotated shapes stay clean). */\nexport const rotFromDTO = (rotation?: number): { rot?: number } =>\n rotation ? { rot: fromPdfRotation(rotation) } : {};\n\n/**\n * Geometry/rotation fields for a BOX kind (square/circle/plain free-text). The\n * model's `rect` is the UNROTATED logical box and `rot` the applied tilt, so:\n * - rot == 0 → `/Rect` IS the box; the transform pair is stated as `null`\n * (TOTAL projection — the engine's tri-state writes preserve omissions, so\n * an omitted field would keep a stale rotation instead of flattening it).\n * - rot != 0 → `/Rect` is the rotated visual AABB (PDFium clips the baked /AP\n * to it), `unrotatedRect` the logical box, `rotation` the PDF angle.\n */\nexport function boxGeomFields(\n rect: Rect,\n rot: number,\n crop: PdfRect,\n): { rect: PdfRect; unrotatedRect: PdfRect | null; rotation: number | null } {\n if (!rot) return { rect: contentToPdfRect(rect, crop), rotation: null, unrotatedRect: null };\n return {\n rect: contentToPdfRect(rotatedAabb(rect, rot), crop),\n unrotatedRect: contentToPdfRect(rect, crop),\n rotation: toPdfRotation(rot),\n };\n}\n\n/** A box geom (square/circle/stamp) from its DTO: when rotated, the LOCAL box\n * is the stored `unrotatedRect` (the AABB `/Rect` is the rendered envelope)\n * and `rot` the converted tilt; unrotated, `/Rect` IS the box. */\nexport function boxGeomFromDTO(\n dto: { rect: PdfRect },\n rotation: number | undefined,\n unrotatedRect: PdfRect | undefined,\n crop: PdfRect,\n ellipse: boolean,\n): Geom {\n const rot = rotation ? fromPdfRotation(rotation) : 0;\n const box = rot && unrotatedRect ? unrotatedRect : dto.rect;\n return { t: 'rect', rect: pdfToContentRect(box, crop), ellipse, ...(rot ? { rot } : {}) };\n}\n\n/** Inset a PdfRect by a `/RD` (PDF user space, y-up: all four are non-negative\n * insets from the matching `/Rect` edge). Used to recover the callout text box. */\nexport const insetPdfRectByRD = (r: PdfRect, rd?: PdfRectDifferences | null): PdfRect =>\n rd\n ? {\n left: r.left + rd.left,\n bottom: r.bottom + rd.bottom,\n right: r.right - rd.right,\n top: r.top - rd.top,\n }\n : r;\n\n/** Engine border fields (`/BS /S`, `/BS /D`, `/BE /I`) → the `Border` union. A\n * cloudy effect wins over the underlying border style (which stays solid). */\nexport function borderFromDTO(d: {\n borderStyle?: string;\n dashArray?: number[];\n cloudyIntensity?: number | null;\n}): Border {\n if ((d.cloudyIntensity ?? 0) > 0) return { kind: 'cloudy', intensity: d.cloudyIntensity! };\n if (d.borderStyle === 'dashed')\n return { kind: 'dashed', dash: d.dashArray?.length ? d.dashArray : [3, 3] };\n return { kind: 'solid' };\n}\n\n/** The writable projection of a `link` value: `goto`/`uri` pass through,\n * read-only arms (`javascript`, `named`, `goto-remote`, `launch`,\n * `unsupported`) yield `null` — they can be carried, never (re)written. */\nexport function writableTarget(t: PdfLinkTarget | null | undefined): PdfLinkTargetWritable | null {\n return t && (t.kind === 'goto' || t.kind === 'uri') ? t : null;\n}\n\nexport const TEXT_MARKUP = new Set(['highlight', 'underline', 'squiggly', 'strikeout']);\n// Geometric kinds that carry the `/C` stroke colour + `/BS` border. Ink belongs\n// here too (it has a stroke but no `/IC`, so its interiorColor reads back null).\nconst STROKE_KINDS = new Set(['square', 'circle', 'line', 'polygon', 'polyline', 'ink']);\n\n/** Engine DTO → content-space `Style` (CSS colours, `Border` union). Exported so\n * selection-aware UIs can read display values straight off a {@link AnnotationDTO}\n * without re-deriving the colour/border mapping. */\nexport function styleFromDTO(dto: AnnotationDTO): Style {\n if (dto.subtype === 'widget') {\n return {\n color: dto.color ? colorToCss(dto.color) : '#1a1a1a',\n interiorColor: dto.interiorColor ? colorToCss(dto.interiorColor) : null,\n strokeWidth: dto.strokeWidth,\n opacity: 1,\n blendMode: dto.blendMode,\n border: dto.borderStyle === 'dashed' ? { kind: 'dashed', dash: [3, 3] } : { kind: 'solid' },\n };\n }\n if (STROKE_KINDS.has(dto.subtype)) {\n const d = dto as Extract<\n AnnotationDTO,\n { interiorColor: Color | null; opacity: number; strokeWidth: number }\n >;\n return {\n color: colorToCss(d.color),\n interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,\n strokeWidth: d.strokeWidth,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: borderFromDTO(d),\n };\n }\n if (TEXT_MARKUP.has(dto.subtype)) {\n const d = dto as Extract<AnnotationDTO, { color: Color }>;\n return {\n color: colorToCss(d.color),\n interiorColor: null,\n strokeWidth: 0,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n if (dto.subtype === 'caret') {\n const d = dto as Extract<AnnotationDTO, { color: Color; opacity: number }>;\n return {\n color: colorToCss(d.color),\n interiorColor: null,\n strokeWidth: 1,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n if (dto.subtype === 'free-text') {\n // `/DA` colour is the border + leader stroke; `/C` is the box background; `/BS`\n // gives the width. A plain text box draws no vector scene, so these only matter\n // for a callout's leader/arrow/box-border (and the style toolbar's readout).\n const d = dto as Extract<AnnotationDTO, { subtype: 'free-text' }>;\n return {\n color: colorToCss(d.color),\n interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,\n strokeWidth: d.strokeWidth,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: borderFromDTO(d),\n };\n }\n if (dto.subtype === 'redact') {\n // `/C` is the marking-stage outline; `/IC` the fill painted on apply.\n // No `/BS` on redact — the outline weight is a client rendering choice.\n const d = dto as Extract<AnnotationDTO, { subtype: 'redact' }>;\n return {\n color: colorToCss(d.color),\n interiorColor: d.interiorColor ? colorToCss(d.interiorColor) : null,\n strokeWidth: 1.5,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n if (dto.subtype === 'text' || dto.subtype === 'file-attachment') {\n // Icon kinds: /C is the icon fill, /CA its opacity — no stroke/fill split.\n const d = dto as Extract<AnnotationDTO, { color: Color; opacity: number }>;\n return {\n color: colorToCss(d.color),\n interiorColor: null,\n strokeWidth: 1,\n opacity: d.opacity,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n }\n return {\n color: '#444444',\n interiorColor: null,\n strokeWidth: 1,\n opacity: 1,\n blendMode: dto.blendMode,\n border: { kind: 'solid' },\n };\n}\n\n/**\n * The flat props vocabulary (CSS colours, house keys) → the engine's widget\n * appearance for `doc.forms` authoring — the SAME mapping the widget patch\n * lowering uses, exported as a boundary utility so the form plugin can style\n * `placeField` from a tool's `currentDefaults` without growing a second CSS\n * parser. Absent keys stay absent (the engine writes nothing for them).\n */\nexport function widgetAppearanceFromProps(props: AnnotationPropsPatch): WidgetAppearance {\n return {\n ...(props.color !== undefined ? { color: cssToColor(props.color) } : {}),\n ...(props.interiorColor !== undefined\n ? { interiorColor: props.interiorColor ? cssToColor(props.interiorColor) : null }\n : {}),\n ...(props.strokeWidth !== undefined ? { strokeWidth: props.strokeWidth } : {}),\n ...(props.border !== undefined\n ? { borderStyle: props.border.kind === 'dashed' ? ('dashed' as const) : ('solid' as const) }\n : {}),\n ...(props.fontFamily !== undefined ? { fontFamily: props.fontFamily as StandardFont } : {}),\n ...(props.fontSize !== undefined ? { fontSize: props.fontSize } : {}),\n ...(props.fontColor !== undefined ? { fontColor: cssToColor(props.fontColor) } : {}),\n ...(props.textAlign !== undefined ? { textAlign: props.textAlign } : {}),\n };\n}\n"],"mappings":";;AAsCA,SAAgB,OAAO,KAA4B;CACjD,OAAO,IAAI,SAAS,iBAChB,OAAO,IAAI,sBACX,IAAI,SAAS,OACX,MAAM,IAAI,OACV,OAAO,IAAI,iBAAiB,GAAG,IAAI;AAC3C;AAIA,MAAM,MAAM,MACV,KAAK,IAAI,GAAG,KAAK,IAAI,KAAK,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CACtC,SAAS,EAAE,CAAC,CACZ,SAAS,GAAG,GAAG;AACpB,MAAa,cAAc,MAAqB,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC,IAAI,GAAG,EAAE,CAAC;AAC9E,SAAgB,WAAW,KAAoB;CAC7C,MAAM,IAAI,IAAI,KAAK;CACnB,MAAM,KAAK,qBAAqB,KAAK,CAAC;CACtC,IAAI,IAAI;EACN,MAAM,IAAI,SAAS,GAAG,IAAI,EAAE;EAC5B,OAAO;GAAE,GAAI,KAAK,KAAM;GAAK,GAAI,KAAK,IAAK;GAAK,GAAG,IAAI;EAAI;CAC7D;CACA,MAAM,KAAK,qBAAqB,KAAK,CAAC;CACtC,IAAI,IAAI;EACN,MAAM,CAAC,GAAG,GAAG,KAAK,GAAG;EACrB,OAAO;GAAE,GAAG,SAAS,IAAI,GAAG,EAAE;GAAG,GAAG,SAAS,IAAI,GAAG,EAAE;GAAG,GAAG,SAAS,IAAI,GAAG,EAAE;EAAE;CAClF;CACA,OAAO;EAAE,GAAG;EAAG,GAAG;EAAG,GAAG;CAAE;AAC5B;AASA,MAAa,iBAAiB,UAA0B,aAAa,CAAC,KAAK;AAC3E,MAAa,mBAAmB,WAA2B,aAAa,CAAC,MAAM;;;AAI/E,MAAa,cAAc,aACzB,WAAW,EAAE,KAAK,gBAAgB,QAAQ,EAAE,IAAI,CAAC;;;;;;;;;;AAWnD,SAAgB,cACd,MACA,KACA,MAC2E;CAC3E,IAAI,CAAC,KAAK,OAAO;EAAE,MAAM,iBAAiB,MAAM,IAAI;EAAG,UAAU;EAAM,eAAe;CAAK;CAC3F,OAAO;EACL,MAAM,iBAAiB,YAAY,MAAM,GAAG,GAAG,IAAI;EACnD,eAAe,iBAAiB,MAAM,IAAI;EAC1C,UAAU,cAAc,GAAG;CAC7B;AACF;;;;AAKA,SAAgB,eACd,KACA,UACA,eACA,MACA,SACM;CACN,MAAM,MAAM,WAAW,gBAAgB,QAAQ,IAAI;CAEnD,OAAO;EAAE,GAAG;EAAQ,MAAM,iBADd,OAAO,gBAAgB,gBAAgB,IAAI,MACP,IAAI;EAAG;EAAS,GAAI,MAAM,EAAE,IAAI,IAAI,CAAC;CAAG;AAC1F;;;AAIA,MAAa,oBAAoB,GAAY,OAC3C,KACI;CACE,MAAM,EAAE,OAAO,GAAG;CAClB,QAAQ,EAAE,SAAS,GAAG;CACtB,OAAO,EAAE,QAAQ,GAAG;CACpB,KAAK,EAAE,MAAM,GAAG;AAClB,IACA;;;AAIN,SAAgB,cAAc,GAInB;CACT,KAAK,EAAE,mBAAmB,KAAK,GAAG,OAAO;EAAE,MAAM;EAAU,WAAW,EAAE;CAAiB;CACzF,IAAI,EAAE,gBAAgB,UACpB,OAAO;EAAE,MAAM;EAAU,MAAM,EAAE,WAAW,SAAS,EAAE,YAAY,CAAC,GAAG,CAAC;CAAE;CAC5E,OAAO,EAAE,MAAM,QAAQ;AACzB;;;;AAKA,SAAgB,eAAe,GAAmE;CAChG,OAAO,MAAM,EAAE,SAAS,UAAU,EAAE,SAAS,SAAS,IAAI;AAC5D;AAEA,MAAa,8BAAc,IAAI,IAAI;CAAC;CAAa;CAAa;CAAY;AAAW,CAAC;AAGtF,MAAM,+BAAe,IAAI,IAAI;CAAC;CAAU;CAAU;CAAQ;CAAW;CAAY;AAAK,CAAC;;;;AAKvF,SAAgB,aAAa,KAA2B;CACtD,IAAI,IAAI,YAAY,UAClB,OAAO;EACL,OAAO,IAAI,QAAQ,WAAW,IAAI,KAAK,IAAI;EAC3C,eAAe,IAAI,gBAAgB,WAAW,IAAI,aAAa,IAAI;EACnE,aAAa,IAAI;EACjB,SAAS;EACT,WAAW,IAAI;EACf,QAAQ,IAAI,gBAAgB,WAAW;GAAE,MAAM;GAAU,MAAM,CAAC,GAAG,CAAC;EAAE,IAAI,EAAE,MAAM,QAAQ;CAC5F;CAEF,IAAI,aAAa,IAAI,IAAI,OAAO,GAAG;EACjC,MAAM,IAAI;EAIV,OAAO;GACL,OAAO,WAAW,EAAE,KAAK;GACzB,eAAe,EAAE,gBAAgB,WAAW,EAAE,aAAa,IAAI;GAC/D,aAAa,EAAE;GACf,SAAS,EAAE;GACX,WAAW,IAAI;GACf,QAAQ,cAAc,CAAC;EACzB;CACF;CACA,IAAI,YAAY,IAAI,IAAI,OAAO,GAAG;EAChC,MAAM,IAAI;EACV,OAAO;GACL,OAAO,WAAW,EAAE,KAAK;GACzB,eAAe;GACf,aAAa;GACb,SAAS,EAAE;GACX,WAAW,IAAI;GACf,QAAQ,EAAE,MAAM,QAAQ;EAC1B;CACF;CACA,IAAI,IAAI,YAAY,SAAS;EAC3B,MAAM,IAAI;EACV,OAAO;GACL,OAAO,WAAW,EAAE,KAAK;GACzB,eAAe;GACf,aAAa;GACb,SAAS,EAAE;GACX,WAAW,IAAI;GACf,QAAQ,EAAE,MAAM,QAAQ;EAC1B;CACF;CACA,IAAI,IAAI,YAAY,aAAa;EAI/B,MAAM,IAAI;EACV,OAAO;GACL,OAAO,WAAW,EAAE,KAAK;GACzB,eAAe,EAAE,gBAAgB,WAAW,EAAE,aAAa,IAAI;GAC/D,aAAa,EAAE;GACf,SAAS,EAAE;GACX,WAAW,IAAI;GACf,QAAQ,cAAc,CAAC;EACzB;CACF;CACA,IAAI,IAAI,YAAY,UAAU;EAG5B,MAAM,IAAI;EACV,OAAO;GACL,OAAO,WAAW,EAAE,KAAK;GACzB,eAAe,EAAE,gBAAgB,WAAW,EAAE,aAAa,IAAI;GAC/D,aAAa;GACb,SAAS,EAAE;GACX,WAAW,IAAI;GACf,QAAQ,EAAE,MAAM,QAAQ;EAC1B;CACF;CACA,IAAI,IAAI,YAAY,UAAU,IAAI,YAAY,mBAAmB;EAE/D,MAAM,IAAI;EACV,OAAO;GACL,OAAO,WAAW,EAAE,KAAK;GACzB,eAAe;GACf,aAAa;GACb,SAAS,EAAE;GACX,WAAW,IAAI;GACf,QAAQ,EAAE,MAAM,QAAQ;EAC1B;CACF;CACA,OAAO;EACL,OAAO;EACP,eAAe;EACf,aAAa;EACb,SAAS;EACT,WAAW,IAAI;EACf,QAAQ,EAAE,MAAM,QAAQ;CAC1B;AACF;;;;;;;;AASA,SAAgB,0BAA0B,OAA+C;CACvF,OAAO;EACL,GAAI,MAAM,UAAU,KAAA,IAAY,EAAE,OAAO,WAAW,MAAM,KAAK,EAAE,IAAI,CAAC;EACtE,GAAI,MAAM,kBAAkB,KAAA,IACxB,EAAE,eAAe,MAAM,gBAAgB,WAAW,MAAM,aAAa,IAAI,KAAK,IAC9E,CAAC;EACL,GAAI,MAAM,gBAAgB,KAAA,IAAY,EAAE,aAAa,MAAM,YAAY,IAAI,CAAC;EAC5E,GAAI,MAAM,WAAW,KAAA,IACjB,EAAE,aAAa,MAAM,OAAO,SAAS,WAAY,WAAsB,QAAkB,IACzF,CAAC;EACL,GAAI,MAAM,eAAe,KAAA,IAAY,EAAE,YAAY,MAAM,WAA2B,IAAI,CAAC;EACzF,GAAI,MAAM,aAAa,KAAA,IAAY,EAAE,UAAU,MAAM,SAAS,IAAI,CAAC;EACnE,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,WAAW,WAAW,MAAM,SAAS,EAAE,IAAI,CAAC;EAClF,GAAI,MAAM,cAAc,KAAA,IAAY,EAAE,WAAW,MAAM,UAAU,IAAI,CAAC;CACxE;AACF"}
|