@paged-media/canvas-wasm 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2027 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ export type MainToWorker = MainToWorkerKind & {
5
+ seq: number;
6
+ protocol: ProtocolVersion;
7
+ };
8
+
9
+ export type WorkerToMain = WorkerToMainKind & {
10
+ seq: number | null;
11
+ protocol: ProtocolVersion;
12
+ };
13
+
14
+
15
+ /**
16
+ * A byte buffer that crosses the message channel. Wraps `Vec<u8>`
17
+ * so transferable-via-`postMessage` semantics are explicit at call
18
+ * sites; the wasm crate decides whether to clone or transfer based
19
+ * on whether the value is the JS-side `Uint8Array` or a Rust-side
20
+ * `Vec`. The wire form is whatever serde produces for `Vec<u8>` —
21
+ * JSON renders an array of numbers; future binary protocols (CBOR
22
+ * / messagepack) render a real bytes blob without code change.
23
+ */
24
+ export type ByteBuf = number[];
25
+
26
+ /**
27
+ * A content-space mutation. Phase 1 carries the *envelope* only —
28
+ * the worker rejects each variant with `WorkerError::NotImplemented`.
29
+ * Phase 3 lights these up incrementally.
30
+ */
31
+ export type Mutation = { op: "insertText"; args: { storyId: string; offset: number; text: string } } | { op: "deleteRange"; args: { storyId: string; start: number; end: number } } | { op: "applyStyle"; args: { storyId: string; start: number; end: number; style: string; scope: StyleScope } } | { op: "insertField"; args: { storyId: string; offset: number; field: FieldKind } } | { op: "moveFrame"; args: { frameId: string; transform: [number, number, number, number, number, number] } } | { op: "resizeFrame"; args: { frameId: string; bounds: [number, number, number, number] } } | { op: "linkFrames"; args: { from: string; to: string } } | { op: "unlinkFrames"; args: { frame: string } } | { op: "insertPage"; args: { afterPageId: PageId | null; masterId: string | null } } | { op: "deletePage"; args: { pageId: PageId } } | { op: "resizePage"; args: { pageId: PageId; bounds: [number, number, number, number] } } | { op: "insertFrame"; args: { pageId: PageId; bounds: [number, number, number, number] } } | { op: "insertTextFrame"; args: { pageId: PageId; bounds: [number, number, number, number] } } | { op: "deleteFrame"; args: { frameId: string } } | { op: "insertLine"; args: { pageId: PageId; start: [number, number]; end: [number, number] } } | { op: "insertPath"; args: { pageId: PageId; anchors: PathAnchorSpec[]; open: boolean; smooth?: boolean } } | { op: "setDocumentDefaults"; args: { fillColor: string | null; strokeColor: string | null; strokeWeight: number | null } } | { op: "setColorSettings"; args: { cmykProfileName: string | null; rgbPolicy: string | null; intent: string | null; bpc: boolean | null } } | { op: "setProofSetup"; args: { profileName: string | null; simulatePaperWhite?: boolean; intent: string | null } } | { op: "importSwatchLibrary"; args: { bytes: number[]; groupName?: string | null } } | { op: "setInkSetting"; args: { spotId: string; convertToProcess?: boolean; aliasTo?: string | null } } | { op: "setUseStandardLabForSpots"; args: { enabled: boolean } } | { op: "pathPointInsert"; args: { elementId: ElementId; index: number; anchor: PathAnchorSpec; prevSubpathStarts?: number[] | null } } | { op: "pathPointRemove"; args: { elementId: ElementId; index: number } } | { op: "pathOpenAt"; args: { elementId: ElementId; index: number } } | { op: "outlineStroke"; args: { elementId: ElementId; width: number; cap: string; join: string; miterLimit: number } } | { op: "offsetPath"; args: { elementId: ElementId; delta: number; join: string; miterLimit: number } } | { op: "simplifyPath"; args: { elementId: ElementId; tolerance: number } } | { op: "createGroup"; args: { memberIds: ElementId[] } } | { op: "dissolveGroup"; args: { groupId: string } } | { op: "setPluginMetadata"; args: { elementId: ElementId; key: string; value?: string | null } } | { op: "pathPointCurveType"; args: { elementId: ElementId; index: number; smooth: boolean } } | { op: "pathPointSet"; args: { elementId: ElementId; index: number; role: PathPointRole; position: [number, number] } } | { op: "batch"; args: { ops: Mutation[] } } | { op: "layerSetVisible"; args: { layerId: string; visible: boolean } } | { op: "layerSetLocked"; args: { layerId: string; locked: boolean } } | { op: "layerSetPrintable"; args: { layerId: string; printable: boolean } } | { op: "layerSetName"; args: { layerId: string; name: string } } | { op: "layerMove"; args: { layerId: string; newIndex: number } } | { op: "layerInsert"; args: { position: number; name: string } } | { op: "layerRemove"; args: { layerId: string } } | { op: "setElementProperty"; args: { elementId: ElementId; path: PropertyPath; value: Value } } | { op: "pathfinderBoolean"; args: { kept: ElementId; others: ElementId[]; kind: PathfinderKind } } | { op: "createSwatch"; args: { spec: SwatchSpec } } | { op: "editSwatch"; args: { swatchId: string; spec: SwatchSpec } } | { op: "deleteSwatch"; args: { swatchId: string } } | { op: "createGradient"; args: { spec: GradientSpec } } | { op: "editGradient"; args: { gradientId: string; spec: GradientSpec } } | { op: "deleteGradient"; args: { gradientId: string } } | { op: "createColorGroup"; args: { spec: ColorGroupSpec } } | { op: "editColorGroup"; args: { groupId: string; spec: ColorGroupSpec } } | { op: "deleteColorGroup"; args: { groupId: string } } | { op: "createParagraphStyle"; args: { selfId?: string | null; name?: string | null; basedOn?: string | null } } | { op: "renameParagraphStyle"; args: { styleId: string; name: string } } | { op: "deleteParagraphStyle"; args: { styleId: string } } | { op: "createCharacterStyle"; args: { selfId?: string | null; name?: string | null; basedOn?: string | null } } | { op: "renameCharacterStyle"; args: { styleId: string; name: string } } | { op: "deleteCharacterStyle"; args: { styleId: string } } | { op: "createObjectStyle"; args: { selfId?: string | null; name?: string | null; basedOn?: string | null } } | { op: "renameObjectStyle"; args: { styleId: string; name: string } } | { op: "deleteObjectStyle"; args: { styleId: string } } | { op: "createCellStyle"; args: { selfId?: string | null; name?: string | null; basedOn?: string | null } } | { op: "renameCellStyle"; args: { styleId: string; name: string } } | { op: "deleteCellStyle"; args: { styleId: string } } | { op: "createTableStyle"; args: { selfId?: string | null; name?: string | null; basedOn?: string | null } } | { op: "renameTableStyle"; args: { styleId: string; name: string } } | { op: "deleteTableStyle"; args: { styleId: string } } | { op: "setStyleProperty"; args: { collection: StyleCollection; styleId: string; path: PropertyPath; value: Value } } | { op: "insertOval"; args: { pageId: PageId; bounds: [number, number, number, number] } } | { op: "insertGuide"; args: { spreadId: string; orientation: GuideOrientationSpec; position: number; pageIndex?: number } } | { op: "moveGuide"; args: { guideId: string; position: number } } | { op: "deleteGuide"; args: { guideId: string } } | { op: "setConditionVisible"; args: { condition: string; visible: boolean } } | { op: "activateConditionSet"; args: { set: string } } | { op: "applyMasterToPage"; args: { page: PageId; master?: string | null } } | { op: "duplicatePage"; args: { page: PageId } } | { op: "insertSection"; args: { atPage: PageId; prefix?: string | null; numberingStyle?: string | null; startAt?: number | null } } | { op: "editSection"; args: { sectionId: string; prefix?: string | null | null; numberingStyle?: string | null; startAt?: number | null | null } } | { op: "deleteSection"; args: { sectionId: string } } | { op: "setRowHeight"; args: { storyId: string; tableId: string; row: number; height?: number | null } } | { op: "setColumnWidth"; args: { storyId: string; tableId: string; col: number; width?: number | null } } | { op: "insertTableRow"; args: { storyId: string; tableId: string; at: number } } | { op: "deleteTableRow"; args: { storyId: string; tableId: string; at: number } } | { op: "insertTableColumn"; args: { storyId: string; tableId: string; at: number } } | { op: "deleteTableColumn"; args: { storyId: string; tableId: string; at: number } };
32
+
33
+ /**
34
+ * Aftercare-A — `RequestWordBounds` reply payload. Story-local byte
35
+ * offsets of the `[start, end)` span the word (or whitespace run)
36
+ * containing the requested offset covers. Same address space as
37
+ * [`LineBounds`] and `HitResult.offset_within_story`.
38
+ */
39
+ export interface WordBounds {
40
+ /**
41
+ * Story byte offset of the word\'s first character.
42
+ */
43
+ start: number;
44
+ /**
45
+ * Story byte offset just past the word\'s last character.
46
+ */
47
+ end: number;
48
+ }
49
+
50
+ /**
51
+ * Axis the snap line guides. `X` is a vertical guide (snaps the x
52
+ * coordinate); `Y` is a horizontal guide (snaps the y coordinate).
53
+ */
54
+ export type SnapAxis = "x" | "y";
55
+
56
+ /**
57
+ * B-04 — creation spec for a page-item group. Members are NodeIds
58
+ * of LEAF page items (flat groups in v1; nesting is a follow-up);
59
+ * the apply layer resolves them to `FrameRef`s, orders them by
60
+ * current document order, and performs the `frames_in_order`
61
+ * surgery so z-order is provably unchanged. `self_id` follows the
62
+ * page-item `u<hex>` convention (minted when absent; echoed
63
+ * resolved in the applied op so the wire reports `createdId`).
64
+ */
65
+ export interface GroupSpec {
66
+ selfId?: string | null;
67
+ members: NodeId[];
68
+ }
69
+
70
+ /**
71
+ * B-06 — `RequestNearestPathPoint` reply payload. Coordinates are
72
+ * in the element\'s local space (the `PathAnchors` space).
73
+ */
74
+ export interface NearestPathPointResult {
75
+ /**
76
+ * Flat index of the segment\'s START anchor.
77
+ */
78
+ segStart: number;
79
+ /**
80
+ * Flat index of the segment\'s END anchor (wraps to the subpath
81
+ * start on a closing segment).
82
+ */
83
+ segEnd: number;
84
+ /**
85
+ * Curve parameter on that segment, 0..=1.
86
+ */
87
+ t: number;
88
+ point: [number, number];
89
+ distance: number;
90
+ }
91
+
92
+ /**
93
+ * Canonical selection / caret. `start == end` is a caret;
94
+ * `start < end` is a range. Endpoints are normalised so `start ≤
95
+ * end` always holds (use `Side` to recover direction information
96
+ * elsewhere if needed).
97
+ */
98
+ export interface ContentSelection {
99
+ storyId: string;
100
+ start: number;
101
+ end: number;
102
+ /**
103
+ * Downstream affinity bit. See module docs.
104
+ */
105
+ affinity?: boolean;
106
+ }
107
+
108
+ /**
109
+ * Coarse LOD tiers requested by the navigator + canvas (per spec §4.4).
110
+ */
111
+ export type LodTier = "snapshot" | "midRes" | "live";
112
+
113
+ /**
114
+ * Concept 2 — full gradient detail: the stop table the ramp
115
+ * editor mutates and the chips render. Stops carry the swatch REF
116
+ * (gradients reference swatches, never inline colours — edits to a
117
+ * component swatch propagate, spot stops survive to Separation at
118
+ * export) plus a display-resolved hex for painting the ramp.
119
+ */
120
+ export interface GradientDetail {
121
+ selfId: string;
122
+ name: string;
123
+ /**
124
+ * \"linear\" | \"radial\" | \"unknown\".
125
+ */
126
+ kind: string;
127
+ stops: GradientStopWire[];
128
+ }
129
+
130
+ /**
131
+ * Concept 2 — one ink row for the Ink Manager: a spot swatch\'s
132
+ * identity + its OUTPUT-TIME settings. Converting to process or
133
+ * aliasing never edits the swatch itself (AC-8) — these are
134
+ * separations decisions consumed by Concept 3\'s export encoding
135
+ * (and, for `useStandardLabForSpots`, by the preview resolver).
136
+ */
137
+ export interface InkSummary {
138
+ /**
139
+ * The spot swatch\'s `Color/<id>`.
140
+ */
141
+ spotId: string;
142
+ /**
143
+ * The ink/colourant name (the swatch name — for spots this IS
144
+ * the colourant identity).
145
+ */
146
+ name: string;
147
+ convertToProcess: boolean;
148
+ /**
149
+ * Output as another ink\'s plate (`Color/<id>` of the alias
150
+ * target). `None` = own plate.
151
+ */
152
+ aliasTo: string | null;
153
+ }
154
+
155
+ /**
156
+ * Concept 2 — one resolved gradient stop.
157
+ */
158
+ export interface GradientStopWire {
159
+ /**
160
+ * `Color/<id>` reference — the model identity.
161
+ */
162
+ stopColorRef: string;
163
+ /**
164
+ * Display-resolved `#rrggbb` via the active CMM (ramp render).
165
+ */
166
+ resolvedRgbHex: string;
167
+ /**
168
+ * 0..=100 position along the ramp.
169
+ */
170
+ locationPct: number;
171
+ /**
172
+ * 0..=100 blend midpoint toward the NEXT stop; `None` = 50.
173
+ */
174
+ midpointPct: number | null;
175
+ }
176
+
177
+ /**
178
+ * Concept 3 — PDF export options as the dialog sends them. Every
179
+ * field is optional/defaulted so the wire stays forward-compatible;
180
+ * the worker maps it onto `paged_export_pdf::ExportOptions`.
181
+ */
182
+ export interface ExportPdfWireOptions {
183
+ /**
184
+ * \"pdf17\" (default) | \"pdfx4\".
185
+ */
186
+ standard?: string | null;
187
+ /**
188
+ * Output-intent profile NAME, resolved against the worker\'s
189
+ * registered profile registry. `None` ⇒ the active working
190
+ * space profile.
191
+ */
192
+ outputIntentProfile?: string | null;
193
+ /**
194
+ * Human-readable output condition for the OutputIntent dict.
195
+ */
196
+ outputCondition?: string | null;
197
+ /**
198
+ * \"preserveNumbers\" (default) | \"convertToDestination\".
199
+ */
200
+ colorPolicy?: string | null;
201
+ /**
202
+ * 0-based inclusive page range; both `None` = all pages.
203
+ */
204
+ pageFrom?: number | null;
205
+ pageTo?: number | null;
206
+ cropMarks?: boolean;
207
+ registrationMarks?: boolean;
208
+ colorBars?: boolean;
209
+ pageInfo?: boolean;
210
+ marksOffsetPt?: number | null;
211
+ /**
212
+ * Bleed override in pt (top, inside/left, bottom,
213
+ * outside/right); `None` = the document\'s declared bleed.
214
+ */
215
+ bleedOverridePt?: [number, number, number, number] | null;
216
+ /**
217
+ * Resample images above this effective ppi; `None` = never.
218
+ */
219
+ downsamplePpi?: number | null;
220
+ /**
221
+ * Raster resolution for effect soft-mask stamps (default 150).
222
+ */
223
+ effectDpi?: number | null;
224
+ /**
225
+ * \"outline\" (default) | \"fail\".
226
+ */
227
+ restrictedFontPolicy?: string | null;
228
+ /**
229
+ * Document title for Info/XMP.
230
+ */
231
+ title?: string | null;
232
+ }
233
+
234
+ /**
235
+ * Description of a node about to be inserted. Carries the minimal
236
+ * Stage-1 supported field set plus `item_transform` — `RemoveNode` →
237
+ * undo → re-insertion round-trips these reliably. (Without the
238
+ * transform, undoing a deleteFrame snapped the frame back to the page
239
+ * origin — the editor-suite AC-E2E-PROVE-3 finding.) Remaining
240
+ * non-essential fields (drop_shadow, opacity, effects, …) still
241
+ * default on re-insertion; that residue of the Stage 1 limitation
242
+ * tightens in later stages.
243
+ */
244
+ export type NodeSpec = { kind: "textFrame"; self_id: string; bounds: [number, number, number, number]; fill_color?: string | null; stroke_color?: string | null; stroke_weight?: number | null; item_transform?: [number, number, number, number, number, number] | null } | { kind: "rectangle"; self_id: string; bounds: [number, number, number, number]; fill_color?: string | null; stroke_color?: string | null; stroke_weight?: number | null; item_transform?: [number, number, number, number, number, number] | null } | { kind: "oval"; self_id: string; bounds: [number, number, number, number]; fill_color?: string | null; stroke_color?: string | null; stroke_weight?: number | null; item_transform?: [number, number, number, number, number, number] | null } | { kind: "graphicLine"; self_id: string; bounds: [number, number, number, number]; anchors?: PathAnchorSpec[]; subpath_starts?: number[]; subpath_open?: boolean[]; stroke_color?: string | null; stroke_weight?: number | null; item_transform?: [number, number, number, number, number, number] | null } | { kind: "polygon"; self_id: string; bounds: [number, number, number, number]; anchors?: PathAnchorSpec[]; subpath_starts?: number[]; subpath_open?: boolean[]; fill_color?: string | null; stroke_color?: string | null; stroke_weight?: number | null; item_transform?: [number, number, number, number, number, number] | null } | { kind: "cloneTranslate"; self_id: string; source: NodeId; dx: number; dy: number; destination_spread_id?: string | null };
245
+
246
+ /**
247
+ * Direction for [`caret_nav`].
248
+ */
249
+ export type CaretDirection = "up" | "down";
250
+
251
+ /**
252
+ * Discriminated payload of a `WorkerToMain` message.
253
+ */
254
+ export type WorkerToMainKind = { kind: "ready"; payload: { protocol: ProtocolVersion } } | { kind: "documentLoaded"; payload: DocumentHandle } | { kind: "loadFailed"; payload: { error: LoadError } } | { kind: "mutationFailed"; payload: { error: WorkerError } } | { kind: "displayListReady"; payload: { pageId: PageId; lod: LodTier; commands: number; layoutGeneration: number; numberingGeneration: number } } | { kind: "hitResult"; payload: HitResult } | { kind: "pagesDirty"; payload: { pageIds: PageId[] } } | { kind: "storyDirty"; payload: { storyId: string } } | { kind: "warning"; payload: { kind: string; details: string } } | { kind: "stats"; payload: DocumentStats } | { kind: "snapshotReady"; payload: SnapshotPng } | { kind: "snapshotFailed"; payload: { error: SnapshotError } } | { kind: "mutationApplied"; payload: { clientSeq: number; appliedSeq: number; pageIds: PageId[]; cacheStats: LayoutCacheStats; createdId?: ElementId | null; pageStructureChanged?: boolean; pageSizesPt?: [number, number][] | null } } | { kind: "selectionGeometry"; payload: { rects: SelectionRect[] } } | { kind: "caretGeometry"; payload: { caret: CaretGeometry | null } } | { kind: "caretNavResult"; payload: { offset?: number | null } } | { kind: "lineBoundsResult"; payload: { bounds?: LineBounds | null } } | { kind: "wordBoundsResult"; payload: { bounds?: WordBounds | null } } | { kind: "undoApplied"; payload: { undoneSeq: number; appliedSeq: number; pageIds: PageId[]; cacheStats: LayoutCacheStats; pageStructureChanged?: boolean; pageSizesPt?: [number, number][] | null } } | { kind: "redoApplied"; payload: { redoneSeq: number; appliedSeq: number; pageIds: PageId[]; cacheStats: LayoutCacheStats; pageStructureChanged?: boolean; pageSizesPt?: [number, number][] | null } } | { kind: "fontRegistered"; payload: { family: string } } | { kind: "fontRegistryCleared" } | { kind: "colorProfileRegistered"; payload: { name: string } } | { kind: "elementSelectionApplied"; payload: { ids: ElementId[] } } | { kind: "marqueeHits"; payload: { ids: ElementId[] } } | { kind: "elementGeometry"; payload: { items: ElementGeometryItem[] } } | { kind: "groupLeaves"; payload: { ids: ElementId[] } } | { kind: "pathAnchors"; payload: { result: PathAnchorsResult | null } } | { kind: "nearestPathPoint"; payload: { result: NearestPathPointResult | null } } | { kind: "layers"; payload: { items: LayerSummary[] } } | { kind: "collectionReply"; payload: { name: CollectionName; items: any } } | { kind: "documentMetaReply"; payload: { meta: DocumentMeta } } | { kind: "colorPreviewReply"; payload: { result: ColorPreview | null } } | { kind: "colorComputeReply"; payload: { rgbHex: string; cmyk: [number, number, number, number] | null; outOfGamut: boolean } } | { kind: "gradientDetailReply"; payload: { result: GradientDetail | null } } | { kind: "swatchLibraryExported"; payload: { aseBytes: number[] } } | { kind: "exportPdfBegun"; payload: { session: number; pageCount: number } } | { kind: "exportPdfProgress"; payload: { session: number; done: number; total: number } } | { kind: "pdfExported"; payload: { pdfBytes: number[]; diagnostics: string[]; findings?: PreflightFinding[] } } | { kind: "exportPdfCancelled"; payload: { session: number } } | { kind: "exportPdfFailed"; payload: { error: string } } | { kind: "idmlExported"; payload: { idmlBytes: number[] } } | { kind: "exportIdmlFailed"; payload: { error: string } } | { kind: "elementProperties"; payload: { result: ElementProperties | null } } | { kind: "sceneTree"; payload: { roots: SceneTreeNode[] } } | { kind: "scriptResult"; payload: { output: string[]; error: string | null } } | { kind: "gestureBegun"; payload: { handle: GestureHandle } } | { kind: "gestureUpdated"; payload: { handle: GestureHandle; pageIds: PageId[]; snapLines?: SnapLine[] } } | { kind: "gestureCommitted"; payload: { handle: GestureHandle; appliedSeq: number; pageIds: PageId[]; cacheStats: LayoutCacheStats } } | { kind: "gestureCancelled"; payload: { handle: GestureHandle; pageIds: PageId[] } } | { kind: "gestureFailed"; payload: { error: GestureFailure } } | { kind: "attachReady"; payload: { gpuActive: boolean; sceneCacheBudget: number } } | { kind: "gestureSnapLines"; payload: { snapLines: SnapLine[] } } | { kind: "resolutionDone"; payload: ResolutionResult };
255
+
256
+ /**
257
+ * Editor-ops — wire mirror of `paged_parse::GradientFeatherParams`.
258
+ * Whole-struct authoring (kind + axis + stop LIST change together;
259
+ * `Value` has no generic list form, so the drop-shadow per-field
260
+ * shape doesn\'t fit). The renderer already draws this effect; only
261
+ * authoring was missing. `stop_color` round-trips faithfully but the
262
+ * rasterizer currently consumes `alpha_pct` only.
263
+ */
264
+ export interface GradientFeatherSpec {
265
+ /**
266
+ * `\"Linear\"` or `\"Radial\"`.
267
+ */
268
+ gradientType?: string | null;
269
+ startPoint?: [number, number] | null;
270
+ endPoint?: [number, number] | null;
271
+ angleDeg?: number | null;
272
+ stops?: GradientFeatherStopSpec[];
273
+ }
274
+
275
+ /**
276
+ * Editor-ops — wire mirror of `paged_parse::GradientFeatherStop`
277
+ * (the AST type predates `PartialEq`/`Tsify`; the mirror keeps the
278
+ * op wire-shaped, the `PathAnchorSpec` precedent).
279
+ */
280
+ export interface GradientFeatherStopSpec {
281
+ stopColor?: string | null;
282
+ locationPct: number;
283
+ alphaPct: number;
284
+ midpointPct?: number;
285
+ }
286
+
287
+ /**
288
+ * Element address the user can select OR a `SetElementProperty`
289
+ * mutation can target. The first six variants are page items
290
+ * (selection state holds these); `StoryRange` is the half-open
291
+ * character range that character / paragraph property writes
292
+ * address. Selection state today never holds `StoryRange` (the
293
+ * text-side caret + range live in `ContentSelection`); the
294
+ * variant exists so the apply layer can be reached via the
295
+ * existing `Mutation::SetElementProperty` wire shape — see
296
+ * `docs/paged/sdk-implementation-plan.md` §3c.1 ADR.
297
+ */
298
+ export type ElementId = { kind: "textFrame"; id: string } | { kind: "rectangle"; id: string } | { kind: "oval"; id: string } | { kind: "polygon"; id: string } | { kind: "graphicLine"; id: string } | { kind: "group"; id: string } | { kind: "storyRange"; id: { story_id: string; start: number; end: number } } | { kind: "table"; id: { story_id: string; table_id: string } } | { kind: "tableCell"; id: { story_id: string; table_id: string; row: number; col: number } };
299
+
300
+ /**
301
+ * Hint to downstream caches about what the apply touched. Lists
302
+ * instead of a single enum so a Batch aggregates by union without
303
+ * losing per-node detail. Consumers (renderer, glyph cache, layout
304
+ * cache) decide which lists to honour. Stays advisory — nothing in
305
+ * `paged-mutate` invalidates anything itself.
306
+ */
307
+ export interface InvalidationHint {
308
+ frameGeometry: NodeId[];
309
+ frameStyle: NodeId[];
310
+ textReflow: NodeId[];
311
+ /**
312
+ * Set when the tree shape changed (any Insert/Remove/Move).
313
+ */
314
+ structural: boolean;
315
+ }
316
+
317
+ /**
318
+ * Hit-test result.
319
+ */
320
+ export interface HitResult {
321
+ frameId: string | null;
322
+ storyId: string | null;
323
+ offsetWithinStory: number | null;
324
+ /**
325
+ * Selected frame\'s bounding box in page-local coordinates.
326
+ * AABB of the transformed corners. Returned for back-compat with
327
+ * callers that only want a quick rectangle.
328
+ */
329
+ frameBounds: FrameBounds | null;
330
+ /**
331
+ * Phase A — typed element identifier, the new canonical handle.
332
+ * `frame_id` is kept as the raw-id alias for back-compat with
333
+ * callers that haven\'t migrated.
334
+ */
335
+ element?: ElementId | null;
336
+ /**
337
+ * Phase A — the element\'s raw `GeometricBounds` (content-box
338
+ * space). Combine with `item_transform` to draw an oriented
339
+ * selection chrome on the main thread without re-deriving the
340
+ * math. `[top, left, bottom, right]`.
341
+ */
342
+ bounds?: [number, number, number, number] | null;
343
+ /**
344
+ * Phase A — composed affine `[a, b, c, d, tx, ty]` on the hit
345
+ * element. `None` for items with no `ItemTransform`.
346
+ */
347
+ itemTransform?: [number, number, number, number, number, number] | null;
348
+ /**
349
+ * Phase A — containing group ancestry, outer-most first. Empty
350
+ * when the hit element is not nested in any group.
351
+ */
352
+ groupChain?: string[];
353
+ /**
354
+ * W3.A1 — table cell context when the point landed inside a cell
355
+ * of the hit frame\'s story. `None` for non-table hits. Carries
356
+ * `(tableId, row, col)` so the canvas can select / mutate the cell
357
+ * without a second query.
358
+ */
359
+ tableContext?: TableHitContext | null;
360
+ }
361
+
362
+ /**
363
+ * How a `SetElementSelection` request combines with the current set.
364
+ * Mirrors the canonical macOS / industry convention:
365
+ * - `Replace` — plain click; selection becomes the request.
366
+ * - `Add` — Shift-click; union (already-selected ids stay).
367
+ * - `Toggle` — Cmd/Ctrl-click; ids already in the set are removed,
368
+ * ids not in the set are added.
369
+ */
370
+ export type SelectionMode = "replace" | "add" | "toggle";
371
+
372
+ /**
373
+ * Inspector P1 — one node in the scene tree. Children are nested
374
+ * (Spread → Page → Group? → frame leaf). `kind` is a short label
375
+ * the panel renders (\"Spread\", \"Page\", \"TextFrame\", \"Group\", …).
376
+ */
377
+ export interface SceneTreeNode {
378
+ /**
379
+ * Element id when the node is selectable (frames, groups). For
380
+ * Spread / Page rows that don\'t address into the gesture spine,
381
+ * `None`.
382
+ */
383
+ id?: ElementId | null;
384
+ kind: string;
385
+ /**
386
+ * Human-readable label. For frames falls back to the kind + raw
387
+ * id; for pages uses the parsed `<Page Name>`.
388
+ */
389
+ label: string;
390
+ children?: SceneTreeNode[];
391
+ }
392
+
393
+ /**
394
+ * Inspector P1 — one row of the inspector. `path` is the
395
+ * `PropertyPath` discriminant (camelCase). `value` mirrors the
396
+ * `Value` wire shape so the panel can pass it through to
397
+ * `Mutation::SetElementProperty` without re-encoding.
398
+ *
399
+ * SDK Phase 3 — `value` is `Option<Value>` (was `Value`). `None`
400
+ * signals \"mixed / indeterminate\" — a `NodeId::StoryRange` whose
401
+ * `CharacterRun`s carry conflicting values for this path returns
402
+ * `None` so the binding renderer can show a placeholder (em-dash)
403
+ * rather than picking an arbitrary winner. For frame-level reads
404
+ * the value is always `Some(_)`.
405
+ */
406
+ export interface PropertyEntry {
407
+ path: PropertyPath;
408
+ value?: Value | null;
409
+ }
410
+
411
+ /**
412
+ * Inspector P1 — typed property snapshot for one element. The
413
+ * Inspector panel maps each entry to the right typed editor:
414
+ * bounds → `BoundsInput`, transform → 6-cell matrix, colour ref →
415
+ * `ColorPicker`, length → `LengthInput`, etc.
416
+ */
417
+ export interface ElementProperties {
418
+ id: ElementId;
419
+ kind: string;
420
+ /**
421
+ * Optional human-readable name (frame label, layer name, …) when
422
+ * the underlying type carries one.
423
+ */
424
+ name?: string | null;
425
+ entries: PropertyEntry[];
426
+ }
427
+
428
+ /**
429
+ * Lightweight serialisable variant — the canvas worker hands this
430
+ * (encoded as a `WorkerToMain` message) to the main thread. The
431
+ * `rgba` payload becomes a PNG so the main thread can stash it in
432
+ * an `<img>` or `ImageBitmap` without per-byte serialisation cost.
433
+ */
434
+ export interface SnapshotPng {
435
+ pageId: PageId;
436
+ widthPx: number;
437
+ heightPx: number;
438
+ layoutGeneration: number;
439
+ numberingGeneration: number;
440
+ pngBytes: number[];
441
+ }
442
+
443
+ /**
444
+ * Modifier state captured on each pointer event. `shift` constrains
445
+ * the gesture (snap rotation to 15°, lock aspect on resize / scale).
446
+ * `alt` resizes from centre.
447
+ *
448
+ * `disable_snap` (Ctrl) makes the snap pass an identity transform on
449
+ * the delta — InDesign-style \"temporarily disable snap\" affordance
450
+ * per plan-2 §8.4. Optional on the wire so older callers keep
451
+ * compiling (defaults to `false`).
452
+ */
453
+ export interface GestureModifiers {
454
+ shift: boolean;
455
+ alt: boolean;
456
+ disableSnap?: boolean;
457
+ }
458
+
459
+ /**
460
+ * Numeric facts about an anchor\'s position. Phase H ships only
461
+ * `page_number`; later phases populate the rest.
462
+ */
463
+ export interface AnchorPosition {
464
+ /**
465
+ * 1-based page number, formatted via the section\'s numbering
466
+ * format. Phase H uses Arabic numerals only.
467
+ */
468
+ pageNumber: number;
469
+ /**
470
+ * Stable page id where the anchor lives. Lets callers map
471
+ * directly to LOD-cache tile keys without another lookup.
472
+ */
473
+ pageId: PageId | null;
474
+ /**
475
+ * Reserved for chapter / section / figure / footnote counters
476
+ * once Phase 2 wires them. Empty today.
477
+ */
478
+ counters: Map<string, number>;
479
+ /**
480
+ * Heading text — the paragraph\'s concatenated `<Content>` text,
481
+ * stripped of trailing whitespace. Empty for non-heading
482
+ * anchors. Phase 2 outline + badge UI uses this directly.
483
+ */
484
+ text?: string;
485
+ /**
486
+ * Heading level (1..6) for `HeadingParagraph` anchors; 0 for
487
+ * other anchor kinds. Lets the outline panel render
488
+ * hierarchical indentation without re-walking the scene\'s
489
+ * anchor table.
490
+ */
491
+ level?: number;
492
+ }
493
+
494
+ /**
495
+ * One active snap line surfaced to the overlay. `position` is in
496
+ * page-local pt on `page_id`.
497
+ */
498
+ export interface SnapLine {
499
+ axis: SnapAxis;
500
+ position: number;
501
+ pageId: PageId;
502
+ }
503
+
504
+ /**
505
+ * One entry in the field diff: a field whose resolved text
506
+ * changed between resolution iterations. The caller (Tier 3 →
507
+ * Tier 2 feedback loop) marks the field\'s containing story as
508
+ * content-dirty and re-runs Tier 2.
509
+ */
510
+ export interface FieldChange {
511
+ fieldId: string;
512
+ storyId: string;
513
+ oldText: string;
514
+ newText: string;
515
+ }
516
+
517
+ /**
518
+ * One stop of a gradient on the wire. Mirrors `GradientStopRef`.
519
+ */
520
+ export interface GradientStopSpec {
521
+ /**
522
+ * `Color/<id>` reference for this stop.
523
+ */
524
+ stopColor: string;
525
+ /**
526
+ * 0..=100 position along the ramp.
527
+ */
528
+ locationPct: number;
529
+ /**
530
+ * 0..=100 midpoint to the next stop; `None` ⇒ linear (50).
531
+ */
532
+ midpointPct?: number | null;
533
+ }
534
+
535
+ /**
536
+ * One-time facts about a loaded document. Sent to the main thread
537
+ * on a successful `LoadDocument` so the navigator + page count UI
538
+ * can render before the first page is rasterised.
539
+ */
540
+ export interface DocumentHandle {
541
+ /**
542
+ * Stable id assigned by the worker; used by the main thread when
543
+ * addressing operations to a specific document (the worker may
544
+ * hold more than one document open in the future).
545
+ */
546
+ docId: string;
547
+ /**
548
+ * Total page count. Stable for the life of the document unless
549
+ * a mutation explicitly inserts / deletes pages.
550
+ */
551
+ pageCount: number;
552
+ /**
553
+ * Page ids in document order. The navigator displays them as
554
+ * \"page N\" with `N = 1 + index`; the canvas uses the ids
555
+ * directly for cache keys.
556
+ */
557
+ pageIds: PageId[];
558
+ /**
559
+ * Per-page dimensions in points. Same length as `page_ids`.
560
+ * The navigator needs these to size thumbnails before any
561
+ * rasterisation has happened.
562
+ */
563
+ pageSizesPt: [number, number][];
564
+ /**
565
+ * Aggregate counts for debugging / UI badges.
566
+ */
567
+ stats: DocumentStats;
568
+ /**
569
+ * Plan-2 §8.3 — ruler guides per page. The overlay renders
570
+ * these and the snap pass treats them as targets. Total volume
571
+ * is small (real docs ship a few dozen at most) so we ship them
572
+ * inline on the handle rather than paging via a separate
573
+ * request.
574
+ */
575
+ rulerGuides?: RulerGuideWire[];
576
+ }
577
+
578
+ /**
579
+ * Opaque, monotone handle returned by `begin_gesture`. Callers pass
580
+ * it back to `update_gesture` / `commit_gesture` / `cancel_gesture`.
581
+ */
582
+ export type GestureHandle = number;
583
+
584
+ /**
585
+ * Oriented geometry for one selected element. `bounds` is the raw
586
+ * `GeometricBounds` (content-box space); `item_transform` is the
587
+ * composed affine. The overlay layer multiplies bounds corners by
588
+ * the transform to draw the oriented selection chrome.
589
+ */
590
+ export interface ElementGeometryItem {
591
+ id: ElementId;
592
+ pageId: PageId;
593
+ /**
594
+ * `[top, left, bottom, right]`.
595
+ */
596
+ bounds: [number, number, number, number];
597
+ /**
598
+ * `[a, b, c, d, tx, ty]`.
599
+ */
600
+ itemTransform?: [number, number, number, number, number, number] | null;
601
+ /**
602
+ * Phase F — `true` when this element hosts a placed image
603
+ * (`Rectangle` with `<Image>` / `<EPSImage>` / `<PDF>` /
604
+ * `<ImportedPage>` nested). The TS overlay uses this to decide
605
+ * whether a Cmd-drag should kick off `TranslateContent` instead
606
+ * of `Translate`.
607
+ */
608
+ hasImage?: boolean;
609
+ }
610
+
611
+ /**
612
+ * Phase 3 Item 4 — one rect-per-line in page-local coords for a
613
+ * content selection range. Defined in the root so the channel
614
+ * (Item 6) can reference it without depending on a yet-to-land
615
+ * `geometry` module.
616
+ */
617
+ export interface SelectionRect {
618
+ pageId: PageId;
619
+ frameId: string | null;
620
+ leftPt: number;
621
+ topPt: number;
622
+ widthPt: number;
623
+ heightPt: number;
624
+ }
625
+
626
+ /**
627
+ * Phase 4 Step 2 — per-rebuild layout cache statistics.
628
+ *
629
+ * Sent piggyback on `MutationApplied` / `UndoApplied` / `RedoApplied`
630
+ * so the main thread\'s HUD can show the incremental-layout win.
631
+ */
632
+ export interface LayoutCacheStats {
633
+ hits: number;
634
+ misses: number;
635
+ len: number;
636
+ capacity: number;
637
+ /**
638
+ * Phase 4 instrumentation — wall-clock duration of the rebuild
639
+ * that produced these stats, in milliseconds. Lets the HUD
640
+ * compare cache wins against the underlying budget (AC-E-1
641
+ * requires < 32 ms).
642
+ */
643
+ rebuildMs: number;
644
+ }
645
+
646
+ /**
647
+ * Phase A→F gesture taxonomy. Translate ships in Phase B, Resize in
648
+ * Phase C; Rotate / Scale stay reserved for Phase D.
649
+ */
650
+ export type GestureType = { kind: "translate" } | { kind: "resize"; handle: ResizeHandle } | { kind: "rotate" } | { kind: "scale" } | { kind: "shear" } | { kind: "translateContent" } | { kind: "rotateContent" } | { kind: "scaleContent" } | { kind: "pathEdit"; address: PathPointAddress };
651
+
652
+ /**
653
+ * Phase C — one of the eight handles on a selection rectangle\'s
654
+ * oriented bbox. Cardinal handles move a single edge; diagonal
655
+ * handles move two edges at once. Naming follows the compass
656
+ * convention every creative tool uses (NW / N / NE / W / E / SW /
657
+ * S / SE).
658
+ */
659
+ export type ResizeHandle = "north" | "south" | "east" | "west" | "northEast" | "northWest" | "southEast" | "southWest";
660
+
661
+ /**
662
+ * Phase D — anchor point passed at `begin_gesture` for gestures that
663
+ * need to know where the user started dragging (rotate / scale; also
664
+ * rotated-frame translate to support world-space delta math).
665
+ * Page-local coords + the page id; the model converts to spread
666
+ * coords by adding the page\'s spread origin.
667
+ */
668
+ export interface GestureAnchor {
669
+ pageId: PageId;
670
+ pointInPage: [number, number];
671
+ }
672
+
673
+ /**
674
+ * Phase H — address of one Bezier handle inside a `Polygon`\'s
675
+ * `PathPointArray`. `index` is the flat anchor index across all
676
+ * subpaths (compound polygons concatenate subpaths into one
677
+ * `anchors` Vec; `subpath_starts` marks each contour\'s first
678
+ * index).
679
+ */
680
+ export interface PathPointAddress {
681
+ index: number;
682
+ role: PathPointRole;
683
+ }
684
+
685
+ /**
686
+ * Phase H — which corner of a `PathAnchor` the path-point edit
687
+ * targets: the anchor itself or one of its two Bezier handles.
688
+ */
689
+ export type PathPointRole = "anchor" | "left" | "right";
690
+
691
+ /**
692
+ * Plan-2 §8.3 — wire shape of a ruler guide. `page_id` matches one
693
+ * of `DocumentHandle::page_ids`. `orientation` is \"vertical\" (snaps
694
+ * on x) or \"horizontal\" (snaps on y); `location` is the page-local
695
+ * coord on the perpendicular axis.
696
+ */
697
+ export interface RulerGuideWire {
698
+ pageId: PageId;
699
+ orientation: GuideOrientationWire;
700
+ location: number;
701
+ }
702
+
703
+ /**
704
+ * Resolution map keyed by anchor id. The `numbering_map()`
705
+ * accessor on `ResolutionResult` exposes a borrow of this.
706
+ */
707
+ export type NumberingMap = Record<AnchorId, AnchorPosition>;
708
+
709
+ /**
710
+ * Result of a successful `apply`. Holds the original op, the
711
+ * pre-computed inverse op (ready to push onto an undo stack), and
712
+ * the invalidation hint.
713
+ */
714
+ export interface AppliedOperation {
715
+ op: Operation;
716
+ inverse: Operation;
717
+ invalidation: InvalidationHint;
718
+ }
719
+
720
+ /**
721
+ * SDK Phase 3 — one character style\'s summary. Same shape as
722
+ * `ParagraphStyleSummary`; separate type so a future SwatchPicker
723
+ * composition can disambiguate styles in its options source.
724
+ */
725
+ export interface CharacterStyleSummary {
726
+ selfId: string;
727
+ name: string;
728
+ basedOn: string | null;
729
+ }
730
+
731
+ /**
732
+ * SDK Phase 3 — one gradient swatch\'s summary. `kind` is the
733
+ * IDML `Type` attribute — `\"linear\"` / `\"radial\"` — so a picker
734
+ * composition can icon-badge linear vs radial.
735
+ */
736
+ export interface GradientSummary {
737
+ selfId: string;
738
+ name: string;
739
+ kind: string;
740
+ }
741
+
742
+ /**
743
+ * SDK Phase 3 — one paragraph style\'s identity + display name +
744
+ * based-on link. Surfaced by `CanvasModel::paragraph_styles()`
745
+ * (and `paged.paragraphStyles()`) so collection-backed Style
746
+ * panels can render the hierarchy without re-parsing styles.xml.
747
+ * The `based_on` field is the parent style\'s `selfId` (the cascade
748
+ * root); `None` means this is a top-level style.
749
+ */
750
+ export interface ParagraphStyleSummary {
751
+ selfId: string;
752
+ name: string;
753
+ basedOn: string | null;
754
+ }
755
+
756
+ /**
757
+ * SDK Phase 3 — one story\'s identity + total character length.
758
+ * Surfaced by `CanvasModel::stories()` and the `paged.stories()`
759
+ * script host function so consumers can pick valid character
760
+ * ranges (e.g. `[0, length)` is always a well-formed StoryRange).
761
+ */
762
+ export interface StorySummary {
763
+ /**
764
+ * IDML `Self` id (`Story/u123`).
765
+ */
766
+ selfId: string;
767
+ /**
768
+ * Total character count across every `CharacterRun.text` in
769
+ * every paragraph. The largest valid `StoryRange.end`.
770
+ */
771
+ characterCount: number;
772
+ /**
773
+ * Number of paragraphs. Useful for binding-renderer fallbacks
774
+ * that want to address \"the whole story\" without computing
775
+ * the character count.
776
+ */
777
+ paragraphCount: number;
778
+ /**
779
+ * panels.md gap 1 — `true` when this story\'s text overflowed the
780
+ * last frame in its chain at build time (overset). Derived from
781
+ * the build\'s `OversetTextDropped` diagnostics; drives the
782
+ * Preflight panel + the red \"+\" overset badge on the frame.
783
+ */
784
+ overset?: boolean;
785
+ }
786
+
787
+ /**
788
+ * SDK Phase 3 — one swatch\'s identity + display name + kind.
789
+ * Surfaced by `CanvasModel::swatches()` and the `paged.swatches()`
790
+ * host fn so collection-backed panels (Swatches, the color picker
791
+ * dropdown, the Character/Stroke fill-color enum-select) can
792
+ * enumerate the document\'s colour palette without re-parsing the
793
+ * graphic resource.
794
+ *
795
+ * `kind` is the IDML colour-model discriminant — `\"process\"` for
796
+ * CMYK/RGB/Lab process colours, `\"spot\"` for named-ink swatches
797
+ * (PANTONE etc.), `\"mixedInk\"` / `\"mixedInkGroup\"` for those
798
+ * composites, and the literal labels `\"none\"` / `\"paper\"` /
799
+ * `\"black\"` / `\"registration\"` for the four special swatches
800
+ * IDML treats as built-ins. Renderers use this to badge the
801
+ * swatch grid.
802
+ */
803
+ export interface SwatchSummary {
804
+ selfId: string;
805
+ name: string;
806
+ kind: string;
807
+ }
808
+
809
+ /**
810
+ * SDK Phase 5 (D1) — closed enumeration of every document
811
+ * collection a panel may bind against. Per
812
+ * `panel-catalog-and-sdk-extension.md` §5.1. The Rust enum and the
813
+ * TS `CollectionName` union (in `packages/catalog/src/types.ts`)
814
+ * stay in lockstep; tsify emits a string-tag enum at the boundary
815
+ * so consumers can pass names verbatim.
816
+ *
817
+ * Not every variant has a backing model accessor yet — the wire
818
+ * surface lands here as the §5 binding ceiling, and the per-
819
+ * collection accessors fill in as panels need them. The
820
+ * `CanvasModel::collection(name)` dispatcher returns an empty
821
+ * `serde_json::Value::Array` for unimplemented entries, surfacing
822
+ * a runtime warning rather than a panic.
823
+ */
824
+ export type CollectionName = "swatches" | "gradients" | "colorGroups" | "paragraphStyles" | "characterStyles" | "objectStyles" | "cellStyles" | "tableStyles" | "layers" | "spreads" | "pages" | "masterPages" | "links" | "articles" | "hyperlinks" | "bookmarks" | "crossReferences" | "conditions" | "conditionSets" | "fonts" | "indexTopics" | "inks" | "sections" | "stories";
825
+
826
+ /**
827
+ * SDK Phase 5 (D1) — singleton document-level state. Per
828
+ * `panel-catalog-and-sdk-extension.md` §5.6. Powers the Info panel,
829
+ * status bar, and any chrome that reflects whole-document state
830
+ * (vs. selection state). Scalar reads of singleton properties; the
831
+ * six fields cover the v1 panel needs.
832
+ *
833
+ * `dirty` mirrors the Project\'s \"has uncommitted edits since the
834
+ * last save\" flag (always `false` at v1 since there\'s no
835
+ * save/export path through the worker yet — the flag exists so
836
+ * the Info panel and tab title can react when one lands).
837
+ */
838
+ export interface DocumentMeta {
839
+ pageCount: number;
840
+ activePage: PageId | null;
841
+ /**
842
+ * User-facing measurement unit — `\"pt\"` / `\"px\"` / `\"in\"` /
843
+ * `\"mm\"` / `\"cm\"` / `\"pica\"` etc. Empty when the IDML doesn\'t
844
+ * declare a default and the renderer hasn\'t established one.
845
+ */
846
+ units: string;
847
+ /**
848
+ * IDML\'s document colour mode — `\"cmyk\"` / `\"rgb\"`. Empty when
849
+ * the source doesn\'t declare it.
850
+ */
851
+ colorMode: string;
852
+ /**
853
+ * Human-readable document name. Often the source `.idml`
854
+ * filename minus extension; empty for synthetic / in-memory
855
+ * documents.
856
+ */
857
+ documentName: string;
858
+ /**
859
+ * `true` when the worker has applied a mutation since
860
+ * `LoadDocument`. Reset on save/export when that path lands.
861
+ */
862
+ dirty: boolean;
863
+ /**
864
+ * Editor-ops — document defaults for newly-created objects (the
865
+ * triple `SetDocumentDefaults` writes). `None` = no fill / no
866
+ * stroke / engine-default weight.
867
+ */
868
+ defaultFillColor?: string | null;
869
+ defaultStrokeColor?: string | null;
870
+ defaultStrokeWeight?: number | null;
871
+ /**
872
+ * Concept 2 — active colour-management settings (the state
873
+ * `SetColorSettings` writes; seeded from the IDML designmap\'s
874
+ * `CMYKProfile`/`SolidColorIntent` at load). `cmyk_profile_name`
875
+ * is `None` until a registered profile is active by name.
876
+ */
877
+ cmykProfileName?: string | null;
878
+ /**
879
+ * Concept 3 — true when ACTUAL profile bytes back the working
880
+ * space (explicit load bytes or a registry hit). The NAME above
881
+ * can be a designmap declaration with no bytes behind it — the
882
+ * export dialog\'s X-4 gate needs this, not the name.
883
+ */
884
+ cmykProfileActive?: boolean;
885
+ rgbPolicy?: string | null;
886
+ renderingIntent?: string | null;
887
+ blackPointCompensation?: boolean | null;
888
+ /**
889
+ * Concept 2 — active soft-proof condition (`None` = proofing
890
+ * off) + its paper-white flag.
891
+ */
892
+ proofProfileName?: string | null;
893
+ proofSimulatePaperWhite?: boolean | null;
894
+ /**
895
+ * Concept 2 (Ink Manager) — global \"Use Standard Lab Values
896
+ * for Spots\" toggle.
897
+ */
898
+ useStandardLabForSpots?: boolean | null;
899
+ }
900
+
901
+ /**
902
+ * SDK Phase 5 (v1 sweep) — one `<Article>` summary. Backs
903
+ * `documentCollection:articles`.
904
+ */
905
+ export interface ArticleSummary {
906
+ selfId: string;
907
+ name: string;
908
+ members: string[];
909
+ }
910
+
911
+ /**
912
+ * SDK Phase 5 (v1 sweep) — one `<Bookmark>` summary. Backs
913
+ * `documentCollection:bookmarks`.
914
+ */
915
+ export interface BookmarkSummary {
916
+ selfId: string;
917
+ name: string;
918
+ destination: string;
919
+ }
920
+
921
+ /**
922
+ * SDK Phase 5 (v1 sweep) — one `<ColorGroup>` definition. Backs
923
+ * `documentCollection:colorGroups` per §5.1. A user-defined
924
+ * grouping of `Color` self_ids the document organises its
925
+ * palette into.
926
+ */
927
+ export interface ColorGroupSummary {
928
+ selfId: string;
929
+ name: string;
930
+ /**
931
+ * Member color/swatch self_ids the group wraps.
932
+ */
933
+ members: string[];
934
+ }
935
+
936
+ /**
937
+ * SDK Phase 5 (v1 sweep) — one `<Condition>` definition. Backs
938
+ * `documentCollection:conditions` per `panel-catalog-and-sdk-
939
+ * extension.md` §5.1. The Conditions panel renders this for
940
+ * inspection; per-condition visibility toggling requires a new
941
+ * `Operation::SetConditionVisible` that v1 doesn\'t ship yet.
942
+ */
943
+ export interface ConditionSummary {
944
+ selfId: string;
945
+ name: string;
946
+ /**
947
+ * Default `true` when the IDML doesn\'t specify (`Visible`
948
+ * attribute is optional).
949
+ */
950
+ visible: boolean;
951
+ /**
952
+ * `\"Underline\"` / `\"Highlight\"` / `\"None\"` (or empty).
953
+ */
954
+ indicatorMethod: string;
955
+ }
956
+
957
+ /**
958
+ * SDK Phase 5 (v1 sweep) — one `<ConditionSet>` definition. Backs
959
+ * `documentCollection:conditionSets` per §5.1. Each entry is a
960
+ * named grouping of Condition self_ids; the editor\'s Conditions
961
+ * panel can use this to toggle a set as a unit (v2 affordance).
962
+ */
963
+ export interface ConditionSetSummary {
964
+ selfId: string;
965
+ name: string;
966
+ /**
967
+ * Member Condition self_ids the set wraps.
968
+ */
969
+ conditions: string[];
970
+ }
971
+
972
+ /**
973
+ * SDK Phase 5 (v1 sweep) — one `<CrossReferenceSource>` summary.
974
+ * Backs `documentCollection:crossReferences`.
975
+ */
976
+ export interface CrossReferenceSummary {
977
+ selfId: string;
978
+ name: string;
979
+ format: string;
980
+ destination: string;
981
+ }
982
+
983
+ /**
984
+ * SDK Phase 5 (v1 sweep) — one `<Hyperlink>` summary. Backs
985
+ * `documentCollection:hyperlinks`.
986
+ */
987
+ export interface HyperlinkSummary {
988
+ selfId: string;
989
+ name: string;
990
+ source: string;
991
+ destination: string;
992
+ }
993
+
994
+ /**
995
+ * SDK Phase 5 (v1 sweep) — one `<Topic>` summary. Backs
996
+ * `documentCollection:indexTopics`.
997
+ */
998
+ export interface IndexTopicSummary {
999
+ selfId: string;
1000
+ name: string;
1001
+ sortOrder: string;
1002
+ }
1003
+
1004
+ /**
1005
+ * SDK Phase 5 (v1 sweep) — one cell-style summary. Backs
1006
+ * `documentCollection:cellStyles`. Apply-an-entity via
1007
+ * `AppliedCellStyle` is wire-shape-only (UnsupportedProperty
1008
+ * until the Table NodeId surface lands); the panel can still
1009
+ * list defined styles today.
1010
+ */
1011
+ export interface CellStyleSummary {
1012
+ selfId: string;
1013
+ name: string;
1014
+ basedOn: string | null;
1015
+ }
1016
+
1017
+ /**
1018
+ * SDK Phase 5 (v1 sweep) — one font family/style entry derived
1019
+ * from the document\'s content. The parse layer doesn\'t carry a
1020
+ * font registry — fonts are referenced from runs + paragraph
1021
+ * styles. The accessor walks them and dedups; the result is the
1022
+ * set of typefaces *used* by the document.
1023
+ */
1024
+ export interface FontSummary {
1025
+ /**
1026
+ * Family name (`\"Open Sans\"`, `\"Helvetica Neue\"`, …). Used as
1027
+ * the row react-key.
1028
+ */
1029
+ family: string;
1030
+ /**
1031
+ * Number of runs/styles that reference this family. Surfaces
1032
+ * \"this font is used N times\" without a full audit pass.
1033
+ */
1034
+ referenceCount: number;
1035
+ /**
1036
+ * panels.md gap 4 — `true` when the family can\'t be resolved to
1037
+ * face bytes by the worker\'s font registry (`BytesResolver`),
1038
+ * so the renderer substituted a fallback. The Fonts/Preflight
1039
+ * panel flags these in red. `false` means at least one style of
1040
+ * the family resolved.
1041
+ *
1042
+ * `embedded` is intentionally omitted: IDML packages reference
1043
+ * fonts by name (the `Fonts/Font_*.xml` resource carries no face
1044
+ * bytes), so the engine can\'t honestly say whether a font is
1045
+ * \"embedded\" — only whether it\'s installed/registered. Surfacing
1046
+ * a fabricated `embedded` flag would mislead the panel.
1047
+ */
1048
+ isMissing?: boolean;
1049
+ }
1050
+
1051
+ /**
1052
+ * SDK Phase 5 (v1 sweep) — one master-spread summary. Backs
1053
+ * `documentCollection:masterPages`. Documents typically ship 1–3
1054
+ * master spreads (A-Master, B-Master, …) that pages reference
1055
+ * via `AppliedMaster`.
1056
+ */
1057
+ export interface MasterPageSummary {
1058
+ selfId: string;
1059
+ label: string;
1060
+ pageCount: number;
1061
+ }
1062
+
1063
+ /**
1064
+ * SDK Phase 5 (v1 sweep) — one object style\'s summary. Backs
1065
+ * `documentCollection:objectStyles` per `panel-catalog-and-sdk-
1066
+ * extension.md` §5.1; consumed by the Object Styles panel via
1067
+ * the `collection-select` primitive to drive an
1068
+ * `appliedObjectStyle` write on the selected frame.
1069
+ */
1070
+ export interface ObjectStyleSummary {
1071
+ selfId: string;
1072
+ name: string;
1073
+ basedOn: string | null;
1074
+ }
1075
+
1076
+ /**
1077
+ * SDK Phase 5 (v1 sweep) — one page summary. Backs
1078
+ * `documentCollection:pages`. Mirrors `DocumentHandle.page_ids`
1079
+ * + `page_sizes_pt` so a Pages-as-collection panel can render a
1080
+ * thumbnail/label list. The Navigator (existing legacy panel)
1081
+ * uses the same data through a different surface.
1082
+ */
1083
+ export interface PageSummary {
1084
+ /**
1085
+ * Stable id (matches `PageId` everywhere else).
1086
+ */
1087
+ selfId: string;
1088
+ /**
1089
+ * 1-based index — what the user types in \"Go to page #\".
1090
+ */
1091
+ index: number;
1092
+ /**
1093
+ * `[width, height]` in points.
1094
+ */
1095
+ sizePt: [number, number];
1096
+ /**
1097
+ * panels.md gap 10 — page margins in pt (from the page\'s
1098
+ * `<MarginPreference>`). All four default to 0 when the page
1099
+ * declared no margins. The editor\'s margin-box overlay insets
1100
+ * the page rect by these.
1101
+ */
1102
+ marginTopPt?: number;
1103
+ marginLeftPt?: number;
1104
+ marginBottomPt?: number;
1105
+ marginRightPt?: number;
1106
+ /**
1107
+ * panels.md gap 10 — column grid inside the margin box.
1108
+ * `column_count` defaults to 1, `column_gutter_pt` to 0.
1109
+ */
1110
+ columnCount?: number;
1111
+ columnGutterPt?: number;
1112
+ /**
1113
+ * panels.md gap 10 — document bleed in pt (top, left, bottom,
1114
+ * right), from `<DocumentPreference>`. Document-level (the same
1115
+ * values on every page); carried per-page so the overlay can
1116
+ * draw the bleed box without a second round-trip. All 0 when the
1117
+ * document declares no bleed.
1118
+ */
1119
+ bleedTopPt?: number;
1120
+ bleedLeftPt?: number;
1121
+ bleedBottomPt?: number;
1122
+ bleedRightPt?: number;
1123
+ }
1124
+
1125
+ /**
1126
+ * SDK Phase 5 (v1 sweep) — one placed-image link summary. Backs
1127
+ * `documentCollection:links` per `panel-catalog-and-sdk-extension.md`
1128
+ * §5.1. Each entry is a `(frame, image_link)` pair derived from
1129
+ * the parse layer\'s `Rectangle::image_link` / `Oval::image_link` /
1130
+ * `Polygon::image_link` fields. The Links panel renders this list
1131
+ * for inspection; the per-link \"relocate\" / \"update\" actions land
1132
+ * when those Operations ship.
1133
+ *
1134
+ * `host_kind` lets a future panel disambiguate \"this link sits on
1135
+ * a Rectangle vs. an Oval\". `host_self_id` is the host frame\'s
1136
+ * IDML `Self` id; the panel uses it as the row react-key.
1137
+ */
1138
+ export interface LinkSummary {
1139
+ hostSelfId: string;
1140
+ hostKind: string;
1141
+ uri: string;
1142
+ /**
1143
+ * panels.md gap 2 — `\"ok\"` when the build resolved + decoded the
1144
+ * link, `\"missing\"` when the renderer fell back to the grey
1145
+ * missing-image placeholder (`ImageLinkMissing` /
1146
+ * `ImageDecodeFailed` diagnostic for this frame). Derived from
1147
+ * the build\'s render diagnostics, so it reflects the SAME
1148
+ * resolution outcome the rendered page shows.
1149
+ */
1150
+ status?: string;
1151
+ /**
1152
+ * panels.md gap 3 — placed-image colour space (`\"CMYK\"` /
1153
+ * `\"RGB\"` / `\"Gray\"` / `\"LAB\"`), from the `<Image Space>`
1154
+ * attribute InDesign baked at export. `None` when the IDML
1155
+ * omits it (synthetic fixtures, vector placements).
1156
+ */
1157
+ colorspace?: string | null;
1158
+ /**
1159
+ * panels.md gap 3 — effective ppi at print size (native ppi ÷
1160
+ * placement scale), from the `<Image EffectivePpi>` attribute.
1161
+ * The number a preflight resolution check compares against a
1162
+ * 300-ppi floor. `None` when the IDML omits it.
1163
+ */
1164
+ effectivePpi?: number | null;
1165
+ }
1166
+
1167
+ /**
1168
+ * SDK Phase 5 (v1 sweep) — one spread summary. Backs
1169
+ * `documentCollection:spreads`. `pageCount` is the number of
1170
+ * `<Page>` children in the spread; `label` is the spread\'s
1171
+ * `Self` id (or filename when missing).
1172
+ */
1173
+ export interface SpreadSummary {
1174
+ selfId: string;
1175
+ label: string;
1176
+ pageCount: number;
1177
+ /**
1178
+ * W3.A0 — the spread\'s live `<Guide>` set, refreshed on every
1179
+ * `collection(\"spreads\")` request. `DocumentHandle.ruler_guides`
1180
+ * is load-time-only (it doesn\'t pick up `InsertGuide` /
1181
+ * `MoveGuide` / `DeleteGuide` mutations), so the editor re-queries
1182
+ * this collection after an undo/redo to re-sync its overlay
1183
+ * mirror. Empty for spreads with no guides.
1184
+ */
1185
+ guides?: GuideSummary[];
1186
+ }
1187
+
1188
+ /**
1189
+ * SDK Phase 5 (v1 sweep) — one table-style summary. Backs
1190
+ * `documentCollection:tableStyles`. Same shape + apply-an-entity
1191
+ * pattern as `CellStyleSummary`.
1192
+ */
1193
+ export interface TableStyleSummary {
1194
+ selfId: string;
1195
+ name: string;
1196
+ basedOn: string | null;
1197
+ }
1198
+
1199
+ /**
1200
+ * SDK Phase 5 (v1 sweep) — resolved colour readout for a single
1201
+ * swatch. The Color panel uses this to surface \"what does this
1202
+ * swatch actually look like\" — CMYK percentages for spot / CMYK
1203
+ * process inks, and an RGB hex string for the display fallback
1204
+ * the renderer paints with. Editor sliders are v2.
1205
+ */
1206
+ export interface ColorPreview {
1207
+ selfId: string;
1208
+ name: string;
1209
+ /**
1210
+ * IDML colour model — `\"process\"` / `\"spot\"` / `\"mixedInk\"`
1211
+ * / `\"none\"` / `\"paper\"` / `\"black\"` / `\"registration\"`.
1212
+ */
1213
+ model: string;
1214
+ /**
1215
+ * CMYK percent values (0..=100). `None` for non-CMYK swatches
1216
+ * (e.g. RGB / Lab process colours; spots whose alternate
1217
+ * isn\'t CMYK).
1218
+ */
1219
+ cmyk: [number, number, number, number] | null;
1220
+ /**
1221
+ * Display RGB as `#rrggbb`. Always present (the renderer
1222
+ * computes a fallback RGB for every swatch).
1223
+ */
1224
+ rgbHex: string;
1225
+ /**
1226
+ * Concept 2 — out-of-gamut against the document\'s active CMYK
1227
+ * working space (false when no working profile is configured).
1228
+ */
1229
+ outOfGamut?: boolean;
1230
+ /**
1231
+ * Concept 2 — the RAW authored space + channels (IDML units),
1232
+ * so the swatch editor seeds losslessly (a Lab swatch edits in
1233
+ * Lab, not via its display RGB).
1234
+ */
1235
+ space?: string | null;
1236
+ value?: number[] | null;
1237
+ }
1238
+
1239
+ /**
1240
+ * SDK Phase 5 (v1 sweep) — wire enum for Pathfinder ops. Mirrors
1241
+ * `pathfinder::PathfinderKind` (the internal enum used by the
1242
+ * flo_curves layer) — kept separate so the apply layer doesn\'t
1243
+ * leak `flo_curves` types onto the wire.
1244
+ */
1245
+ export type PathfinderKind = "union" | "intersect" | "subtract" | "exclude";
1246
+
1247
+ /**
1248
+ * Stable identifier for a scene-graph node. The string payload is the
1249
+ * IDML `Self` attribute (e.g. `\"TextFrame/u14\"`) — stable for the
1250
+ * lifetime of the document. Operations reference nodes by ID, never
1251
+ * by path or index, so an Op generated on one client applies
1252
+ * meaningfully on another even after the tree has shuffled.
1253
+ *
1254
+ * Variants today cover the page-item kinds the inspector mutates plus
1255
+ * the structural containers an `InsertNode`/`MoveNode` Op can target
1256
+ * as a parent.
1257
+ */
1258
+ export type NodeId = { kind: "TextFrame"; id: string } | { kind: "Rectangle"; id: string } | { kind: "Oval"; id: string } | { kind: "Polygon"; id: string } | { kind: "GraphicLine"; id: string } | { kind: "Group"; id: string } | { kind: "Spread"; id: string } | { kind: "Page"; id: string } | { kind: "Layer"; id: string } | { kind: "StoryRange"; id: { story_id: string; start: number; end: number } } | { kind: "Table"; id: { story_id: string; table_id: string } } | { kind: "TableCell"; id: { story_id: string; table_id: string; row: number; col: number } };
1259
+
1260
+ /**
1261
+ * Stable page identity, independent of position in the page vector.
1262
+ *
1263
+ * Derived from the IDML `<Page Self=\"...\">` attribute where present;
1264
+ * synthesised as `\"page-<spread_idx>-<local_idx>\"` when missing
1265
+ * (older / synthetic fixtures without `Self`). The canvas keys
1266
+ * display-list caches and LOD tiles by `PageId`, so the value must
1267
+ * stay stable across re-layouts — only document-structural edits
1268
+ * (insert/delete page) should ever change the set of `PageId`s.
1269
+ */
1270
+ export type PageId = string;
1271
+
1272
+ /**
1273
+ * Step 5 — `RequestPathAnchors` reply payload. `anchors.len()` may
1274
+ * be zero (e.g. a Rectangle with no `<PathGeometry>`); the overlay
1275
+ * treats that as \"nothing to draw\" without surfacing an error.
1276
+ */
1277
+ export interface PathAnchorsResult {
1278
+ id: ElementId;
1279
+ pageId: PageId;
1280
+ anchors: PathAnchorTriple[];
1281
+ /**
1282
+ * Per-contour boundaries. Empty for the common single-contour
1283
+ * case so callers can iterate a single subpath without special-
1284
+ * casing the empty `subpath_starts` vector.
1285
+ */
1286
+ subpathStarts: number[];
1287
+ /**
1288
+ * Parallel to `subpath_starts` (or, when `subpath_starts` is
1289
+ * empty, a single entry for the single contour). `true` ⇒ the
1290
+ * contour is open. Lets the overlay emit closing-edge insert
1291
+ * hit-zones for closed subpaths only.
1292
+ */
1293
+ subpathOpen?: boolean[];
1294
+ /**
1295
+ * `[a, b, c, d, tx, ty]`. None ⇒ identity.
1296
+ */
1297
+ itemTransform?: [number, number, number, number, number, number] | null;
1298
+ }
1299
+
1300
+ /**
1301
+ * Step 5 — one anchor\'s three control points, in the polygon\'s
1302
+ * inner coords (before `item_transform` + page-origin shift). The
1303
+ * overlay applies the same affine chain it already uses for selection
1304
+ * chrome.
1305
+ */
1306
+ export interface PathAnchorTriple {
1307
+ anchor: [number, number];
1308
+ left: [number, number];
1309
+ right: [number, number];
1310
+ }
1311
+
1312
+ /**
1313
+ * Structural counts. The main thread surfaces these in the debug
1314
+ * HUD. Mirrors `paged-renderer::PipelineStats` but lives in serde-
1315
+ * friendly form so it can cross the message channel.
1316
+ */
1317
+ export interface DocumentStats {
1318
+ spreads: number;
1319
+ pages: number;
1320
+ frames: number;
1321
+ stories: number;
1322
+ paragraphs: number;
1323
+ runs: number;
1324
+ glyphs: number;
1325
+ lines: number;
1326
+ /**
1327
+ * panels.md gap 1 — number of distinct stories whose text
1328
+ * overflows the last frame in its chain (overset). Derived from
1329
+ * the build\'s `OversetTextDropped` diagnostics, not from
1330
+ * `PipelineStats`, so `DocumentStats::from(&PipelineStats)`
1331
+ * leaves this 0 and the `handle()` builder backfills it from the
1332
+ * document\'s render diagnostics. Drives the Preflight panel\'s
1333
+ * \"N overset stories\" badge.
1334
+ */
1335
+ overset_stories?: number;
1336
+ }
1337
+
1338
+ /**
1339
+ * The canonical mutation primitive. A closed set, extended only with
1340
+ * deliberation. Collection mutations (swatches, styles) operate on the
1341
+ * document\'s `BTreeMap` palettes/stylesheets rather than the scene
1342
+ * tree, so they\'re top-level variants rather than `InsertNode`.
1343
+ */
1344
+ export type Operation = { kind: "SetProperty"; node: NodeId; path: PropertyPath; value: Value } | { kind: "InsertNode"; parent: NodeId; position: number; node: NodeSpec; z_slot?: number | null } | { kind: "RemoveNode"; node: NodeId } | { kind: "MoveNode"; node: NodeId; new_parent: NodeId; position: number } | { kind: "Batch"; ops: Operation[] } | { kind: "InsertPage"; after_page_id?: string | null; master_id?: string | null; spread_self_id?: string | null; page_self_id?: string | null; restore_spread_json?: string | null } | { kind: "RemovePage"; page_id: string } | { kind: "MoveLayer"; layer_id: string; new_index: number } | { kind: "InsertLayer"; position: number; name: string; self_id?: string | null } | { kind: "RemoveLayer"; layer_id: string } | { kind: "CreateSwatch"; spec: SwatchSpec } | { kind: "EditSwatch"; swatch_id: string; spec: SwatchSpec } | { kind: "DeleteSwatch"; swatch_id: string } | { kind: "CreateParagraphStyle"; self_id?: string | null; name?: string | null; based_on?: string | null; restore_json?: string | null } | { kind: "RenameParagraphStyle"; style_id: string; name: string } | { kind: "DeleteParagraphStyle"; style_id: string } | { kind: "CreateCharacterStyle"; self_id?: string | null; name?: string | null; based_on?: string | null; restore_json?: string | null } | { kind: "RenameCharacterStyle"; style_id: string; name: string } | { kind: "DeleteCharacterStyle"; style_id: string } | { kind: "CreateObjectStyle"; self_id?: string | null; name?: string | null; based_on?: string | null; restore_json?: string | null } | { kind: "RenameObjectStyle"; style_id: string; name: string } | { kind: "DeleteObjectStyle"; style_id: string } | { kind: "CreateCellStyle"; self_id?: string | null; name?: string | null; based_on?: string | null; restore_json?: string | null } | { kind: "RenameCellStyle"; style_id: string; name: string } | { kind: "DeleteCellStyle"; style_id: string } | { kind: "CreateTableStyle"; self_id?: string | null; name?: string | null; based_on?: string | null; restore_json?: string | null } | { kind: "RenameTableStyle"; style_id: string; name: string } | { kind: "DeleteTableStyle"; style_id: string } | { kind: "CreateGroup"; spec: GroupSpec } | { kind: "DissolveGroup"; group_id: string; restore_slots?: number[] | null } | { kind: "CreateGradient"; spec: GradientSpec } | { kind: "EditGradient"; gradient_id: string; spec: GradientSpec } | { kind: "DeleteGradient"; gradient_id: string } | { kind: "CreateColorGroup"; spec: ColorGroupSpec } | { kind: "EditColorGroup"; group_id: string; spec: ColorGroupSpec } | { kind: "DeleteColorGroup"; group_id: string } | { kind: "SetStyleProperty"; collection: StyleCollection; style_id: string; path: PropertyPath; value: Value } | { kind: "PathfinderBoolean"; kept: NodeId; others: NodeId[]; opKind: PathfinderKind } | { kind: "LinkFrames"; from: string; to: string } | { kind: "UnlinkFrames"; frame: string; prev_next?: string | null } | { kind: "ApplyStyle"; story_id: string; start: number; end: number; style: string; scope: StyleScope } | { kind: "InsertField"; story_id: string; offset: number; field: FieldKind } | { kind: "DeleteField"; story_id: string; offset: number; field: FieldKind } | { kind: "InsertGuide"; spread_id: string; orientation: GuideOrientationSpec; position: number; page_index?: number; guide_id?: string | null } | { kind: "MoveGuide"; guide_id: string; position: number } | { kind: "DeleteGuide"; guide_id: string } | { kind: "SetConditionVisible"; condition: string; visible: boolean } | { kind: "ActivateConditionSet"; set: string } | { kind: "RestoreConditionVisibility"; states: [string, boolean][] } | { kind: "ApplyMasterToPage"; page: string; master?: string | null } | { kind: "DuplicatePage"; page: string; clone_spread_json?: string | null } | { kind: "InsertSection"; at_page: string; prefix?: string | null; numbering_style?: string | null; start_at?: number | null; self_id?: string | null } | { kind: "EditSection"; section_id: string; prefix?: string | null | null; numbering_style?: string | null; start_at?: number | null | null } | { kind: "DeleteSection"; section_id: string } | { kind: "SetRowHeight"; story_id: string; table_id: string; row: number; height?: number | null } | { kind: "SetColumnWidth"; story_id: string; table_id: string; col: number; width?: number | null } | { kind: "InsertTableRow"; story_id: string; table_id: string; at: number; restore?: TableLineRestoreJson | null } | { kind: "DeleteTableRow"; story_id: string; table_id: string; at: number } | { kind: "InsertTableColumn"; story_id: string; table_id: string; at: number; restore?: TableLineRestoreJson | null } | { kind: "DeleteTableColumn"; story_id: string; table_id: string; at: number };
1345
+
1346
+ /**
1347
+ * The discriminated payload of a `MainToWorker` message. Tagged so
1348
+ * TS can do `switch (msg.kind) { case \"loadDocument\": ... }` against
1349
+ * camelCase field names. `rename_all_fields` cascades to struct
1350
+ * variants so e.g. `cmyk_icc_profile` becomes `cmykIccProfile` on
1351
+ * the wire — the TS protocol mirror locks the camelCase contract.
1352
+ */
1353
+ export type MainToWorkerKind = { kind: "hello" } | { kind: "loadDocument"; payload: { bytes: number[]; font?: number[] | null; cmykIccProfile?: number[] | null } } | { kind: "registerFont"; payload: { family: string; style?: string | null; bytes: number[] } } | { kind: "clearFontRegistry" } | { kind: "registerColorProfile"; payload: { name: string; bytes: number[] } } | { kind: "mutate"; payload: Mutation } | { kind: "requestPage"; payload: { pageId: PageId; lod: LodTier } } | { kind: "hitTest"; payload: { pageId: PageId; docPoint: [number, number]; filter: HitFilter } } | { kind: "requestSnapshot"; payload: { pageId: PageId; targetWidthPx: number; dpi?: number | null } } | { kind: "setSelection"; payload: { selection: ContentSelection | null } } | { kind: "requestSelectionGeometry"; payload: { selection: ContentSelection } } | { kind: "requestCaretGeometry"; payload: { selection: ContentSelection } } | { kind: "requestCaretNav"; payload: { storyId: string; offset: number; direction: CaretDirection } } | { kind: "requestLineBounds"; payload: { storyId: string; offset: number } } | { kind: "requestWordBounds"; payload: { storyId: string; offset: number } } | { kind: "undo" } | { kind: "redo" } | { kind: "setElementSelection"; payload: { ids: ElementId[]; mode: SelectionMode } } | { kind: "requestMarqueeHits"; payload: { pageId: PageId; rect: [number, number, number, number] } } | { kind: "requestElementGeometry"; payload: { ids: ElementId[] } } | { kind: "requestGroupLeaves"; payload: { groupId: string } } | { kind: "requestPathAnchors"; payload: { id: ElementId } } | { kind: "requestNearestPathPoint"; payload: { id: ElementId; point: [number, number] } } | { kind: "requestLayers" } | { kind: "requestCollection"; payload: { name: CollectionName } } | { kind: "requestDocumentMeta" } | { kind: "requestColorPreview"; payload: { swatchId: string } } | { kind: "requestColorCompute"; payload: { space: string; value: number[]; tint?: number | null; model?: string | null; alternateSpace?: string | null; alternateValue?: number[] | null } } | { kind: "requestGradientDetail"; payload: { gradientId: string } } | { kind: "exportSwatchLibrary"; payload: { groupId?: string | null } } | { kind: "executeScript"; payload: { source: string } } | { kind: "exportPdfBegin"; payload: { options: ExportPdfWireOptions } } | { kind: "exportPdfPage"; payload: { session: number } } | { kind: "exportPdfFinish"; payload: { session: number } } | { kind: "exportPdfCancel"; payload: { session: number } } | { kind: "exportIdml"; payload: {} } | { kind: "requestElementProperties"; payload: { id: ElementId } } | { kind: "requestSceneTree" } | { kind: "beginGesture"; payload: { nodes: ElementId[]; gesture: GestureType; anchor?: GestureAnchor | null; cameraScale?: number | null } } | { kind: "updateGesture"; payload: { handle: GestureHandle; delta: [number, number]; modifiers: GestureModifiers } } | { kind: "commitGesture"; payload: { handle: GestureHandle } } | { kind: "cancelGesture"; payload: { handle: GestureHandle } };
1354
+
1355
+ /**
1356
+ * Track J — wire-shape mirror of `paged_parse::PathAnchor`. The
1357
+ * parse-side type doesn\'t carry `Deserialize`/`PartialEq`/`Tsify`,
1358
+ * and the mutate API needs all three so this Op crosses the wasm
1359
+ * boundary. The field shapes match exactly: `anchor` is the
1360
+ * on-curve point, `left` / `right` are the incoming / outgoing
1361
+ * Bezier handles, all in the page item\'s inner coordinate system.
1362
+ */
1363
+ export interface PathAnchorSpec {
1364
+ anchor: [number, number];
1365
+ left: [number, number];
1366
+ right: [number, number];
1367
+ }
1368
+
1369
+ /**
1370
+ * Track M — wire-shape mirror of `paged_parse::Layer`. Surfaces
1371
+ * everything the Layers panel needs without leaking parse-side
1372
+ * fields the wasm boundary doesn\'t understand. `z` is the layer\'s
1373
+ * zero-based index in `designmap.layers` (top-first, matching the
1374
+ * renderer\'s paint order via `layer_z_index`).
1375
+ */
1376
+ export interface LayerSummary {
1377
+ selfId: string;
1378
+ name: string | null;
1379
+ visible: boolean;
1380
+ locked: boolean;
1381
+ printable: boolean;
1382
+ z: number;
1383
+ }
1384
+
1385
+ /**
1386
+ * Tsify-exposed snapshot of the SAB layout. The TS-side worker glue
1387
+ * reads this once at startup and asserts its own hardcoded mirror
1388
+ * matches; any drift triggers a `protocolMismatch` warning identical
1389
+ * to the `PROTOCOL_VERSION` reconciliation. Keeping the layout in
1390
+ * Rust lets a single edit drive both sides — TS sees the new value
1391
+ * the next time wasm rebuilds.
1392
+ */
1393
+ export interface GestureSabLayout {
1394
+ bytes: number;
1395
+ offsetHandleLo: number;
1396
+ offsetHandleHi: number;
1397
+ offsetDx: number;
1398
+ offsetDy: number;
1399
+ offsetModifiers: number;
1400
+ offsetSeq: number;
1401
+ offsetGenLo: number;
1402
+ offsetGenHi: number;
1403
+ modifierShift: number;
1404
+ modifierAlt: number;
1405
+ modifierDisableSnap: number;
1406
+ }
1407
+
1408
+ /**
1409
+ * Tsify-exposed snapshot of the camera SAB layout. The TS-side
1410
+ * `CameraBuffer` reads this once at startup via `cameraSabLayout()`
1411
+ * and asserts its own hardcoded `OFFSET_*` constants match — any
1412
+ * drift triggers a `protocolMismatch` warning on the canvas.
1413
+ */
1414
+ export interface CameraSabLayout {
1415
+ bytes: number;
1416
+ offsetScale: number;
1417
+ offsetTx: number;
1418
+ offsetTy: number;
1419
+ offsetGenLo: number;
1420
+ offsetGenHi: number;
1421
+ }
1422
+
1423
+ /**
1424
+ * Typed `LoadDocument` failure. Each variant maps to a specific UI
1425
+ * recovery in the main thread (corrupted file → \"try another file\";
1426
+ * missing font → \"install or substitute\"; etc.).
1427
+ */
1428
+ export type LoadError = { kind: "parse"; message: string } | { kind: "scene"; message: string } | { kind: "build"; message: string };
1429
+
1430
+ /**
1431
+ * Typed payload for a `SetProperty` Op. Each variant carries a value
1432
+ * of a specific kind; the apply layer\'s `TypeMismatch` error fires if
1433
+ * the variant doesn\'t match what the path expects.
1434
+ */
1435
+ export type Value = { type: "bounds"; value: [number, number, number, number] } | { type: "colorRef"; value: string | null } | { type: "length"; value: number | null } | { type: "transform"; value: [number, number, number, number, number, number] | null } | { type: "pathPoint"; value: { address: PathPointAddress; position: [number, number] } } | { type: "pathPointInsert"; value: { index: number; anchor: PathAnchorSpec; prevSubpathStarts?: number[] | null } } | { type: "pathPointRemove"; value: { index: number; prevSubpathStarts?: number[] | null } } | { type: "pathPointCurveType"; value: { index: number; smooth: boolean; prev?: PathAnchorSpec | null } } | { type: "pluginMetadata"; value: { key: string; value: string | null; prev?: string | null | null } } | { type: "bool"; value: boolean } | { type: "text"; value: string } | { type: "framePath"; value: { anchors: PathAnchorSpec[]; subpathStarts: number[] } } | { type: "pathOpenAt"; value: { index: number; prevAnchors?: PathAnchorSpec[] | null; prevSubpathStarts?: number[] | null; prevSubpathOpen?: boolean[] | null } } | { type: "outlineStroke"; value: { width: number; cap: string; join: string; miterLimit: number; prevAnchors?: PathAnchorSpec[] | null; prevSubpathStarts?: number[] | null; prevSubpathOpen?: boolean[] | null } } | { type: "offsetPath"; value: { delta: number; join: string; miterLimit: number; prevAnchors?: PathAnchorSpec[] | null; prevSubpathStarts?: number[] | null; prevSubpathOpen?: boolean[] | null } } | { type: "simplifyPath"; value: { tolerance: number; prevAnchors?: PathAnchorSpec[] | null; prevSubpathStarts?: number[] | null; prevSubpathOpen?: boolean[] | null } } | { type: "gradientFeather"; value: GradientFeatherSpec | null } | { type: "paragraphRule"; value: ParagraphRuleSpec | null } | { type: "tabStops"; value: TabStopSpec[] };
1436
+
1437
+ /**
1438
+ * Typed property path for `SetProperty` Ops. A closed enum (rather
1439
+ * than free-form `Vec<String>`) preserves Rust\'s exhaustiveness
1440
+ * guarantee inside `apply`/`invert`, and the `serde` rename lets the
1441
+ * wire format read like the dotted path the briefing illustrates
1442
+ * (`\"fill.color\"`) — so JS callers don\'t need to learn the Rust
1443
+ * enum shape.
1444
+ */
1445
+ export type PropertyPath = "frameBounds" | "frameFillColor" | "frameStrokeColor" | "frameStrokeWeight" | "frameOpacity" | "frameTransform" | "imageContentTransform" | "framePathPoint" | "pathPointInsert" | "pathPointRemove" | "pathPointCurveType" | "layerVisible" | "layerLocked" | "layerPrintable" | "layerName" | "characterFontSize" | "characterLeading" | "characterTracking" | "characterFillColor" | "paragraphSpaceBefore" | "paragraphSpaceAfter" | "paragraphFirstLineIndent" | "appliedParagraphStyle" | "appliedCharacterStyle" | "appliedObjectStyle" | "appliedCellStyle" | "appliedTableStyle" | "framePath" | "frameNonprinting" | "frameFillTint" | "frameGradientFillAngle" | "frameGradientFillLength" | "frameGradientStrokeAngle" | "frameGradientStrokeLength" | "pathOpenAt" | "outlineStroke" | "offsetPath" | "simplifyPath" | "frameGradientFeather" | "pageBounds" | "frameDropShadowMode" | "frameDropShadowXOffset" | "frameDropShadowYOffset" | "frameDropShadowSize" | "frameDropShadowOpacity" | "frameDropShadowColor" | "frameDropShadow" | "frameFittingCrops" | "frameFittingType" | "frameTextWrapMode" | "frameTextWrapOffsets" | "paragraphJustification" | "frameStrokeEndCap" | "frameInsetSpacing" | "appliedConditions" | "characterFontFamily" | "characterFontStyle" | "characterKerningMethod" | "characterCase" | "characterPosition" | "characterLanguage" | "characterBaselineShift" | "characterHorizontalScale" | "characterVerticalScale" | "characterSkew" | "characterUnderline" | "characterStrikethru" | "characterLigatures" | "characterOtfFeatures" | "paragraphLeftIndent" | "paragraphRightIndent" | "paragraphDropCapCharacters" | "paragraphDropCapLines" | "paragraphHyphenation" | "paragraphKeepLinesTogether" | "paragraphKeepWithNext" | "paragraphRuleAbove" | "paragraphRuleBelow" | "paragraphTabStops" | "paragraphListType" | "paragraphBulletCharacter" | "paragraphNumberingFormat" | "textFrameColumnCount" | "textFrameColumnGutter" | "textFrameColumnBalance" | "textFrameVerticalJustification" | "textFrameAutoSizing" | "textFrameFirstBaseline" | "textWrapInvert" | "frameFittingReferencePoint" | "frameAutoFit" | "frameStrokeType" | "frameStrokeJoin" | "frameStrokeMiterLimit" | "frameStrokeAlignment" | "frameStrokeGapColor" | "frameStrokeGapTint" | "frameCornerOptionTopLeft" | "frameCornerOptionTopRight" | "frameCornerOptionBottomLeft" | "frameCornerOptionBottomRight" | "frameCornerRadiusTopLeft" | "frameCornerRadiusTopRight" | "frameCornerRadiusBottomLeft" | "frameCornerRadiusBottomRight" | "frameRotationAngle" | "frameScaleX" | "frameScaleY" | "frameFlipH" | "frameFlipV" | "frameOverprintFill" | "frameOverprintStroke" | "frameInnerShadowEnabled" | "frameInnerShadowBlendMode" | "frameInnerShadowColor" | "frameInnerShadowOpacity" | "frameInnerShadowAngle" | "frameInnerShadowDistance" | "frameInnerShadowSize" | "frameInnerShadowChoke" | "frameInnerShadowNoise" | "frameOuterGlowEnabled" | "frameOuterGlowBlendMode" | "frameOuterGlowColor" | "frameOuterGlowOpacity" | "frameOuterGlowSpread" | "frameOuterGlowSize" | "frameOuterGlowNoise" | "frameInnerGlowEnabled" | "frameInnerGlowBlendMode" | "frameInnerGlowColor" | "frameInnerGlowOpacity" | "frameInnerGlowChoke" | "frameInnerGlowSize" | "frameInnerGlowSource" | "frameInnerGlowNoise" | "frameBevelEnabled" | "frameBevelStyle" | "frameBevelTechnique" | "frameBevelDepth" | "frameBevelDirection" | "frameBevelSize" | "frameBevelSoften" | "frameBevelAngle" | "frameBevelAltitude" | "frameBevelHighlightColor" | "frameBevelShadowColor" | "frameBevelHighlightOpacity" | "frameBevelShadowOpacity" | "frameSatinEnabled" | "frameSatinBlendMode" | "frameSatinColor" | "frameSatinOpacity" | "frameSatinAngle" | "frameSatinDistance" | "frameSatinSize" | "frameSatinInvert" | "frameFeatherEnabled" | "frameFeatherWidth" | "frameFeatherCornerType" | "frameFeatherNoise" | "frameFeatherChoke" | "frameDirectionalFeatherEnabled" | "frameDirectionalFeatherLeftWidth" | "frameDirectionalFeatherRightWidth" | "frameDirectionalFeatherTopWidth" | "frameDirectionalFeatherBottomWidth" | "frameDirectionalFeatherAngle" | "frameDirectionalFeatherNoise" | "frameDirectionalFeatherChoke" | "frameBlendMode" | "nextTextFrame" | "previousTextFrame" | "cellFillColor" | "cellFillTint" | "cellInsetTop" | "cellInsetLeft" | "cellInsetBottom" | "cellInsetRight" | "cellVerticalJustification" | "tableRowCount" | "tableColumnCount" | "pluginMetadata";
1446
+
1447
+ /**
1448
+ * Typed worker-side error for non-load operations. Mutations,
1449
+ * hit-tests, page requests all report through this. Variants are
1450
+ * kept stable across protocol versions.
1451
+ */
1452
+ export type WorkerError = { kind: "notImplemented"; details: { what: string } } | { kind: "unknownPage"; details: { pageId: PageId } } | { kind: "noDocument" };
1453
+
1454
+ /**
1455
+ * W0.2 — wire mirror of `paged_parse::TabStop`. The `ParagraphTabStops`
1456
+ * path replaces the paragraph\'s whole `<TabList>` in one op; `Value`
1457
+ * has no per-element list-edit form, so the UI sends the full new
1458
+ * stop list (the gradient-feather stop-list precedent).
1459
+ */
1460
+ export interface TabStopSpec {
1461
+ position: number;
1462
+ alignment?: string | null;
1463
+ alignmentCharacter?: string | null;
1464
+ leader?: string | null;
1465
+ }
1466
+
1467
+ /**
1468
+ * W0.2 — wire mirror of `paged_parse::styles::ParagraphRule` (the
1469
+ * AST type predates `Tsify`; the mirror keeps the op wire-shaped,
1470
+ * the `GradientFeatherSpec` precedent). Carries every field the
1471
+ * parser models so the whole-struct `ParagraphRuleAbove` /
1472
+ * `ParagraphRuleBelow` paths round-trip a paragraph\'s rule verbatim.
1473
+ */
1474
+ export interface ParagraphRuleSpec {
1475
+ on?: boolean | null;
1476
+ color?: string | null;
1477
+ tint?: number | null;
1478
+ weight?: number | null;
1479
+ offset?: number | null;
1480
+ leftIndent?: number | null;
1481
+ rightIndent?: number | null;
1482
+ width?: string | null;
1483
+ }
1484
+
1485
+ /**
1486
+ * W0.5 — character- vs paragraph-level style application for
1487
+ * [`Operation::ApplyStyle`].
1488
+ */
1489
+ export type StyleScope = "paragraph" | "character";
1490
+
1491
+ /**
1492
+ * W0.5 — the kind of field marker inserted by
1493
+ * [`Operation::InsertField`]. Extensible; v1 implements `PageNumber`
1494
+ * (the IDML auto current-page-number marker, U+E018).
1495
+ */
1496
+ export type FieldKind = "pageNumber" | "nextPageNumber";
1497
+
1498
+ /**
1499
+ * W0.5 — wire mirror of `paged_parse::GuideOrientation`
1500
+ * (which is `Deserialize` but lives in the parse crate; kept here so
1501
+ * the operation wire type doesn\'t depend on the parser\'s
1502
+ * serialization shape).
1503
+ */
1504
+ export type GuideOrientationSpec = "vertical" | "horizontal";
1505
+
1506
+ /**
1507
+ * W3.A0 — one live ruler guide on a spread, carried inline on
1508
+ * [`SpreadSummary`]. `id` is the positional id the guide-CRUD
1509
+ * mutations mint (`\"Guide/<spreadSelf>/<index>\"`), so the editor can
1510
+ * address a `MoveGuide` / `DeleteGuide` at it without a second
1511
+ * round-trip. `position` is the page-local coordinate on the
1512
+ * perpendicular axis (x for `Vertical`, y for `Horizontal`).
1513
+ */
1514
+ export interface GuideSummary {
1515
+ /**
1516
+ * Positional id — `\"Guide/<spreadSelf>/<index>\"`. Matches the id
1517
+ * `Operation::InsertGuide` mints (see `apply::guide_id_for`).
1518
+ */
1519
+ id: string;
1520
+ /**
1521
+ * `\"vertical\"` (snaps on x) or `\"horizontal\"` (snaps on y).
1522
+ */
1523
+ orientation: GuideOrientationWire;
1524
+ /**
1525
+ * Page-local coordinate on the perpendicular axis (pt).
1526
+ */
1527
+ position: number;
1528
+ /**
1529
+ * Zero-based index into the spread\'s pages (IDML\'s `PageIndex`).
1530
+ */
1531
+ pageIndex: number;
1532
+ }
1533
+
1534
+ /**
1535
+ * W3.A1 — wire shape of [`crate::hit::TableHitContext`]: the table
1536
+ * cell a `HitTest` landed in.
1537
+ */
1538
+ export interface TableHitContext {
1539
+ tableId: string;
1540
+ row: number;
1541
+ col: number;
1542
+ }
1543
+
1544
+ /**
1545
+ * What the resolver produced this pass. The canvas worker reads
1546
+ * `numbering_map` to drive the running-header / page-number
1547
+ * rendering, walks `field_diff` to feed the Tier 2 re-layout
1548
+ * queue, and walks `dirty_pages` to bump per-page
1549
+ * `numbering_generation` counters.
1550
+ */
1551
+ export interface ResolutionResult {
1552
+ numbering: NumberingMap;
1553
+ fieldDiff: FieldChange[];
1554
+ dirtyPages: PageId[];
1555
+ /**
1556
+ * Number of iterations the resolver ran. Spec caps at 4;
1557
+ * reaching the cap is a warning the caller surfaces in the
1558
+ * debug HUD.
1559
+ */
1560
+ iterations: number;
1561
+ /**
1562
+ * Per-page running header — for each page, the most recent
1563
+ * heading paragraph at-or-before that page. Drives the
1564
+ * `RunningHeader(style)` field substitution in master content.
1565
+ * One entry per page in document order.
1566
+ */
1567
+ runningHeaders?: RunningHeader[];
1568
+ /**
1569
+ * Materialised TOC entries from `Document::resolve_toc()`.
1570
+ * Empty when the document has no `<TOCStyle>` definitions or
1571
+ * none of its paragraphs match TOC entry styles.
1572
+ */
1573
+ toc?: TocEntry[];
1574
+ /**
1575
+ * Count of footnote-body anchors in the document. Reserved
1576
+ * for the parser-side footnote work; renders as a HUD badge.
1577
+ */
1578
+ footnoteCount?: number;
1579
+ }
1580
+
1581
+ /**
1582
+ * What to consider when hit-testing. The inspector + editor route
1583
+ * pointer events through this. Phase 1 only implements `Frame`.
1584
+ */
1585
+ export type HitFilter = "frame" | "text" | "any";
1586
+
1587
+ /**
1588
+ * Which style collection a `SetStyleProperty` targets.
1589
+ */
1590
+ export type StyleCollection = "paragraph" | "character" | "object" | "cell" | "table";
1591
+
1592
+ /**
1593
+ * Wire description of a colour group, mirroring `ColorGroupEntry`.
1594
+ */
1595
+ export interface ColorGroupSpec {
1596
+ selfId?: string | null;
1597
+ name?: string | null;
1598
+ /**
1599
+ * `Color/<id>` (or `Swatch/<id>`) member refs, in order.
1600
+ */
1601
+ members?: string[];
1602
+ }
1603
+
1604
+ /**
1605
+ * Wire description of a gradient swatch, mirroring `GradientEntry`.
1606
+ */
1607
+ export interface GradientSpec {
1608
+ selfId?: string | null;
1609
+ name?: string | null;
1610
+ /**
1611
+ * `Type`: `\"Linear\"` | `\"Radial\"`.
1612
+ */
1613
+ kind: string;
1614
+ stops: GradientStopSpec[];
1615
+ }
1616
+
1617
+ /**
1618
+ * Wire-format description of a colour swatch (`<Color>`), mirroring
1619
+ * the editable fields of `paged_parse::ColorEntry` with primitive,
1620
+ * `Deserialize`-able types (the AST `ColorEntry` is `Serialize`-only).
1621
+ * Carried by the swatch-collection mutations so create / edit /
1622
+ * delete-undo are lossless. `space` / `model` / `alternate_space` are
1623
+ * the IDML attribute strings (`ColorSpace::as_attr` etc.).
1624
+ */
1625
+ export interface SwatchSpec {
1626
+ /**
1627
+ * IDML `Self` id. `None` on create ⇒ the apply layer assigns a
1628
+ * deterministic non-colliding `Color/u<n>`.
1629
+ */
1630
+ selfId?: string | null;
1631
+ name?: string | null;
1632
+ /**
1633
+ * `Space` attribute: `\"CMYK\"` | `\"RGB\"` | `\"LAB\"` | `\"Gray\"`.
1634
+ */
1635
+ space: string;
1636
+ /**
1637
+ * Channel values in `space` (4 for CMYK, 3 for RGB/Lab, 1 for Gray).
1638
+ */
1639
+ value: number[];
1640
+ /**
1641
+ * `Model`: `\"Process\"` (default) | `\"Spot\"`.
1642
+ */
1643
+ model?: string | null;
1644
+ alternateSpace?: string | null;
1645
+ alternateValue?: number[];
1646
+ tint?: number | null;
1647
+ alpha?: number | null;
1648
+ }
1649
+
1650
+ /**
1651
+ * Wire-format errors for the gesture envelope. Mirrors the variants
1652
+ * of `crate::gesture::GestureError` so the channel doesn\'t expose the
1653
+ * internal `thiserror` representation.
1654
+ */
1655
+ export type GestureFailure = { kind: "noDocument" } | { kind: "unsupportedGesture"; details: { reason: string } } | { kind: "alreadyActive"; details: { handle: GestureHandle } } | { kind: "handleMismatch" } | { kind: "elementNotFound"; details: { id: ElementId } } | { kind: "rotatedFrameUnsupported" } | { kind: "emptySelection" } | { kind: "missingAnchor" } | { kind: "unknownAnchorPage"; details: { page_id: PageId } } | { kind: "other"; details: { message: string } };
1656
+
1657
+ /**
1658
+ * `RequestLineBounds` reply payload.
1659
+ */
1660
+ export interface LineBounds {
1661
+ /**
1662
+ * Story offset of the line\'s first character.
1663
+ */
1664
+ lineStart: number;
1665
+ /**
1666
+ * Story offset just past the line\'s last character.
1667
+ */
1668
+ lineEnd: number;
1669
+ }
1670
+
1671
+ /**
1672
+ * panels.md gap 20 — one structured PDF-export preflight finding for
1673
+ * the export dialog\'s findings list. The wire mirror of
1674
+ * `paged_export_pdf::PreflightFinding`. `severity` is `\"warning\"` /
1675
+ * `\"error\"`; `code` is a stable machine tag (`\"font_not_embeddable\"`
1676
+ * / `\"image_missing_bytes\"`); `page_index` is the 0-based body-page
1677
+ * the finding was raised on (`None` for document-level findings).
1678
+ */
1679
+ export interface PreflightFinding {
1680
+ code: string;
1681
+ severity: string;
1682
+ message: string;
1683
+ pageIndex?: number | null;
1684
+ }
1685
+
1686
+ /**
1687
+ * panels.md gaps 9/10/19 — one `<Section>` definition. Backs
1688
+ * `documentCollection:sections`. The Pages panel groups page
1689
+ * thumbnails by section and labels each group with its prefix +
1690
+ * numbering style; `start_page_index` + `page_count` let it draw
1691
+ * the section bands. `page_count` is computed by walking the body
1692
+ * pages between this section\'s start and the next section\'s start
1693
+ * (or the document end).
1694
+ */
1695
+ export interface SectionSummary {
1696
+ /**
1697
+ * IDML `Self` id of the `<Section>`.
1698
+ */
1699
+ selfId: string;
1700
+ /**
1701
+ * `SectionPrefix` (e.g. `\"A-\"`); empty when the section has no
1702
+ * prefix or doesn\'t include it in labels.
1703
+ */
1704
+ prefix: string;
1705
+ /**
1706
+ * Page-number style — `\"arabic\"` / `\"upperRoman\"` /
1707
+ * `\"lowerRoman\"` / `\"upperAlpha\"` / `\"lowerAlpha\"`. The label a
1708
+ * panel renders next to the section band.
1709
+ */
1710
+ labelStyle: string;
1711
+ /**
1712
+ * 0-based flat body-page index where this section begins (the
1713
+ * page whose `Self` matches `PageStart`). `None` when the
1714
+ * section\'s start page can\'t be located in the built document.
1715
+ */
1716
+ startPageIndex?: number | null;
1717
+ /**
1718
+ * Number of body pages this section spans (up to the next
1719
+ * section\'s start, or the document end).
1720
+ */
1721
+ pageCount: number;
1722
+ }
1723
+
1724
+ export interface CaretGeometry {
1725
+ pageId: PageId;
1726
+ frameId: string | null;
1727
+ /**
1728
+ * Page-local x of the caret leading edge.
1729
+ */
1730
+ xPt: number;
1731
+ /**
1732
+ * Page-local y of the caret top (baseline - ascent).
1733
+ */
1734
+ topPt: number;
1735
+ /**
1736
+ * Total caret height (ascent + descent).
1737
+ */
1738
+ heightPt: number;
1739
+ }
1740
+
1741
+ export interface FrameBounds {
1742
+ left: number;
1743
+ top: number;
1744
+ right: number;
1745
+ bottom: number;
1746
+ }
1747
+
1748
+ export interface RunningHeader {
1749
+ pageId: PageId;
1750
+ pageNumber: number;
1751
+ /**
1752
+ * Most recent heading at-or-before this page. Empty before the
1753
+ * first heading.
1754
+ */
1755
+ text: string;
1756
+ level: number;
1757
+ }
1758
+
1759
+ export interface TocEntry {
1760
+ level: number;
1761
+ text: string;
1762
+ /**
1763
+ * 1-based body page number, or 0 if the entry\'s host story
1764
+ * has no body-page placement (orphan).
1765
+ */
1766
+ pageNumber: number;
1767
+ /**
1768
+ * Original IDML paragraph style name the entry was matched
1769
+ * against — useful for debugging / styling.
1770
+ */
1771
+ includeStyle: string;
1772
+ }
1773
+
1774
+ export type AnchorId = string;
1775
+
1776
+ export type GuideOrientationWire = "vertical" | "horizontal";
1777
+
1778
+ export type ProtocolVersion = number;
1779
+
1780
+ export type SnapshotError = { kind: "unknownPage"; details: { page_id: PageId } } | { kind: "pngEncode"; details: string } | { kind: "invalidWidth"; details: number };
1781
+
1782
+
1783
+ /**
1784
+ * Worker-side state holder. The JS worker creates one of these
1785
+ * per worker lifetime and forwards `MessageEvent.data` to
1786
+ * `handle_message` after JSON parsing.
1787
+ */
1788
+ export class CanvasWorker {
1789
+ free(): void;
1790
+ [Symbol.dispose](): void;
1791
+ /**
1792
+ * Phase 3 — caret geometry for a JSON-encoded
1793
+ * `ContentSelection`. Returns a JSON-encoded `CaretGeometry`
1794
+ * or `null` when the selection's story has no captured
1795
+ * layout. The Overlay calls this on selection change to
1796
+ * position the caret.
1797
+ */
1798
+ caretGeometryJson(selection_json: string): string | undefined;
1799
+ /**
1800
+ * Whether GPU is initialised. The worker checks this each
1801
+ * frame to decide which render path to take. Cheap; just a
1802
+ * pointer-null check.
1803
+ */
1804
+ gpuReady(): boolean;
1805
+ /**
1806
+ * simple — no nested serde-wasm-bindgen conversions, just
1807
+ * `Vec<u8>` bytes in and bytes out.
1808
+ */
1809
+ handleMessage(input: string): string;
1810
+ /**
1811
+ * Initialise the WebGPU + Vello surface presenter against
1812
+ * `canvas`. Async because the browser's adapter and device
1813
+ * requests are Promise-based. On success the worker can call
1814
+ * `presentFrame` per render tick; on failure the worker
1815
+ * stays on the CPU snapshot-blit fallback path.
1816
+ *
1817
+ * `width` / `height` are device-pixel dimensions; the JS
1818
+ * caller passes `canvas.width` and `canvas.height` which it
1819
+ * has already sized to `cssWidth * dpr`.
1820
+ */
1821
+ initGpu(canvas: OffscreenCanvas, width: number, height: number): Promise<boolean>;
1822
+ /**
1823
+ * Direct binary entry point for `loadDocument`. Bypasses the
1824
+ * JSON channel so multi-MB IDMLs don't have to ride as a
1825
+ * 8×-inflated `number[]` array (which on wasm32 trips the
1826
+ * 2 GB `Vec::with_capacity` cap during serde parse — the
1827
+ * megapacks ≥100 MB panic with "capacity overflow" through
1828
+ * the JSON path). Returns a JSON string that the JS side
1829
+ * parses with the same `WorkerToMain` shape `handleMessage`
1830
+ * would produce — `documentLoaded` on success, `loadFailed`
1831
+ * otherwise.
1832
+ */
1833
+ loadDocumentDirect(seq: number, bytes: Uint8Array, font?: Uint8Array | null, cmyk_icc_profile?: Uint8Array | null): string;
1834
+ constructor();
1835
+ /**
1836
+ * Number of pages in the loaded document, or 0 if no
1837
+ * document is loaded.
1838
+ */
1839
+ pageCount(): number;
1840
+ /**
1841
+ * Per-page dimensions for the worker's render loop. Returns
1842
+ * a flat `[page_id_len, ...page_id_utf8, w_pt, h_pt]`-style
1843
+ * blob? No — wasm-bindgen handles `Vec<JsValue>` poorly.
1844
+ * Easier: each call returns one page; iterate by index.
1845
+ * Returns `None` past the end. Tuple is `[page_id, w_pt, h_pt]`
1846
+ * serialised as a JS array.
1847
+ */
1848
+ pageInfo(index: number): Array<any> | undefined;
1849
+ /**
1850
+ * Render the visible pages at the current camera into the
1851
+ * bound surface. Camera operates in CSS pixels; the
1852
+ * presenter applies `dpr` internally as we bake it into the
1853
+ * per-page transforms below.
1854
+ *
1855
+ * Returns `false` if the surface presenter isn't initialised
1856
+ * or no document is loaded — the worker falls back to its
1857
+ * CPU path in that case.
1858
+ */
1859
+ presentFrame(scale: number, tx: number, ty: number, dpr: number): boolean;
1860
+ /**
1861
+ * Sub-phase D — render `page_id` to a PNG via the Vello GPU
1862
+ * path (off-surface). Returns `None` if GPU is not
1863
+ * initialised, the page id is unknown, or the underlying
1864
+ * readback fails. The fidelity suite calls this with
1865
+ * `BACKEND=gpu` to test the production hot path; the CPU
1866
+ * path (`renderTilePng`) stays as the deterministic
1867
+ * fallback used in CI.
1868
+ */
1869
+ renderPageVelloPng(page_id: string, dpi: number): Promise<Uint8Array | undefined>;
1870
+ /**
1871
+ * Worker-internal tile rendering. Bypasses the JSON
1872
+ * `RequestSnapshot` round-trip — for the render loop that
1873
+ * fires every frame, the JSON serialize/parse cost of a
1874
+ * 1024px PNG (~megabyte of `[n, n, n, ...]` text) dominates
1875
+ * the actual rasterization. Returns raw PNG bytes the JS
1876
+ * side feeds straight to `createImageBitmap(blob)`.
1877
+ *
1878
+ * Returns `None` (→ `undefined` on the JS side) if no
1879
+ * document is loaded or the page id is unknown.
1880
+ */
1881
+ renderTilePng(page_id: string, target_width_px: number): Uint8Array | undefined;
1882
+ /**
1883
+ * Resize the GPU surface. Worker calls this from a
1884
+ * ResizeObserver on the host canvas element.
1885
+ */
1886
+ resizeGpu(width: number, height: number): void;
1887
+ /**
1888
+ * Run the Tier 3 resolver against the current model.
1889
+ * Returns the result as a JSON string the JS side can
1890
+ * parse via `JSON.parse`. `null` when no document is loaded.
1891
+ * The worker invokes this after `LoadDocument` succeeds and
1892
+ * posts the parsed result as an unsolicited `resolutionDone`
1893
+ * message to the main thread. Phase 2 — heading anchors and
1894
+ * their assigned page numbers become visible in the UI.
1895
+ */
1896
+ runResolveJson(): string | undefined;
1897
+ /**
1898
+ * Number of cached page scenes currently resident. Surfaced
1899
+ * for the HUD / DevTools — a developer-facing memory probe.
1900
+ */
1901
+ sceneCacheSize(): number;
1902
+ /**
1903
+ * Phase 3 — selection geometry (rect-per-line) for a
1904
+ * JSON-encoded `ContentSelection`. Returns a JSON array of
1905
+ * `SelectionRect`. Empty array for caret selections.
1906
+ */
1907
+ selectionGeometryJson(selection_json: string): string | undefined;
1908
+ /**
1909
+ * Override the LRU budget. Useful from a developer console
1910
+ * when measuring memory behaviour.
1911
+ */
1912
+ setSceneCacheBudget(max_entries: number): void;
1913
+ /**
1914
+ * Handle one main-thread message. Input is the JSON string
1915
+ * the JS side produced via `JSON.stringify(msg)`. Output is
1916
+ * the JSON string the JS side should `JSON.parse` and post
1917
+ * back to the main thread. Returning a string (rather than
1918
+ * a wasm-bindgen-serialised object) keeps the boundary
1919
+ * Step 5d/5e — raw-arg update-gesture entry. The worker drains
1920
+ * the gesture SAB every tick and calls this without going
1921
+ * through `handleMessage`'s JSON envelope. Returns an empty
1922
+ * string on failure (no document loaded or gesture has gone
1923
+ * stale — the worker drops the tick). On success returns a
1924
+ * JSON string with the dirty page set + active snap guides so
1925
+ * the worker can post a `GestureSnapLines` notification and
1926
+ * run its `markDirty` invalidation without re-querying.
1927
+ *
1928
+ * The 64-bit handle arrives split into low/high words because
1929
+ * JS Numbers can't represent the full u64 range cleanly.
1930
+ * `modifier_bits`: bit 0 = shift, bit 1 = alt, bit 2 =
1931
+ * disable_snap (Ctrl, plan-2 §8.4). Matches the SAB layout
1932
+ * in `packages/shell/src/gestures/gesture-sab.ts`.
1933
+ */
1934
+ updateGestureRaw(handle_lo: number, handle_hi: number, dx: number, dy: number, modifier_bits: number): string;
1935
+ /**
1936
+ * Protocol version constant; the JS side compares against
1937
+ * its bundled value before sending `LoadDocument`.
1938
+ */
1939
+ readonly protocolVersion: number;
1940
+ }
1941
+
1942
+ export function cameraSabBytes(): number;
1943
+
1944
+ export function cameraSabLayout(): CameraSabLayout;
1945
+
1946
+ export function gestureSabBytes(): number;
1947
+
1948
+ export function gestureSabLayout(): GestureSabLayout;
1949
+
1950
+ export function on_start(): void;
1951
+
1952
+ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
1953
+
1954
+ export interface InitOutput {
1955
+ readonly memory: WebAssembly.Memory;
1956
+ readonly __wbg_canvasworker_free: (a: number, b: number) => void;
1957
+ readonly cameraSabBytes: () => number;
1958
+ readonly cameraSabLayout: () => any;
1959
+ readonly canvasworker_caretGeometryJson: (a: number, b: number, c: number) => [number, number];
1960
+ readonly canvasworker_gpuReady: (a: number) => number;
1961
+ readonly canvasworker_handleMessage: (a: number, b: number, c: number) => [number, number];
1962
+ readonly canvasworker_initGpu: (a: number, b: any, c: number, d: number) => any;
1963
+ readonly canvasworker_loadDocumentDirect: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number) => [number, number];
1964
+ readonly canvasworker_new: () => number;
1965
+ readonly canvasworker_pageCount: (a: number) => number;
1966
+ readonly canvasworker_pageInfo: (a: number, b: number) => any;
1967
+ readonly canvasworker_presentFrame: (a: number, b: number, c: number, d: number, e: number) => [number, number, number];
1968
+ readonly canvasworker_protocolVersion: (a: number) => number;
1969
+ readonly canvasworker_renderPageVelloPng: (a: number, b: number, c: number, d: number) => any;
1970
+ readonly canvasworker_renderTilePng: (a: number, b: number, c: number, d: number) => [number, number];
1971
+ readonly canvasworker_resizeGpu: (a: number, b: number, c: number) => void;
1972
+ readonly canvasworker_runResolveJson: (a: number) => [number, number];
1973
+ readonly canvasworker_sceneCacheSize: (a: number) => number;
1974
+ readonly canvasworker_selectionGeometryJson: (a: number, b: number, c: number) => [number, number];
1975
+ readonly canvasworker_setSceneCacheBudget: (a: number, b: number) => void;
1976
+ readonly canvasworker_updateGestureRaw: (a: number, b: number, c: number, d: number, e: number, f: number) => [number, number];
1977
+ readonly gestureSabLayout: () => any;
1978
+ readonly on_start: () => void;
1979
+ readonly gestureSabBytes: () => number;
1980
+ readonly qcms_enable_iccv4: () => void;
1981
+ readonly qcms_profile_precache_output_transform: (a: number) => void;
1982
+ readonly qcms_transform_data_bgra_out_lut: (a: number, b: number, c: number, d: number) => void;
1983
+ readonly qcms_transform_data_bgra_out_lut_precache: (a: number, b: number, c: number, d: number) => void;
1984
+ readonly qcms_transform_data_rgb_out_lut: (a: number, b: number, c: number, d: number) => void;
1985
+ readonly qcms_transform_data_rgb_out_lut_precache: (a: number, b: number, c: number, d: number) => void;
1986
+ readonly qcms_transform_data_rgba_out_lut: (a: number, b: number, c: number, d: number) => void;
1987
+ readonly qcms_transform_data_rgba_out_lut_precache: (a: number, b: number, c: number, d: number) => void;
1988
+ readonly qcms_transform_release: (a: number) => void;
1989
+ readonly qcms_profile_is_bogus: (a: number) => number;
1990
+ readonly qcms_white_point_sRGB: (a: number) => void;
1991
+ readonly lut_inverse_interp16: (a: number, b: number, c: number) => number;
1992
+ readonly lut_interp_linear16: (a: number, b: number, c: number) => number;
1993
+ readonly wasm_bindgen__convert__closures_____invoke__hba9dab33e391dce8: (a: number, b: number, c: any) => [number, number];
1994
+ readonly wasm_bindgen__convert__closures_____invoke__h2a9a86477ca3734e: (a: number, b: number, c: any, d: any) => void;
1995
+ readonly wasm_bindgen__convert__closures_____invoke__h84d34b615e684f5e: (a: number, b: number, c: any) => void;
1996
+ readonly __wbindgen_malloc: (a: number, b: number) => number;
1997
+ readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
1998
+ readonly __wbindgen_exn_store: (a: number) => void;
1999
+ readonly __externref_table_alloc: () => number;
2000
+ readonly __wbindgen_externrefs: WebAssembly.Table;
2001
+ readonly __wbindgen_free: (a: number, b: number, c: number) => void;
2002
+ readonly __wbindgen_destroy_closure: (a: number, b: number) => void;
2003
+ readonly __externref_table_dealloc: (a: number) => void;
2004
+ readonly __wbindgen_start: () => void;
2005
+ }
2006
+
2007
+ export type SyncInitInput = BufferSource | WebAssembly.Module;
2008
+
2009
+ /**
2010
+ * Instantiates the given `module`, which can either be bytes or
2011
+ * a precompiled `WebAssembly.Module`.
2012
+ *
2013
+ * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
2014
+ *
2015
+ * @returns {InitOutput}
2016
+ */
2017
+ export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
2018
+
2019
+ /**
2020
+ * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
2021
+ * for everything else, calls `WebAssembly.instantiate` directly.
2022
+ *
2023
+ * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
2024
+ *
2025
+ * @returns {Promise<InitOutput>}
2026
+ */
2027
+ export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;