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