@arbidocs/blocks 0.4.101 → 0.4.102

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/chunk-6MG62I5B.cjs +272 -0
  2. package/dist/chunk-6MG62I5B.cjs.map +1 -0
  3. package/dist/chunk-EQB3WELX.js +269 -0
  4. package/dist/chunk-EQB3WELX.js.map +1 -0
  5. package/dist/document-tools/AdoptSignatureDialog.d.ts +25 -0
  6. package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
  7. package/dist/document-tools/SignatureRequestBanner.d.ts +18 -0
  8. package/dist/document-tools/index.cjs +175 -0
  9. package/dist/document-tools/index.cjs.map +1 -1
  10. package/dist/document-tools/index.d.ts +3 -1
  11. package/dist/document-tools/index.js +168 -3
  12. package/dist/document-tools/index.js.map +1 -1
  13. package/dist/document-tools/viewer/GuidedSigningViewer.d.ts +26 -0
  14. package/dist/document-tools/viewer/SignatureFieldsOverlay.d.ts +41 -0
  15. package/dist/document-tools/viewer/SignatureRequestEditor.d.ts +26 -0
  16. package/dist/document-tools/viewer/index.cjs +983 -0
  17. package/dist/document-tools/viewer/index.cjs.map +1 -1
  18. package/dist/document-tools/viewer/index.d.ts +3 -0
  19. package/dist/document-tools/viewer/index.js +983 -5
  20. package/dist/document-tools/viewer/index.js.map +1 -1
  21. package/node_modules/@arbidocs/coedit/LICENSE +21 -0
  22. package/node_modules/@arbidocs/coedit/dist/encoding.cjs +751 -0
  23. package/node_modules/@arbidocs/coedit/dist/encoding.cjs.map +1 -0
  24. package/node_modules/@arbidocs/coedit/dist/encoding.d.cts +192 -0
  25. package/node_modules/@arbidocs/coedit/dist/encoding.d.ts +192 -0
  26. package/node_modules/@arbidocs/coedit/dist/encoding.js +716 -0
  27. package/node_modules/@arbidocs/coedit/dist/encoding.js.map +1 -0
  28. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs +1759 -0
  29. package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs.map +1 -0
  30. package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.cts +39 -0
  31. package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.ts +39 -0
  32. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js +1736 -0
  33. package/node_modules/@arbidocs/coedit/dist/hocuspocus.js.map +1 -0
  34. package/node_modules/@arbidocs/coedit/dist/index.cjs +1692 -0
  35. package/node_modules/@arbidocs/coedit/dist/index.cjs.map +1 -0
  36. package/node_modules/@arbidocs/coedit/dist/index.d.cts +16 -0
  37. package/node_modules/@arbidocs/coedit/dist/index.d.ts +16 -0
  38. package/node_modules/@arbidocs/coedit/dist/index.js +1664 -0
  39. package/node_modules/@arbidocs/coedit/dist/index.js.map +1 -0
  40. package/node_modules/@arbidocs/coedit/dist/server.cjs +1852 -0
  41. package/node_modules/@arbidocs/coedit/dist/server.cjs.map +1 -0
  42. package/node_modules/@arbidocs/coedit/dist/server.d.cts +43 -0
  43. package/node_modules/@arbidocs/coedit/dist/server.d.ts +43 -0
  44. package/node_modules/@arbidocs/coedit/dist/server.js +1822 -0
  45. package/node_modules/@arbidocs/coedit/dist/server.js.map +1 -0
  46. package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.cts +82 -0
  47. package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.ts +82 -0
  48. package/node_modules/@arbidocs/coedit/dist/template.cjs +1627 -0
  49. package/node_modules/@arbidocs/coedit/dist/template.cjs.map +1 -0
  50. package/node_modules/@arbidocs/coedit/dist/template.d.cts +125 -0
  51. package/node_modules/@arbidocs/coedit/dist/template.d.ts +125 -0
  52. package/node_modules/@arbidocs/coedit/dist/template.js +1612 -0
  53. package/node_modules/@arbidocs/coedit/dist/template.js.map +1 -0
  54. package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.cts +8 -0
  55. package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.ts +8 -0
  56. package/node_modules/@arbidocs/coedit/package.json +68 -0
  57. package/node_modules/@docx-editor.dev/core/LICENSE +201 -0
  58. package/node_modules/@docx-editor.dev/core/README.md +125 -0
  59. package/node_modules/@docx-editor.dev/core/THIRD_PARTY_NOTICES.md +56 -0
  60. package/node_modules/@docx-editor.dev/core/dist/automation.cjs +1 -0
  61. package/node_modules/@docx-editor.dev/core/dist/automation.d.ts +162 -0
  62. package/node_modules/@docx-editor.dev/core/dist/automation.js +1 -0
  63. package/node_modules/@docx-editor.dev/core/dist/binding.cjs +1 -0
  64. package/node_modules/@docx-editor.dev/core/dist/binding.d.ts +164 -0
  65. package/node_modules/@docx-editor.dev/core/dist/binding.js +1 -0
  66. package/node_modules/@docx-editor.dev/core/dist/chunk-2GO5T2JU.cjs +1 -0
  67. package/node_modules/@docx-editor.dev/core/dist/chunk-2RC2EPND.js +3 -0
  68. package/node_modules/@docx-editor.dev/core/dist/chunk-4GBTELJV.cjs +28 -0
  69. package/node_modules/@docx-editor.dev/core/dist/chunk-4R3TEXMN.js +18 -0
  70. package/node_modules/@docx-editor.dev/core/dist/chunk-5CSUYANV.js +1 -0
  71. package/node_modules/@docx-editor.dev/core/dist/chunk-6APGXLBB.cjs +3 -0
  72. package/node_modules/@docx-editor.dev/core/dist/chunk-6AWEKBLB.cjs +1 -0
  73. package/node_modules/@docx-editor.dev/core/dist/chunk-6EYYL7FL.js +1 -0
  74. package/node_modules/@docx-editor.dev/core/dist/chunk-6JIJOZDW.js +1 -0
  75. package/node_modules/@docx-editor.dev/core/dist/chunk-BTQKU64Q.cjs +1 -0
  76. package/node_modules/@docx-editor.dev/core/dist/chunk-E7BQA6UP.js +2 -0
  77. package/node_modules/@docx-editor.dev/core/dist/chunk-EO4C5QJW.cjs +2 -0
  78. package/node_modules/@docx-editor.dev/core/dist/chunk-ETTO6GK3.js +1 -0
  79. package/node_modules/@docx-editor.dev/core/dist/chunk-FIJZIQXA.cjs +18 -0
  80. package/node_modules/@docx-editor.dev/core/dist/chunk-FRXAOVTB.js +28 -0
  81. package/node_modules/@docx-editor.dev/core/dist/chunk-J6BVWIDB.js +2 -0
  82. package/node_modules/@docx-editor.dev/core/dist/chunk-JGNVNT2A.cjs +2 -0
  83. package/node_modules/@docx-editor.dev/core/dist/chunk-K5U2PLDP.cjs +2 -0
  84. package/node_modules/@docx-editor.dev/core/dist/chunk-KKIJG3C6.js +2 -0
  85. package/node_modules/@docx-editor.dev/core/dist/chunk-LWDSDCMO.js +27 -0
  86. package/node_modules/@docx-editor.dev/core/dist/chunk-NBCVVZOM.cjs +1 -0
  87. package/node_modules/@docx-editor.dev/core/dist/chunk-O2AL2HSJ.cjs +1 -0
  88. package/node_modules/@docx-editor.dev/core/dist/chunk-O5INAWZQ.js +1 -0
  89. package/node_modules/@docx-editor.dev/core/dist/chunk-QMLCVPCD.cjs +1 -0
  90. package/node_modules/@docx-editor.dev/core/dist/chunk-RCHS4ZEH.cjs +27 -0
  91. package/node_modules/@docx-editor.dev/core/dist/chunk-RIYSCEFQ.js +2 -0
  92. package/node_modules/@docx-editor.dev/core/dist/chunk-S6J4O5XP.js +1 -0
  93. package/node_modules/@docx-editor.dev/core/dist/chunk-SRPILEWV.cjs +5 -0
  94. package/node_modules/@docx-editor.dev/core/dist/chunk-TSLBZ26X.js +1 -0
  95. package/node_modules/@docx-editor.dev/core/dist/chunk-UKVVUHZL.cjs +1 -0
  96. package/node_modules/@docx-editor.dev/core/dist/chunk-VDNNLG6X.js +2 -0
  97. package/node_modules/@docx-editor.dev/core/dist/chunk-VHAVHCQY.js +7 -0
  98. package/node_modules/@docx-editor.dev/core/dist/chunk-VX43VBAX.cjs +7 -0
  99. package/node_modules/@docx-editor.dev/core/dist/chunk-Z6WBFXJU.js +5 -0
  100. package/node_modules/@docx-editor.dev/core/dist/chunk-ZUHOMK52.cjs +2 -0
  101. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.cjs +1 -0
  102. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.d.ts +270 -0
  103. package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.js +1 -0
  104. package/node_modules/@docx-editor.dev/core/dist/collaboration.cjs +1 -0
  105. package/node_modules/@docx-editor.dev/core/dist/collaboration.d.ts +269 -0
  106. package/node_modules/@docx-editor.dev/core/dist/collaboration.js +1 -0
  107. package/node_modules/@docx-editor.dev/core/dist/contracts/document.cjs +1 -0
  108. package/node_modules/@docx-editor.dev/core/dist/contracts/document.d.ts +290 -0
  109. package/node_modules/@docx-editor.dev/core/dist/contracts/document.js +0 -0
  110. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.cjs +1 -0
  111. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.d.ts +22 -0
  112. package/node_modules/@docx-editor.dev/core/dist/contracts/editor.js +1 -0
  113. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.cjs +1 -0
  114. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.d.ts +103 -0
  115. package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.js +0 -0
  116. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.cjs +1 -0
  117. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.d.ts +143 -0
  118. package/node_modules/@docx-editor.dev/core/dist/contracts/modules.js +1 -0
  119. package/node_modules/@docx-editor.dev/core/dist/contracts/types.cjs +1 -0
  120. package/node_modules/@docx-editor.dev/core/dist/contracts/types.d.ts +11 -0
  121. package/node_modules/@docx-editor.dev/core/dist/contracts/types.js +0 -0
  122. package/node_modules/@docx-editor.dev/core/dist/custom-node-writes-cvL5rhcD.d.ts +323 -0
  123. package/node_modules/@docx-editor.dev/core/dist/dist-PKZR6RSH.js +2 -0
  124. package/node_modules/@docx-editor.dev/core/dist/document-protection-BAGVGqaP.d.ts +20 -0
  125. package/node_modules/@docx-editor.dev/core/dist/editor-Ci7IZGmG.d.ts +2448 -0
  126. package/node_modules/@docx-editor.dev/core/dist/editor-scope-OHPwVQ5l.d.ts +84 -0
  127. package/node_modules/@docx-editor.dev/core/dist/editor.cjs +1 -0
  128. package/node_modules/@docx-editor.dev/core/dist/editor.css +15 -0
  129. package/node_modules/@docx-editor.dev/core/dist/editor.d.ts +1394 -0
  130. package/node_modules/@docx-editor.dev/core/dist/editor.js +1 -0
  131. package/node_modules/@docx-editor.dev/core/dist/export.cjs +2 -0
  132. package/node_modules/@docx-editor.dev/core/dist/export.d.ts +391 -0
  133. package/node_modules/@docx-editor.dev/core/dist/export.js +2 -0
  134. package/node_modules/@docx-editor.dev/core/dist/failure-NS2lsya4.d.ts +115 -0
  135. package/node_modules/@docx-editor.dev/core/dist/font-resolver-BVQB14qT.d.ts +256 -0
  136. package/node_modules/@docx-editor.dev/core/dist/harfbuzz.wasm +0 -0
  137. package/node_modules/@docx-editor.dev/core/dist/headless-document-view-qH331moE.d.ts +143 -0
  138. package/node_modules/@docx-editor.dev/core/dist/image-resources-BN-hUgCn.d.ts +211 -0
  139. package/node_modules/@docx-editor.dev/core/dist/index-Bsg7oIKP.d.ts +3869 -0
  140. package/node_modules/@docx-editor.dev/core/dist/index.cjs +1 -0
  141. package/node_modules/@docx-editor.dev/core/dist/index.d.ts +53 -0
  142. package/node_modules/@docx-editor.dev/core/dist/index.js +1 -0
  143. package/node_modules/@docx-editor.dev/core/dist/layout-shaping-BEyuiQOk.d.ts +246 -0
  144. package/node_modules/@docx-editor.dev/core/dist/layout.cjs +1 -0
  145. package/node_modules/@docx-editor.dev/core/dist/layout.d.ts +3151 -0
  146. package/node_modules/@docx-editor.dev/core/dist/layout.js +1 -0
  147. package/node_modules/@docx-editor.dev/core/dist/node-module-shim-TTKTT66I.js +1 -0
  148. package/node_modules/@docx-editor.dev/core/dist/note-properties-4Y9o6Gyk.d.ts +68 -0
  149. package/node_modules/@docx-editor.dev/core/dist/omml-equation-CuzBL5DD.d.ts +85 -0
  150. package/node_modules/@docx-editor.dev/core/dist/output.cjs +1 -0
  151. package/node_modules/@docx-editor.dev/core/dist/output.d.ts +97 -0
  152. package/node_modules/@docx-editor.dev/core/dist/output.js +1 -0
  153. package/node_modules/@docx-editor.dev/core/dist/protocol-Bqk4Izjc.d.ts +1651 -0
  154. package/node_modules/@docx-editor.dev/core/dist/review-pane-D9jm8DcY.d.ts +128 -0
  155. package/node_modules/@docx-editor.dev/core/dist/review-paragraph-order-DT-n6ouC.d.ts +85 -0
  156. package/node_modules/@docx-editor.dev/core/dist/revision-projection-DZ4kKVev.d.ts +242 -0
  157. package/node_modules/@docx-editor.dev/core/dist/semantic-cell-selection-D9D1KSXq.d.ts +464 -0
  158. package/node_modules/@docx-editor.dev/core/dist/semantic-interaction-CIC-PooQ.d.ts +135 -0
  159. package/node_modules/@docx-editor.dev/core/dist/semantic-paint-BME37OMv.d.ts +326 -0
  160. package/node_modules/@docx-editor.dev/core/dist/semantic-record-queries-CBlZqZNa.d.ts +177 -0
  161. package/node_modules/@docx-editor.dev/core/dist/semantic-records-4B3WwFAi.d.ts +3532 -0
  162. package/node_modules/@docx-editor.dev/core/dist/store.cjs +1 -0
  163. package/node_modules/@docx-editor.dev/core/dist/store.d.ts +2706 -0
  164. package/node_modules/@docx-editor.dev/core/dist/store.js +1 -0
  165. package/node_modules/@docx-editor.dev/core/dist/tree-package-fragment-BeeKxDw8.d.ts +1201 -0
  166. package/node_modules/@docx-editor.dev/core/dist/tree-session-contract-CVbmlMlq.d.ts +664 -0
  167. package/node_modules/@docx-editor.dev/core/dist/types-barrel-D3xCgQX6.d.ts +4269 -0
  168. package/node_modules/@docx-editor.dev/core/licenses/HarfBuzz-COPYING.txt +42 -0
  169. package/node_modules/@docx-editor.dev/core/package.json +140 -0
  170. package/node_modules/@docx-editor.dev/react/LICENSE +201 -0
  171. package/node_modules/@docx-editor.dev/react/README.md +141 -0
  172. package/node_modules/@docx-editor.dev/react/THIRD_PARTY_NOTICES.md +18 -0
  173. package/node_modules/@docx-editor.dev/react/dist/index.d.mts +4928 -0
  174. package/node_modules/@docx-editor.dev/react/dist/index.d.ts +4928 -0
  175. package/node_modules/@docx-editor.dev/react/dist/index.js +4 -0
  176. package/node_modules/@docx-editor.dev/react/dist/index.mjs +4 -0
  177. package/node_modules/@docx-editor.dev/react/package.json +74 -0
  178. package/node_modules/@docx-editor.dev/react/src/styles/editor.css +6 -0
  179. package/node_modules/@docx-editor.dev/react/src/styles/zIndex.ts +28 -0
  180. package/package.json +26 -15
@@ -0,0 +1,2448 @@
1
+ import { d as ResolvedRevisionMarkup, a as ReviewDisplayMode } from './revision-projection-DZ4kKVev.js';
2
+ import { a as ResolvedReviewPane } from './review-pane-D9jm8DcY.js';
3
+ import { t as DocAnchor, g as ReviewRevisionKind, c as ReviewCommentItem, b as ReviewRevisionItem, d as ReviewCustomItem, al as SourceCrop, am as DrawingKind, an as ImageWrapTarget, ao as DrawingPositionInput, ap as DrawingLocks, r as ColorValue, x as ExecErrorCode, aq as ParagraphFormatCommand, ar as Watermark, E as ExecResult, n as ContentControlFilter, o as DocRange, k as RunFormatting, p as Revision, as as Rect, at as SelectionPin, au as Unsubscribe } from './types-barrel-D3xCgQX6.js';
4
+ import { H as HistoryDiagnostic, V as ViewScope, a as HistoryGroup, b as EditorExecOptions, E as EditorScope } from './editor-scope-OHPwVQ5l.js';
5
+ import { DocEdits, DocQueries, DocQueryResults, ContentControlSummary } from './contracts/document.js';
6
+ import { InteractionOutcome } from './contracts/interaction.js';
7
+ import { a as SemanticSelection, S as SemanticPosition } from './semantic-interaction-CIC-PooQ.js';
8
+ import { b as ImageResourceState, S as SupportedImageMime } from './image-resources-BN-hUgCn.js';
9
+ import { D as DocumentProtectionState } from './document-protection-BAGVGqaP.js';
10
+ import { C as CollaborationStatus } from './failure-NS2lsya4.js';
11
+
12
+ /**
13
+ * What a fit mode fits the page to.
14
+ *
15
+ * One member today. It is a union rather than a boolean because Word's other two — the whole
16
+ * sheet including its height, and the text column inside the margins — are the same
17
+ * computation with a different numerator, and a later change adds one without breaking the
18
+ * shape a host already stores.
19
+ */
20
+ type ZoomFitTarget = 'pageWidth';
21
+ /**
22
+ * Where the display scale comes from.
23
+ *
24
+ * `fixed` is a number the engine holds until someone changes it. `fit` is a number the engine
25
+ * recomputes whenever the room beside the page changes — a resized window, an opened comments
26
+ * rail, a docked navigation pane — bounded by `minZoom`/`maxZoom`.
27
+ *
28
+ * The bounds are what make one mode serve both cases. The default, `'auto'`, is this fit
29
+ * bounded at both ends: it leaves a page that fits at 100%, shrinks one that does not, and
30
+ * stops at 50% — past which it would be trading a scrollbar nobody minds for a page nobody
31
+ * can read.
32
+ */
33
+ type ZoomMode = {
34
+ readonly type: 'fixed';
35
+ } | {
36
+ readonly type: 'fit';
37
+ readonly fit: ZoomFitTarget;
38
+ /** Never shrink past this. Defaults to the contract floor, 0.1. */
39
+ readonly minZoom?: number;
40
+ /** Never grow past this. `1` is the "shrink only" rule. Defaults to the ceiling, 5. */
41
+ readonly maxZoom?: number;
42
+ };
43
+
44
+ /**
45
+ * What `editor.on(...)` can be subscribed to, and what each handler receives.
46
+ *
47
+ * These are PUSH notifications and are not interchangeable with reading `snapshot()`: a snapshot
48
+ * read cannot observe an event that was never emitted, which is why adapter behaviour is asserted
49
+ * against these rather than against the snapshot.
50
+ */
51
+ interface EditorEvents {
52
+ /** Local viewer preferences changed through the API or review dialog. */
53
+ revisionMarkupChange: (settings: ResolvedRevisionMarkup) => void;
54
+ /** A document mutation committed, with the ids it touched. */
55
+ change: (change: DocumentChange) => void;
56
+ /** The selection or its derived formatting moved. */
57
+ selectionChange: (snapshot: EditorSnapshot) => void;
58
+ error: (error: EditorError) => void;
59
+ historyDiagnostic: (diagnostic: HistoryDiagnostic) => void;
60
+ /**
61
+ * An explicit request landed on a review item, and its card or balloon should open.
62
+ *
63
+ * Fires each time Next Change or Previous Change lands (`source: 'navigate'`), and each time
64
+ * `setActiveReviewItem(key, { announce: true })` succeeds (`source: 'host'`). It fires again
65
+ * when the item was already active, so a card the reader closed can open again.
66
+ *
67
+ * It does not fire for a caret move, a click in the page, a dismissal (`key` of `null`), a
68
+ * refused activation, or `setActiveReviewItem(key)` without `announce: true`. A remote edit in a
69
+ * collaboration session never fires it: it is a local view event.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * editor.on('reviewItemReveal', ({ key, source }) => {
74
+ * openMyBalloon(key); // `source` is 'navigate' or 'host'
75
+ * });
76
+ * ```
77
+ */
78
+ reviewItemReveal: (event: ReviewItemRevealEvent) => void;
79
+ }
80
+ /**
81
+ * The payload of the `reviewItemReveal` event.
82
+ *
83
+ * @public
84
+ */
85
+ interface ReviewItemRevealEvent {
86
+ /**
87
+ * The key of the review item to open, as `getReviewItems()` without `pairReplacements`
88
+ * lists it. Next Change and Previous Change step through that unpaired queue, so for a
89
+ * replacement this is the key of its deletion or its insertion. `setActiveReviewItem`
90
+ * reports the key it was given, so a call with a pair's key reports that key here and in
91
+ * {@link ReviewItemRevealEvent.pairKey}.
92
+ */
93
+ readonly key: string;
94
+ /**
95
+ * The key that `getReviewItems({ pairReplacements: true })` gives the replacement this item
96
+ * belongs to. Present only when the item is a paired replacement or one half of one. A
97
+ * host that lists pairs opens `pairKey ?? key`.
98
+ */
99
+ readonly pairKey?: string;
100
+ /**
101
+ * What asked for the item. `'navigate'` is Next Change or Previous Change, from the menu,
102
+ * the toolbar, a shortcut, or `exec({ type: 'navigateReviewChange' })`. `'host'` is a call
103
+ * to `setActiveReviewItem` (and so `useReview().setActive`) with `announce: true`.
104
+ */
105
+ readonly source: ReviewItemRevealSource;
106
+ }
107
+ /** What asked to reveal a review item. See {@link ReviewItemRevealEvent.source}. @public */
108
+ type ReviewItemRevealSource = 'navigate' | 'host';
109
+ /**
110
+ * The payload of the `change` event / `onChange`. It carries revision + identity
111
+ * deltas, NOT serialized bytes: serializing a whole DOCX on every keystroke would
112
+ * be prohibitive for large documents. Call `save()` to get bytes on demand.
113
+ */
114
+ interface DocumentChange {
115
+ /** Replacement events must not start another external processing request. Absent for edits. */
116
+ readonly source?: 'load' | 'refresh' | 'recovery';
117
+ /** Package revision after this change — `getDocumentHandle()`'s number, monotonic. */
118
+ readonly revision: number;
119
+ /** Block ids created/deleted/edited by this change, when the engine reports them. */
120
+ readonly created?: readonly string[];
121
+ readonly deleted?: readonly string[];
122
+ readonly dirty?: readonly string[];
123
+ }
124
+
125
+ /**
126
+ * Where a scroll places its target in the viewport.
127
+ *
128
+ * - `'start'`: near the top, like a jump to a heading.
129
+ * - `'center'`: centred.
130
+ * - `'centerIfNeeded'`: still while the target is on screen, centred when it has to move.
131
+ * - `'nearest'`: the minimum scroll, which leaves the target at the edge it came in from.
132
+ *
133
+ * Each method that takes a placement states its own default.
134
+ *
135
+ * @public
136
+ */
137
+ type ScrollPlacement = 'start' | 'center' | 'centerIfNeeded' | 'nearest';
138
+ /**
139
+ * Scroll settings for {@link EditorAnchorNavigation.scrollToAnchor}. Every field is optional.
140
+ * The fields match document refresh `NavigateToChangeOptions`. @public
141
+ */
142
+ interface ScrollToAnchorOptions {
143
+ /**
144
+ * Target placement. The default depends on the method: `scrollToAnchor` uses
145
+ * `'centerIfNeeded'`, which keeps the viewport still for a visible target, and
146
+ * `scrollToBlock` uses `'start'`.
147
+ */
148
+ readonly block?: ScrollPlacement;
149
+ /** Default: instant. Reduced motion uses instant even when smooth is requested. */
150
+ readonly behavior?: 'instant' | 'smooth';
151
+ /** Edge padding for start/nearest placement, in CSS pixels. Default: 24. Finite and nonnegative. */
152
+ readonly offsetPx?: number;
153
+ }
154
+ /** Opacity fade settings. Reduced motion limits fades to 125 milliseconds. @public */
155
+ interface AnchorHighlightAnimation {
156
+ /** Fade duration in milliseconds. Default: 180. Must be finite and between 0 and 10000. */
157
+ readonly durationMs?: number;
158
+ /** Automatic and explicit exit fade duration. Defaults to durationMs. Range: 0 through 10000. */
159
+ readonly exitDurationMs?: number;
160
+ /** CSS timing function for both fades. Defaults to --doc-motion-ease-out. This option does not accept CSS variables. */
161
+ readonly easing?: string;
162
+ }
163
+ /**
164
+ * Presentation for temporary paragraph highlights. Each call starts from these defaults.
165
+ * Document refresh `RefreshHighlightOptions` extends this type, so one style object serves both. @public
166
+ */
167
+ interface AnchorHighlightOptions {
168
+ /**
169
+ * CSS color, including var(). Default: a light blue theme token,
170
+ * var(--doc-anchor-highlight-color) for anchors and var(--doc-refresh-highlight-color) for refresh.
171
+ */
172
+ readonly color?: string;
173
+ /** Fill opacity, from 0 to 1. Default: 0.14. Does not change document text opacity. */
174
+ readonly opacity?: number;
175
+ /** Extra space on each edge, in CSS pixels at 100% zoom. Default: 4. Must be finite and nonnegative. */
176
+ readonly padding?: number;
177
+ /** Corner radius in CSS pixels at 100% zoom. Default: 6. Must be finite and nonnegative. */
178
+ readonly borderRadius?: number;
179
+ /** Border width in CSS pixels at 100% zoom. Default: 0. Finite and nonnegative. */
180
+ readonly borderWidth?: number;
181
+ /** CSS border color. Defaults to color. Use an alpha color for a translucent border; opacity controls only the fill. */
182
+ readonly borderColor?: string;
183
+ /** Border pattern. Default: solid. */
184
+ readonly borderStyle?: 'solid' | 'dashed' | 'dotted';
185
+ /** Optional CSS classes for shadows or patterns. The editor controls highlight placement and size. */
186
+ readonly className?: string;
187
+ /** Milliseconds before dismissal starts. Default: 3000. Set `null` to keep highlights until you dismiss them. Maximum: 2147483647. */
188
+ readonly timeoutMs?: number | null;
189
+ /** Default: true, a 180-millisecond fade. False disables motion. Repeated calls for the same paragraph do not restart the fade. */
190
+ readonly animation?: boolean | AnchorHighlightAnimation;
191
+ }
192
+ /** Explicit highlight dismissal. @public */
193
+ interface ClearAnchorHighlightOptions {
194
+ /** Defaults to the last highlight call's exit animation. False removes highlights immediately. */
195
+ readonly animation?: boolean | AnchorHighlightAnimation;
196
+ }
197
+ /** Navigation and temporary highlights for external paragraph references. @public */
198
+ interface EditorAnchorNavigation {
199
+ /**
200
+ * Reveal a paragraph by its `w14:paraId` without changing selection, focus, or editing scope.
201
+ * With `search`, reveal the start of the matched text. Matching follows {@link DocAnchor}.
202
+ * By default, an offscreen target is centered and an already visible target does not move the viewport.
203
+ *
204
+ * Supports laid-out body, table, header, footer, footnote, and endnote paragraphs.
205
+ * Repeated headers and footers use their first laid-out occurrence. Text boxes are unsupported.
206
+ * Returns true when the target is visible or scrolling succeeds. Returns false for invalid,
207
+ * missing, or ambiguous targets, or targets without layout positions.
208
+ * Also returns false without a mounted, measurable scroll container.
209
+ * Invalid options throw `TypeError` or `RangeError`. Works in viewing mode.
210
+ * Does not change document content or undo history.
211
+ *
212
+ * @example
213
+ * ```ts
214
+ * const revealed = editor.scrollToAnchor({ paraId: '1B4C77A2' });
215
+ * ```
216
+ * @public
217
+ */
218
+ scrollToAnchor(anchor: DocAnchor, options?: ScrollToAnchorOptions): boolean;
219
+ /**
220
+ * Highlight the paragraph that a {@link DocAnchor} resolves to, without scrolling.
221
+ * Matching follows `scrollToAnchor`; `search` must resolve, and the whole paragraph is marked.
222
+ * A new call replaces the previous anchor highlight. Repeating a call resets its timeout.
223
+ *
224
+ * Supports body, table, and block content control paragraphs with layout positions.
225
+ * Returns false for invalid, missing, or ambiguous targets, or targets without layout positions.
226
+ * Also returns false for headers, footers, notes, and text boxes, or without a mounted document.
227
+ * A false result leaves the current highlight unchanged.
228
+ * The method validates options first. Invalid numbers throw `RangeError`.
229
+ * Invalid colors, border styles, or animation settings throw `TypeError`.
230
+ *
231
+ * The highlight never changes selection, focus, document content, or undo history. Loading or
232
+ * replacing the document removes it.
233
+ *
234
+ * @example
235
+ * ```ts
236
+ * if (editor.scrollToAnchor(anchor)) editor.highlightAnchor(anchor, { timeoutMs: 1500 });
237
+ * ```
238
+ * @public
239
+ */
240
+ highlightAnchor(anchor: DocAnchor, options?: AnchorHighlightOptions): boolean;
241
+ /**
242
+ * Dismiss the anchor highlight with a fade, or immediately with `animation: false`.
243
+ * Validates options even when nothing is highlighted. @public
244
+ */
245
+ clearAnchorHighlight(options?: ClearAnchorHighlightOptions): void;
246
+ }
247
+
248
+ /**
249
+ * One text range to mark. A `TextMatch` from `findMatches()` is a valid range, so search
250
+ * results pass straight through. @public
251
+ */
252
+ interface HighlightRange {
253
+ /** Paragraph that holds the range: `TextMatch.blockId`. IDs belong to the open document. */
254
+ readonly blockId: string;
255
+ /** UTF-16 offset in the paragraph's model text, as `TextMatch.start` counts it. */
256
+ readonly start: number;
257
+ /** Range length in the same units. A zero length marks nothing. */
258
+ readonly length: number;
259
+ /** Story that holds the paragraph. Informational; `blockId` already names the paragraph. */
260
+ readonly scope?: ViewScope;
261
+ /**
262
+ * Model text the range must cover to paint. Set it for ranges computed outside the editor,
263
+ * such as on a server, so a range that no longer matches the document never paints. When it
264
+ * is omitted, a range must keep covering the text it covered when it was first set.
265
+ */
266
+ readonly expectedText?: string;
267
+ }
268
+ /** Presentation for one named highlight set. Every field is optional. @public */
269
+ interface HighlightOptions {
270
+ /**
271
+ * Fill for every range: a CSS color or `var()` expression.
272
+ * Default: `var(--doc-text-highlight-color)`, a translucent yellow.
273
+ */
274
+ readonly color?: string;
275
+ /**
276
+ * Index of the active range, or `-1` for none. An index past the last range also means
277
+ * none. The active range takes `activeColor` and the `docx-text-highlight--active` class.
278
+ * Default: `-1`.
279
+ */
280
+ readonly activeIndex?: number;
281
+ /** Fill for the active range. Default: `var(--doc-text-highlight-active-color)`, orange. */
282
+ readonly activeColor?: string;
283
+ /** Space-separated CSS classes added to every mark of this set. */
284
+ readonly className?: string;
285
+ /**
286
+ * Stacking order between sets, as an integer from -1000 to 1000. A higher value paints
287
+ * on top. Sets with equal priority stack in the order they were first set. Default: `0`.
288
+ * The built-in Find pane uses the set name `search` with priority `10`.
289
+ */
290
+ readonly priority?: number;
291
+ }
292
+ /** What `setHighlights()` resolved against the open document. @public */
293
+ interface HighlightResult {
294
+ /** Ranges that resolve to their text in the open document and can paint. */
295
+ readonly applied: number;
296
+ /**
297
+ * Ranges that do not resolve or cannot paint: an unknown paragraph, offsets past the
298
+ * paragraph end, a zero length, text that differs from `expectedText`, or a story without
299
+ * a layout position.
300
+ */
301
+ readonly unavailable: number;
302
+ }
303
+ /** A client-space rectangle, compatible with `DOMRect` readers such as positioning libraries. @public */
304
+ interface HighlightRect {
305
+ readonly x: number;
306
+ readonly y: number;
307
+ readonly width: number;
308
+ readonly height: number;
309
+ readonly top: number;
310
+ readonly right: number;
311
+ readonly bottom: number;
312
+ readonly left: number;
313
+ }
314
+ /**
315
+ * One painted mark under a point. `R` is your range type: pass ranges with extra fields,
316
+ * such as a glossary definition, and read them back from `range`. @public
317
+ */
318
+ interface HighlightHit<R extends HighlightRange = HighlightRange> {
319
+ /** Set name passed to `setHighlights()`. */
320
+ readonly name: string;
321
+ /** Index of the range in the array passed to `setHighlights()`. */
322
+ readonly index: number;
323
+ /**
324
+ * The range object exactly as it was passed, including your own fields. Its offsets are
325
+ * the ones you passed; `start` and `length` are where the text is now.
326
+ */
327
+ readonly range: R;
328
+ /** Current start of the highlighted text in its paragraph, after edits moved it. */
329
+ readonly start: number;
330
+ /** Current length of the highlighted text. */
331
+ readonly length: number;
332
+ /** Whether this range is the set's active range. */
333
+ readonly active: boolean;
334
+ /** The marked line box under the point, in client coordinates. Anchor popovers to it. */
335
+ readonly rect: HighlightRect;
336
+ }
337
+ /**
338
+ * Paint-only text highlights: search results, glossary terms, review findings.
339
+ *
340
+ * Highlights are view state. They never change the document, selection, focus, or undo
341
+ * history, they are never saved, and they are not shared with collaborators. @public
342
+ */
343
+ interface EditorHighlights {
344
+ /**
345
+ * Mark text ranges as one named set, replacing the set's previous ranges and options.
346
+ *
347
+ * Names are 1 to 64 letters, digits, `-`, or `_`, and start with a letter. Each set paints
348
+ * in its own layer, so sets never replace each other. An empty `ranges` array clears the
349
+ * set. At most 32 sets exist at once. A set paints its first 10000 ranges and counts the
350
+ * rest as unavailable. The name `search` belongs to the shared document search.
351
+ *
352
+ * Ranges cover the body, tables, headers, footers, footnotes, endnotes, and anchored text
353
+ * boxes in the body. A range moves with its text when an edit before it shifts the
354
+ * paragraph. When an edit changes the text inside a range, the range stops painting, so a
355
+ * mark never covers the wrong text. Search again after edits to mark new occurrences.
356
+ *
357
+ * Loading, refreshing, or recovering the document removes every set. Invalid names,
358
+ * ranges, or options throw
359
+ * `TypeError` or `RangeError` and leave the current highlights unchanged.
360
+ *
361
+ * @example
362
+ * ```ts
363
+ * const matches = editor.findMatches('Supplier', { wholeWord: true });
364
+ * editor.setHighlights('search', matches, { activeIndex: 0 });
365
+ * ```
366
+ * @public
367
+ */
368
+ setHighlights(name: string, ranges: readonly HighlightRange[], options?: HighlightOptions): HighlightResult;
369
+ /** Remove one highlight set, or every set when `name` is omitted. @public */
370
+ clearHighlights(name?: string): void;
371
+ /**
372
+ * The marks under a client point, topmost first. Use it from `pointermove` or `click`
373
+ * handlers on the editor to show definitions or details for a marked term.
374
+ * Only marks on painted pages are reported. @public
375
+ */
376
+ getHighlightsAt<R extends HighlightRange = HighlightRange>(clientX: number, clientY: number): readonly HighlightHit<R>[];
377
+ }
378
+
379
+ /** One review item under a client point. @public */
380
+ interface ReviewItemHit {
381
+ /** The item, as `getReviewItems()` with the same query returns it. */
382
+ readonly placement: ReviewItemPlacement;
383
+ /**
384
+ * The item's painted band on the line under the point, in client coordinates. It covers the
385
+ * part of the item's range on that line, not the whole range. Anchor popovers to it.
386
+ */
387
+ readonly rect: HighlightRect;
388
+ }
389
+ /** Hit testing for hosts that draw their own review chrome. @public */
390
+ interface EditorReviewHits {
391
+ /**
392
+ * The review items whose text is under a client point, innermost first.
393
+ *
394
+ * An item hits when the CHARACTER under the point is inside one of its ranges, so the
395
+ * right half of a range's last character still hits, and the left half of the next
396
+ * character does not. Ranges that cover no characters, such as a tracked paragraph mark or
397
+ * a comment on an empty range, never hit. Items without a range never hit.
398
+ *
399
+ * The test covers every story the review queue lists and the pages paint: the body,
400
+ * tables, headers, footers, footnotes, and endnotes. Only painted pages are tested, so a
401
+ * point over a page that is not built returns no items.
402
+ *
403
+ * The result reports every item whose range covers the character, including replies,
404
+ * which share their thread's range, and resolved comments. Filter on
405
+ * `placement.parentId`, `placement.parentRevisionId`, or `placement.resolved` to find the
406
+ * card that owns the hit. Order follows the review queue's own rule for the caret: the
407
+ * narrowest range first, then comments before custom nodes before revisions, then the
408
+ * most deeply nested revision.
409
+ *
410
+ * A point hits the glyph band of a line, the same band a text highlight marks. A point in
411
+ * the spacing between lines hits nothing. `query` filters the items the same way it
412
+ * filters `getReviewItems()`. Coordinates that are not finite numbers return an empty
413
+ * array. Each call reads the whole review queue, so call it from a click, not on every
414
+ * pointer move.
415
+ *
416
+ * @example
417
+ * ```ts
418
+ * pages.addEventListener('click', (event) => {
419
+ * const [hit] = editor.getReviewItemsAt(event.clientX, event.clientY);
420
+ * if (hit) showBalloon(hit.placement.key, hit.rect);
421
+ * });
422
+ * ```
423
+ * @public
424
+ */
425
+ getReviewItemsAt(clientX: number, clientY: number, query?: ReviewItemQuery): readonly ReviewItemHit[];
426
+ /**
427
+ * The bands one review item paints, one per line part, in client coordinates.
428
+ *
429
+ * `key` is a `ReviewItemPlacement.key`. Bands follow page order, and within a page the
430
+ * body comes before headers, footers, and notes. Only painted pages contribute. An unknown
431
+ * key, an item without a range, or an item with no text on a painted page returns an
432
+ * empty array. Anchor a balloon to the first band, or join the bands for an outline.
433
+ *
434
+ * @example
435
+ * ```ts
436
+ * const [first] = editor.getReviewItemRects(placement.key);
437
+ * if (first) positionBalloon(first);
438
+ * ```
439
+ * @public
440
+ */
441
+ getReviewItemRects(key: string): readonly HighlightRect[];
442
+ }
443
+
444
+ /**
445
+ * Narrows what `getReviewItems` returns.
446
+ *
447
+ * Filtering revision kinds is how a host hides structural cards it has no UI for,
448
+ * `placement: false` skips the layout pass entirely when only metadata is wanted, and
449
+ * `pairReplacements` lists a typed-over selection as one decision.
450
+ */
451
+ interface ReviewItemQuery {
452
+ /**
453
+ * Revision kinds to leave out of the returned items, for example structural kinds that the
454
+ * host has no card for. Default: none. Comments and custom items are never removed. This
455
+ * filters only the returned data; to stop the caret from activating the same kinds, call
456
+ * `setReviewActivationExclusions`.
457
+ */
458
+ readonly excludeRevisionKinds?: readonly ReviewRevisionKind[];
459
+ /** When false, skip layout geometry; metadata is unchanged and anchors are null. Default true. */
460
+ readonly placement?: boolean;
461
+ /**
462
+ * When true, list a deletion and the insertion that directly follows it as one
463
+ * `'replace'` item. Default false.
464
+ *
465
+ * Two revisions pair when they are next to each other among the queue's revisions, the
466
+ * deletion comes first, both have the same author, nesting level and `readOnly` value, and
467
+ * the deletion's last range ends at the same paragraph and offset where the insertion's
468
+ * first range starts. The pair's `text` is the inserted words and `replacedText` the
469
+ * deleted words. The two halves are not listed separately.
470
+ *
471
+ * Kinds in {@link excludeRevisionKinds} are removed before pairing, so an excluded deletion
472
+ * or insertion never pairs. Excluding `'replace'` removes the pairs too.
473
+ *
474
+ * The pair's `key` is stable while both halves are pending, and every key-addressed verb
475
+ * accepts it whatever query you read it with. Accepting or rejecting it resolves both
476
+ * halves in one transaction and one undo step. Activating it opens the deletion; the pair
477
+ * reports `isActive` while either half is active. A reply anchors over the inserted words,
478
+ * and replies to either half are listed under the pair.
479
+ */
480
+ readonly pairReplacements?: boolean;
481
+ }
482
+
483
+ /**
484
+ * How activating a review item places it in the viewport, and whether it announces the
485
+ * reveal.
486
+ *
487
+ * @public
488
+ */
489
+ interface ReviewActivationOptions {
490
+ /**
491
+ * Where the item lands, or `false` to open it without scrolling at all.
492
+ *
493
+ * Default `'centerIfNeeded'`: silent while the item is already on screen, centred when it
494
+ * has to travel. `'nearest'` scrolls the minimum instead, which parks the item flush
495
+ * against the edge it came in from; `'start'` puts it near the top, the way a jump to a
496
+ * heading reads. `false` is for a host whose own list already drives the scroll and does
497
+ * not want the engine competing with it.
498
+ *
499
+ * It governs the reveal of the ITEM. An item in a header, a footer or a note also opens
500
+ * that story, and opening one always brings its band into view — a story the reader cannot
501
+ * see is one they cannot read the change in, which is the whole point of activating it.
502
+ */
503
+ readonly reveal?: ScrollPlacement | false;
504
+ /**
505
+ * Whether a successful activation fires the `reviewItemReveal` event. Default `false`.
506
+ *
507
+ * Pass `true` to open the item the way Next Change does: the packaged review UI opens its
508
+ * balloon, or opens a closed review pane at its card when the pane's `opening` setting is
509
+ * `'auto'`. The item becomes active either way.
510
+ *
511
+ * @example
512
+ * ```ts
513
+ * editor.setActiveReviewItem(key, { announce: true });
514
+ * ```
515
+ */
516
+ readonly announce?: boolean;
517
+ }
518
+
519
+ /**
520
+ * What every review card carries, whatever kind of decision it represents.
521
+ *
522
+ * Presentation-ready by design: author, initials, date and text are derived by the ENGINE,
523
+ * because deriving them means walking runs and reading `w15:commentsEx`. An adapter doing that
524
+ * walk would put document derivation in the host and would have to be written once per
525
+ * framework.
526
+ */
527
+ interface ReviewItemPlacementBase {
528
+ /** Stable and unique per decision within this editor instance. */
529
+ readonly key: string;
530
+ /** The engine's own id for the comment, the revision, or the custom node. */
531
+ readonly id: string;
532
+ readonly author: string;
533
+ /** Initials for an avatar: `@w:initials` when the file carries one, else from the name. */
534
+ readonly initials: string;
535
+ /** `@w:date`, absent when the file omits it — Word does when date stamping is off. */
536
+ readonly date?: string;
537
+ /**
538
+ * The comment's body, the words the revision covers, or the custom card's detail.
539
+ *
540
+ * PLAIN TEXT, and it must be rendered as text: a `.docx` is a zip of XML an attacker
541
+ * controls end to end, so this string is untrusted and never markup.
542
+ */
543
+ readonly text: string;
544
+ /**
545
+ * Replies to this item, in document order.
546
+ *
547
+ * Comments AND revisions carry them: OOXML gives `w:ins` and `w:del` no body, so replying
548
+ * to a tracked change writes a comment over the change's own range, and the reply belongs
549
+ * inside the card for the change rather than beside it.
550
+ */
551
+ readonly replyIds: readonly string[];
552
+ /**
553
+ * True when the engine cannot resolve this kind structurally, so accept and reject must
554
+ * not be offered. A card offering a button the engine will refuse is worse than one that
555
+ * explains why it cannot.
556
+ */
557
+ readonly readOnly: boolean;
558
+ /**
559
+ * Whether {@link Editor.setActiveReviewItem} would take this key.
560
+ *
561
+ * False for an item with no resolvable range, for a custom node without `reviewCard`
562
+ * (`carded: false`), and for a revision kind the host's rail excluded through
563
+ * {@link Editor.setReviewActivationExclusions} — the queue still LISTS
564
+ * those, because `getReviewItems` answers "what does this document hold" rather than "what
565
+ * may be clicked", and a host filtering the two apart needs to be told which is which. A
566
+ * card drawn for an item that cannot be activated is a card that does nothing when clicked.
567
+ */
568
+ readonly activatable: boolean;
569
+ /** Document-space Y of the anchor, or null when the item has no resolvable range. */
570
+ readonly anchorY: number | null;
571
+ readonly pageIndex: number | null;
572
+ readonly isActive: boolean;
573
+ }
574
+ /** A comment thread's card. @public */
575
+ interface ReviewCommentPlacement extends ReviewItemPlacementBase {
576
+ readonly kind: 'comment';
577
+ /** Whether `w15:commentsEx` marks the thread done. */
578
+ readonly resolved: boolean;
579
+ /** The comment this replies to, absent at the top of a thread. */
580
+ readonly parentId?: string;
581
+ /**
582
+ * The REVISION this comment answers, absent unless it does.
583
+ *
584
+ * A surface listing top-level cards must skip these as well as the ones with a
585
+ * {@link parentId}: the card is rendered inside the change it answers, and a rail that
586
+ * only checked `parentId` drew the reply twice.
587
+ */
588
+ readonly parentRevisionId?: string;
589
+ readonly item: ReviewCommentItem;
590
+ }
591
+ /** A tracked change's card. @public */
592
+ interface ReviewRevisionPlacement extends ReviewItemPlacementBase {
593
+ readonly kind: 'revision';
594
+ /** Which decision this is. */
595
+ readonly revisionKind: ReviewRevisionKind;
596
+ /**
597
+ * The words a replacement decision removes when {@link revisionKind} is `'replace'`.
598
+ * The built-in reader lists separate deletion and insertion cards unless the query sets
599
+ * {@link ReviewItemQuery.pairReplacements}.
600
+ */
601
+ readonly replacedText?: string;
602
+ readonly item: ReviewRevisionItem;
603
+ }
604
+ /** A custom node's card (`defineCustomNode` with a `reviewCard` hook). @public */
605
+ interface ReviewCustomPlacement extends ReviewItemPlacementBase {
606
+ readonly kind: 'custom';
607
+ readonly item: ReviewCustomItem;
608
+ }
609
+ /**
610
+ * A DISCRIMINATED union on {@link ReviewItemPlacementBase.kind}: narrowing the kind
611
+ * narrows `item` and the kind-specific fields with it, so a consumer never writes the
612
+ * `placement.kind === 'custom' && placement.item.kind === 'custom'` double check.
613
+ */
614
+ type ReviewItemPlacement = ReviewCommentPlacement | ReviewRevisionPlacement | ReviewCustomPlacement;
615
+
616
+ /** Selection and unsupported-change policy for a bulk review decision. @public */
617
+ interface ResolveReviewChangesOptions {
618
+ action: 'accept' | 'reject';
619
+ /** Defaults to revisions included by author visibility and the tracked-changes predicate. */
620
+ scope?: 'visible' | 'document';
621
+ /** Exact keys from getReviewItems(); overrides scope. Duplicate keys resolve once. */
622
+ keys?: readonly string[];
623
+ /** Defaults to skip. Strict refuses the entire selection if any target cannot resolve. */
624
+ unsupported?: 'skip' | 'fail';
625
+ }
626
+ /**
627
+ * Who and when a change of tracked-change author records. Shared by both selections.
628
+ * @public
629
+ */
630
+ interface ReviewChangesAttribution {
631
+ /**
632
+ * The author to record. Defaults to the editor's `author`, so a reviewer adopts changes as
633
+ * their own. A command with neither refuses, because `w:author` is required.
634
+ */
635
+ author?: string;
636
+ /** An ISO 8601 `xsd:dateTime` to record. Omit it to keep each change's own date. */
637
+ date?: string;
638
+ /** Defaults to skip. Strict refuses the entire selection if any target cannot change. */
639
+ unsupported?: 'skip' | 'fail';
640
+ }
641
+ /**
642
+ * Selection and attribution for a change of tracked-change author. The changes stay pending.
643
+ *
644
+ * Select exact `keys` from `getReviewItems()`, or a `scope` narrowed by `authors`. The two
645
+ * selections exclude each other.
646
+ * @public
647
+ */
648
+ type SetReviewChangesAuthorOptions = ReviewChangesAttribution & ({
649
+ /** Exact keys from getReviewItems(). Duplicate keys change once. */
650
+ keys: readonly string[];
651
+ scope?: never;
652
+ authors?: never;
653
+ } | {
654
+ keys?: never;
655
+ /** Defaults to revisions shown by author visibility and the tracked-changes filter. */
656
+ scope?: 'visible' | 'document';
657
+ /** Only the changes these authors made, within `scope`. Matches `w:author` exactly. */
658
+ authors?: readonly string[];
659
+ });
660
+
661
+ /**
662
+ * How a keystroke reaches the document.
663
+ *
664
+ * `'suggesting'` changes what an edit MEANS rather than whether it is allowed: typing writes
665
+ * `w:ins` and deleting writes `w:del` over the words it would have removed, so every change
666
+ * arrives as a proposal somebody else accepts or rejects.
667
+ */
668
+ type DocumentEditingMode = 'editing' | 'suggesting' | 'viewing';
669
+
670
+ /**
671
+ * Header/footer and footnote/endnote public contract types for the Editor facade.
672
+ *
673
+ * Separated from `editor.ts` so the facade file stays under the max-lines gate while
674
+ * furniture/notes APIs remain one cohesive vocabulary. Re-exported from `editor.ts`
675
+ * so consumers keep importing `@docx-editor.dev/core/contracts/editor`.
676
+ */
677
+ /** Furniture variant selected by section title-page / even-and-odd flags. */
678
+ type FurnitureVariant = 'default' | 'first' | 'even';
679
+ /** Header/footer editing state: which region is being edited, if any. */
680
+ interface HeaderFooterState {
681
+ readonly editing: 'header' | 'footer' | null;
682
+ readonly sectionIndex: number;
683
+ /** Furniture variant in effect on the page used to enter the scope. */
684
+ readonly variant?: FurnitureVariant;
685
+ /** Relationship id of the open story (`EditorScope.rId`). */
686
+ readonly rId?: string;
687
+ /** Package part name of the open story. */
688
+ readonly partName?: string;
689
+ /**
690
+ * Whether the resolved part is inherited from a preceding section ("Same as Previous")
691
+ * rather than declared on this section.
692
+ */
693
+ readonly inherited?: boolean;
694
+ /** Section `w:titlePg` — first-page furniture is distinct when true. */
695
+ readonly titlePage?: boolean;
696
+ /** Document `w:evenAndOddHeaders` — even-page furniture is distinct when true. */
697
+ readonly evenAndOddHeaders?: boolean;
698
+ /** Section header distance from sheet edge, twips (`w:pgMar w:header`). */
699
+ readonly headerDistanceTwips?: number;
700
+ /** Section footer distance from sheet edge, twips (`w:pgMar w:footer`). */
701
+ readonly footerDistanceTwips?: number;
702
+ }
703
+ /** Footnote vs endnote — the public Editor vocabulary. */
704
+ type NoteKind = 'footnote' | 'endnote';
705
+ /** Authored note-numbering fields as Word's properties dialog writes them. */
706
+ interface AuthoredNoteNumbering {
707
+ readonly pos?: string;
708
+ readonly numFmt?: string;
709
+ readonly numStart?: number;
710
+ readonly numRestart?: string;
711
+ }
712
+ /** Resolved note-numbering fields after document/section cascade. */
713
+ interface ResolvedNoteNumbering {
714
+ readonly pos: string;
715
+ readonly numFmt: string;
716
+ readonly numStart: number;
717
+ readonly numRestart: string;
718
+ }
719
+ /** One note kind's resolved + authored properties for the caret section. */
720
+ interface NotePropertiesSide {
721
+ readonly resolved: ResolvedNoteNumbering;
722
+ readonly documentAuthored?: AuthoredNoteNumbering;
723
+ readonly sectionAuthored?: AuthoredNoteNumbering;
724
+ }
725
+ /** Resolved and authored note properties for the caret section — properties dialog read-model. */
726
+ interface NotePropertiesState {
727
+ readonly sectionIndex: number;
728
+ readonly footnote: NotePropertiesSide;
729
+ readonly endnote: NotePropertiesSide;
730
+ }
731
+ /** Optional slot targeting shared by remove / link / unlink furniture commands. */
732
+ interface HeaderFooterSlotArgs {
733
+ position?: 'header' | 'footer';
734
+ /** Prefer over `firstPage` / `evenPage` when selecting a furniture variant. */
735
+ variant?: FurnitureVariant;
736
+ firstPage?: boolean;
737
+ evenPage?: boolean;
738
+ sectionIndex?: number;
739
+ }
740
+ /**
741
+ * Header/footer lifecycle and page-field commands on {@link EditorCommands}.
742
+ *
743
+ * Kept as a mixin so `editor.ts` can extend it without inlining the furniture vocabulary.
744
+ */
745
+ interface EditorHeaderFooterCommands {
746
+ /**
747
+ * Open a header or footer for editing, materialising an empty one if the section has
748
+ * none — which is what a double-click on the header band means in Word.
749
+ *
750
+ * Prefer `variant` when selecting first/even/default furniture. `firstPage` /
751
+ * `evenPage` remain supported for existing callers (`firstPage: true` ≡ `variant:
752
+ * 'first'`; `evenPage: true` ≡ `variant: 'even'`). Creating a missing `first` part
753
+ * also enables section `w:titlePg` in the same undo unit; creating a missing `even`
754
+ * part also enables document `w:evenAndOddHeaders` in the same undo unit.
755
+ */
756
+ editHeaderFooter: {
757
+ position: 'header' | 'footer';
758
+ variant?: FurnitureVariant;
759
+ firstPage?: boolean;
760
+ evenPage?: boolean;
761
+ sectionIndex?: number;
762
+ };
763
+ /** Leave header/footer editing and return to the body. */
764
+ exitHeaderFooter: Record<never, never>;
765
+ /**
766
+ * Delete a declared header/footer reference (and GC the part when orphaned). When the
767
+ * editor is already in furniture scope, omitted fields default to the active story.
768
+ */
769
+ removeHeaderFooter: HeaderFooterSlotArgs;
770
+ /**
771
+ * Turn on "Same as Previous" for a section's furniture slot (drop its declared ref).
772
+ * Refused on the first section. Omitted fields default to the active story when scoped.
773
+ */
774
+ linkHeaderFooterToPrevious: HeaderFooterSlotArgs;
775
+ /**
776
+ * Turn off "Same as Previous": clone the inherited part into a declared reference.
777
+ * When the active scope was the inherited rId, the editor rebinds to the clone.
778
+ */
779
+ unlinkHeaderFooterFromPrevious: HeaderFooterSlotArgs;
780
+ /**
781
+ * Section/document furniture options: `titlePg` and header/footer distances on a
782
+ * section; `evenAndOddHeaders` document-wide in settings.
783
+ */
784
+ setHeaderFooterOptions: {
785
+ sectionIndex?: number;
786
+ titlePage?: boolean;
787
+ evenAndOddHeaders?: boolean;
788
+ headerDistanceTwips?: number;
789
+ footerDistanceTwips?: number;
790
+ };
791
+ /**
792
+ * Insert an allowlisted page-number field at the caret. Only valid while a header or
793
+ * footer scope is open. `PAGE_X_OF_Y` writes PAGE + " of " + NUMPAGES as one undo unit.
794
+ */
795
+ insertPageField: {
796
+ field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y';
797
+ };
798
+ }
799
+ /**
800
+ * Footnote/endnote lifecycle and properties commands on {@link EditorCommands}.
801
+ */
802
+ interface EditorNoteCommands {
803
+ /** Insert a footnote or endnote reference at the caret (body only). */
804
+ insertNote: {
805
+ noteKind: NoteKind;
806
+ };
807
+ /** Delete a note and its body reference together. */
808
+ deleteNote: {
809
+ noteKind: NoteKind;
810
+ noteId: number;
811
+ };
812
+ /** Convert one note to the other kind. */
813
+ convertNote: {
814
+ fromKind: NoteKind;
815
+ noteId: number;
816
+ };
817
+ /** Convert every note of one kind to the other in document order (one undo step). */
818
+ convertAllNotes: {
819
+ fromKind: NoteKind;
820
+ };
821
+ /**
822
+ * Footnote and endnote properties for the section — numbering format, restart rule
823
+ * and position, as Word's dialog offers them.
824
+ */
825
+ setNoteProperties: {
826
+ scope?: 'document' | 'section';
827
+ sectionIndex?: number;
828
+ footnote?: {
829
+ numFmt?: string;
830
+ numRestart?: string;
831
+ position?: string;
832
+ numStart?: number;
833
+ };
834
+ endnote?: {
835
+ numFmt?: string;
836
+ numRestart?: string;
837
+ position?: string;
838
+ numStart?: number;
839
+ };
840
+ };
841
+ }
842
+
843
+ /**
844
+ * Format painter commands for the Editor facade.
845
+ *
846
+ * Separated from `editor.ts` so the facade file stays under the max-lines gate while the
847
+ * painter keeps one cohesive vocabulary. Re-exported from `editor.ts`, so consumers keep
848
+ * importing `@docx-editor.dev/core/contracts/editor`.
849
+ */
850
+ /**
851
+ * Word's Format Painter, as the two halves a keyboard user drives separately.
852
+ *
853
+ * The pair is deliberately NOT one command with a direction flag: `copyFormatting` reads
854
+ * and `pasteFormatting` writes, so they answer `can` differently — copying is allowed on a
855
+ * document open for viewing, and applying is not.
856
+ */
857
+ interface EditorFormatPainterCommands {
858
+ /**
859
+ * Capture the formatting at the selection (Word's Ctrl+Shift+C).
860
+ *
861
+ * Reads the RESOLVED cascade rather than the direct run properties, so painting from a
862
+ * styled paragraph carries what the reader sees rather than the little the paragraph
863
+ * happens to state itself.
864
+ *
865
+ * The LEVEL follows the selection, as Word's does. A range inside one paragraph captures
866
+ * character formatting alone; a range that covers a paragraph mark — a whole paragraph, a
867
+ * multi-paragraph selection, or a collapsed caret — captures the paragraph style and its
868
+ * direct paragraph properties as well.
869
+ *
870
+ * Non-mutating: the capture lives on the editor, not in the document, and it survives
871
+ * until the next capture or until the editor is detached.
872
+ */
873
+ copyFormatting: Record<never, never>;
874
+ /**
875
+ * Apply the captured formatting to the current selection (Word's Ctrl+Shift+V).
876
+ *
877
+ * Refused with `no formatting has been copied` until `copyFormatting` has run. Paragraph
878
+ * formatting is applied only when the capture carries it; the text itself never moves.
879
+ *
880
+ * Three things stay on the TARGET rather than being painted over, because they are outside
881
+ * the property vocabulary an op may name — the same limit `clearFormatting` states:
882
+ * paragraph borders (`w:pBdr`), the run's character style (`w:rStyle`), and character
883
+ * shading (`w:rPr/w:shd`), which is resolved and painted but cannot be authored.
884
+ */
885
+ pasteFormatting: Record<never, never>;
886
+ }
887
+ /**
888
+ * How long the painter stays armed.
889
+ *
890
+ * Word's two gestures, named: a single press arms it for ONE application, a double press
891
+ * locks it on until the user presses `Esc`. `'off'` is the resting state.
892
+ */
893
+ type FormatPainterMode = 'off' | 'once' | 'locked';
894
+ /**
895
+ * What a capture carries.
896
+ *
897
+ * `'run'` is character formatting alone — the level a range INSIDE one paragraph copies.
898
+ * `'paragraph'` adds the paragraph style and its direct paragraph properties, which is what
899
+ * a selection covering a paragraph mark copies. `'none'` means nothing has been captured.
900
+ */
901
+ type FormatPainterLevel = 'none' | 'run' | 'paragraph';
902
+ /**
903
+ * Painter state, as the editor publishes it.
904
+ *
905
+ * Chrome state rather than document state, so it moves through the same report every other
906
+ * observable surface state uses — a toolbar's pressed state has one source. It lives in the
907
+ * CONTRACTS lane rather than beside the surface implementation because `EditorSnapshot`
908
+ * names it, and the contracts lane may not reach into the editor lane.
909
+ */
910
+ interface FormatPainterSurfaceState {
911
+ readonly mode: FormatPainterMode;
912
+ readonly level: FormatPainterLevel;
913
+ }
914
+
915
+ /** Crop edge in UI percent (0–100). @public */
916
+ interface ImageCropPercent {
917
+ readonly left: number;
918
+ readonly top: number;
919
+ readonly right: number;
920
+ readonly bottom: number;
921
+ }
922
+ /** Crop edge in OOXML permille (0–100000). */
923
+ interface ImageCropPermille {
924
+ readonly left: number;
925
+ readonly top: number;
926
+ readonly right: number;
927
+ readonly bottom: number;
928
+ }
929
+ /** Projection fraction (0–1) → UI percent (0–100). */
930
+ declare function cropPercentFromSourceCrop(crop: SourceCrop): ImageCropPercent;
931
+ /** UI percent (0–100) → projection fraction (0–1). */
932
+ declare function sourceCropFromCropPercent(crop: ImageCropPercent): SourceCrop;
933
+ /** UI percent → OOXML permille. */
934
+ declare function cropPermilleFromPercent(percent: number): number;
935
+ /** OOXML permille → UI percent. */
936
+ declare function cropPercentFromPermille(permille: number): number;
937
+ /** UI percent crop → permille for tree ops / a:srcRect. */
938
+ declare function cropPermilleFromCropPercent(crop: ImageCropPercent): ImageCropPermille;
939
+ /** Permille crop → UI percent. */
940
+ declare function cropPercentFromCropPermille(crop: ImageCropPermille): ImageCropPercent;
941
+ /**
942
+ * Whether a crop is expressible: every edge finite and in range, and opposite edges not
943
+ * overlapping.
944
+ *
945
+ * Opposite edges matter — a left plus right crop summing past 100% describes a negative width,
946
+ * which DrawingML has no way to store.
947
+ */
948
+ declare function validateImageCropPercent(crop: ImageCropPercent): boolean;
949
+
950
+ /**
951
+ * The selected-image read model, split out of `editor.ts`.
952
+ *
953
+ * Separated so the facade file stays under the max-lines gate while the image vocabulary
954
+ * stays one cohesive shape. Re-exported from `editor.ts`, so consumers keep importing
955
+ * `@docx-editor.dev/core/contracts/editor`.
956
+ */
957
+
958
+ /**
959
+ * Canonical selected-image read model shared by {@link EditorSnapshot.image} and
960
+ * {@link Editor.getSelectedImage}.
961
+ *
962
+ * @public
963
+ */
964
+ interface SelectedImageState {
965
+ readonly id: string;
966
+ readonly kind: DrawingKind;
967
+ readonly widthEmu: number;
968
+ readonly heightEmu: number;
969
+ /** Crop inset per edge in UI percent (0–100); OOXML stores permille (×1000). */
970
+ readonly crop: ImageCropPercent;
971
+ readonly rotationDegrees: number;
972
+ readonly wrap: ImageWrapTarget;
973
+ readonly position: DrawingPositionInput | null;
974
+ readonly name: string;
975
+ readonly title: string;
976
+ readonly description: string;
977
+ readonly hyperlink: string | null;
978
+ readonly locks: DrawingLocks;
979
+ readonly hidden: boolean;
980
+ readonly resourceStatus: ImageResourceState['kind'];
981
+ readonly intrinsic: Readonly<{
982
+ readonly pixelWidth: number;
983
+ readonly pixelHeight: number;
984
+ readonly dpiX: number;
985
+ readonly dpiY: number;
986
+ }> | null;
987
+ readonly canResize: boolean;
988
+ readonly canMove: boolean;
989
+ readonly canChangeWrap: boolean;
990
+ readonly canCrop: boolean;
991
+ }
992
+ /**
993
+ * The selected image and what may be done to it — the `imageContext` query's answer.
994
+ *
995
+ * An alias of `SelectedImageState`, kept as its own name because it is the query's result type
996
+ * and chrome is written against it.
997
+ *
998
+ * @public
999
+ */
1000
+ type ImageContext = SelectedImageState;
1001
+
1002
+ /** Where the caret sits inside a table: its shape and current cell. */
1003
+ interface TableContext {
1004
+ readonly rows: number;
1005
+ readonly columns: number;
1006
+ /** Zero-based, within the table. */
1007
+ readonly rowIndex: number;
1008
+ /** Zero-based, within the row. */
1009
+ readonly columnIndex: number;
1010
+ }
1011
+ /** Which cell edges a table border command targets. */
1012
+ type TableBorderTarget = 'all' | 'outside' | 'inside' | 'none' | 'top' | 'bottom' | 'left' | 'right';
1013
+ /** Concrete scopes that apply a complete border spec. */
1014
+ type TableBorderEdgeTarget = Exclude<TableBorderTarget, 'none'>;
1015
+ /**
1016
+ * Allowlisted OOXML table border line styles.
1017
+ *
1018
+ * Kept identical to `store/table-border-style.ts`; `table-border-style-parity.test-d.ts`
1019
+ * fails if the contract and store vocabularies drift.
1020
+ */
1021
+ type TableBorderStyle = 'single' | 'dashed' | 'dotted' | 'double' | 'triple' | 'thick';
1022
+ /** Complete border spec for {@link EditorCommands.setTableBorders}. Size is in eighths of a point. */
1023
+ interface TableBorderSpec {
1024
+ readonly style: TableBorderStyle;
1025
+ readonly size: number;
1026
+ readonly color: ColorValue;
1027
+ }
1028
+ /** Vertical placement of content inside selected table cells. @public */
1029
+ type TableCellVerticalAlignment = 'top' | 'center' | 'bottom';
1030
+ /**
1031
+ * Adjacent grid columns addressed by an internal divider resize gesture.
1032
+ *
1033
+ * `sourceRevision` is the PACKAGE revision of the layout the target was read from — the number
1034
+ * `getDocumentHandle()` reports, never one story's own. Commit MUST refuse when it no longer
1035
+ * equals the current one, even if an older layout remains published for geometry.
1036
+ */
1037
+ interface TableColumnDividerResizeTarget {
1038
+ readonly sourceRevision: number;
1039
+ readonly tableId: string;
1040
+ readonly leftGridColumnId: string;
1041
+ readonly rightGridColumnId: string;
1042
+ readonly isHeaderRepeat: boolean;
1043
+ }
1044
+ /**
1045
+ * Last grid column and table width addressed by an outer-right-edge resize gesture.
1046
+ *
1047
+ * `sourceRevision` follows the same rule as {@link TableColumnDividerResizeTarget}: the package
1048
+ * revision of the layout the target was read from, and commit refuses once it no longer equals
1049
+ * the current one.
1050
+ */
1051
+ interface TableRightEdgeResizeTarget {
1052
+ readonly sourceRevision: number;
1053
+ readonly tableId: string;
1054
+ readonly gridColumnId: string;
1055
+ readonly isHeaderRepeat: boolean;
1056
+ }
1057
+ /** Explicit row occurrence. `sourceRevision` per {@link TableColumnDividerResizeTarget}. */
1058
+ interface TableRowOccurrenceTarget {
1059
+ readonly sourceRevision: number;
1060
+ readonly tableId: string;
1061
+ readonly rowId: string;
1062
+ readonly isHeaderRepeat: boolean;
1063
+ }
1064
+ /** Explicit column occurrence. `sourceRevision` per {@link TableColumnDividerResizeTarget}. */
1065
+ interface TableColumnOccurrenceTarget {
1066
+ readonly sourceRevision: number;
1067
+ readonly tableId: string;
1068
+ readonly gridColumnId: string;
1069
+ readonly isHeaderRepeat: boolean;
1070
+ }
1071
+
1072
+ /**
1073
+ * An opaque handle to a loaded document — its stable identity and current
1074
+ * revision. The canonical authored state is the engine's `PackageModel`, NOT a
1075
+ * simplified tree; advanced automation (`DocxEditor.run(handle, …)`) addresses a
1076
+ * document through this handle rather than a serialized structure. Kept
1077
+ * deliberately minimal and open so it can carry more identity later without a
1078
+ * breaking change.
1079
+ */
1080
+ interface DocumentHandle {
1081
+ /** Package revision: rises for every edit, wherever it landed. Safe to compare. */
1082
+ readonly revision: number;
1083
+ }
1084
+ /**
1085
+ * What `createDocxEditor`/`load` accept as a document: raw DOCX bytes, an existing
1086
+ * in-memory `DocumentHandle` (shared/handed off), or `'blank'`. The engine is byte-native
1087
+ * (`PackageModel` is canonical); there is intentionally no structured-tree input,
1088
+ * which would be lossy against the canonical package.
1089
+ *
1090
+ * `'blank'` is Word's blank template, the same bytes `blankDocumentBytes()` returns from
1091
+ * `@docx-editor.dev/core/editor`. OMITTING the document is not a way to ask for an empty
1092
+ * one: with no document there is no editing surface, so every command refuses with "no
1093
+ * document is loaded" behind a loading screen waiting for bytes that are not coming.
1094
+ *
1095
+ * The two spellings serve different gestures. `'blank'` is a CONSTANT, so an adapter that
1096
+ * remounts on document identity holds one document — right for MOUNTING.
1097
+ * `blankDocumentBytes()` allocates, so it starts a fresh document every call — right for
1098
+ * File › New. Call the function into `load()` or host state, never inline in a prop,
1099
+ * where a new array per render rebuilds the editor per render.
1100
+ */
1101
+ type DocumentSource = ArrayBuffer | Uint8Array | DocumentHandle | 'blank';
1102
+ /** A concrete font face requested by authored document content. */
1103
+ interface FontFaceRequest {
1104
+ readonly family: string;
1105
+ readonly weight: number;
1106
+ readonly style: 'normal' | 'italic';
1107
+ }
1108
+ /** Immutable, byte-backed font face supplied to layout and browser paint. */
1109
+ interface FontSource {
1110
+ readonly request: FontFaceRequest;
1111
+ readonly id: string;
1112
+ readonly bytes: Uint8Array;
1113
+ readonly hash: string;
1114
+ readonly faceIndex: number;
1115
+ readonly availability?: 'available' | 'forbidden';
1116
+ }
1117
+ /** An explicit authored-font substitution. No implicit platform fallback is performed. */
1118
+ interface FontSourceSubstitution {
1119
+ readonly from: FontFaceRequest;
1120
+ readonly to: FontFaceRequest;
1121
+ /** Word line-box metrics for the requested face, expressed as em ratios. */
1122
+ readonly lineMetrics?: {
1123
+ readonly heightEm: number;
1124
+ readonly baselineEm: number;
1125
+ };
1126
+ }
1127
+ /**
1128
+ * Public font source configuration sampled when an adapter mounts. It must be immutable for that
1129
+ * editor lifetime; remount the adapter to replace bytes or substitutions atomically.
1130
+ */
1131
+ interface FontConfiguration {
1132
+ /** Selectable provider families, independent of loaded bytes. Listing them performs no fetch. */
1133
+ readonly supportedFamilies?: readonly string[];
1134
+ readonly epoch: number;
1135
+ readonly maxFontBytes: number;
1136
+ readonly sources: readonly FontSource[];
1137
+ readonly substitutions?: readonly FontSourceSubstitution[];
1138
+ readonly defaultFont: {
1139
+ readonly family: string;
1140
+ readonly sizeHalfPoints: number;
1141
+ };
1142
+ readonly language?: string;
1143
+ }
1144
+ /**
1145
+ * Why a font was not admitted.
1146
+ *
1147
+ * Distinguished rather than collapsed because the responses differ: `overLimit` and `malformed`
1148
+ * are the caller's own bytes, while `forbidden` and `hashMismatch` mean the source was not what
1149
+ * it claimed and the load should not be retried. `wasmUnavailable` alone is a HOST fault — the
1150
+ * shaper's WASM never loaded, `diagnostic` carries the remedy — surface it as a setup error.
1151
+ */
1152
+ type EditorFontErrorCode = 'initializationFailed' | 'wasmUnavailable' | 'missing' | 'forbidden' | 'overLimit' | 'malformed' | 'hashMismatch' | 'metadataMismatch' | 'fontFaceLoadFailed' | 'unsupportedFaceIndex' | 'missingFont' | 'hashInvalid' | 'fontMismatch' | 'unsupportedFace' | 'loadFailed';
1153
+ /** Typed adapter error reported both through `onFontError` and accessible alert UI. */
1154
+ declare class EditorFontError extends Error {
1155
+ readonly name: string;
1156
+ readonly code: EditorFontErrorCode;
1157
+ readonly request?: FontFaceRequest;
1158
+ readonly diagnostic?: string;
1159
+ constructor(code: EditorFontErrorCode, message: string, details?: {
1160
+ readonly request?: FontFaceRequest;
1161
+ readonly diagnostic?: string;
1162
+ readonly cause?: unknown;
1163
+ });
1164
+ }
1165
+ /**
1166
+ * A selection endpoint, in either vocabulary the engine resolves.
1167
+ *
1168
+ * {@link DocAnchor} addresses a paragraph by its `w14:paraId`, which is what an LLM or an
1169
+ * automation script can name in a payload. {@link SemanticPosition} addresses it by the
1170
+ * paragraph id the painted surface and the ops already use, with a UTF-16 offset inside it.
1171
+ *
1172
+ * Neither subsumes the other. A paraId survives being written to a file and read back, so it
1173
+ * is the one an out-of-process caller can hold; but it is OPTIONAL in the document, and
1174
+ * `ParagraphSummary.paraId` says so — a paragraph the file gave no `w14:paraId` cannot be
1175
+ * reached by a `DocAnchor` at all. The paragraph id reaches every paragraph.
1176
+ */
1177
+ type EditorPosition = DocAnchor | SemanticPosition;
1178
+ /**
1179
+ * A selection, in one endpoint vocabulary or the other.
1180
+ *
1181
+ * The two do NOT mix: a range is a pair of paraId anchors, or a semantic anchor/head pair,
1182
+ * and `can()` refuses anything else with the engine's own reason. Spelled as two arms rather
1183
+ * than `{ from: EditorPosition; to: EditorPosition }` for exactly that reason — the looser
1184
+ * shape would type a mixed pair the engine rejects at runtime.
1185
+ */
1186
+ type EditorSelection = SemanticSelection | {
1187
+ from: DocAnchor;
1188
+ to: DocAnchor;
1189
+ };
1190
+ /**
1191
+ * Whether a command would be accepted, and why not when it would not.
1192
+ *
1193
+ * The `reason` is the ENGINE's own words, which is what lets disabled chrome explain itself
1194
+ * instead of guessing — see `toolbarCommandState`.
1195
+ */
1196
+ type CanResult = {
1197
+ ok: true;
1198
+ } | {
1199
+ ok: false;
1200
+ code: ExecErrorCode;
1201
+ reason: string;
1202
+ };
1203
+ /**
1204
+ * The engine's whole public surface: load and save, execute and query, observe and subscribe.
1205
+ *
1206
+ * Commands go through `can` before `exec` — the same check chrome uses to decide whether a
1207
+ * control is enabled, so a button and the engine never disagree about what is possible.
1208
+ *
1209
+ * `snapshot()` is version-cached: the same reference until state actually moves, with
1210
+ * reference-stable sub-objects, which is what makes it safe as a `useSyncExternalStore` source.
1211
+ *
1212
+ * @example
1213
+ * ```ts
1214
+ * const editor = createDocxEditor({ container });
1215
+ * editor.load(bytes);
1216
+ * if (editor.can({ type: 'toggleBold' }).ok) editor.exec({ type: 'toggleBold' });
1217
+ * const bytesOut = await editor.save();
1218
+ * ```
1219
+ */
1220
+ interface Editor extends EditorAnchorNavigation, EditorHighlights, EditorReviewHits {
1221
+ /**
1222
+ * Load a new document (DOCX bytes, `'blank'`, or a handle), replacing the current one.
1223
+ *
1224
+ * A large document mounts behind one painted frame, so a loading screen keyed on
1225
+ * `snapshot().isOpening` can show instead of a frozen page; a small one mounts before
1226
+ * this returns. Callers that need the document synchronously do not have to care:
1227
+ * `save`, `exec` and `selectMatch` complete a scheduled open before they run.
1228
+ */
1229
+ load(document: DocumentSource): void;
1230
+ /**
1231
+ * Serialize the current document, finalizing pending text form values first.
1232
+ * Invalid input rejects with `EditorError.code === 'invalidArgs'` and remains editable.
1233
+ * Validation does not open a dialog. Other write refusals also reject the save.
1234
+ */
1235
+ save(): Promise<ArrayBuffer>;
1236
+ getDocumentHandle(): DocumentHandle;
1237
+ /** Create an explicit gesture handle; creates no undo entry. */
1238
+ beginHistoryGroup(): HistoryGroup;
1239
+ exec(command: EditorCommand, options?: EditorExecOptions): ExecResult;
1240
+ /** Dry run: reports whether `exec` would apply. Never reports `changed`. */
1241
+ can(command: EditorCommand, options?: EditorExecOptions): CanResult;
1242
+ /**
1243
+ * Dry run for byte commands that require {@link Editor.executeImageCommand}.
1244
+ * Generic {@link Editor.can} on `insertImage` / `replaceImage` refuses with an async-path
1245
+ * reason; this method answers whether async execution can proceed right now.
1246
+ */
1247
+ canExecuteImageCommand(command: Extract<EditorCommand, {
1248
+ type: 'insertImage' | 'replaceImage';
1249
+ }>, options?: {
1250
+ scope?: EditorScope;
1251
+ }): CanResult;
1252
+ /** Insert or replace picture bytes as one package undo unit. */
1253
+ executeImageCommand(command: Extract<EditorCommand, {
1254
+ type: 'insertImage' | 'replaceImage';
1255
+ }>): Promise<ExecResult>;
1256
+ /**
1257
+ * Whether a formatting command is currently APPLIED at the selection — distinct from
1258
+ * `can`, which answers whether it may run.
1259
+ *
1260
+ * A toolbar must show that bold is on, and the repo's own guidance is that controls
1261
+ * reflect live editor state rather than being static. `can` cannot answer this, and the
1262
+ * legacy adapter answered it by reading a ProseMirror `EditorState` directly, which the
1263
+ * greenfield architecture forbids in adapters.
1264
+ *
1265
+ * The derivation EXISTS for marks and alignment: `toggleMark` bold/italic/underline/
1266
+ * strike answers from the snapshot's selection formatting (Word's agreement rule — true
1267
+ * only when the WHOLE selection carries the mark), and `setAlignment` compares the
1268
+ * command's `align` (with justify↔`both` mapped the way `exec` writes it) to the
1269
+ * selection's paragraph alignment. Every other command still returns `false`: it must
1270
+ * never return a value it has not actually derived from canonical state, and `false` is
1271
+ * the honest answer while a derivation does not exist.
1272
+ */
1273
+ isActive(command: EditorCommand, options?: {
1274
+ scope?: EditorScope;
1275
+ }): boolean;
1276
+ /** Paragraph/character styles defined by the document, for the style picker. */
1277
+ getDocumentStyles(): readonly {
1278
+ readonly styleId: string;
1279
+ readonly name: string;
1280
+ readonly type: string;
1281
+ /**
1282
+ * How the style looks, so a picker can show each entry in its own face rather than a
1283
+ * list of identical rows. Presentation only, and already bounded for a CSS sink.
1284
+ */
1285
+ readonly preview: {
1286
+ readonly fontFamily: string | null;
1287
+ readonly fontSizePt: number | null;
1288
+ readonly bold: boolean;
1289
+ readonly italic: boolean;
1290
+ readonly color: string | null;
1291
+ };
1292
+ }[];
1293
+ /** Font families the document actually uses, for the font picker. */
1294
+ getDocumentFonts(): readonly string[];
1295
+ /**
1296
+ * Selectable standard and provider-supported families plus the configured catalog (the default face,
1297
+ * the Word-name families the substitution map stands in for, and host-registered
1298
+ * source families) merged with {@link getDocumentFonts}. Never empty — a brand-new
1299
+ * document offers the same standard choices. This does not report installed or loaded fonts.
1300
+ */
1301
+ getAvailableFonts(): readonly string[];
1302
+ /**
1303
+ * The document theme's ten picker colours (`a:clrScheme`) in Word's column order
1304
+ * (Background 1, Text 1, Background 2, Text 2, Accent 1-6), each a six-digit hex
1305
+ * without '#'. Empty when the document has no complete scheme — the picker then
1306
+ * falls back to a default palette.
1307
+ */
1308
+ getDocumentThemeColors(): readonly {
1309
+ readonly slot: string;
1310
+ readonly hex: string;
1311
+ }[];
1312
+ /** Heading outline for the navigation panel, in document order. */
1313
+ getOutline(): readonly {
1314
+ readonly text: string;
1315
+ readonly level: number;
1316
+ readonly blockId: string;
1317
+ }[];
1318
+ /** Comment threads anchored in the document. */
1319
+ getComments(): readonly {
1320
+ readonly id: string;
1321
+ readonly text: string;
1322
+ readonly resolved: boolean;
1323
+ }[];
1324
+ /** Formatting at the current selection, for toolbar value display (font, size, colour,
1325
+ * alignment, list state). `null` when nothing is selected or nothing is derivable. */
1326
+ getSelectionFormatting(): {
1327
+ readonly fontFamily?: string;
1328
+ readonly fontSizeHalfPoints?: number;
1329
+ readonly styleId?: string;
1330
+ readonly alignment?: string;
1331
+ readonly bold?: boolean;
1332
+ readonly italic?: boolean;
1333
+ readonly underline?: boolean;
1334
+ } | null;
1335
+ /**
1336
+ * Find across body, headers, footers, footnotes, endnotes, and selectable text boxes.
1337
+ *
1338
+ * The search narrows to the body and its selectable text boxes when other stories cannot open.
1339
+ * This includes viewing mode and surfaces without header, footer, or note entry methods.
1340
+ * Text boxes in footnotes and endnotes remain excluded until their drawings are selectable.
1341
+ */
1342
+ findMatches(query: string, options?: {
1343
+ readonly matchCase?: boolean;
1344
+ readonly wholeWord?: boolean;
1345
+ }): readonly TextMatch[];
1346
+ /** Find many terms in one pass, such as a glossary: one result list per term, in order. */
1347
+ findMatches(queries: readonly string[], options?: {
1348
+ readonly matchCase?: boolean;
1349
+ readonly wholeWord?: boolean;
1350
+ }): readonly (readonly TextMatch[])[];
1351
+ /**
1352
+ * Move the selection to a found match — what a find dialog's next/previous do.
1353
+ *
1354
+ * Separate from `findMatches` because finding is a read and selecting is a write, and
1355
+ * a caller may want the count without moving the caret.
1356
+ */
1357
+ selectMatch(match: TextMatch): ExecResult;
1358
+ /** The image at the selection, for the image toolbar and transform controls. */
1359
+ getSelectedImage(): SelectedImageState | null;
1360
+ /** The table containing the selection, for the table toolbar. `null` outside a table. */
1361
+ getSelectedTable(): {
1362
+ readonly blockId: string;
1363
+ readonly rowCount: number;
1364
+ readonly columnCount: number;
1365
+ readonly cell: {
1366
+ readonly row: number;
1367
+ readonly column: number;
1368
+ } | null;
1369
+ } | null;
1370
+ /** Live rectangular cell selection, if any. `null` when the caret is not in a cell rectangle. */
1371
+ getTableCellSelection(): {
1372
+ readonly tableId: string;
1373
+ readonly rows: {
1374
+ readonly from: number;
1375
+ readonly to: number;
1376
+ };
1377
+ readonly columns: {
1378
+ readonly from: number;
1379
+ readonly to: number;
1380
+ };
1381
+ readonly cellIds: readonly string[];
1382
+ } | null;
1383
+ /** Update table furniture aria labels without remounting the editor. */
1384
+ setTableInteractionLabel(resolver: (key: 'table.insertRowBelow' | 'table.insertColumnRight') => string): void;
1385
+ /** Section page setup — size, orientation and margins — for the page-setup dialog. */
1386
+ getPageSetup(): PageSetup | null;
1387
+ /** The document watermark, for the watermark dialog. */
1388
+ getWatermark(): {
1389
+ readonly kind: 'text' | 'image';
1390
+ readonly text?: string;
1391
+ } | null;
1392
+ /** Header/footer editing state: which region is being edited, if any. */
1393
+ getHeaderFooterState(): HeaderFooterState | null;
1394
+ /** Resolved and authored note properties for the caret section — properties dialog read-model. */
1395
+ getNotePropertiesState(): NotePropertiesState | null;
1396
+ /** Plain-text note preview for hover chrome. */
1397
+ getNotePreviewText(scopeId: string): string | null;
1398
+ /** Tracked changes in the document — body AND header/footer stories. */
1399
+ getTrackedChanges(): readonly {
1400
+ readonly id: string;
1401
+ readonly kind: string;
1402
+ readonly author?: string;
1403
+ /** Which story holds the change, so a consumer can group or filter by region. */
1404
+ readonly story?: 'body' | 'header' | 'footer' | 'footnote' | 'endnote';
1405
+ }[];
1406
+ /**
1407
+ * Every pending decision in the document, with where its card belongs.
1408
+ *
1409
+ * Derived from the document TREE, not from what is painted: a queue derived from laid-out
1410
+ * spans empties by half the moment the reader switches to a resolved display mode, and the
1411
+ * changes that vanished become unreachable from the surface meant to resolve them.
1412
+ *
1413
+ * `anchorY` comes from layout records. A surface must not measure painted DOM for it — that
1414
+ * is a repaint behind the document and fails outright during pagination.
1415
+ */
1416
+ getReviewItems(query?: ReviewItemQuery): readonly ReviewItemPlacement[];
1417
+ /**
1418
+ * Set the view-time tracked-change filter, or clear it with `null`.
1419
+ *
1420
+ * The predicate receives each full revision item. A false result renders that revision as
1421
+ * accepted by default. With `reject`, excluded content, moves, paragraph marks, and table-row
1422
+ * insertions/deletions use their rejected projection; formatting and other property-change
1423
+ * records keep their current values with revision markup hidden. Both modes are view-only: they
1424
+ * change no OOXML and do not change saved bytes. Calling this method again re-evaluates every
1425
+ * revision, even when the function reference is unchanged.
1426
+ */
1427
+ setTrackedChangesFilter(predicate: TrackedChangePredicate | null, mode?: TrackedChangeFilterMode): void;
1428
+ /**
1429
+ * Custom-node definitions registered through `createDocxEditor({ modules })`, in
1430
+ * registration order.
1431
+ *
1432
+ * OPAQUE to the engine — the capability package that defined them narrows them back.
1433
+ * Published so chrome components can default to the registered definitions instead of
1434
+ * every surface taking the same `nodes` array and drifting.
1435
+ */
1436
+ getCustomNodeDefinitions(): readonly unknown[];
1437
+ /**
1438
+ * Report a custom-node diagnostic to the modules registered on THIS editor.
1439
+ *
1440
+ * The capability package raises these from its own read paths as well as from the review
1441
+ * derivation, and both have to reach the same listeners — the ones belonging to this instance.
1442
+ * Keeping the channel here rather than in the package is what stops two editors on one page
1443
+ * hearing about each other's documents.
1444
+ *
1445
+ * Opaque, like `getCustomNodeDefinitions`: what a diagnostic means belongs to whoever raised it.
1446
+ */
1447
+ reportCustomNodeDiagnostic(diagnostic: unknown): void;
1448
+ /**
1449
+ * How edits are written: directly, as suggestions, or not at all.
1450
+ *
1451
+ * Runtime state, unlike the construction-time `DocxEditorConfig.mode` — a reader who switches
1452
+ * to Viewing and back expects the same document, not a remount.
1453
+ */
1454
+ getEditingMode(): DocumentEditingMode;
1455
+ setEditingMode(mode: DocumentEditingMode): ExecResult;
1456
+ /**
1457
+ * Whether the review pane is showing its cards.
1458
+ *
1459
+ * Engine-owned, like zoom: the toolbar toggles it, the rail renders from it, and the
1460
+ * document shifts to make room for it. Three consumers, one answer.
1461
+ */
1462
+ isReviewPaneOpen(): boolean;
1463
+ /**
1464
+ * Layout points to CSS pixels, zoom included.
1465
+ *
1466
+ * Published because {@link ReviewItemPlacement.anchorY} is in the engine's own unit, and a
1467
+ * host that re-derived the factor would own a second copy of the points-to-pixels rule.
1468
+ * The first copy drifted the moment it was written: a rail that used zoom alone put every
1469
+ * card at three quarters of its true height.
1470
+ */
1471
+ getRenderScale(): number;
1472
+ /**
1473
+ * A counter that changes exactly when {@link getReviewItems} would return something new.
1474
+ *
1475
+ * Lets a subscriber re-derive on a real change rather than on every event.
1476
+ */
1477
+ getReviewRevision(): number;
1478
+ /**
1479
+ * Comment on the current selection.
1480
+ *
1481
+ * Anchored to the RETAINED range when there is one, so a compose box that took focus does
1482
+ * not lose the words it is about — that is what retention exists for. Refused on a
1483
+ * collapsed caret: a comment with no range has nothing to point at, and Word writes none.
1484
+ */
1485
+ addComment(text: string, author?: string): ExecResult;
1486
+ /**
1487
+ * Where a comment on the current selection would sit, in the same space as
1488
+ * {@link ReviewItemPlacement.anchorY}, or null when nothing is selected.
1489
+ *
1490
+ * Published so a host can place an "add a comment" affordance beside the selected text
1491
+ * without deriving document geometry, which is the one thing an adapter must not do.
1492
+ */
1493
+ getSelectionPlacement(): {
1494
+ readonly anchorY: number;
1495
+ readonly pageIndex: number;
1496
+ } | null;
1497
+ /**
1498
+ * Card to document: a COLLAPSED caret at the range start, and a scroll to it. `null` clears it.
1499
+ *
1500
+ * REPORTS, like {@link acceptReviewItem} and for the same reason. Activation is refused for
1501
+ * an item with no resolvable range, for a kind the host's rail excluded (see
1502
+ * {@link setReviewActivationExclusions}), for a custom node without `reviewCard`, and when
1503
+ * the story it lives in will not open — and a host walking a queue with next/previous
1504
+ * controls has no other way to learn that a step did nothing. Consult {@link ReviewItemPlacement.activatable} to avoid asking.
1505
+ *
1506
+ * With `options.announce: true`, a call that lands fires `reviewItemReveal` with
1507
+ * `source: 'host'`, also when the item was already active, so the packaged review UI opens
1508
+ * the item's balloon or card. By default it fires nothing. A `null` key fires nothing.
1509
+ */
1510
+ setActiveReviewItem(key: string | null, options?: ReviewActivationOptions): ExecResult;
1511
+ /**
1512
+ * The key of the ACTIVATED review item: the one {@link setActiveReviewItem}, Next Change, or
1513
+ * Previous Change made active, while the caret stays in it.
1514
+ *
1515
+ * Two ideas of "active" exist. The caret-active item is the one the caret is in, however it
1516
+ * got there: `isActive` on the placements {@link getReviewItems} returns, and `activeKey` in
1517
+ * `useReview()`. The activated item is narrower: only an explicit activation sets it, so a
1518
+ * caret that merely lands in a change leaves this `null`. Open a balloon or card for the
1519
+ * activated item, and highlight the caret-active one.
1520
+ *
1521
+ * Pass the query you read items with, so the key matches theirs: with
1522
+ * `pairReplacements: true`, a paired replacement reports the pair's key; without it, the
1523
+ * key of the half the caret is in. The value changes with the selection, so read it again
1524
+ * on `selectionChange`.
1525
+ *
1526
+ * @example
1527
+ * ```ts
1528
+ * const query = { pairReplacements: true };
1529
+ * editor.on('selectionChange', () => {
1530
+ * const activated = editor.getActivatedReviewItemKey(query);
1531
+ * if (activated !== null) showMyCard(activated);
1532
+ * });
1533
+ * ```
1534
+ */
1535
+ getActivatedReviewItemKey(query?: ReviewItemQuery): string | null;
1536
+ /**
1537
+ * Revision kinds the caret must never activate, or null for none.
1538
+ *
1539
+ * A host rail that hides some kinds (structural and format cards, typically) tells the
1540
+ * engine here, so a click on tracked text cannot activate a card the rail does not
1541
+ * render — the band would light and nothing on screen would answer it.
1542
+ * `formattingKinds` limits a format exclusion to those OOXML property-change names,
1543
+ * allowing other formatting decisions to retain sidebar activation.
1544
+ */
1545
+ setReviewActivationExclusions(kinds: readonly ReviewRevisionKind[] | null, options?: {
1546
+ readonly formattingKinds?: readonly string[];
1547
+ }): void;
1548
+ /**
1549
+ * Accept or reject the revision behind a card.
1550
+ *
1551
+ * Every site carrying the revision's `(id, author, date)` triple resolves in ONE transaction
1552
+ * and one undo step: a tracked row insertion is `w:trPr/w:ins` on the row plus `w:cellIns`
1553
+ * on each cell, and resolving them separately would leave the row half-tracked.
1554
+ *
1555
+ * Refused for a card whose kind the engine cannot resolve structurally, which is why
1556
+ * `readOnly` is on the item — a surface should not offer the button in the first place.
1557
+ */
1558
+ acceptReviewItem(key: string): ExecResult;
1559
+ rejectReviewItem(key: string): ExecResult;
1560
+ /**
1561
+ * Resolve or reopen the comment thread behind a review card.
1562
+ *
1563
+ * The thread state is written through the same package transaction as every other comment
1564
+ * mutation, so `commentsExtended.xml`, Undo and save/reopen cannot disagree. Repeating the
1565
+ * state already on the item succeeds without adding an undo entry.
1566
+ */
1567
+ setCommentResolved(key: string, resolved: boolean): ExecResult;
1568
+ /**
1569
+ * Discard the item behind a card: the destructive half of the review verbs.
1570
+ *
1571
+ * On a COMMENT it deletes the thread — the `w:comment` body, the `w15:commentEx` record and
1572
+ * the story's range markers, in one transaction and therefore one undo step. Word deletes a
1573
+ * conversation rather than one remark, and a reply whose parent is gone has nothing left to
1574
+ * answer.
1575
+ *
1576
+ * On a REVISION it rejects the change, which is what discarding a suggestion means: the
1577
+ * proposal goes away and the document reads as it did before. Deliberately the same verb, so
1578
+ * a surface can put one "remove this" affordance on every card instead of branching.
1579
+ *
1580
+ * Refused on a custom node's card, which is informational, and on a revision kind the engine
1581
+ * cannot resolve — the same rule {@link rejectReviewItem} follows.
1582
+ */
1583
+ deleteReviewItem(key: string): ExecResult;
1584
+ /**
1585
+ * Reply to a review item.
1586
+ *
1587
+ * Against a comment this is a threaded reply. Against a REVISION it is a comment anchored
1588
+ * over that revision's range: OOXML gives `w:ins` and `w:del` no body and no thread, so
1589
+ * there is nowhere else for the text to live.
1590
+ *
1591
+ * The author is AMBIENT — `DocxEditorConfig.author`, the way the rest of the authored commands
1592
+ * source it — and the argument overrides it for one call. `CT_Comment` makes `@w:author`
1593
+ * required, so a reply with neither is refused rather than written as an empty attribute.
1594
+ */
1595
+ replyToReviewItem(key: string, text: string, author?: string): ExecResult;
1596
+ setActiveScope(scope: ViewScope): void;
1597
+ getActiveScope(): ViewScope;
1598
+ query<K extends keyof EditorQueries>(query: {
1599
+ type: K;
1600
+ } & EditorQueries[K], options?: {
1601
+ scope?: EditorScope;
1602
+ }): EditorQueryResults[K];
1603
+ snapshot(options?: {
1604
+ scope?: EditorScope;
1605
+ }): EditorSnapshot;
1606
+ getTotalPages(): number;
1607
+ /**
1608
+ * One-based page at the caret (default), or at the centre of the mounted scroll viewport.
1609
+ * Viewport mode falls back to the caret when no measurable viewport is attached.
1610
+ */
1611
+ getCurrentPage(mode?: 'viewport' | 'caret'): number;
1612
+ /**
1613
+ * Display scale of the painted pages. 1 is 100%.
1614
+ *
1615
+ * Zoom is ENGINE-OWNED rather than a host prop, so the toolbar's zoom control, the
1616
+ * scale a host paints at, and the factor hit testing divides by cannot disagree —
1617
+ * a host that scaled its own transform without telling the engine would land every
1618
+ * click at the wrong content point.
1619
+ */
1620
+ /**
1621
+ * Scroll a page or a block into view. Returns false when the target does not exist or
1622
+ * the host has no scroll container — a caller can tell "not found" from "scrolled".
1623
+ */
1624
+ scrollToPage(pageNumber: number): boolean;
1625
+ /**
1626
+ * `options` takes the {@link ScrollToAnchorOptions} fields. `block` defaults to `'start'`
1627
+ * here (`scrollToAnchor` defaults to `'centerIfNeeded'`), `behavior` to `'instant'`, and
1628
+ * `offsetPx` to 24. An invalid option also returns false, and nothing scrolls.
1629
+ */
1630
+ scrollToBlock(blockId: string, options?: ScrollToAnchorOptions): boolean;
1631
+ getZoom(): number;
1632
+ /**
1633
+ * Set the display scale. Values outside a sane range are rejected rather than
1634
+ * clamped silently, so a caller learns its input was refused.
1635
+ *
1636
+ * Also LEAVES any fit mode: a reader who picks 150% has said what they want, and a
1637
+ * viewport resize must not take it back off them. Call `setZoomMode` to go back.
1638
+ */
1639
+ setZoom(zoom: number): ExecResult;
1640
+ /** Whether the scale is a number the engine holds, or one it recomputes from the viewport. */
1641
+ getZoomMode(): ZoomMode;
1642
+ /**
1643
+ * Choose between holding a scale and tracking the viewport.
1644
+ *
1645
+ * `'auto'` is the shorthand for {@link ZoomMode}'s bounded page-width fit and the default
1646
+ * for a new editor: a window wide enough for the sheet stays at 100%, and a narrower one
1647
+ * shrinks rather than growing a horizontal scrollbar — down to 50%, past which the page
1648
+ * keeps a legible size and the scrollbar is the better trade. Refused (`invalidArgs`) for a
1649
+ * value that is not a mode, in the same spirit as `setZoom`.
1650
+ *
1651
+ * A fit tracks the scroller's CONTENT box, so anything that reserves width beside the page
1652
+ * — an open comments rail, a docked navigation pane — shrinks the document by exactly what
1653
+ * it took. Nothing else has to be told.
1654
+ */
1655
+ setZoomMode(mode: ZoomMode | 'auto'): ExecResult;
1656
+ /** Page boxes in stack coordinates, each with the text area the engine laid out.
1657
+ * `contentBox` is the page inset by the section margin. Rulers use it for margin zones.
1658
+ * The engine's margin is uniform, so do not present this as per-side fidelity.
1659
+ * Empty before the first layout, which is the honest answer rather than a guessed page. */
1660
+ getPageGeometry(): readonly {
1661
+ index: number;
1662
+ box: Rect;
1663
+ contentBox: Rect;
1664
+ }[];
1665
+ /** Replaces the module-scope cache-invalidation calls adapters make today. */
1666
+ relayout(options?: {
1667
+ sync?: boolean;
1668
+ }): void;
1669
+ focus(scope?: EditorScope): InteractionOutcome<void>;
1670
+ /** Pin the selection while chrome has focus. Returns null while detached. */
1671
+ retainSelection(): SelectionPin | null;
1672
+ /** Release only the pin installed by the matching {@link retainSelection} call. */
1673
+ releaseSelection(pin: SelectionPin): void;
1674
+ destroy(): void;
1675
+ on<E extends keyof EditorEvents>(event: E, handler: EditorEvents[E]): Unsubscribe;
1676
+ }
1677
+ /**
1678
+ * Open by declaration merging: extensions contribute keys from `core/plugin`.
1679
+ * `exec` resolves `{ type, ... }` through the extension registry, which is
1680
+ * already the production dispatch path.
1681
+ */
1682
+ /**
1683
+ * In the editor a command targets the current selection unless told otherwise,
1684
+ * and authoring is ambient — the author comes from `DocxEditorConfig`/the session,
1685
+ * the way the Office JS API sources it from context — so the document layer's
1686
+ * required `target` and `author` both become optional here.
1687
+ */
1688
+ type EditorCommandShape<T> = {
1689
+ [K in keyof T]: Omit<T[K], 'target' | 'author'> & (T[K] extends {
1690
+ target: infer G;
1691
+ } ? {
1692
+ target?: G;
1693
+ } : unknown) & (T[K] extends {
1694
+ author: infer A;
1695
+ } ? {
1696
+ author?: A;
1697
+ } : unknown);
1698
+ };
1699
+
1700
+ /**
1701
+ * Decides whether one tracked change renders as markup.
1702
+ *
1703
+ * Return `true` to keep the revision visible as tracked markup. Return `false` to render it with
1704
+ * the selected {@link TrackedChangeFilterMode} without changing the document. The callback
1705
+ * receives the complete revision item, including its author, date, kind, text, ranges, nesting,
1706
+ * and resolution metadata.
1707
+ */
1708
+ type TrackedChangePredicate = (revision: ReviewRevisionItem) => boolean;
1709
+ /** How revisions excluded by a tracked-changes predicate project into the view. */
1710
+ type TrackedChangeFilterMode = 'accept' | 'reject';
1711
+
1712
+ /**
1713
+ * Every command the editor accepts, keyed by name with its payload as the value.
1714
+ *
1715
+ * Extends the document-level {@link DocEdits} vocabulary with the things only a LIVE editor has:
1716
+ * selection, view state, chrome modes, header/footer and note editing. An interface rather than a
1717
+ * closed union so an extension can widen it by declaration merging.
1718
+ */
1719
+ interface EditorCommands extends EditorCommandShape<DocEdits>, EditorHeaderFooterCommands, EditorNoteCommands, EditorFormatPainterCommands {
1720
+ /** Switch how edits are written. A view command: it changes no document state. */
1721
+ setEditingMode: {
1722
+ mode: DocumentEditingMode;
1723
+ };
1724
+ /**
1725
+ * Show or hide the review pane.
1726
+ *
1727
+ * A view command rather than a document edit, and a COMMAND rather than a host flag so the
1728
+ * toolbar button gets its pressed state from the same place every other button does. Both
1729
+ * adapters and any host chrome read one answer.
1730
+ */
1731
+ toggleReviewPane: Record<never, never>;
1732
+ /** Open the local review settings dialog supplied by the review module. */
1733
+ openRevisionMarkupDialog: Record<never, never>;
1734
+ /** Word's Show/Hide paragraph marks; presentation only. */
1735
+ toggleParagraphMarks: Record<never, never>;
1736
+ /** Word's Protect Document: enforce filling-in-forms protection, or lift the enforced one. */
1737
+ toggleDocumentProtection: Record<never, never>;
1738
+ /** Navigate tracked changes, including hidden formatting balloons, and wrap at the end. */
1739
+ navigateReviewChange: {
1740
+ direction: 'next' | 'previous';
1741
+ };
1742
+ /** Resolve eligible changes shown by the active filters, or an explicit scope, in one undo step. */
1743
+ resolveAllReviewChanges: ResolveReviewChangesOptions;
1744
+ /** Attribute eligible changes to another author, keeping them pending, in one undo step. */
1745
+ setReviewChangesAuthor: SetReviewChangesAuthorOptions;
1746
+ /** Change the review projection without accepting or rejecting document revisions. */
1747
+ setReviewDisplayMode: {
1748
+ mode: ReviewDisplayMode;
1749
+ };
1750
+ toggleMark: {
1751
+ mark: string;
1752
+ };
1753
+ setMarkAttr: {
1754
+ mark: string;
1755
+ attr: string;
1756
+ value: unknown;
1757
+ };
1758
+ /**
1759
+ * Word's Clear All Formatting (Home > Font > the eraser).
1760
+ *
1761
+ * Takes direct CHARACTER formatting off the selected text, and resets every paragraph the
1762
+ * selection touches to the document's default paragraph style with its direct paragraph
1763
+ * properties dropped — alignment, indents, spacing, list membership. Character formatting
1764
+ * is a range and paragraph formatting is not, so a partial selection clears the text it
1765
+ * covers and still resets the paragraph it sits in, which is Word's split.
1766
+ *
1767
+ * Formatting inherited from a style is not touched: this removes what the document states
1768
+ * DIRECTLY, so the text falls back to what its style gives it rather than to nothing.
1769
+ *
1770
+ * A CHARACTER STYLE survives, and so do paragraph borders and hidden text. Those live
1771
+ * outside the property vocabulary an edit can name — a run's `w:rStyle`, `w:vanish` and
1772
+ * `w:bdr`, a paragraph's `w:pBdr` and `w:outlineLvl` — and are preserved rather than
1773
+ * dropped, which is where this stops short of Word: clearing a run that carries a
1774
+ * character style leaves that style's face on it.
1775
+ */
1776
+ clearFormatting: Record<never, never>;
1777
+ /**
1778
+ * Physical alignment on every paragraph the selection touches. A right-to-left paragraph
1779
+ * reaches its right margin with `w:jc="left"`, so the written value follows each
1780
+ * paragraph's direction.
1781
+ */
1782
+ setAlignment: {
1783
+ align: 'left' | 'center' | 'right' | 'justify';
1784
+ };
1785
+ /**
1786
+ * Word's Left-to-Right and Right-to-Left Text Direction: the base direction (`w:bidi`) of
1787
+ * every paragraph the selection touches, table cells included. `rtl` writes `w:bidi`.
1788
+ * `ltr` removes a direct `w:bidi`, and writes `w:bidi w:val="0"` only where a style would
1789
+ * otherwise make the paragraph right-to-left. Run text, run direction (`w:rtl`)
1790
+ * and `w:jc` are untouched: alignment and indents are leading and trailing sides, so a
1791
+ * start-aligned paragraph moves to the other margin with its direction.
1792
+ * A paragraph already in the requested direction is left as it is.
1793
+ */
1794
+ setParagraphDirection: {
1795
+ direction: 'ltr' | 'rtl';
1796
+ };
1797
+ /**
1798
+ * Word's Line Spacing, on every paragraph the selection touches.
1799
+ *
1800
+ * `value` is in the unit the RULE implies, which is the unit Word's own dialog uses:
1801
+ * LINES for `multiple` (1, 1.15, 1.5, 2), points for `exact` and `atLeast`. The
1802
+ * OOXML attribute is one number meaning two different quantities depending on
1803
+ * `w:lineRule`, and a caller should not have to know which.
1804
+ */
1805
+ setLineSpacing: {
1806
+ rule: 'multiple' | 'exact' | 'atLeast';
1807
+ value: number;
1808
+ };
1809
+ /**
1810
+ * Space above and below a paragraph, in points, on every paragraph the selection
1811
+ * touches. Omitting a field leaves it as authored; `null` clears it, which is how
1812
+ * Word's "Remove space before/after paragraph" differs from setting it to zero.
1813
+ */
1814
+ setParagraphSpacing: {
1815
+ beforePt?: number | null;
1816
+ afterPt?: number | null;
1817
+ };
1818
+ /**
1819
+ * Exact paragraph indent, in twips, on every paragraph the selection touches.
1820
+ *
1821
+ * Omitting a field leaves it as authored; `null` clears it so the paragraph falls back to
1822
+ * its style, the same distinction `setParagraphSpacing` draws — a zero blocks the cascade,
1823
+ * a missing attribute does not.
1824
+ *
1825
+ * `firstLine` is ONE SIGNED offset from the left indent: negative IS the hanging indent.
1826
+ * OOXML spells it as two mutually exclusive attributes (`w:firstLine`/`w:hanging`, where
1827
+ * hanging wins per §17.3.1.12); collapsing them here means a caller cannot state a
1828
+ * contradiction, and matches the single signed value Word's own model keeps.
1829
+ */
1830
+ setIndent: {
1831
+ left?: number | null;
1832
+ right?: number | null;
1833
+ firstLine?: number | null;
1834
+ };
1835
+ /**
1836
+ * The Paragraph dialog as one command: alignment, indents, spacing, line spacing and
1837
+ * the five paragraph flags, applied to every paragraph the selection touches.
1838
+ *
1839
+ * ONE undo step, because a dialog is one gesture. The single-purpose commands beside it
1840
+ * (`setAlignment`, `setIndent`, `setLineSpacing`, `setParagraphSpacing`) stay the right
1841
+ * choice for a toolbar button; this is for chrome that changes several at once.
1842
+ */
1843
+ setParagraphFormat: ParagraphFormatCommand;
1844
+ toggleList: {
1845
+ kind: 'bullet' | 'ordered';
1846
+ };
1847
+ insertRow: {
1848
+ where: 'above' | 'below';
1849
+ target?: TableRowOccurrenceTarget;
1850
+ };
1851
+ insertColumn: {
1852
+ where: 'left' | 'right';
1853
+ target?: TableColumnOccurrenceTarget;
1854
+ };
1855
+ deleteRow: {
1856
+ target?: TableRowOccurrenceTarget;
1857
+ };
1858
+ deleteColumn: {
1859
+ target?: TableColumnOccurrenceTarget;
1860
+ };
1861
+ deleteTable: Record<never, never>;
1862
+ mergeCells: Record<never, never>;
1863
+ splitCell: {
1864
+ rows: number;
1865
+ cols: number;
1866
+ };
1867
+ /** Selected-cell fill. `null` clears direct fill so the table-style cascade applies again. */
1868
+ setCellFill: {
1869
+ color: ColorValue | null;
1870
+ };
1871
+ /** Vertically align content inside the selected table cells. */
1872
+ setTableCellVerticalAlignment: {
1873
+ alignment: TableCellVerticalAlignment;
1874
+ };
1875
+ toggleHeaderRow: Record<never, never>;
1876
+ /**
1877
+ * Selected-cell borders. Concrete edge scopes require a complete spec;
1878
+ * `{ scope: 'none', target }` clears only that active edge target and MUST NOT carry `spec`.
1879
+ */
1880
+ setTableBorders: {
1881
+ scope: 'none';
1882
+ target: TableBorderEdgeTarget;
1883
+ } | {
1884
+ scope: TableBorderEdgeTarget;
1885
+ spec: TableBorderSpec;
1886
+ };
1887
+ /**
1888
+ * Commit an internal column-divider resize from an explicit pointer target.
1889
+ * Widths are twips for the adjacent pair; their sum must match the pre-drag total.
1890
+ */
1891
+ commitTableColumnDividerResize: {
1892
+ target: TableColumnDividerResizeTarget;
1893
+ leftWidthTwips: number;
1894
+ rightWidthTwips: number;
1895
+ };
1896
+ /**
1897
+ * Commit an outer-right table-edge resize from an explicit pointer target.
1898
+ * Updates the last grid column and overall table width together.
1899
+ */
1900
+ commitTableRightEdgeResize: {
1901
+ target: TableRightEdgeResizeTarget;
1902
+ columnWidthTwips: number;
1903
+ tableWidthTwips: number;
1904
+ };
1905
+ /**
1906
+ * Select a table region — the whole table, the current row, or the current column.
1907
+ * Legacy's table toolbar offers all three.
1908
+ */
1909
+ selectTableRegion: {
1910
+ region: 'table' | 'row' | 'column';
1911
+ };
1912
+ /**
1913
+ * Table-level properties from the table properties dialog: preferred width and
1914
+ * its unit (`dxa`, `pct`, `auto`), and horizontal justification. `null` clears a
1915
+ * property; omitting it leaves the current value alone.
1916
+ */
1917
+ setTableProperties: {
1918
+ width?: number | null;
1919
+ widthType?: string | null;
1920
+ justification?: 'left' | 'center' | 'right' | null;
1921
+ };
1922
+ /**
1923
+ * Section-level page setup: the fields Word's Page Setup dialog and the rulers'
1924
+ * margin drags change. Twips throughout, matching OOXML. Every field is optional —
1925
+ * a margin drag sends one, the dialog sends several — and an omitted field is left
1926
+ * as it is rather than reset. `scope` is Word's "Apply to": `'document'` (the
1927
+ * default) writes every section; `'section'` writes only the section the selection
1928
+ * is in. An orientation change without explicit dimensions swaps each written
1929
+ * section's own dimensions, preserving distinct paper sizes.
1930
+ */
1931
+ setPageSetup: {
1932
+ pageWidth?: number;
1933
+ pageHeight?: number;
1934
+ marginTop?: number;
1935
+ marginRight?: number;
1936
+ marginBottom?: number;
1937
+ marginLeft?: number;
1938
+ orientation?: 'portrait' | 'landscape';
1939
+ scope?: 'document' | 'section';
1940
+ };
1941
+ /** Remove the tab stop at this position (twips) from the current paragraph. */
1942
+ removeTabMark: {
1943
+ positionTwips: number;
1944
+ };
1945
+ /**
1946
+ * Replace one found match with `text`. Addressed by {@link TextMatch} rather than a
1947
+ * `DocTarget` because that is what `findMatches` hands back, and re-deriving a target
1948
+ * from it in the caller is where an off-by-one would come from. An empty `text`
1949
+ * deletes the match, which is what a find/replace dialog means by replacing with
1950
+ * nothing.
1951
+ */
1952
+ replaceMatch: {
1953
+ match: TextMatch;
1954
+ text: string;
1955
+ };
1956
+ /**
1957
+ * Replace EVERY match of `query` in one undoable step. Separate from looping
1958
+ * `replaceMatch` because each replacement shifts the offsets of the ones after it —
1959
+ * legacy applied its edits back-to-front for exactly this reason, and that ordering
1960
+ * belongs with whoever owns the offsets.
1961
+ */
1962
+ replaceAllMatches: {
1963
+ query: string;
1964
+ text: string;
1965
+ matchCase?: boolean;
1966
+ wholeWord?: boolean;
1967
+ };
1968
+ /**
1969
+ * How the selected image sits relative to text. `inline` flows in the line; the rest
1970
+ * are `wp:anchor` variants, with `squareLeft`/`squareRight` distinguishing which side
1971
+ * text wraps on. Legacy's vocabulary, unchanged.
1972
+ */
1973
+ setImageWrapType: {
1974
+ drawingNodeId?: string;
1975
+ expectedPackageRevision?: number;
1976
+ target: 'inline' | 'square' | 'squareLeft' | 'squareRight' | 'tight' | 'through' | 'topAndBottom' | 'behind' | 'inFront';
1977
+ /** Where an inline image sat, so promoting it to an anchor keeps its place. */
1978
+ initialPositionEmu?: {
1979
+ horizontalEmu: number;
1980
+ verticalEmu: number;
1981
+ };
1982
+ };
1983
+ /** Rotate or flip the selected image. Legacy composed these into a CSS transform. */
1984
+ transformImage: {
1985
+ drawingNodeId?: string;
1986
+ expectedPackageRevision?: number;
1987
+ action: 'rotateCW' | 'rotateCCW' | 'flipH' | 'flipV';
1988
+ };
1989
+ /** Anchor position of the selected floating image, from the position dialog. */
1990
+ setImagePosition: {
1991
+ drawingNodeId?: string;
1992
+ expectedPackageRevision?: number;
1993
+ horizontalEmu?: number;
1994
+ verticalEmu?: number;
1995
+ relativeToH?: string;
1996
+ relativeToV?: string;
1997
+ };
1998
+ /** Size, alt text, crop, position, and border of the selected image, from the properties dialog. */
1999
+ setImageProperties: {
2000
+ /** Expected drawing node id captured when the dialog opened. */
2001
+ drawingNodeId?: string;
2002
+ /** Package revision captured when the dialog opened. */
2003
+ expectedPackageRevision?: number;
2004
+ /** Selection anchor captured when the dialog opened. */
2005
+ selectionParagraphId?: string;
2006
+ /** Selection offset captured when the dialog opened. */
2007
+ selectionOffset?: number;
2008
+ widthEmu?: number;
2009
+ heightEmu?: number;
2010
+ alt?: string;
2011
+ title?: string;
2012
+ description?: string;
2013
+ hyperlink?: string | null;
2014
+ crop?: ImageCropPercent;
2015
+ resetToNaturalSize?: boolean;
2016
+ wrap?: ImageWrapTarget;
2017
+ horizontalEmu?: number;
2018
+ verticalEmu?: number;
2019
+ relativeToH?: string;
2020
+ relativeToV?: string;
2021
+ borderWidthEmu?: number;
2022
+ borderColor?: ColorValue;
2023
+ };
2024
+ /**
2025
+ * Insert a raster image at the caret as one package undo unit.
2026
+ *
2027
+ * `widthPoints`/`heightPoints` are the extent to insert AT MOST: Word's insert rule, an
2028
+ * extent that does not fit where the caret flows (its cell, column, or page content box)
2029
+ * is scaled down proportionally to fit. Read the committed extent back from
2030
+ * `snapshot().image` or `getSelectedImage()`; use `setImageProperties` to enlarge past
2031
+ * the fit afterwards.
2032
+ */
2033
+ /** Insert a rectangular body textbox and enter its text. */
2034
+ insertTextBox: Record<never, never>;
2035
+ insertImage: {
2036
+ data: Uint8Array;
2037
+ mime: SupportedImageMime;
2038
+ widthPoints: number;
2039
+ heightPoints: number;
2040
+ expectedPackageRevision?: number;
2041
+ title?: string;
2042
+ description?: string;
2043
+ hyperlink?: string;
2044
+ };
2045
+ /** Replace the selected picture's bytes as one package undo unit. */
2046
+ replaceImage: {
2047
+ data: Uint8Array;
2048
+ mime?: SupportedImageMime;
2049
+ drawingNodeId?: string;
2050
+ expectedPackageRevision?: number;
2051
+ };
2052
+ /** Delete the selected picture drawing as one package undo unit. */
2053
+ deleteImage: {
2054
+ drawingNodeId?: string;
2055
+ expectedPackageRevision?: number;
2056
+ };
2057
+ setWatermark: {
2058
+ watermark: Watermark | null;
2059
+ };
2060
+ /** Insert a generated, hyperlink-enabled TOC for heading levels 1–3 at the selection. */
2061
+ insertToc: Record<never, never>;
2062
+ /** Open options for the selected or context-clicked legacy text form. */
2063
+ editTextFormField: Record<never, never>;
2064
+ refreshToc: {
2065
+ tocId?: string;
2066
+ mode?: 'entire' | 'pageNumbers';
2067
+ };
2068
+ undo: Record<never, never>;
2069
+ redo: Record<never, never>;
2070
+ /**
2071
+ * Move the selection. Three accepted forms, and `can()` names all three when it refuses:
2072
+ * a collapsed paraId anchor, a range of two paraId anchors, or a semantic anchor/head pair.
2073
+ *
2074
+ * `{ anchor }` takes a {@link DocAnchor} rather than an {@link EditorPosition} because a
2075
+ * collapsed SEMANTIC position is spelled as a range whose anchor and head are equal, which
2076
+ * is what a caret already is.
2077
+ */
2078
+ setSelection: {
2079
+ anchor: DocAnchor;
2080
+ } | {
2081
+ range: EditorSelection;
2082
+ };
2083
+ /** Select the whole body. Word's Ctrl+A, as a command rather than only a keystroke. */
2084
+ selectAll: Record<never, never>;
2085
+ /**
2086
+ * Put the selected text on the clipboard. Reports `changed: false` — the document is
2087
+ * untouched.
2088
+ *
2089
+ * Refused at a collapsed selection: there is nothing to copy, and a live Copy row over an
2090
+ * empty selection silently no-ops.
2091
+ */
2092
+ copy: Record<never, never>;
2093
+ /**
2094
+ * Put the selected text on the clipboard and delete it. Refused at a collapsed selection,
2095
+ * and — unlike `copy` — in a read-only document.
2096
+ *
2097
+ * The clipboard write is dispatched but NOT awaited, and its failure does not fail the
2098
+ * command: the deletion has already happened by then, and reporting an edit as failed
2099
+ * because a clipboard write lost a race would be a lie about the document.
2100
+ */
2101
+ cut: Record<never, never>;
2102
+ /**
2103
+ * Insert the clipboard payload at the selection, replacing it.
2104
+ *
2105
+ * PAYLOAD COMES IN. `exec` is synchronous and reading the clipboard is not — it prompts
2106
+ * in Chrome and is refused outright by Firefox and Safari — so an engine-owned read
2107
+ * would have to either turn every command's result into a promise or lie about this
2108
+ * one's. The caller reads the clipboard inside the click or keystroke that asked for
2109
+ * the paste, which is where the permission gesture belongs, and hands the engine what
2110
+ * it read.
2111
+ *
2112
+ * `html`, when present, routes through the same fidelity order as the paste event:
2113
+ * an embedded fragment first, then the bounded external-HTML projection, then `text` —
2114
+ * degrading on any refusal. Without `html`, the plain lane inserts `text` with
2115
+ * newlines becoming real paragraph boundaries, as this command always has.
2116
+ */
2117
+ paste: {
2118
+ text: string;
2119
+ html?: string;
2120
+ };
2121
+ /**
2122
+ * Insert `text` as if typed, whatever richer flavours the clipboard held.
2123
+ *
2124
+ * The plain twin `paste` deliberately lacked while there was no rich lane; with one,
2125
+ * "paste" and "paste without formatting" are two different user intentions
2126
+ * (Cmd+V / Cmd+Shift+V) and each needs a name a menu row can call.
2127
+ */
2128
+ pasteWithoutFormatting: {
2129
+ text: string;
2130
+ };
2131
+ }
2132
+ /**
2133
+ * One command, as a discriminated union derived from {@link EditorCommands}.
2134
+ *
2135
+ * This is what `can` and `exec` take. Widening `EditorCommands` widens it automatically.
2136
+ */
2137
+ type EditorCommand = {
2138
+ [K in keyof EditorCommands]: {
2139
+ type: K;
2140
+ } & EditorCommands[K];
2141
+ }[keyof EditorCommands];
2142
+ /**
2143
+ * Every query the editor answers, keyed by name with its arguments as the value.
2144
+ *
2145
+ * Extends {@link DocQueries} with the reads that only mean something against a live, laid-out
2146
+ * document: the selection, its formatting, the table or hyperlink under the caret.
2147
+ */
2148
+ interface EditorQueries extends DocQueries {
2149
+ selection: Record<never, never>;
2150
+ selectionFormatting: Record<never, never>;
2151
+ tableContext: Record<never, never>;
2152
+ hyperlinkAt: {
2153
+ pos?: number;
2154
+ fallbackHref?: string;
2155
+ };
2156
+ selectedText: Record<never, never>;
2157
+ watermark: Record<never, never>;
2158
+ splitCellConfig: Record<never, never>;
2159
+ contentControlAt: {
2160
+ filter?: ContentControlFilter;
2161
+ };
2162
+ isInsideToc: {
2163
+ pos: number;
2164
+ };
2165
+ trackedChanges: Record<never, never>;
2166
+ }
2167
+ /**
2168
+ * One query, as a discriminated union derived from {@link EditorQueries}.
2169
+ *
2170
+ * This is what `query` takes; {@link EditorQueryResults} says what each answers.
2171
+ */
2172
+ type EditorQuery = {
2173
+ [K in keyof EditorQueries]: {
2174
+ type: K;
2175
+ } & EditorQueries[K];
2176
+ }[keyof EditorQueries];
2177
+ /** What each editor query returns. Keyed identically to `EditorQueries`. */
2178
+ interface EditorQueryResults extends DocQueryResults {
2179
+ selection: DocRange | null;
2180
+ selectionFormatting: RunFormatting | null;
2181
+ tableContext: TableContext | null;
2182
+ hyperlinkAt: HyperlinkInfo | null;
2183
+ selectedText: string;
2184
+ watermark: Watermark | null;
2185
+ splitCellConfig: {
2186
+ maxRows: number;
2187
+ maxCols: number;
2188
+ } | null;
2189
+ contentControlAt: ContentControlSummary | null;
2190
+ isInsideToc: boolean;
2191
+ trackedChanges: readonly Revision[];
2192
+ }
2193
+ /**
2194
+ * One occurrence of a search query in the document.
2195
+ *
2196
+ * Carries TWO addresses on purpose. `blockId` + `start` is the engine's own: stable
2197
+ * across edits and independent of ordering. `paragraphIndex` + `runIndex` + `runOffset`
2198
+ * is the positional one a find/replace UI needs to show and navigate results, and it is
2199
+ * derived from the same walk rather than left to the caller to reconstruct — a caller
2200
+ * guessing at run boundaries would send the selection to the wrong place.
2201
+ *
2202
+ * A match can span runs when formatting changes mid-word; the run address is where it
2203
+ * STARTS. `scope` identifies a non-body story so navigation opens the correct surface.
2204
+ * A frame scope selects its anchoring drawing and never places a caret inside its story.
2205
+ * A match inside a field result reports the field atom's model range. Its `length` is one,
2206
+ * while `text` carries the visible match and can be longer. Select with `start` and `length`.
2207
+ * Never derive the selected length from `text.length`.
2208
+ */
2209
+ interface TextMatch {
2210
+ readonly blockId: string;
2211
+ /** Character offset within the paragraph's concatenated run text. */
2212
+ readonly start: number;
2213
+ readonly length: number;
2214
+ /**
2215
+ * Paragraph ordinal within this match's story. Table and nested-table paragraphs count.
2216
+ * Non-paragraph blocks add no ordinal.
2217
+ */
2218
+ readonly paragraphIndex: number;
2219
+ /** Index of the run the match starts in, and the offset within that run. */
2220
+ readonly runIndex: number;
2221
+ readonly runOffset: number;
2222
+ /** Story containing the match. Absence means the body. */
2223
+ readonly scope?: ViewScope;
2224
+ /** The matched text as it appears in the document. */
2225
+ readonly text: string;
2226
+ /**
2227
+ * Paragraph text immediately before and after the match, bounded at the derivation
2228
+ * boundary. A results list shows the match in its sentence — "…as described in this
2229
+ * **Exhi**bit A" — and nothing else in the contract can reach paragraph text, so a
2230
+ * caller would otherwise have to re-read the document to render one row.
2231
+ *
2232
+ * Optional and additive: an implementation that has not derived them omits them, and a
2233
+ * consumer treats absent as empty.
2234
+ */
2235
+ readonly contextBefore?: string;
2236
+ readonly contextAfter?: string;
2237
+ }
2238
+ /**
2239
+ * The hyperlink under a position: where it points, how far it reaches, and what Word shows on
2240
+ * hover.
2241
+ *
2242
+ * `href` has already been through `sanitizeHref` — it comes from a file, so a `javascript:` or
2243
+ * `data:` target is dropped at the parse boundary rather than here.
2244
+ */
2245
+ interface HyperlinkInfo {
2246
+ readonly href: string;
2247
+ readonly range: DocRange;
2248
+ /**
2249
+ * `w:tooltip` on the `w:hyperlink` — the text Word shows on hover, and what the
2250
+ * hyperlink dialog seeds its tooltip field with when editing an existing link.
2251
+ */
2252
+ readonly tooltip?: string;
2253
+ }
2254
+ /**
2255
+ * Section page setup — size, orientation and margins, in twips — as `getPageSetup()`
2256
+ * and `snapshot().pageSetup` report it and the `setPageSetup` command writes it. In a
2257
+ * multi-section document this is the setup of the section the SELECTION is in, which
2258
+ * is what a ruler or a dialog reflects — Word's behaviour.
2259
+ */
2260
+ interface PageSetup {
2261
+ readonly pageWidthTwips: number;
2262
+ readonly pageHeightTwips: number;
2263
+ readonly orientation: 'portrait' | 'landscape';
2264
+ readonly marginsTwips: {
2265
+ readonly top: number;
2266
+ readonly right: number;
2267
+ readonly bottom: number;
2268
+ readonly left: number;
2269
+ };
2270
+ /** Binding gutter (`w:gutter`), folded into the left margin by layout. */
2271
+ readonly gutterTwips?: number;
2272
+ }
2273
+ /**
2274
+ * A read model of the current editor state, safe to hand to framework
2275
+ * rendering. Named `EditorSnapshot` rather than `EditorState` so it never
2276
+ * collides with an editing engine's own state type.
2277
+ */
2278
+ interface EditorSnapshot {
2279
+ readonly scope: EditorScope;
2280
+ /** Whether the editor is still waiting for a document: no bytes handed over yet, and no
2281
+ * parse failure. Bytes count from the moment they are supplied, not from the moment
2282
+ * pages paint, so this stays false across a detach and remount. Safe to gate a mount
2283
+ * point on — it never depends on one existing. */
2284
+ readonly isLoading: boolean;
2285
+ /**
2286
+ * Whether a supplied document is still on its way to painted pages. Opening a large
2287
+ * document mounts behind one painted frame so a loading screen can show instead of a
2288
+ * frozen page; this is true for exactly that window, and across it the previous
2289
+ * document (if any) stays on screen. Show a loading overlay while it holds — but gate
2290
+ * only chrome on it, never the mount point, which must stay mounted for the open to
2291
+ * complete ({@link EditorSnapshot.isLoading} is the gate-safe flag). Optional and
2292
+ * additive: absent means the implementation has not derived it, read as `false`.
2293
+ */
2294
+ readonly isOpening?: boolean;
2295
+ readonly parseError: string | null;
2296
+ /** Whether the loaded document is being edited: a patchable document opened in edit mode. A
2297
+ * read-only document (tables/SDTs/unpreservable) or `mode: 'view'` reports false. */
2298
+ readonly editable: boolean;
2299
+ readonly zoom: number;
2300
+ /**
2301
+ * Where {@link EditorSnapshot.zoom} came from.
2302
+ *
2303
+ * Both are needed, and neither implies the other: `zoom` is the resolved scale a ruler
2304
+ * multiplies by, `zoomMode` is what a zoom control has to show as selected. A menu that
2305
+ * ticked the entry matching the percentage would tick "75%" while the editor was tracking
2306
+ * the viewport and about to move off it.
2307
+ *
2308
+ * Optional and additive like `pageSetup`; absent means the implementation has not derived
2309
+ * it, and a consumer reads absent as a plain fixed scale.
2310
+ */
2311
+ readonly zoomMode?: ZoomMode;
2312
+ readonly selection: DocRange | null;
2313
+ /**
2314
+ * Whether the selection is a CARET rather than a range. `true` when nothing is loaded.
2315
+ *
2316
+ * Separate from `selection` because `DocRange` addresses paragraphs by paraId and carries
2317
+ * no offsets, so a caret and a range inside one paragraph are the same value there.
2318
+ * Answering this from `query({ type: 'selectedText' })` builds the whole selected string
2319
+ * to produce one bit, on every tick a host's selector runs.
2320
+ */
2321
+ readonly selectionCollapsed: boolean;
2322
+ readonly formatting: RunFormatting | null;
2323
+ readonly table: TableContext | null;
2324
+ /**
2325
+ * The table of contents the last right-click landed on, or null.
2326
+ *
2327
+ * NOT caret context, unlike `table`: a right-click leaves the selection where it was, and
2328
+ * a generated TOC refuses the caret outright, so a host's context menu could otherwise
2329
+ * never tell which table of contents it was opened over. Cleared by a right-click
2330
+ * anywhere else.
2331
+ */
2332
+ readonly tocContext: {
2333
+ readonly id: string;
2334
+ } | null;
2335
+ readonly image: ImageContext | null;
2336
+ readonly page: {
2337
+ readonly current: number;
2338
+ readonly total: number;
2339
+ };
2340
+ /**
2341
+ * Whether undo/redo have anything to apply, derived from the session's history.
2342
+ * Optional and additive: an implementation that has not derived them omits them,
2343
+ * and a consumer treats absent as `false` — the honest empty answer.
2344
+ */
2345
+ readonly canUndo?: boolean;
2346
+ readonly canRedo?: boolean;
2347
+ /**
2348
+ * The section's page setup, reference-stable across ticks that did not change it.
2349
+ * Optional and additive like `canUndo`: absent means the implementation has not
2350
+ * derived it, `null` means no document is loaded.
2351
+ */
2352
+ readonly pageSetup?: PageSetup | null;
2353
+ /**
2354
+ * Whether the review pane is showing its cards.
2355
+ *
2356
+ * In the SNAPSHOT because chrome reflects it: the toolbar's comments button is pressed
2357
+ * while it is open, and a button reads its pressed state from the snapshot like every
2358
+ * other button. Kept off the snapshot it stayed pressed after the pane closed, because a
2359
+ * value-equal snapshot correctly refuses to re-render.
2360
+ */
2361
+ readonly reviewPaneOpen?: boolean;
2362
+ /**
2363
+ * The review pane settings in force: every field of `ReviewPaneOptions`, such as when the
2364
+ * pane opens by itself and what it does when its card column does not fit. Change them with
2365
+ * `setReviewPaneOptions`. Never saved. Always
2366
+ * set: an editor without a review module reports `DEFAULT_REVIEW_PANE`.
2367
+ */
2368
+ readonly reviewPane: ResolvedReviewPane;
2369
+ /** Whether Show/Hide paragraph marks is enabled. */
2370
+ readonly showParagraphMarks?: boolean;
2371
+ /** The document's `w:documentProtection`, as the file states it; null with no document. */
2372
+ readonly documentProtection?: DocumentProtectionState | null;
2373
+ /** The displayed revision projection. The document and its revision history stay unchanged. */
2374
+ readonly reviewDisplayMode?: ReviewDisplayMode;
2375
+ /** Resolved local viewer preferences. Never saved into the document. */
2376
+ readonly revisionMarkup: ResolvedRevisionMarkup;
2377
+ /**
2378
+ * Whether the document carries review content — tracked changes or comment
2379
+ * anchors — independent of any registered review module.
2380
+ *
2381
+ * The free tier's honest signal: revisions render in their final-state
2382
+ * projection there, so without this a host cannot tell its user "this
2383
+ * document has tracked changes" — the one fact the upsell hint needs.
2384
+ * Optional and additive like `canUndo`; derived cheaply from store
2385
+ * vocabulary and memoized per revision.
2386
+ */
2387
+ readonly hasReviewContent?: boolean;
2388
+ /** Authors whose revisions currently render as accepted and whose comments stay hidden. */
2389
+ readonly hiddenReviewAuthors?: readonly string[];
2390
+ /**
2391
+ * Lifecycle of the attached collaboration replica, or `'inactive'` when no
2392
+ * collaboration module is registered.
2393
+ *
2394
+ * The free tier's honest upsell signal: a host can render from this value
2395
+ * without importing `@docx-editor.dev/pro`. When a module is registered the
2396
+ * field follows the session's `status()`.
2397
+ */
2398
+ readonly collaborationStatus: CollaborationStatus | 'inactive';
2399
+ /**
2400
+ * How edits are written right now.
2401
+ *
2402
+ * In the snapshot for the same reason `reviewPaneOpen` is: the editing-mode control shows
2403
+ * it, and a control reads what it shows from the snapshot like every other control.
2404
+ */
2405
+ readonly editingMode?: DocumentEditingMode;
2406
+ /**
2407
+ * Why the last edit was refused, or null.
2408
+ *
2409
+ * The engine knew — `lastRejection` has been on the surface all along — and nothing
2410
+ * published it, so a keystroke refused because the document is open for viewing, or
2411
+ * because suggesting has no author to attribute a proposal to, looked to the user like
2412
+ * the editor had simply stopped responding.
2413
+ */
2414
+ readonly lastRejection?: string | null;
2415
+ /**
2416
+ * Document font families that are NOT AVAILABLE: declared by the document, but with no byte
2417
+ * source admitted, no redirect to an admitted face, nothing embedded, and nothing the platform
2418
+ * could resolve. Chrome shows a compatibility notice from this the way Word does.
2419
+ *
2420
+ * A family the app answers with a metric-compatible stand-in — Word's Times New Roman
2421
+ * with Liberation Serif — is AVAILABLE and stays out: the outlines differ, the advance
2422
+ * widths do not, so wrap and pagination land where Word puts them. The face a `w:sym`
2423
+ * names (MS Gothic for a checkbox, Wingdings for a bullet) stays out too, because it
2424
+ * paints one code point rather than text, and has no metric twin an app could supply.
2425
+ *
2426
+ * Optional and additive like `canUndo`: absent means the implementation has not derived
2427
+ * it; empty means every family resolved (or no document is loaded).
2428
+ */
2429
+ readonly fontSubstitutions?: readonly string[];
2430
+ /**
2431
+ * Format painter arming, and the level of what it holds. Here for the same reason
2432
+ * `lastRejection` is: it moves no revision and no caret, so a mode the snapshot does not
2433
+ * carry is a mode no toolbar can reflect. Optional and additive.
2434
+ */
2435
+ readonly formatPainter?: FormatPainterSurfaceState;
2436
+ }
2437
+ /**
2438
+ * An error the engine raised, carrying a machine-readable `code` alongside the message.
2439
+ *
2440
+ * `code` is optional because an `Error` from deeper down (a parser, a codec) is surfaced as-is
2441
+ * rather than wrapped in a fabricated code.
2442
+ */
2443
+ interface EditorError extends Error {
2444
+ readonly code?: string;
2445
+ }
2446
+
2447
+ export { EditorFontError as E, cropPercentFromCropPermille as s, cropPercentFromPermille as t, cropPercentFromSourceCrop as u, cropPermilleFromCropPercent as v, cropPermilleFromPercent as w, sourceCropFromCropPercent as x, validateImageCropPercent as y };
2448
+ export type { EditorHighlights as $, AnchorHighlightOptions as A, TableBorderEdgeTarget as B, CanResult as C, DocumentSource as D, FontFaceRequest as F, TableBorderSpec as G, HighlightRange as H, ImageContext as I, TableBorderStyle as J, TableContext as K, AuthoredNoteNumbering as L, DocumentChange as M, DocumentEditingMode as N, DocumentHandle as O, EditorAnchorNavigation as P, EditorCommandShape as Q, ReviewItemHit as R, ScrollToAnchorOptions as S, TextMatch as T, EditorCommands as U, EditorError as V, EditorEvents as W, EditorFontErrorCode as X, EditorFormatPainterCommands as Y, ZoomMode as Z, EditorHeaderFooterCommands as _, FontConfiguration as a, EditorNoteCommands as a0, EditorPosition as a1, EditorQueries as a2, EditorQuery as a3, EditorQueryResults as a4, EditorReviewHits as a5, EditorSelection as a6, FormatPainterLevel as a7, FormatPainterMode as a8, FurnitureVariant as a9, ZoomFitTarget as aA, HeaderFooterSlotArgs as aa, HeaderFooterState as ab, HyperlinkInfo as ac, NoteKind as ad, NotePropertiesSide as ae, NotePropertiesState as af, PageSetup as ag, ResolveReviewChangesOptions as ah, ResolvedNoteNumbering as ai, ReviewActivationOptions as aj, ReviewChangesAttribution as ak, ReviewCommentPlacement as al, ReviewCustomPlacement as am, ReviewItemPlacement as an, ReviewItemPlacementBase as ao, ReviewItemQuery as ap, ReviewItemRevealEvent as aq, ReviewItemRevealSource as ar, ReviewRevisionPlacement as as, SetReviewChangesAuthorOptions as at, TableBorderTarget as au, TableCellVerticalAlignment as av, TableColumnDividerResizeTarget as aw, TableColumnOccurrenceTarget as ax, TableRightEdgeResizeTarget as ay, TableRowOccurrenceTarget as az, FontSource as b, FontSourceSubstitution as c, EditorSnapshot as d, EditorCommand as e, ClearAnchorHighlightOptions as f, ScrollPlacement as g, AnchorHighlightAnimation as h, Editor as i, HighlightResult as j, HighlightOptions as k, HighlightHit as l, HighlightRect as m, ImageCropPercent as n, ImageCropPermille as o, SelectedImageState as p, TrackedChangeFilterMode as q, TrackedChangePredicate as r, FormatPainterSurfaceState as z };