@arbidocs/blocks 0.4.100 → 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.
- package/dist/agents/index.cjs +207 -207
- package/dist/agents/index.js +2 -2
- package/dist/{chunk-NJX774HB.js → chunk-5NQIBJPP.js} +3 -3
- package/dist/{chunk-NJX774HB.js.map → chunk-5NQIBJPP.js.map} +1 -1
- package/dist/chunk-6MG62I5B.cjs +272 -0
- package/dist/chunk-6MG62I5B.cjs.map +1 -0
- package/dist/{chunk-NW3LFDZL.cjs → chunk-DDYXFALG.cjs} +3 -3
- package/dist/{chunk-NW3LFDZL.cjs.map → chunk-DDYXFALG.cjs.map} +1 -1
- package/dist/chunk-EQB3WELX.js +269 -0
- package/dist/chunk-EQB3WELX.js.map +1 -0
- package/dist/{chunk-B7P73VHX.cjs → chunk-FAGQTB3D.cjs} +30 -214
- package/dist/chunk-FAGQTB3D.cjs.map +1 -0
- package/dist/{chunk-6HZNFOHW.js → chunk-G5JH2YMQ.js} +3 -3
- package/dist/{chunk-6HZNFOHW.js.map → chunk-G5JH2YMQ.js.map} +1 -1
- package/dist/{chunk-72PQ42YI.js → chunk-MYALCKDR.js} +34 -217
- package/dist/chunk-MYALCKDR.js.map +1 -0
- package/dist/{chunk-O24WPHLD.cjs → chunk-Y5XW57U4.cjs} +5 -5
- package/dist/{chunk-O24WPHLD.cjs.map → chunk-Y5XW57U4.cjs.map} +1 -1
- package/dist/{chunk-E2QWWLK5.js → chunk-YGREW5TZ.js} +3 -3
- package/dist/{chunk-E2QWWLK5.js.map → chunk-YGREW5TZ.js.map} +1 -1
- package/dist/{chunk-IE55TWIG.cjs → chunk-ZT2EBBSC.cjs} +5 -5
- package/dist/{chunk-IE55TWIG.cjs.map → chunk-ZT2EBBSC.cjs.map} +1 -1
- package/dist/connect/docx.cjs +6 -6
- package/dist/connect/docx.js +4 -4
- package/dist/connect/index.cjs +3 -3
- package/dist/connect/index.js +2 -2
- package/dist/document-tools/AdoptSignatureDialog.d.ts +25 -0
- package/dist/document-tools/DocumentToolButtons.d.ts +2 -0
- package/dist/document-tools/SignatureRequestBanner.d.ts +18 -0
- package/dist/document-tools/index.cjs +175 -0
- package/dist/document-tools/index.cjs.map +1 -1
- package/dist/document-tools/index.d.ts +3 -1
- package/dist/document-tools/index.js +168 -3
- package/dist/document-tools/index.js.map +1 -1
- package/dist/document-tools/viewer/GuidedSigningViewer.d.ts +26 -0
- package/dist/document-tools/viewer/SignatureFieldsOverlay.d.ts +41 -0
- package/dist/document-tools/viewer/SignatureRequestEditor.d.ts +26 -0
- package/dist/document-tools/viewer/index.cjs +983 -0
- package/dist/document-tools/viewer/index.cjs.map +1 -1
- package/dist/document-tools/viewer/index.d.ts +3 -0
- package/dist/document-tools/viewer/index.js +983 -5
- package/dist/document-tools/viewer/index.js.map +1 -1
- package/dist/docx/NativeDocxEditor.d.ts +1 -1
- package/dist/docx/definitions/DefinedTerms.d.ts +1 -12
- package/dist/docx/definitions/commands.d.ts +3 -27
- package/dist/docx/index.cjs +35 -39
- package/dist/docx/index.d.ts +1 -1
- package/dist/docx/index.js +3 -3
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +1 -1
- package/dist/files/index.js +1 -1
- package/dist/home/index.cjs +1 -1
- package/dist/home/index.js +1 -1
- package/dist/index.cjs +253 -253
- package/dist/index.js +3 -3
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/studio/index.cjs +1 -1
- package/dist/studio/index.js +1 -1
- package/dist/workflow-canvas/index.cjs +9 -9
- package/dist/workflow-canvas/index.js +2 -2
- package/node_modules/@arbidocs/coedit/LICENSE +21 -0
- package/node_modules/@arbidocs/coedit/dist/encoding.cjs +751 -0
- package/node_modules/@arbidocs/coedit/dist/encoding.cjs.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/encoding.d.cts +192 -0
- package/node_modules/@arbidocs/coedit/dist/encoding.d.ts +192 -0
- package/node_modules/@arbidocs/coedit/dist/encoding.js +716 -0
- package/node_modules/@arbidocs/coedit/dist/encoding.js.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs +1759 -0
- package/node_modules/@arbidocs/coedit/dist/hocuspocus.cjs.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.cts +39 -0
- package/node_modules/@arbidocs/coedit/dist/hocuspocus.d.ts +39 -0
- package/node_modules/@arbidocs/coedit/dist/hocuspocus.js +1736 -0
- package/node_modules/@arbidocs/coedit/dist/hocuspocus.js.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/index.cjs +1692 -0
- package/node_modules/@arbidocs/coedit/dist/index.cjs.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/index.d.cts +16 -0
- package/node_modules/@arbidocs/coedit/dist/index.d.ts +16 -0
- package/node_modules/@arbidocs/coedit/dist/index.js +1664 -0
- package/node_modules/@arbidocs/coedit/dist/index.js.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/server.cjs +1852 -0
- package/node_modules/@arbidocs/coedit/dist/server.cjs.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/server.d.cts +43 -0
- package/node_modules/@arbidocs/coedit/dist/server.d.ts +43 -0
- package/node_modules/@arbidocs/coedit/dist/server.js +1822 -0
- package/node_modules/@arbidocs/coedit/dist/server.js.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.cts +82 -0
- package/node_modules/@arbidocs/coedit/dist/session-Cf9iu1Vt.d.ts +82 -0
- package/node_modules/@arbidocs/coedit/dist/template.cjs +1627 -0
- package/node_modules/@arbidocs/coedit/dist/template.cjs.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/template.d.cts +125 -0
- package/node_modules/@arbidocs/coedit/dist/template.d.ts +125 -0
- package/node_modules/@arbidocs/coedit/dist/template.js +1612 -0
- package/node_modules/@arbidocs/coedit/dist/template.js.map +1 -0
- package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.cts +8 -0
- package/node_modules/@arbidocs/coedit/dist/versions-DXiFQMA6.d.ts +8 -0
- package/node_modules/@arbidocs/coedit/package.json +68 -0
- package/node_modules/@docx-editor.dev/core/LICENSE +201 -0
- package/node_modules/@docx-editor.dev/core/README.md +125 -0
- package/node_modules/@docx-editor.dev/core/THIRD_PARTY_NOTICES.md +56 -0
- package/node_modules/@docx-editor.dev/core/dist/automation.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/automation.d.ts +162 -0
- package/node_modules/@docx-editor.dev/core/dist/automation.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/binding.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/binding.d.ts +164 -0
- package/node_modules/@docx-editor.dev/core/dist/binding.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-2GO5T2JU.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-2RC2EPND.js +3 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-4GBTELJV.cjs +28 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-4R3TEXMN.js +18 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-5CSUYANV.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-6APGXLBB.cjs +3 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-6AWEKBLB.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-6EYYL7FL.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-6JIJOZDW.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-BTQKU64Q.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-E7BQA6UP.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-EO4C5QJW.cjs +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-ETTO6GK3.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-FIJZIQXA.cjs +18 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-FRXAOVTB.js +28 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-J6BVWIDB.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-JGNVNT2A.cjs +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-K5U2PLDP.cjs +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-KKIJG3C6.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-LWDSDCMO.js +27 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-NBCVVZOM.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-O2AL2HSJ.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-O5INAWZQ.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-QMLCVPCD.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-RCHS4ZEH.cjs +27 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-RIYSCEFQ.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-S6J4O5XP.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-SRPILEWV.cjs +5 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-TSLBZ26X.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-UKVVUHZL.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-VDNNLG6X.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-VHAVHCQY.js +7 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-VX43VBAX.cjs +7 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-Z6WBFXJU.js +5 -0
- package/node_modules/@docx-editor.dev/core/dist/chunk-ZUHOMK52.cjs +2 -0
- package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.d.ts +270 -0
- package/node_modules/@docx-editor.dev/core/dist/collaboration/replication.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/collaboration.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/collaboration.d.ts +269 -0
- package/node_modules/@docx-editor.dev/core/dist/collaboration.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/document.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/document.d.ts +290 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/document.js +0 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/editor.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/editor.d.ts +22 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/editor.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.d.ts +103 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/interaction.js +0 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/modules.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/modules.d.ts +143 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/modules.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/types.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/types.d.ts +11 -0
- package/node_modules/@docx-editor.dev/core/dist/contracts/types.js +0 -0
- package/node_modules/@docx-editor.dev/core/dist/custom-node-writes-cvL5rhcD.d.ts +323 -0
- package/node_modules/@docx-editor.dev/core/dist/dist-PKZR6RSH.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/document-protection-BAGVGqaP.d.ts +20 -0
- package/node_modules/@docx-editor.dev/core/dist/editor-Ci7IZGmG.d.ts +2448 -0
- package/node_modules/@docx-editor.dev/core/dist/editor-scope-OHPwVQ5l.d.ts +84 -0
- package/node_modules/@docx-editor.dev/core/dist/editor.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/editor.css +15 -0
- package/node_modules/@docx-editor.dev/core/dist/editor.d.ts +1394 -0
- package/node_modules/@docx-editor.dev/core/dist/editor.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/export.cjs +2 -0
- package/node_modules/@docx-editor.dev/core/dist/export.d.ts +391 -0
- package/node_modules/@docx-editor.dev/core/dist/export.js +2 -0
- package/node_modules/@docx-editor.dev/core/dist/failure-NS2lsya4.d.ts +115 -0
- package/node_modules/@docx-editor.dev/core/dist/font-resolver-BVQB14qT.d.ts +256 -0
- package/node_modules/@docx-editor.dev/core/dist/harfbuzz.wasm +0 -0
- package/node_modules/@docx-editor.dev/core/dist/headless-document-view-qH331moE.d.ts +143 -0
- package/node_modules/@docx-editor.dev/core/dist/image-resources-BN-hUgCn.d.ts +211 -0
- package/node_modules/@docx-editor.dev/core/dist/index-Bsg7oIKP.d.ts +3869 -0
- package/node_modules/@docx-editor.dev/core/dist/index.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/index.d.ts +53 -0
- package/node_modules/@docx-editor.dev/core/dist/index.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/layout-shaping-BEyuiQOk.d.ts +246 -0
- package/node_modules/@docx-editor.dev/core/dist/layout.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/layout.d.ts +3151 -0
- package/node_modules/@docx-editor.dev/core/dist/layout.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/node-module-shim-TTKTT66I.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/note-properties-4Y9o6Gyk.d.ts +68 -0
- package/node_modules/@docx-editor.dev/core/dist/omml-equation-CuzBL5DD.d.ts +85 -0
- package/node_modules/@docx-editor.dev/core/dist/output.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/output.d.ts +97 -0
- package/node_modules/@docx-editor.dev/core/dist/output.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/protocol-Bqk4Izjc.d.ts +1651 -0
- package/node_modules/@docx-editor.dev/core/dist/review-pane-D9jm8DcY.d.ts +128 -0
- package/node_modules/@docx-editor.dev/core/dist/review-paragraph-order-DT-n6ouC.d.ts +85 -0
- package/node_modules/@docx-editor.dev/core/dist/revision-projection-DZ4kKVev.d.ts +242 -0
- package/node_modules/@docx-editor.dev/core/dist/semantic-cell-selection-D9D1KSXq.d.ts +464 -0
- package/node_modules/@docx-editor.dev/core/dist/semantic-interaction-CIC-PooQ.d.ts +135 -0
- package/node_modules/@docx-editor.dev/core/dist/semantic-paint-BME37OMv.d.ts +326 -0
- package/node_modules/@docx-editor.dev/core/dist/semantic-record-queries-CBlZqZNa.d.ts +177 -0
- package/node_modules/@docx-editor.dev/core/dist/semantic-records-4B3WwFAi.d.ts +3532 -0
- package/node_modules/@docx-editor.dev/core/dist/store.cjs +1 -0
- package/node_modules/@docx-editor.dev/core/dist/store.d.ts +2706 -0
- package/node_modules/@docx-editor.dev/core/dist/store.js +1 -0
- package/node_modules/@docx-editor.dev/core/dist/tree-package-fragment-BeeKxDw8.d.ts +1201 -0
- package/node_modules/@docx-editor.dev/core/dist/tree-session-contract-CVbmlMlq.d.ts +664 -0
- package/node_modules/@docx-editor.dev/core/dist/types-barrel-D3xCgQX6.d.ts +4269 -0
- package/node_modules/@docx-editor.dev/core/licenses/HarfBuzz-COPYING.txt +42 -0
- package/node_modules/@docx-editor.dev/core/package.json +140 -0
- package/node_modules/@docx-editor.dev/react/LICENSE +201 -0
- package/node_modules/@docx-editor.dev/react/README.md +141 -0
- package/node_modules/@docx-editor.dev/react/THIRD_PARTY_NOTICES.md +18 -0
- package/node_modules/@docx-editor.dev/react/dist/index.d.mts +4928 -0
- package/node_modules/@docx-editor.dev/react/dist/index.d.ts +4928 -0
- package/node_modules/@docx-editor.dev/react/dist/index.js +4 -0
- package/node_modules/@docx-editor.dev/react/dist/index.mjs +4 -0
- package/node_modules/@docx-editor.dev/react/package.json +74 -0
- package/node_modules/@docx-editor.dev/react/src/styles/editor.css +6 -0
- package/node_modules/@docx-editor.dev/react/src/styles/zIndex.ts +28 -0
- package/package.json +26 -15
- package/src/docx/README.md +2 -3
- package/dist/chunk-72PQ42YI.js.map +0 -1
- package/dist/chunk-B7P73VHX.cjs.map +0 -1
|
@@ -0,0 +1,3869 @@
|
|
|
1
|
+
import { W as TreeDocOp, co as TextFormFieldRange, cn as TextFormFieldOptions, au as Unsubscribe, E as ExecResult, ao as DrawingPositionInput, aM as DrawingTransform, A as ParagraphTabStop, y as IndentFormatting, z as ParagraphFlags, aB as ParagraphDisagreements, aj as DrawingTreeDocOp, at as SelectionPin, Q as OoxmlPackage, g as ReviewRevisionKind, an as ImageWrapTarget } from './types-barrel-D3xCgQX6.js';
|
|
2
|
+
import { k as FieldResultsMode, I as InsertImageInput, S as StoryScope, A as ApplyImagePropertiesInput, i as ImageIntentResult } from './tree-package-fragment-BeeKxDw8.js';
|
|
3
|
+
import { a as ImageDecodePort, S as SupportedImageMime } from './image-resources-BN-hUgCn.js';
|
|
4
|
+
import './document-protection-BAGVGqaP.js';
|
|
5
|
+
import { EditorModule, ReviewModuleContribution } from './contracts/modules.js';
|
|
6
|
+
import { D as DocumentSource, a as FontConfiguration, Z as ZoomMode, E as EditorFontError, i as Editor, e as EditorCommand, C as CanResult, p as SelectedImageState, z as FormatPainterSurfaceState, g as ScrollPlacement, r as TrackedChangePredicate, q as TrackedChangeFilterMode, F as FontFaceRequest, b as FontSource, I as ImageContext, B as TableBorderEdgeTarget, G as TableBorderSpec, J as TableBorderStyle, K as TableContext } from './editor-Ci7IZGmG.js';
|
|
7
|
+
import { e as RevisionMarkupOptions, a as ReviewDisplayMode, i as RevisionMarkupChromeHandlers, d as ResolvedRevisionMarkup } from './revision-projection-DZ4kKVev.js';
|
|
8
|
+
import { S as SemanticPosition, a as SemanticSelection, N as NavigationCommand } from './semantic-interaction-CIC-PooQ.js';
|
|
9
|
+
import { e as FontConfigurationFragment, g as FontResolver, i as MarkedFontResolver, f as FontResolutionRequest } from './font-resolver-BVQB14qT.js';
|
|
10
|
+
import { R as ReviewPaneOptions } from './review-pane-D9jm8DcY.js';
|
|
11
|
+
import { EditorCollaborationSession, CollaborationRemoteSelection, CollaborationModuleContribution } from './collaboration.js';
|
|
12
|
+
import { d as RevisionStyles, R as ReviewAuthorInfo, c as RevisionAuthorStyle, F as FieldShadingMode, f as DrawingPaintStrings } from './semantic-paint-BME37OMv.js';
|
|
13
|
+
import { b as ResolvedFootnoteProperties, R as ResolvedEndnoteProperties, A as AuthoredNoteProperties } from './note-properties-4Y9o6Gyk.js';
|
|
14
|
+
import { S as SemanticLayout, T as TextMeasurer, C as ContentControlBoundaryRecord } from './semantic-records-4B3WwFAi.js';
|
|
15
|
+
import { B as BookmarkIndex } from './custom-node-writes-cvL5rhcD.js';
|
|
16
|
+
import { C as CellSelection, S as SectionProperties } from './semantic-cell-selection-D9D1KSXq.js';
|
|
17
|
+
import { T as TreeDocxSessionView, a as TreeApplyResult } from './tree-session-contract-CVbmlMlq.js';
|
|
18
|
+
import { C as CollaborationStatus } from './failure-NS2lsya4.js';
|
|
19
|
+
import { V as ViewScope, b as EditorExecOptions } from './editor-scope-OHPwVQ5l.js';
|
|
20
|
+
import './contracts/document.js';
|
|
21
|
+
import './contracts/interaction.js';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* A blank document, freshly zipped per call (the caller may hand the
|
|
25
|
+
* bytes to a loader that takes ownership). Calibri 11pt and Word's Normal paragraph
|
|
26
|
+
* spacing are authored in `w:docDefaults`, Word's built-in style gallery in `styles.xml`,
|
|
27
|
+
* and US Letter geometry in the section. Word opens the saved file.
|
|
28
|
+
*
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
declare function blankDocumentBytes(): Uint8Array;
|
|
32
|
+
|
|
33
|
+
type TableCommandSelectionPolicy = {
|
|
34
|
+
readonly kind: 'preserveSelection';
|
|
35
|
+
} | {
|
|
36
|
+
readonly kind: 'adoptCommittedCaret';
|
|
37
|
+
};
|
|
38
|
+
type TableCommandPlan = {
|
|
39
|
+
readonly ok: true;
|
|
40
|
+
readonly ops: readonly TreeDocOp[];
|
|
41
|
+
readonly selection: TableCommandSelectionPolicy;
|
|
42
|
+
} | {
|
|
43
|
+
readonly ok: false;
|
|
44
|
+
readonly code: 'unsupported' | 'invalidArgs' | 'locked';
|
|
45
|
+
readonly reason: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
type NotePropertiesSlice = {
|
|
49
|
+
readonly resolved: ResolvedFootnoteProperties | ResolvedEndnoteProperties;
|
|
50
|
+
readonly documentAuthored?: AuthoredNoteProperties;
|
|
51
|
+
readonly sectionAuthored?: AuthoredNoteProperties;
|
|
52
|
+
};
|
|
53
|
+
type NotePropertiesStateSnapshot = {
|
|
54
|
+
readonly sectionIndex: number;
|
|
55
|
+
readonly footnote: NotePropertiesSlice;
|
|
56
|
+
readonly endnote: NotePropertiesSlice;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/** Priority of an editor-owned popup renderer. @public */
|
|
60
|
+
interface PopupChromeRegistrationOptions {
|
|
61
|
+
/** Use only when no manually registered renderer exists. */
|
|
62
|
+
readonly fallback?: boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A core-owned content-control value edit.
|
|
66
|
+
*
|
|
67
|
+
* `kind` names the widget that was pressed. A `checkbox` session carries the current state as
|
|
68
|
+
* `'true'` / `'false'` and expects the opposite (or the same) back through `apply`; the
|
|
69
|
+
* packaged pop-ups apply the toggle at once, so a host only sees it when it renders the
|
|
70
|
+
* widget itself. A `buildingBlockGallery` session is a list session: `items` are the
|
|
71
|
+
* glossary's blocks for the control's gallery, named by `w:docPartPr/w:name`, and `apply`
|
|
72
|
+
* takes a name. A `picture` session carries the control's drawing node id as `value` and
|
|
73
|
+
* takes new image bytes through `replaceImage`; `apply` refuses, since no text stands for an
|
|
74
|
+
* image.
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
interface ContentControlWidgetSession {
|
|
78
|
+
readonly controlId: string;
|
|
79
|
+
readonly kind: 'dropdown' | 'comboBox' | 'date' | 'checkbox' | 'picture' | 'buildingBlockGallery';
|
|
80
|
+
readonly items: readonly {
|
|
81
|
+
readonly displayText: string;
|
|
82
|
+
readonly value: string;
|
|
83
|
+
}[];
|
|
84
|
+
readonly value: string;
|
|
85
|
+
/** The editor's regional locale, for a date picker's month, weekday and first-day rules. */
|
|
86
|
+
readonly locale: string;
|
|
87
|
+
readonly anchor: HTMLElement | null;
|
|
88
|
+
readonly signal: AbortSignal;
|
|
89
|
+
canApply(): boolean;
|
|
90
|
+
apply(value: string): boolean;
|
|
91
|
+
cancel(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Picture sessions only: replace the control's image with these bytes. The engine sniffs
|
|
94
|
+
* the format (PNG, JPEG, GIF, BMP or WebP) and keeps the drawing's size. Resolves false
|
|
95
|
+
* when the bytes are not a supported image, the control no longer takes a write, or the
|
|
96
|
+
* document is open for viewing or suggesting. Cancellation during decoding prevents
|
|
97
|
+
* the commit; only one replacement may be pending for a session.
|
|
98
|
+
*/
|
|
99
|
+
replaceImage?(bytes: Uint8Array): Promise<boolean>;
|
|
100
|
+
}
|
|
101
|
+
/** Framework rendering for content-control value widgets. @public */
|
|
102
|
+
interface ContentControlWidgetChromeHandlers {
|
|
103
|
+
readonly onRequest?: (session: ContentControlWidgetSession) => void;
|
|
104
|
+
/**
|
|
105
|
+
* Session kinds this renderer takes. Defaults to `dropdown`, `comboBox`, `date` and
|
|
106
|
+
* `buildingBlockGallery` (the list-shaped sessions), so a renderer written for the pop-ups
|
|
107
|
+
* never receives a checkbox or picture press it does not expect. Include `'checkbox'` to
|
|
108
|
+
* take those presses too; the engine then leaves the toggle to `apply`, and a press nobody
|
|
109
|
+
* takes toggles the box as before. Include `'picture'` to own the image pick; a press nobody
|
|
110
|
+
* takes opens the engine's own file picker.
|
|
111
|
+
*/
|
|
112
|
+
readonly kinds?: readonly ContentControlWidgetSession['kind'][];
|
|
113
|
+
}
|
|
114
|
+
/** An invalid protected-field acknowledgement. @public */
|
|
115
|
+
interface InvalidTextFormFieldSession {
|
|
116
|
+
readonly type: 'number' | 'date';
|
|
117
|
+
readonly signal: AbortSignal;
|
|
118
|
+
/** Clear the unchanged invalid value, if the target still permits it. */
|
|
119
|
+
acknowledge(): void;
|
|
120
|
+
/** Dismiss without clearing the authored value. */
|
|
121
|
+
cancel(): void;
|
|
122
|
+
}
|
|
123
|
+
/** Framework rendering for invalid protected-field acknowledgements. @public */
|
|
124
|
+
interface InvalidTextFormFieldChromeHandlers {
|
|
125
|
+
readonly onRequest?: (session: InvalidTextFormFieldSession) => void;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** A core-owned options edit. Its signal aborts when the dialog must close. @public */
|
|
129
|
+
interface TextFormFieldDialogSession {
|
|
130
|
+
readonly field: TextFormFieldRange;
|
|
131
|
+
readonly signal: AbortSignal;
|
|
132
|
+
/** Whether the current target exists and permits editing. Draft validation happens on apply. */
|
|
133
|
+
canApply(): boolean;
|
|
134
|
+
/** Save one undoable edit. A refused write leaves the session open. */
|
|
135
|
+
apply(text: string, options: TextFormFieldOptions): boolean;
|
|
136
|
+
/** Close without changing the document. Safe to call more than once. */
|
|
137
|
+
cancel(): void;
|
|
138
|
+
}
|
|
139
|
+
/** Framework-owned presentation for core-owned Field Options sessions. @public */
|
|
140
|
+
interface TextFormFieldChromeHandlers {
|
|
141
|
+
readonly onRequest?: (session: TextFormFieldDialogSession) => void;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Receives the element that shows the loading indicator on the first page, while a large
|
|
146
|
+
* document lays out its remaining pages.
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* ```ts
|
|
150
|
+
* editor.setOpeningIndicatorHost({
|
|
151
|
+
* publish(element) {
|
|
152
|
+
* // Render your indicator into `element`, or remove it when `element` is null.
|
|
153
|
+
* },
|
|
154
|
+
* });
|
|
155
|
+
* ```
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
interface OpeningIndicatorHost {
|
|
160
|
+
/**
|
|
161
|
+
* Called with the indicator element when the first pages show, and with `null` when the
|
|
162
|
+
* remaining pages are laid out or the open is abandoned. The element is empty while a host
|
|
163
|
+
* is set: render the host's content into it. It is centered on the first page, at most 30%
|
|
164
|
+
* of the window height below the page top, and scrolls with the document.
|
|
165
|
+
*/
|
|
166
|
+
publish(element: HTMLElement | null): void;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* A hyperlink as the surface reports it: its identity, where it sits, and the SANITIZED
|
|
171
|
+
* target. `href: null` is an inert link — a refused scheme or a dangling relationship — which
|
|
172
|
+
* a UI shows and offers to edit but must never offer to open.
|
|
173
|
+
*/
|
|
174
|
+
interface SurfaceHyperlink {
|
|
175
|
+
/** Canonical node id of the `w:hyperlink`. */
|
|
176
|
+
readonly id: string;
|
|
177
|
+
readonly paragraphId: string;
|
|
178
|
+
/** UTF-16 range of the link's display text within its paragraph. */
|
|
179
|
+
readonly start: number;
|
|
180
|
+
readonly end: number;
|
|
181
|
+
readonly text: string;
|
|
182
|
+
readonly kind: 'external' | 'internal' | 'unresolved';
|
|
183
|
+
/** Sanitized projection: an absolute URL, `#anchor`, or null when inert. */
|
|
184
|
+
readonly href: string | null;
|
|
185
|
+
/** The authored target, for an editor to seed its input with. */
|
|
186
|
+
readonly authored: string;
|
|
187
|
+
readonly anchor?: string;
|
|
188
|
+
readonly tooltip?: string;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Reading and writing hyperlinks on the surface.
|
|
192
|
+
*
|
|
193
|
+
* Every href that leaves here has already been through `sanitizeHref` — targets come from files,
|
|
194
|
+
* so `javascript:`, `data:` and `vbscript:` are dropped at the parse boundary rather than trusted
|
|
195
|
+
* to be filtered by whoever renders them.
|
|
196
|
+
*/
|
|
197
|
+
interface HyperlinkOps {
|
|
198
|
+
/** Every link in the paragraph the caret is in. */
|
|
199
|
+
linksInCaretParagraph(): SurfaceHyperlink[];
|
|
200
|
+
/** The link the caret sits in, or null. */
|
|
201
|
+
linkAtCaret(): SurfaceHyperlink | null;
|
|
202
|
+
/**
|
|
203
|
+
* The FIELD link whose painted atom the caret sits on, or null.
|
|
204
|
+
*
|
|
205
|
+
* Separate from {@link linkAtCaret} on purpose: a `HYPERLINK` field is not a tree node, so
|
|
206
|
+
* the typed lane never returns one, and link-create must not mistake a field atom for an
|
|
207
|
+
* editable link. Resolved from the layout projection, boundary-inclusive.
|
|
208
|
+
*/
|
|
209
|
+
fieldLinkAtCaret(): SurfaceHyperlink | null;
|
|
210
|
+
/** The link with this node id, or null. */
|
|
211
|
+
linkById(linkId: string): SurfaceHyperlink | null;
|
|
212
|
+
/**
|
|
213
|
+
* Apply a link to the selection, or retarget the one the caret is already in.
|
|
214
|
+
*
|
|
215
|
+
* `text` replaces the display text when supplied. Returns whether anything committed;
|
|
216
|
+
* a refusal leaves the document exactly as it was.
|
|
217
|
+
*/
|
|
218
|
+
applyHyperlink(input: {
|
|
219
|
+
readonly url?: string;
|
|
220
|
+
readonly anchor?: string;
|
|
221
|
+
readonly text?: string;
|
|
222
|
+
readonly tooltip?: string;
|
|
223
|
+
}): boolean;
|
|
224
|
+
/** Take the link off the one at the caret (or a named one). Returns whether it committed. */
|
|
225
|
+
removeHyperlink(linkId?: string): boolean;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/** A click on a painted link, after native navigation was refused. */
|
|
229
|
+
interface HyperlinkActivation {
|
|
230
|
+
readonly link: SurfaceHyperlink;
|
|
231
|
+
/** The clicked line fragment's viewport rect, so a popover can be placed under it. */
|
|
232
|
+
readonly rect: {
|
|
233
|
+
readonly left: number;
|
|
234
|
+
readonly top: number;
|
|
235
|
+
readonly bottom: number;
|
|
236
|
+
readonly right: number;
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Moving the caret and the viewport: to a position, to a bookmark, or out to an external target.
|
|
241
|
+
*
|
|
242
|
+
* {@link SurfaceNavigation.openExternal} is THE external-activation call site, and it refuses
|
|
243
|
+
* anything but an already-sanitized href. Routing an authored target through some other path is
|
|
244
|
+
* how a document gets to choose where a click goes.
|
|
245
|
+
*/
|
|
246
|
+
interface SurfaceNavigation {
|
|
247
|
+
/** Snap to a semantic position using layout geometry, then place the caret there. */
|
|
248
|
+
goToPosition(position: {
|
|
249
|
+
paragraphId: string;
|
|
250
|
+
offset: number;
|
|
251
|
+
}): boolean;
|
|
252
|
+
/**
|
|
253
|
+
* Scroll a bookmark into view and place the caret at it. Answers false for a name no
|
|
254
|
+
* bookmark declares — an inert click, which is what Word does with a dangling anchor.
|
|
255
|
+
*/
|
|
256
|
+
goToBookmark(name: string): boolean;
|
|
257
|
+
/**
|
|
258
|
+
* THE external-activation call site. Refuses anything but a sanitized projection, so a
|
|
259
|
+
* caller cannot route an authored target through it by mistake.
|
|
260
|
+
*/
|
|
261
|
+
openExternal(href: string | null): boolean;
|
|
262
|
+
destroy(): void;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/** One addressable inline equation and its compact editable projection. */
|
|
266
|
+
interface SurfaceEquation {
|
|
267
|
+
readonly id: string;
|
|
268
|
+
readonly paragraphId: string;
|
|
269
|
+
readonly start: number;
|
|
270
|
+
readonly end: number;
|
|
271
|
+
readonly linear: string;
|
|
272
|
+
readonly fallbackText: string;
|
|
273
|
+
/** True when every source construct belongs to the editable subset. */
|
|
274
|
+
readonly supported: boolean;
|
|
275
|
+
}
|
|
276
|
+
/** A user click on one painted equation. */
|
|
277
|
+
interface EquationActivation {
|
|
278
|
+
readonly equation: SurfaceEquation;
|
|
279
|
+
readonly rect: {
|
|
280
|
+
readonly left: number;
|
|
281
|
+
readonly top: number;
|
|
282
|
+
readonly right: number;
|
|
283
|
+
readonly bottom: number;
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
/** Boundary-inclusive lookup, matching the hyperlink and field atom popovers. */
|
|
287
|
+
declare function equationAtPosition(equations: readonly SurfaceEquation[], position: SemanticPosition): SurfaceEquation | null;
|
|
288
|
+
type EquationAction = 'replace' | 'remove';
|
|
289
|
+
/** Engine-owned capability result for equation editing chrome. */
|
|
290
|
+
type EquationCanResult = {
|
|
291
|
+
readonly ok: true;
|
|
292
|
+
} | {
|
|
293
|
+
readonly ok: false;
|
|
294
|
+
readonly code: 'locked' | 'notFound' | 'unsupported';
|
|
295
|
+
readonly reason: string;
|
|
296
|
+
};
|
|
297
|
+
/** Surface equation reads and atomic replace/remove writes. */
|
|
298
|
+
interface EquationOps {
|
|
299
|
+
equationsInCaretParagraph(): SurfaceEquation[];
|
|
300
|
+
equationAtCaret(): SurfaceEquation | null;
|
|
301
|
+
equationById(equationId: string): SurfaceEquation | null;
|
|
302
|
+
/** Whether equation chrome can run an action, with the engine-owned refusal reason. */
|
|
303
|
+
can(equationId: string, action: EquationAction): EquationCanResult;
|
|
304
|
+
applyEquation(equationId: string, linear: string): boolean;
|
|
305
|
+
removeEquation(equationId: string): boolean;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Everything {@link createDocxEditor} accepts. Every field is optional.
|
|
310
|
+
*
|
|
311
|
+
* `container` is the one that changes the shape of the whole lifecycle: omitting it produces an
|
|
312
|
+
* instance that does no DOM work until `attach(el)`, which is what lets a provider own the editor
|
|
313
|
+
* before any component has rendered a mount point.
|
|
314
|
+
*
|
|
315
|
+
* @public
|
|
316
|
+
*/
|
|
317
|
+
interface DocxEditorConfig {
|
|
318
|
+
/**
|
|
319
|
+
* The element the paginated surface mounts into. The surface owns this subtree.
|
|
320
|
+
*
|
|
321
|
+
* Optional: an instance created WITHOUT a container stashes its document bytes and does
|
|
322
|
+
* no DOM work until `attach(el)` — the provider-first shape, where the editor exists
|
|
323
|
+
* before any component has rendered a mount point. With a container, the document mounts
|
|
324
|
+
* immediately at construction, exactly as before.
|
|
325
|
+
*/
|
|
326
|
+
container?: HTMLElement;
|
|
327
|
+
/**
|
|
328
|
+
* A document to load at construction: DOCX bytes, or `'blank'` for Word's blank
|
|
329
|
+
* template. A `DocumentHandle` cannot be re-opened (the handle is identity, not
|
|
330
|
+
* content), so passing one emits a typed `error` event rather than silently loading
|
|
331
|
+
* nothing. Omitting this mounts NO document, which is not the same as an empty one.
|
|
332
|
+
*/
|
|
333
|
+
document?: DocumentSource;
|
|
334
|
+
/**
|
|
335
|
+
* Font bytes for Word-accurate (HarfBuzz-shaped) line wrap and pagination. Omitted,
|
|
336
|
+
* layout falls back to a fixed-width estimate; fonts embedded in the document are
|
|
337
|
+
* wired in automatically either way. For Word's default faces (Calibri, Times New
|
|
338
|
+
* Roman, …) pass `await loadDefaultFonts()` from `@docx-editor.dev/fonts` — a bare
|
|
339
|
+
* fragment (`{ sources, substitutions }`) is accepted and composed with defaults, or
|
|
340
|
+
* merge several origins yourself with `composeFontConfiguration`. Sampled per load;
|
|
341
|
+
* failures degrade to the fixed measurer and report through `onFontError`.
|
|
342
|
+
*
|
|
343
|
+
* Pass a {@link FontResolver} instead to resolve ON DEMAND: the function is called once
|
|
344
|
+
* per load, after the document is parsed, with the families it actually declares, and
|
|
345
|
+
* only what it returns is loaded. A document naming nothing the resolver covers costs
|
|
346
|
+
* nothing. Note that a fetching resolver makes opening a document perform network
|
|
347
|
+
* requests — the engine never supplies one, so that stays your call.
|
|
348
|
+
*/
|
|
349
|
+
fonts?: FontConfiguration | FontConfigurationFragment | FontResolver;
|
|
350
|
+
author?: string;
|
|
351
|
+
/** BCP-47 locale for regional date input and generated labels; defaults to en-US. */
|
|
352
|
+
locale?: string;
|
|
353
|
+
/** Drawing and form-control UI labels; defaults to English when omitted. */
|
|
354
|
+
translate?: (key: string, params?: Record<string, string | number>) => string;
|
|
355
|
+
/**
|
|
356
|
+
* Capability modules to register — the seam `@docx-editor.dev/pro` plugs in
|
|
357
|
+
* through. Omitted, the editor runs the free tier: lossless round-trip,
|
|
358
|
+
* final-state revision rendering, review chrome disabled with the engine's
|
|
359
|
+
* reason. See {@link EditorModule}.
|
|
360
|
+
*/
|
|
361
|
+
modules?: readonly EditorModule[];
|
|
362
|
+
/**
|
|
363
|
+
* The mode the editor opens in — one prop, matching the toolbar's three-state pill.
|
|
364
|
+
*
|
|
365
|
+
* - `'edit'` — opens in editing, even when the document's `w:trackRevisions` asks for
|
|
366
|
+
* tracked changes; the reader still moves between modes from the toolbar.
|
|
367
|
+
* - `'suggesting'` — opens in suggesting. It needs what suggesting always needs — a
|
|
368
|
+
* review module and an {@link DocxEditorConfig.author} — and falls back to editing
|
|
369
|
+
* with the reason published when either is missing. A missing author is a host
|
|
370
|
+
* configuration error and is also reported once on the console; the editor enters
|
|
371
|
+
* suggesting as soon as {@link DocxEditorInstance.setAuthor} names one.
|
|
372
|
+
* - `'view'` — read-only: every mutating command through the facade is refused, and
|
|
373
|
+
* the toolbar cannot leave viewing.
|
|
374
|
+
* - Omitted — the DOCUMENT decides: a package carrying `w:trackRevisions` opens in
|
|
375
|
+
* suggesting, everything else in editing.
|
|
376
|
+
*/
|
|
377
|
+
mode?: 'edit' | 'view' | 'suggesting';
|
|
378
|
+
/**
|
|
379
|
+
* How painted tracked changes are coloured. Presentation only — nothing is serialised.
|
|
380
|
+
*
|
|
381
|
+
* - `'author'` (the DEFAULT) — every change takes its author's colour from the
|
|
382
|
+
* `--doc-review-author-N` ramp, by order of first appearance, as Word does. Restyle a
|
|
383
|
+
* slot under `.docx-editor` to change the ramp.
|
|
384
|
+
* - `'kind'` — insertions green, deletions red, so "added" and "removed" are what a
|
|
385
|
+
* glance tells apart, whoever proposed them.
|
|
386
|
+
* - {@link RevisionAuthorAssignments} — style the named authors; `others` decides
|
|
387
|
+
* whether the rest take the ramp (the default) or the kind colours.
|
|
388
|
+
*
|
|
389
|
+
* The opening value. In React this is authored declaratively — `DocxEditor.ColorByChangeType`
|
|
390
|
+
* and `DocxEditor.AuthorStyle` compose and apply it, seeding this config for the first
|
|
391
|
+
* paint — so React hosts never pass it by hand; it is the entry for headless hosts. Read
|
|
392
|
+
* the document's resolved roster with `getReviewAuthors`. Applies wherever revision
|
|
393
|
+
* markup paints: the full all-markup view needs a review module registered; without one
|
|
394
|
+
* the proposed view still marks surviving insertions.
|
|
395
|
+
*/
|
|
396
|
+
revisionStyles?: RevisionStyles;
|
|
397
|
+
/** Initial local revision presentation and tracking preferences. */
|
|
398
|
+
revisionMarkup?: RevisionMarkupOptions;
|
|
399
|
+
/** Initial review projection. Markup modes require a review module. */
|
|
400
|
+
reviewDisplayMode?: ReviewDisplayMode;
|
|
401
|
+
/**
|
|
402
|
+
* How the reader edits saved field results.
|
|
403
|
+
*
|
|
404
|
+
* - `'atomic'` (the DEFAULT) — every field is one unit: typing beside a field lands before
|
|
405
|
+
* or after it, and Backspace removes it whole.
|
|
406
|
+
* - `'editable'` — fields that show their saved result (DATE, TIME, MERGEFIELD, HYPERLINK
|
|
407
|
+
* display text, QUOTE, FILENAME, FILLIN, SEQ, and the save, print, and creation dates)
|
|
408
|
+
* accept typing, deletion, and selection inside the result. Fields the engine computes
|
|
409
|
+
* live (PAGE, NUMPAGES, REF, PAGEREF, DOCPROPERTY, and others) stay one unit.
|
|
410
|
+
*
|
|
411
|
+
* Editable results must be unnested. Simple fields inside complex field results are not
|
|
412
|
+
* supported in editable mode.
|
|
413
|
+
*
|
|
414
|
+
* Fixed for the instance. `'editable'` with a collaboration module throws a `TypeError`:
|
|
415
|
+
* shared paragraph text keeps every field one unit.
|
|
416
|
+
*/
|
|
417
|
+
fieldResults?: FieldResultsMode;
|
|
418
|
+
/** Override raster decode for insert/replace image commands; defaults to browser/headless. */
|
|
419
|
+
imageDecodePort?: ImageDecodePort;
|
|
420
|
+
/**
|
|
421
|
+
* The scale to open at, as a fixed number.
|
|
422
|
+
*
|
|
423
|
+
* Supplying one also picks the mode: an editor given a `zoom` and no `zoomMode` opens
|
|
424
|
+
* FIXED at that value and stays there. An embedder that pinned 100% keeps 100%.
|
|
425
|
+
*/
|
|
426
|
+
zoom?: number;
|
|
427
|
+
/**
|
|
428
|
+
* Where the scale comes from. Defaults to `'auto'` — fit the page width, between 50% and
|
|
429
|
+
* 100% — unless {@link DocxEditorConfig.zoom} is supplied, which means fixed.
|
|
430
|
+
*
|
|
431
|
+
* `'auto'` leaves a window wide enough for the sheet exactly where it is today and shrinks
|
|
432
|
+
* a narrower one instead of growing a horizontal scrollbar. Pass `{ type: 'fixed' }` for
|
|
433
|
+
* the old unconditional behaviour.
|
|
434
|
+
*/
|
|
435
|
+
zoomMode?: ZoomMode | 'auto';
|
|
436
|
+
onFontError?: (error: EditorFontError) => void;
|
|
437
|
+
/** Localized labels for table insertion furniture on the painted surface. */
|
|
438
|
+
tableInteractionLabel?: (key: 'table.insertRowBelow' | 'table.insertColumnRight') => string;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Which measurer the current document's layout runs on, and whether shaped resolution is
|
|
442
|
+
* still in flight. Returned by {@link DocxEditorInstance.fontMeasurement}.
|
|
443
|
+
*/
|
|
444
|
+
interface FontMeasurementState {
|
|
445
|
+
/** `fixed` estimates advance widths; `shaped` measures real font bytes with HarfBuzz. */
|
|
446
|
+
readonly measurer: 'fixed' | 'shaped';
|
|
447
|
+
/** True while font resolution for the current document is still running. */
|
|
448
|
+
readonly resolving: boolean;
|
|
449
|
+
/** The shaped measurer's identity (admitted face hashes); absent while fixed. */
|
|
450
|
+
readonly producer?: string;
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* The host chrome that answers the engine's hyperlink gestures.
|
|
454
|
+
*
|
|
455
|
+
* A CLICK on an external link and Ctrl/Cmd+K both mean "the user wants the link UI", and the
|
|
456
|
+
* engine deliberately does not know what that looks like. Registered rather than passed at
|
|
457
|
+
* construction because the chrome mounts after the editor does, and it survives a document
|
|
458
|
+
* reload — the surface is rebuilt, the handlers are not.
|
|
459
|
+
*/
|
|
460
|
+
interface HyperlinkChromeHandlers {
|
|
461
|
+
/** A plain click on an external or inert link: show the popover at `activation.rect`. */
|
|
462
|
+
readonly onPopover?: (activation: HyperlinkActivation) => void;
|
|
463
|
+
/** Ctrl/Cmd+K: open insert-or-edit for the selection. */
|
|
464
|
+
readonly onRequest?: () => void;
|
|
465
|
+
}
|
|
466
|
+
/** Host chrome that edits a clicked Office Math equation. */
|
|
467
|
+
interface EquationChromeHandlers {
|
|
468
|
+
readonly onPopover?: (activation: EquationActivation) => void;
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* The concrete facade type: the full `Editor` contract plus the instance-only surface.
|
|
472
|
+
*
|
|
473
|
+
* `surface`, `stateVersion`, `attach` and `detach` live HERE rather than on `Editor`:
|
|
474
|
+
* they are what a store binding and a mounting host need, not what document commands
|
|
475
|
+
* need. Production adapters program against `Editor` for everything else.
|
|
476
|
+
*/
|
|
477
|
+
interface DocxEditorInstance extends Editor {
|
|
478
|
+
/** Bumps on mount, detach, destroy, and document reload — guards async image intents. */
|
|
479
|
+
readonly mountGeneration: number;
|
|
480
|
+
/**
|
|
481
|
+
* The underlying paginated surface for harnesses and tests that need capabilities the
|
|
482
|
+
* contract does not carry yet (select-all, node-id addressed selection).
|
|
483
|
+
*/
|
|
484
|
+
readonly surface: PaginatedSurface | null;
|
|
485
|
+
/**
|
|
486
|
+
* Wire the host's hyperlink chrome to the engine's gestures — a click on an external
|
|
487
|
+
* link, and Ctrl/Cmd+K. Returns an unsubscribe that restores whatever was registered
|
|
488
|
+
* before, so a popover component can register in an effect and clean up in its teardown.
|
|
489
|
+
*
|
|
490
|
+
* Instance-only, like `surface`: it is what a MOUNTING host needs, not what a document
|
|
491
|
+
* command needs.
|
|
492
|
+
*/
|
|
493
|
+
setHyperlinkChrome(handlers: HyperlinkChromeHandlers): Unsubscribe;
|
|
494
|
+
/**
|
|
495
|
+
* Register local revision settings chrome. Disposal cancels its active sessions.
|
|
496
|
+
* Manual renderers take priority over fallback renderers. Pass null to use native chrome
|
|
497
|
+
* until disposal restores the previous registration.
|
|
498
|
+
*/
|
|
499
|
+
setRevisionMarkupChrome(handlers: RevisionMarkupChromeHandlers | null, options?: PopupChromeRegistrationOptions): Unsubscribe;
|
|
500
|
+
/** Register Field Options chrome. Disposal closes sessions owned by this registration. */
|
|
501
|
+
setTextFormFieldChrome(handlers: TextFormFieldChromeHandlers, options?: PopupChromeRegistrationOptions): Unsubscribe;
|
|
502
|
+
/** Register typed content-control widget chrome. */
|
|
503
|
+
setContentControlWidgetChrome(handlers: ContentControlWidgetChromeHandlers, options?: PopupChromeRegistrationOptions): Unsubscribe;
|
|
504
|
+
/** Register invalid protected-field acknowledgement chrome. */
|
|
505
|
+
setInvalidTextFormFieldChrome(handlers: InvalidTextFormFieldChromeHandlers, options?: PopupChromeRegistrationOptions): Unsubscribe;
|
|
506
|
+
/** Wire the host equation popover to painted equation clicks. */
|
|
507
|
+
setEquationChrome(handlers: EquationChromeHandlers): Unsubscribe;
|
|
508
|
+
/**
|
|
509
|
+
* Render the host's own component as the remote-caret label, or restore the default
|
|
510
|
+
* collaborator-name label with `null`. The engine keeps owning label geometry, class,
|
|
511
|
+
* and presence colour; the host owns the content of each published element.
|
|
512
|
+
*
|
|
513
|
+
* Instance-only, like `setHyperlinkChrome`: it is what a MOUNTING host needs. Tolerated
|
|
514
|
+
* before `attach` and after `detach` — the registration waits and applies on the next
|
|
515
|
+
* mount, and it survives a document reload the way the hyperlink chrome does.
|
|
516
|
+
*/
|
|
517
|
+
setRemoteCaretLabelHost(host: RemoteCaretLabelHost | null): void;
|
|
518
|
+
/**
|
|
519
|
+
* Render the host's own loading indicator on the first page while a large document lays out
|
|
520
|
+
* its remaining pages, or restore the packaged spinner with `null`. The engine keeps owning
|
|
521
|
+
* the element and its place on the page; the host owns its content.
|
|
522
|
+
*
|
|
523
|
+
* Instance-only, like `setRemoteCaretLabelHost`, and tolerated at any time: a host set
|
|
524
|
+
* before the open applies when the first pages show. `DocxEditor.Loading` with `overlay`
|
|
525
|
+
* registers one for you, so set this only when you build your own loading screen.
|
|
526
|
+
*
|
|
527
|
+
* @example
|
|
528
|
+
* ```ts
|
|
529
|
+
* editor.setOpeningIndicatorHost({
|
|
530
|
+
* publish(element) {
|
|
531
|
+
* element?.replaceChildren(document.createTextNode('Opening…'));
|
|
532
|
+
* },
|
|
533
|
+
* });
|
|
534
|
+
* ```
|
|
535
|
+
*/
|
|
536
|
+
setOpeningIndicatorHost(host: OpeningIndicatorHost | null): void;
|
|
537
|
+
/**
|
|
538
|
+
* Monotonic version of the observable editor state. Bumps whenever anything
|
|
539
|
+
* `snapshot()` reports could have moved — a committed change, a selection move, zoom,
|
|
540
|
+
* load success or failure, attach/detach, destroy. An external store (React's
|
|
541
|
+
* `useSyncExternalStore`) uses it as a cheap "did anything change" signal; `snapshot()`
|
|
542
|
+
* itself is cached per version and returns a stable reference between bumps.
|
|
543
|
+
*/
|
|
544
|
+
stateVersion(): number;
|
|
545
|
+
/**
|
|
546
|
+
* Which measurer the current document's layout runs on, and whether shaped
|
|
547
|
+
* resolution is still in flight — the honest "are wrap points Word-accurate yet?"
|
|
548
|
+
* readout a host shows instead of guessing. `fixed` with `resolving: false` is the
|
|
549
|
+
* steady state for a document with no usable font source (the documented zero-config
|
|
550
|
+
* fallback); `shaped` means HarfBuzz measurement over real font bytes. Changes bump
|
|
551
|
+
* `stateVersion()`.
|
|
552
|
+
*/
|
|
553
|
+
fontMeasurement(): FontMeasurementState;
|
|
554
|
+
/**
|
|
555
|
+
* Every author the review surface DRAWS, in Word's slot order, with the colour the review
|
|
556
|
+
* chrome draws them in. The discovery surface a legend or colour picker builds on —
|
|
557
|
+
* authors depend on the loaded file, so they cannot be known at configuration time.
|
|
558
|
+
*
|
|
559
|
+
* The colour is the author's, not the document's: under `'kind'` the painted text goes to
|
|
560
|
+
* the insertion/deletion colours while the cards keep these accents, so a legend built
|
|
561
|
+
* from this describes the rail rather than the page.
|
|
562
|
+
*
|
|
563
|
+
* BOTH HALVES OF REVIEW. Authors of tracked changes come first, numbered by where their
|
|
564
|
+
* first change appears; authors who only commented follow. One person therefore draws in
|
|
565
|
+
* one colour across their comments and their edits, which is what a reader assumes the
|
|
566
|
+
* moment they learn the pairing on either. The order puts commenters last so that adding
|
|
567
|
+
* a comment can never renumber a tracked change the painter has already drawn.
|
|
568
|
+
*
|
|
569
|
+
* The complete attached-document roster. A reviewer remains listed while this view hides
|
|
570
|
+
* their changes, so the reviewer menu can turn them on again. Empty while detached.
|
|
571
|
+
* Reference-stable between changes, so it is safe as a dependency; changes bump
|
|
572
|
+
* `stateVersion()`.
|
|
573
|
+
*/
|
|
574
|
+
getReviewAuthors(): readonly ReviewAuthorInfo[];
|
|
575
|
+
/** Whether this author's revisions and comments are shown in the current review view. */
|
|
576
|
+
isReviewAuthorVisible(author: string): boolean;
|
|
577
|
+
/**
|
|
578
|
+
* Show one author's markup, or render their revisions as accepted and hide their comments.
|
|
579
|
+
* This changes view state only. It does not apply tree operations or change saved bytes.
|
|
580
|
+
*/
|
|
581
|
+
setReviewAuthorVisible(author: string, visible: boolean): void;
|
|
582
|
+
/** Show or hide every reviewer in one layout pass. */
|
|
583
|
+
setAllReviewAuthorsVisible(visible: boolean): void;
|
|
584
|
+
/** Restore every reviewer to the shown state. */
|
|
585
|
+
showAllReviewAuthors(): void;
|
|
586
|
+
/**
|
|
587
|
+
* The presence colour the engine paints for one display name — the answer the remote
|
|
588
|
+
* caret label takes, so chrome built on this cannot disagree with the painted caret.
|
|
589
|
+
*
|
|
590
|
+
* A name the review roster draws takes its resolved colour, sanitized exactly as the
|
|
591
|
+
* paint sink sanitizes it: a declared colour the paint refuses falls to the author's
|
|
592
|
+
* ramp-slot token. Any other name takes the next slot from the engine's stable
|
|
593
|
+
* allocator, in first-resolution order, and keeps it for the session. While no document
|
|
594
|
+
* is attached this returns `'var(--doc-accent)'`, the same default the overlay CSS
|
|
595
|
+
* falls back to.
|
|
596
|
+
*/
|
|
597
|
+
presenceColorFor(name: string): string;
|
|
598
|
+
/**
|
|
599
|
+
* The live collaboration replica, or null when this editor is not in a room.
|
|
600
|
+
*
|
|
601
|
+
* Presence chrome reads it from here rather than being handed it: the editor already holds
|
|
602
|
+
* the session a `collaborationModule` contributed, so a host that threads it down to every
|
|
603
|
+
* avatar and caret consumer is passing something the tree below it can already see.
|
|
604
|
+
*/
|
|
605
|
+
collaborationSession(): EditorCollaborationSession | null;
|
|
606
|
+
/**
|
|
607
|
+
* The configured author used when a comment or reply omits an explicit author.
|
|
608
|
+
*
|
|
609
|
+
* @internal Review compose chrome uses this to draw an unfinished comment in the same
|
|
610
|
+
* author colour it will receive after commit.
|
|
611
|
+
*/
|
|
612
|
+
getConfiguredAuthor(): string | null;
|
|
613
|
+
/**
|
|
614
|
+
* Set the author for runtime editor state.
|
|
615
|
+
*
|
|
616
|
+
* Unlike the construction-time {@link DocxEditorConfig.author}, this value applies to every
|
|
617
|
+
* later comment, reply, and tracked change. It does not rewrite existing revisions. The value
|
|
618
|
+
* survives document reloads and font remounts. An empty or whitespace value clears the author,
|
|
619
|
+
* after which suggesting refuses writes with its existing reason.
|
|
620
|
+
*
|
|
621
|
+
* Naming an author also completes a request for suggesting that was refused for want of
|
|
622
|
+
* one — a `mode: 'suggesting'` or a document's `w:trackRevisions` that opened in editing —
|
|
623
|
+
* unless the reader has chosen a mode since.
|
|
624
|
+
*
|
|
625
|
+
* @public
|
|
626
|
+
*/
|
|
627
|
+
setAuthor(author: string | undefined): void;
|
|
628
|
+
/**
|
|
629
|
+
* Set the host editing mode without rebuilding the editor.
|
|
630
|
+
*
|
|
631
|
+
* This has the same meaning as {@link DocxEditorConfig.mode}. Passing `undefined` lets the
|
|
632
|
+
* document's tracking settings select the mode again. A host change clears the reader's
|
|
633
|
+
* toolbar choice, so a later document reload can adopt `w:trackRevisions` again.
|
|
634
|
+
*
|
|
635
|
+
* @public
|
|
636
|
+
*/
|
|
637
|
+
setMode(mode: 'edit' | 'view' | 'suggesting' | undefined): void;
|
|
638
|
+
/**
|
|
639
|
+
* Set the drawing and form-control label resolver without rebuilding the editor.
|
|
640
|
+
* Open dialogs preserve their controls and input; later surface mounts use the same resolver.
|
|
641
|
+
*
|
|
642
|
+
* @public
|
|
643
|
+
*/
|
|
644
|
+
setTranslate(translate: ((key: string, params?: Record<string, string | number>) => string) | undefined): void;
|
|
645
|
+
/**
|
|
646
|
+
* Set regional date input and generated labels without rebuilding the editor.
|
|
647
|
+
* Stored dates are preserved; an in-progress field edit retains its starting locale.
|
|
648
|
+
* Omitted, invalid, and unsupported locales use en-US. Translation catalogues fall back by language.
|
|
649
|
+
*
|
|
650
|
+
* @public
|
|
651
|
+
*/
|
|
652
|
+
setLocale(locale: string | undefined): void;
|
|
653
|
+
/**
|
|
654
|
+
* The style declared for one author, whether or not the SURFACE has published them yet —
|
|
655
|
+
* so review chrome can draw a card the rail is holding before the roster catches up.
|
|
656
|
+
*
|
|
657
|
+
* {@link DocxEditorInstance.getReviewAuthors} answers for every author of a tracked
|
|
658
|
+
* change or a comment, so this is a narrow fallback rather than the way to reach a
|
|
659
|
+
* commenter.
|
|
660
|
+
*
|
|
661
|
+
* @internal The seam `@docx-editor.dev/pro`'s review rail resolves those authors
|
|
662
|
+
* through. A consumer reads `useReviewAuthor` (pro) or `useReviewAuthors` (react)
|
|
663
|
+
* instead; nothing here answers a question those two do not.
|
|
664
|
+
*/
|
|
665
|
+
getReviewAuthorStyle(author: string): RevisionAuthorStyle | undefined;
|
|
666
|
+
/**
|
|
667
|
+
* Replace how tracked changes are coloured, live. Paint-level: pages repaint without a
|
|
668
|
+
* layout pass, and the caret, selection and undo history stay where they are. Pass
|
|
669
|
+
* `'author'` to restore the default, or `'kind'` to opt out to the green/red
|
|
670
|
+
* rendering. Survives a document reload.
|
|
671
|
+
*
|
|
672
|
+
* The imperative PRIMITIVE beneath React's declarative lane: `DocxEditor.ColorByChangeType`
|
|
673
|
+
* and `DocxEditor.AuthorStyle` drive this seam, and React hosts declare those instead
|
|
674
|
+
* of calling it. Call it directly from headless and non-React hosts.
|
|
675
|
+
*/
|
|
676
|
+
setRevisionStyles(styles: RevisionStyles): void;
|
|
677
|
+
/** Merge local preferences and emit revisionMarkupChange after a change.
|
|
678
|
+
* Invalid settings throw TypeError without changing the previous settings.
|
|
679
|
+
*/
|
|
680
|
+
setRevisionMarkup(options: RevisionMarkupOptions): void;
|
|
681
|
+
/**
|
|
682
|
+
* Change the review pane settings: every field of `ReviewPaneOptions`, such as when the
|
|
683
|
+
* pane opens by itself and what it does when its card column does not fit. An omitted
|
|
684
|
+
* field keeps its value. Read the settings in force
|
|
685
|
+
* from `snapshot().reviewPane`. They stay in force across `load()` and are never saved into
|
|
686
|
+
* the document. This sets how the pane behaves; to open or close the pane itself, use
|
|
687
|
+
* `useReview().setPaneOpen` or the `toggleReviewPane` command.
|
|
688
|
+
*
|
|
689
|
+
* Returns `changed: false` on success, like every view-only call, because `changed` answers
|
|
690
|
+
* for the document; to detect a settings change, compare the `snapshot().reviewPane`
|
|
691
|
+
* reference, which changes only when a setting changes. Refused with `unsupported` when no review module is registered, and
|
|
692
|
+
* with `invalidArgs` for an unknown field or value. A refusal changes nothing.
|
|
693
|
+
*
|
|
694
|
+
* @example
|
|
695
|
+
* ```ts
|
|
696
|
+
* const result = editor.setReviewPaneOptions({ opening: 'manual', overflow: 'shrinkPage' });
|
|
697
|
+
* if (!result.ok) console.warn(result.reason);
|
|
698
|
+
* ```
|
|
699
|
+
*/
|
|
700
|
+
setReviewPaneOptions(options: ReviewPaneOptions): ExecResult;
|
|
701
|
+
/**
|
|
702
|
+
* Mount into `el`. If the instance holds pending document bytes (created without a
|
|
703
|
+
* container, or previously detached), they mount now — under the shaped measurer when
|
|
704
|
+
* fonts have resolved in the meantime. Attaching while already mounted elsewhere moves
|
|
705
|
+
* the live content via `session.save()`.
|
|
706
|
+
*
|
|
707
|
+
* HONEST COSTS: a mount from bytes is a fresh session — the undo stack and the caret do
|
|
708
|
+
* not survive re-attach (the same cost as the async font remount). After `destroy()`
|
|
709
|
+
* this is a no-op that emits a typed `error` event: a destroyed instance never remounts.
|
|
710
|
+
*/
|
|
711
|
+
attach(el: HTMLElement): void;
|
|
712
|
+
/**
|
|
713
|
+
* Tear down the painted surface, stashing the CURRENT document bytes
|
|
714
|
+
* (`session.save()`) so a later `attach` restores the content — but not the undo stack
|
|
715
|
+
* or the caret. No-op when already detached or destroyed.
|
|
716
|
+
*/
|
|
717
|
+
detach(): void;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
/** Which of the eight resize handles a drag started from, by compass direction. */
|
|
721
|
+
type ImageResizeHandle = 'n' | 'ne' | 'e' | 'se' | 's' | 'sw' | 'w' | 'nw';
|
|
722
|
+
/** EMUs per point. DrawingML stores extents in EMU; layout works in points. */
|
|
723
|
+
declare const EMU_PER_POINT = 12700;
|
|
724
|
+
/** Points to EMU, rounded — EMUs are integral in the file. */
|
|
725
|
+
declare function pointsToEmu(points: number): number;
|
|
726
|
+
/** EMU to points. Unrounded, so overlay geometry keeps sub-point precision during a drag. */
|
|
727
|
+
declare function emuToOverlayPoints(emu: number): number;
|
|
728
|
+
/**
|
|
729
|
+
* The extent a resize drag produces, in EMU.
|
|
730
|
+
*
|
|
731
|
+
* Computed from the drag's START extent rather than the previous frame's, so a drag that reverses
|
|
732
|
+
* direction lands exactly where it began instead of accumulating rounding error.
|
|
733
|
+
*
|
|
734
|
+
* `preserveAspect` behaves the way Word's handles do: a corner handle scales by whichever axis
|
|
735
|
+
* moved further, while an edge handle drives the other axis from the original ratio. Both axes
|
|
736
|
+
* are floored at one point, so a drag past the opposite edge cannot invert the image.
|
|
737
|
+
*/
|
|
738
|
+
declare function computeResizedImageExtentEmu(startWidthEmu: number, startHeightEmu: number, handle: ImageResizeHandle, deltaWidthPt: number, deltaHeightPt: number, preserveAspect: boolean): {
|
|
739
|
+
readonly cx: number;
|
|
740
|
+
readonly cy: number;
|
|
741
|
+
};
|
|
742
|
+
/**
|
|
743
|
+
* The position a move drag produces, preserving the anchoring the file already used.
|
|
744
|
+
*
|
|
745
|
+
* A `frame`-mode position keeps its `relativeToH`/`relativeToV` bases and only shifts the offsets
|
|
746
|
+
* it actually had — writing an offset the file omitted would re-anchor the drawing to a different
|
|
747
|
+
* reference and move it somewhere the drag never pointed.
|
|
748
|
+
*/
|
|
749
|
+
declare function computeMovedImagePosition(start: DrawingPositionInput, deltaXPt: number, deltaYPt: number): DrawingPositionInput;
|
|
750
|
+
|
|
751
|
+
type ImageMutationPreconditions = Readonly<{
|
|
752
|
+
mountGeneration: number;
|
|
753
|
+
packageRevision: number;
|
|
754
|
+
drawingNodeId: string | null;
|
|
755
|
+
selectionParagraphId: string;
|
|
756
|
+
selectionOffset: number;
|
|
757
|
+
}>;
|
|
758
|
+
/**
|
|
759
|
+
* The selected image and what may be done to it, or null when nothing image-like is selected.
|
|
760
|
+
*
|
|
761
|
+
* Unsupported placeholders, hidden drawings, and select-locked drawings cannot be selected.
|
|
762
|
+
*/
|
|
763
|
+
declare function selectedImageStateOf(surface: PaginatedSurface | null): SelectedImageState | null;
|
|
764
|
+
/**
|
|
765
|
+
* Snapshot the state an image mutation was planned against: mount generation, package revision,
|
|
766
|
+
* and the selection anchor.
|
|
767
|
+
*
|
|
768
|
+
* Taken at the START of a drag so the commit can be checked against it with
|
|
769
|
+
* {@link isStaleImageInteractionCommit}. A pointer gesture spans many frames, and a document that
|
|
770
|
+
* moved underneath it must not have the gesture's final coordinates applied to it.
|
|
771
|
+
*/
|
|
772
|
+
declare function captureImageMutationPreconditions(editor: Pick<DocxEditorInstance, 'surface' | 'mountGeneration'>): ImageMutationPreconditions | null;
|
|
773
|
+
/**
|
|
774
|
+
* Whether an insert or replace would be accepted — the `can` half of the can-before-exec pair.
|
|
775
|
+
*
|
|
776
|
+
* Refuses in suggesting mode, since an image property edit has no tracked-change representation.
|
|
777
|
+
*/
|
|
778
|
+
declare function canExecuteImageCommand(command: Extract<EditorCommand, {
|
|
779
|
+
type: 'insertImage' | 'replaceImage';
|
|
780
|
+
}>, surface: PaginatedSurface | null): CanResult;
|
|
781
|
+
/**
|
|
782
|
+
* Run an insert or replace, re-checking the same gates {@link canExecuteImageCommand} applies.
|
|
783
|
+
*
|
|
784
|
+
* Async because image bytes must be decoded to derive their natural extent before the drawing can
|
|
785
|
+
* be projected — the one editor command that cannot complete synchronously.
|
|
786
|
+
*/
|
|
787
|
+
declare function executeImageCommand(editor: DocxEditorInstance, command: Extract<EditorCommand, {
|
|
788
|
+
type: 'insertImage' | 'replaceImage';
|
|
789
|
+
}>): Promise<ExecResult>;
|
|
790
|
+
/** How far one arrow-key press nudges a selected image, in points. */
|
|
791
|
+
declare const IMAGE_OVERLAY_NUDGE_PT = 1;
|
|
792
|
+
/** How far Shift+arrow nudges a selected image, in points. */
|
|
793
|
+
declare const IMAGE_OVERLAY_NUDGE_SHIFT_PT = 10;
|
|
794
|
+
/**
|
|
795
|
+
* One in-flight image drag: where it started, and everything needed to decide at commit time
|
|
796
|
+
* whether the document still describes what the gesture was planned against.
|
|
797
|
+
*
|
|
798
|
+
* Both revisions are captured because they move independently — layout can re-flow without the
|
|
799
|
+
* package changing, and vice versa.
|
|
800
|
+
*/
|
|
801
|
+
interface ImageInteractionSession {
|
|
802
|
+
readonly drawingNodeId: string;
|
|
803
|
+
readonly startBounds: {
|
|
804
|
+
readonly x: number;
|
|
805
|
+
readonly y: number;
|
|
806
|
+
readonly width: number;
|
|
807
|
+
readonly height: number;
|
|
808
|
+
};
|
|
809
|
+
readonly startWidthEmu: number;
|
|
810
|
+
readonly startHeightEmu: number;
|
|
811
|
+
readonly startPosition: DrawingPositionInput | null;
|
|
812
|
+
readonly anchorFrameOrigin: {
|
|
813
|
+
readonly x: number;
|
|
814
|
+
readonly y: number;
|
|
815
|
+
} | null;
|
|
816
|
+
readonly transform: DrawingTransform;
|
|
817
|
+
readonly mode: 'move' | 'resize';
|
|
818
|
+
readonly handle: ImageResizeHandle | null;
|
|
819
|
+
readonly preconditions: ImageMutationPreconditions;
|
|
820
|
+
readonly layoutRevision: number;
|
|
821
|
+
readonly packageRevision: number;
|
|
822
|
+
readonly kind: 'inline' | 'anchored';
|
|
823
|
+
}
|
|
824
|
+
/**
|
|
825
|
+
* How an image drag scrolls the page when it reaches the viewport edge.
|
|
826
|
+
*
|
|
827
|
+
* Returns the delta ACTUALLY applied rather than the one requested, because a drag at the end of
|
|
828
|
+
* the document cannot scroll further and the overlay must not move the image by a distance the
|
|
829
|
+
* page did not travel.
|
|
830
|
+
*/
|
|
831
|
+
interface ImageOverlayScrollPort {
|
|
832
|
+
/** Scroll by a preview delta and return the actual applied document-space delta in points. */
|
|
833
|
+
scrollBy(deltaY: number): number;
|
|
834
|
+
}
|
|
835
|
+
/**
|
|
836
|
+
* The painted geometry of the selected drawing, plus what the overlay is allowed to do to it.
|
|
837
|
+
*
|
|
838
|
+
* Carries BOTH the painted rect (points, for hit-testing and handle placement) and the stored
|
|
839
|
+
* extent (EMU, for writing back), so the overlay never has to convert between the two spaces to
|
|
840
|
+
* decide what it is looking at.
|
|
841
|
+
*/
|
|
842
|
+
interface SelectedDrawingOverlayTarget {
|
|
843
|
+
/** Keep the text area available for pointer editing through the frame. */
|
|
844
|
+
readonly textbox?: boolean;
|
|
845
|
+
readonly id: string;
|
|
846
|
+
readonly pageIndex: number;
|
|
847
|
+
readonly x: number;
|
|
848
|
+
readonly y: number;
|
|
849
|
+
readonly width: number;
|
|
850
|
+
readonly height: number;
|
|
851
|
+
readonly kind: 'inline' | 'anchored';
|
|
852
|
+
readonly widthEmu: number;
|
|
853
|
+
readonly heightEmu: number;
|
|
854
|
+
readonly position: DrawingPositionInput | null;
|
|
855
|
+
readonly anchorFrameOrigin: {
|
|
856
|
+
readonly x: number;
|
|
857
|
+
readonly y: number;
|
|
858
|
+
} | null;
|
|
859
|
+
readonly transform: DrawingTransform;
|
|
860
|
+
readonly canResize: boolean;
|
|
861
|
+
readonly canMove: boolean;
|
|
862
|
+
/** Hard lock from `noChangeAspect` — never overridden by Shift. */
|
|
863
|
+
readonly aspectLocked: boolean;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* The painted geometry of the selected drawing, for the resize/move overlay — or null.
|
|
867
|
+
*
|
|
868
|
+
* Stricter than {@link selectedImageStateOf}: it also requires a COLLAPSED selection, because a
|
|
869
|
+
* range that merely contains a drawing is a text selection, and drawing handles over it would
|
|
870
|
+
* claim an object the user did not single out.
|
|
871
|
+
*/
|
|
872
|
+
declare function selectedDrawingOverlayTargetOf(surface: PaginatedSurface | null): SelectedDrawingOverlayTarget | null;
|
|
873
|
+
/**
|
|
874
|
+
* Whether a drag's commit should be refused because the document moved under it — the refusal to
|
|
875
|
+
* return, or null when the commit is still valid.
|
|
876
|
+
*
|
|
877
|
+
* Checks the mount generation and both revisions captured by
|
|
878
|
+
* {@link captureImageMutationPreconditions}. A gesture spans many frames, so this is the one
|
|
879
|
+
* place that decides its coordinates still describe the document they were measured against.
|
|
880
|
+
*/
|
|
881
|
+
declare function isStaleImageInteractionCommit(editor: Pick<DocxEditorInstance, 'surface' | 'mountGeneration'>, session: ImageInteractionSession): ExecResult | null;
|
|
882
|
+
|
|
883
|
+
/** Points → CSS pixels at the given zoom (matches `mountPaginatedSurface` / semantic paint). */
|
|
884
|
+
declare function surfacePaintScale(zoom: number): number;
|
|
885
|
+
/** Layout points to CSS pixels. Pair with {@link surfacePaintScale} for the current zoom. */
|
|
886
|
+
declare function layoutPointsToCssPixels(points: number, paintScale: number): number;
|
|
887
|
+
/** CSS pixels back to layout points — what a pointer event's coordinates must go through. */
|
|
888
|
+
declare function cssPixelsToLayoutPoints(pixels: number, paintScale: number): number;
|
|
889
|
+
/**
|
|
890
|
+
* What an overlay needs to place itself over the painted pages: the zoom scale, and where each
|
|
891
|
+
* page sits horizontally.
|
|
892
|
+
*
|
|
893
|
+
* Per-page X offsets rather than one origin, because pages are centred independently and a
|
|
894
|
+
* narrower page in a mixed-size document does not start where its neighbours do.
|
|
895
|
+
*/
|
|
896
|
+
interface SurfaceOverlayCoordinates {
|
|
897
|
+
readonly paintScale: number;
|
|
898
|
+
readonly pageOffsetX: ReadonlyMap<number, number>;
|
|
899
|
+
}
|
|
900
|
+
/** A rectangle in one page's content frame, in layout points. */
|
|
901
|
+
interface OverlayFrameRect {
|
|
902
|
+
readonly pageIndex: number;
|
|
903
|
+
readonly x: number;
|
|
904
|
+
readonly y: number;
|
|
905
|
+
readonly width: number;
|
|
906
|
+
readonly height: number;
|
|
907
|
+
}
|
|
908
|
+
/** Page-content frame → sheet-space CSS pixels (matches `paintSelectionOverlay`). */
|
|
909
|
+
declare function overlayFrameToSheetCssPixels(layout: SemanticLayout, frame: OverlayFrameRect, coordinates: SurfaceOverlayCoordinates): {
|
|
910
|
+
readonly left: number;
|
|
911
|
+
readonly top: number;
|
|
912
|
+
readonly width: number;
|
|
913
|
+
readonly height: number;
|
|
914
|
+
};
|
|
915
|
+
/**
|
|
916
|
+
* Where the painted surface's box begins inside overlay chrome's containing block, in CSS pixels.
|
|
917
|
+
*
|
|
918
|
+
* {@link overlayFrameToSheetCssPixels} produces coordinates relative to the surface element —
|
|
919
|
+
* the box the pages paint into — but overlay chrome portals OUTSIDE that element, and its
|
|
920
|
+
* absolutely positioned pieces resolve against the nearest positioned ancestor. The surface
|
|
921
|
+
* centres itself inside that ancestor with a stylesheet margin, so a frame placed without this
|
|
922
|
+
* origin lands at the far left of the viewport, one full centring margin off the image it rings.
|
|
923
|
+
* `offsetLeft`/`offsetTop` measure against the same positioned ancestor the chrome resolves
|
|
924
|
+
* against — every element between the two is static — which is what makes the two spaces agree.
|
|
925
|
+
*/
|
|
926
|
+
declare function overlayHostOrigin(surfaceElement: HTMLElement | null): {
|
|
927
|
+
readonly left: number;
|
|
928
|
+
readonly top: number;
|
|
929
|
+
};
|
|
930
|
+
/** Whether this handle drag should preserve aspect ratio. */
|
|
931
|
+
declare function resizePreservesAspect(handle: ImageResizeHandle, aspectLocked: boolean, shiftKey: boolean, textbox?: boolean): boolean;
|
|
932
|
+
/**
|
|
933
|
+
* Where an anchored drawing's positioning frame begins, in layout points.
|
|
934
|
+
*
|
|
935
|
+
* An anchored drawing's offsets are relative to a base the file names (page, margin, column, …),
|
|
936
|
+
* so a move drag needs that base's origin to turn a pointer delta into a stored offset.
|
|
937
|
+
*/
|
|
938
|
+
interface AnchorFrameOrigin {
|
|
939
|
+
readonly x: number;
|
|
940
|
+
readonly y: number;
|
|
941
|
+
}
|
|
942
|
+
/**
|
|
943
|
+
* One resize frame: the extent to store, and the box to draw while the pointer is still down.
|
|
944
|
+
*
|
|
945
|
+
* Both, because they are different spaces — the extent is EMU for the file, the preview is
|
|
946
|
+
* points for the overlay — and computing them separately would let the handle drift from the
|
|
947
|
+
* rectangle it is dragging.
|
|
948
|
+
*/
|
|
949
|
+
interface ImageResizeResult {
|
|
950
|
+
readonly widthEmu: number;
|
|
951
|
+
readonly heightEmu: number;
|
|
952
|
+
readonly previewBounds: {
|
|
953
|
+
readonly x: number;
|
|
954
|
+
readonly y: number;
|
|
955
|
+
readonly width: number;
|
|
956
|
+
readonly height: number;
|
|
957
|
+
};
|
|
958
|
+
readonly position: DrawingPositionInput | null;
|
|
959
|
+
}
|
|
960
|
+
/**
|
|
961
|
+
* Resolve one resize frame from the pointer's current position.
|
|
962
|
+
*
|
|
963
|
+
* Handles rotation and flips by mapping the SCREEN-space handle back to the drawing's local axes
|
|
964
|
+
* first: dragging the visually-right handle of a 90°-rotated image must change its stored height,
|
|
965
|
+
* and a flipped image's handles move in the opposite direction from where they appear.
|
|
966
|
+
*/
|
|
967
|
+
declare function computeImageResizeResult(options: {
|
|
968
|
+
readonly handle: ImageResizeHandle;
|
|
969
|
+
readonly startWidthEmu: number;
|
|
970
|
+
readonly startHeightEmu: number;
|
|
971
|
+
readonly startBounds: {
|
|
972
|
+
readonly x: number;
|
|
973
|
+
readonly y: number;
|
|
974
|
+
readonly width: number;
|
|
975
|
+
readonly height: number;
|
|
976
|
+
};
|
|
977
|
+
readonly startPosition: DrawingPositionInput | null;
|
|
978
|
+
readonly anchorFrameOrigin?: AnchorFrameOrigin | null;
|
|
979
|
+
readonly deltaXPt: number;
|
|
980
|
+
readonly deltaYPt: number;
|
|
981
|
+
readonly transform: DrawingTransform;
|
|
982
|
+
readonly preserveAspect: boolean;
|
|
983
|
+
readonly kind: 'inline' | 'anchored';
|
|
984
|
+
}): ImageResizeResult;
|
|
985
|
+
/**
|
|
986
|
+
* An {@link ImageOverlayScrollPort} over a real scroll container.
|
|
987
|
+
*
|
|
988
|
+
* Reports the delta the element ACTUALLY scrolled, converted back to points — at the end of the
|
|
989
|
+
* document that is less than asked for, and the overlay must not move the image further than the
|
|
990
|
+
* page travelled.
|
|
991
|
+
*/
|
|
992
|
+
declare function createImageOverlayScrollPort(scroller: HTMLElement, paintScale: number): {
|
|
993
|
+
scrollBy(deltaYPoints: number): number;
|
|
994
|
+
};
|
|
995
|
+
/**
|
|
996
|
+
* The committed result of a whole drag, recomputed from the release coordinates.
|
|
997
|
+
*
|
|
998
|
+
* Recomputed rather than accumulated from the per-frame previews, so rounding applied once per
|
|
999
|
+
* frame cannot add up into a final extent that differs from where the pointer actually stopped.
|
|
1000
|
+
*/
|
|
1001
|
+
interface FinalizedImageOverlayInteraction extends ImageResizeResult {
|
|
1002
|
+
readonly position: DrawingPositionInput | null;
|
|
1003
|
+
}
|
|
1004
|
+
/** Recompute the committed overlay result from release pointer coordinates. */
|
|
1005
|
+
declare function finalizeImageOverlayInteraction(options: {
|
|
1006
|
+
readonly session: ImageInteractionSession;
|
|
1007
|
+
readonly deltaXPt: number;
|
|
1008
|
+
readonly deltaYPt: number;
|
|
1009
|
+
readonly accumulatedScrollPt: number;
|
|
1010
|
+
readonly aspectLocked: boolean;
|
|
1011
|
+
readonly shiftKey: boolean;
|
|
1012
|
+
readonly textbox?: boolean;
|
|
1013
|
+
readonly anchorFrameOrigin: AnchorFrameOrigin | null;
|
|
1014
|
+
}): FinalizedImageOverlayInteraction;
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* How a section-addressed op should name the section a caret is in.
|
|
1018
|
+
*
|
|
1019
|
+
* `w:sectPr` lives on the body story, so the op can only name BODY content — and a caret in a
|
|
1020
|
+
* header or a note is not body content. The three answers are genuinely different, and
|
|
1021
|
+
* collapsing them to "a paragraph or `null`" is what let an unaddressable section quietly
|
|
1022
|
+
* become a document-wide write.
|
|
1023
|
+
*/
|
|
1024
|
+
type SectionAnchor =
|
|
1025
|
+
/** Name this body paragraph. Its section is the one the caret is in. */
|
|
1026
|
+
{
|
|
1027
|
+
readonly kind: 'anchor';
|
|
1028
|
+
readonly paragraphId: string;
|
|
1029
|
+
}
|
|
1030
|
+
/** One section: an anchor names nothing extra, so the op may omit it. */
|
|
1031
|
+
| {
|
|
1032
|
+
readonly kind: 'whole-document';
|
|
1033
|
+
}
|
|
1034
|
+
/**
|
|
1035
|
+
* Several sections, and the caret's holds no paragraph to name.
|
|
1036
|
+
*
|
|
1037
|
+
* An omitted anchor here would write EVERY section, which is what `scope: 'document'` is
|
|
1038
|
+
* for — so answering it to a `scope: 'section'` request changes sections nobody asked
|
|
1039
|
+
* about. There is no anchor that reaches an empty final section: one exists only when every
|
|
1040
|
+
* paragraph already closes an earlier section, so nothing sits at or after it.
|
|
1041
|
+
*/
|
|
1042
|
+
| {
|
|
1043
|
+
readonly kind: 'unaddressable';
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
/**
|
|
1047
|
+
* What a host may set on a surface image insert.
|
|
1048
|
+
*
|
|
1049
|
+
* The decode port and the collaboration actor are the SURFACE's to supply. An actor a host
|
|
1050
|
+
* could pass would be a second identity for the same mint, which is the thing actor-scoped
|
|
1051
|
+
* allocation exists to prevent.
|
|
1052
|
+
*/
|
|
1053
|
+
type SurfaceInsertImageInput = Omit<InsertImageInput, 'decodePort' | 'actorId'>;
|
|
1054
|
+
|
|
1055
|
+
/**
|
|
1056
|
+
* Every field of the Paragraph dialog, in the units the rest of this contract uses:
|
|
1057
|
+
* points for spacing, TWIPS for indents.
|
|
1058
|
+
*
|
|
1059
|
+
* An omitted field is left as authored. Where `null` is allowed it REMOVES the setting,
|
|
1060
|
+
* which is not the same as writing a zero — a zero blocks the cascade, a removal lets the
|
|
1061
|
+
* style through again.
|
|
1062
|
+
*/
|
|
1063
|
+
interface SurfaceParagraphFormat {
|
|
1064
|
+
readonly alignment?: 'left' | 'center' | 'right' | 'both';
|
|
1065
|
+
/** Base direction; see `directionalParagraphEntry` for what each value writes. */
|
|
1066
|
+
readonly direction?: 'ltr' | 'rtl';
|
|
1067
|
+
readonly spaceBeforePt?: number | null;
|
|
1068
|
+
readonly spaceAfterPt?: number | null;
|
|
1069
|
+
readonly lineSpacing?: {
|
|
1070
|
+
readonly rule: 'multiple' | 'exact' | 'atLeast';
|
|
1071
|
+
readonly value: number;
|
|
1072
|
+
} | null;
|
|
1073
|
+
readonly indentLeftTwips?: number | null;
|
|
1074
|
+
readonly indentRightTwips?: number | null;
|
|
1075
|
+
/** ONE signed first-line offset: negative is a hanging indent (§17.3.1.12). */
|
|
1076
|
+
readonly indentFirstLineTwips?: number | null;
|
|
1077
|
+
readonly contextualSpacing?: boolean;
|
|
1078
|
+
readonly keepNext?: boolean;
|
|
1079
|
+
readonly keepLines?: boolean;
|
|
1080
|
+
readonly widowControl?: boolean;
|
|
1081
|
+
readonly pageBreakBefore?: boolean;
|
|
1082
|
+
/**
|
|
1083
|
+
* Replace the paragraph's custom tab stops. An empty list CLEARS them, which is what Word's
|
|
1084
|
+
* "Clear All" does; omit the field to leave them as authored.
|
|
1085
|
+
*/
|
|
1086
|
+
readonly tabStops?: readonly ParagraphTabStop[];
|
|
1087
|
+
}
|
|
1088
|
+
/** One property in a batched paragraph write. */
|
|
1089
|
+
interface ParagraphPropertyEdit {
|
|
1090
|
+
readonly localName: string;
|
|
1091
|
+
/** A null-valued attribute REMOVES that attribute; see `setParagraphProperty`. */
|
|
1092
|
+
readonly attributes?: Record<string, string | null>;
|
|
1093
|
+
/** Keep the attributes this entry does not name, for multi-setting elements. */
|
|
1094
|
+
readonly mergeAttributes?: boolean;
|
|
1095
|
+
/**
|
|
1096
|
+
* For `w:jc` only: `attributes.val` names a PHYSICAL edge, as a toolbar button does. The
|
|
1097
|
+
* writer converts it per paragraph, because a bidi paragraph reaches its right margin
|
|
1098
|
+
* with `left` (see `jcValueForAlignment`).
|
|
1099
|
+
*/
|
|
1100
|
+
readonly physicalAlignment?: boolean;
|
|
1101
|
+
/**
|
|
1102
|
+
* For `w:bidi` only: the base direction the paragraph must END in. The writer spells it per
|
|
1103
|
+
* paragraph and skips one already in that direction (see `directionalParagraphEntry`).
|
|
1104
|
+
*/
|
|
1105
|
+
readonly paragraphDirection?: 'ltr' | 'rtl';
|
|
1106
|
+
/** Drop the paragraph's own element of this name instead of writing one. */
|
|
1107
|
+
readonly remove?: boolean;
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
/**
|
|
1111
|
+
* Which review write is being committed through `commitReviewOps`.
|
|
1112
|
+
*
|
|
1113
|
+
* The callback that performs the write is opaque, so a lane deciding whether to allow it cannot
|
|
1114
|
+
* tell an Accept from a comment delete. That mattered once a replica was attached: these paths
|
|
1115
|
+
* reach the store directly rather than through `applyTreeOps`, and the ones that graft a package
|
|
1116
|
+
* and swap the shell record no primitive effects — they replicate as NOTHING, leaving the peer a
|
|
1117
|
+
* `commentReference` naming a comment it never received. Naming the write lets each be admitted
|
|
1118
|
+
* only once a two-replica test proves it arrives whole.
|
|
1119
|
+
*/
|
|
1120
|
+
type ReviewWriteIntent = 'revision-resolve' | 'revision-attribution' | 'comment-add' | 'comment-reply' | 'comment-resolve' | 'comment-delete' | 'package-scoped';
|
|
1121
|
+
|
|
1122
|
+
/**
|
|
1123
|
+
* Everything an overlay needs to paint over one rendered frame of the surface.
|
|
1124
|
+
*
|
|
1125
|
+
* `pages` is the materialized page set (absent when every page is built), and `scale` and
|
|
1126
|
+
* `pageOffsetX` are the values the page painter used, so overlay geometry lands on the text.
|
|
1127
|
+
*/
|
|
1128
|
+
interface SurfaceOverlayFrame {
|
|
1129
|
+
readonly layer: HTMLElement;
|
|
1130
|
+
readonly layout: SemanticLayout;
|
|
1131
|
+
readonly revision: number;
|
|
1132
|
+
readonly scale: number;
|
|
1133
|
+
readonly pages?: ReadonlySet<number>;
|
|
1134
|
+
readonly pageOffsetX?: ReadonlyMap<number, number>;
|
|
1135
|
+
readonly measurer?: TextMeasurer;
|
|
1136
|
+
}
|
|
1137
|
+
/** A painter the surface calls after every render, and on request. */
|
|
1138
|
+
type SurfaceOverlayPainter = (frame: SurfaceOverlayFrame) => void;
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* Content-control interaction lane on the paginated surface.
|
|
1142
|
+
*
|
|
1143
|
+
* Chrome toggles are surface state; value / remove commit through tree ops.
|
|
1144
|
+
*/
|
|
1145
|
+
interface ContentControlOps {
|
|
1146
|
+
/** Toggle show-all boundary chrome. No layout reflow. */
|
|
1147
|
+
setShowAll(show: boolean): void;
|
|
1148
|
+
/** Toggle form-fill Tab navigation mode. */
|
|
1149
|
+
setFormFill(active: boolean): void;
|
|
1150
|
+
/** Whether show-all chrome is on. */
|
|
1151
|
+
showAll(): boolean;
|
|
1152
|
+
/** Whether form-fill navigation is on. */
|
|
1153
|
+
formFill(): boolean;
|
|
1154
|
+
/** Innermost control at the caret from layout boundary records. */
|
|
1155
|
+
atCaret(): ContentControlBoundaryRecord | null;
|
|
1156
|
+
/**
|
|
1157
|
+
* Move to the next or previous editable control (tabIndex, then document order).
|
|
1158
|
+
*
|
|
1159
|
+
* Skips content-locked and bound controls. Selects the control's content for replacement.
|
|
1160
|
+
* Returns whether navigation landed somewhere.
|
|
1161
|
+
*/
|
|
1162
|
+
navigate(direction: 'next' | 'previous'): boolean;
|
|
1163
|
+
/**
|
|
1164
|
+
* Set a control's value through `setContentControlValue`. Honours lock / bound refusals.
|
|
1165
|
+
* Returns whether the op committed.
|
|
1166
|
+
*/
|
|
1167
|
+
setValue(controlId: string, value: string): boolean;
|
|
1168
|
+
/**
|
|
1169
|
+
* Unwrap a control keeping its content (`removeContentControl`). Defaults to the control
|
|
1170
|
+
* at the caret. Returns whether the op committed.
|
|
1171
|
+
*/
|
|
1172
|
+
remove(controlId?: string): boolean;
|
|
1173
|
+
/**
|
|
1174
|
+
* Engine reason a widget or remove action is disabled, or null when allowed.
|
|
1175
|
+
*
|
|
1176
|
+
* `edit` covers content / value changes; `remove` covers unwrap.
|
|
1177
|
+
*/
|
|
1178
|
+
disabledReason(controlId: string, action: 'edit' | 'remove'): string | null;
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Content-control chrome the surface owns, not the document.
|
|
1182
|
+
*
|
|
1183
|
+
* Boundary furniture visibility and form-fill navigation are surface chrome, not model
|
|
1184
|
+
* bytes — toggling them never reflows layout records.
|
|
1185
|
+
*/
|
|
1186
|
+
interface ContentControlSurfaceState {
|
|
1187
|
+
/** Show boundary chrome for every control. */
|
|
1188
|
+
readonly showAll: boolean;
|
|
1189
|
+
/** Tab / Shift+Tab navigate between editable controls. */
|
|
1190
|
+
readonly formFill: boolean;
|
|
1191
|
+
/** Innermost control containing the caret, or null. */
|
|
1192
|
+
readonly activeControlId: string | null;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
/**
|
|
1196
|
+
* What one paint did.
|
|
1197
|
+
*
|
|
1198
|
+
* Four answers rather than a boolean, because the two FAILURES are different problems with
|
|
1199
|
+
* different words for the user: `'nothingToPaint'` says the selection holds nothing the
|
|
1200
|
+
* capture can reach, and `'refused'` says the document would not take the write — a locked
|
|
1201
|
+
* content control, a collaboration gate, a document open for viewing. Collapsed to false,
|
|
1202
|
+
* a refused paint told the reader to select some text.
|
|
1203
|
+
*
|
|
1204
|
+
* `'armed'` is the collapsed-caret outcome: no text to paint, so the character half went to
|
|
1205
|
+
* the stored-marks lane and the next characters typed will carry it.
|
|
1206
|
+
*/
|
|
1207
|
+
type FormatPainterPaintResult = 'painted' | 'armed' | 'nothingToPaint' | 'refused';
|
|
1208
|
+
/** Word's Format Painter over the surface. */
|
|
1209
|
+
interface FormatPainterOps {
|
|
1210
|
+
state(): FormatPainterSurfaceState;
|
|
1211
|
+
/**
|
|
1212
|
+
* Capture the formatting at the selection. False when the selection resolves to no span
|
|
1213
|
+
* the layout has published yet — there is nothing to read.
|
|
1214
|
+
*/
|
|
1215
|
+
capture(): boolean;
|
|
1216
|
+
/** Paint the captured formatting over the current selection. */
|
|
1217
|
+
apply(): FormatPainterPaintResult;
|
|
1218
|
+
/**
|
|
1219
|
+
* One press of the painter control, with Word's meaning.
|
|
1220
|
+
*
|
|
1221
|
+
* A press while the painter is off captures and arms it for a single application. A press
|
|
1222
|
+
* that lands within the double-press window locks it on. A press while it is armed and
|
|
1223
|
+
* outside that window turns it off.
|
|
1224
|
+
*
|
|
1225
|
+
* The double-press window is the ENGINE's, deliberately: the alternative is each adapter
|
|
1226
|
+
* binding its own `dblclick` beside its own `click`, which is two hosts deciding
|
|
1227
|
+
* separately what a double-click means and drifting the moment one of them changes.
|
|
1228
|
+
*
|
|
1229
|
+
* False when there was nothing at the selection to capture, so a control can report a
|
|
1230
|
+
* refusal rather than looking as though it armed.
|
|
1231
|
+
*/
|
|
1232
|
+
press(): boolean;
|
|
1233
|
+
/** Turn the painter off, keeping the capture. `Esc` and a finished single application. */
|
|
1234
|
+
disarm(): void;
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Where the last pass spent its time, and how much work it actually did.
|
|
1239
|
+
*
|
|
1240
|
+
* The durations are the surface's own three phases — layout, paint, selection sync — timed
|
|
1241
|
+
* separately because they fail separately: a full relayout, a full repaint and a forced
|
|
1242
|
+
* reflow each have a different fix. The counters come free from machinery that already
|
|
1243
|
+
* exists: the layout session says how much was re-placed versus reused, and the scheduler
|
|
1244
|
+
* says how often work was thrown away as stale. `placed` equal to `total` on every
|
|
1245
|
+
* keystroke is the one-glance sign that incremental layout is not engaging.
|
|
1246
|
+
*/
|
|
1247
|
+
interface PaginatedSurfacePerf {
|
|
1248
|
+
/** Time the last layout pass took, in milliseconds. */
|
|
1249
|
+
readonly layoutMs: number;
|
|
1250
|
+
/** Time the last paint took — building and swapping the page DOM. */
|
|
1251
|
+
readonly paintMs: number;
|
|
1252
|
+
/** Time the last selection sync took — writing the model selection into the browser. */
|
|
1253
|
+
readonly selectionMs: number;
|
|
1254
|
+
/** Paragraphs the last pass re-placed, against the number in the document. */
|
|
1255
|
+
readonly placed: number;
|
|
1256
|
+
readonly total: number;
|
|
1257
|
+
/** Pages carried over from the previous layout without being rebuilt. */
|
|
1258
|
+
readonly reusedPages: number;
|
|
1259
|
+
/** Passes that could not resume and laid the document out from the top. */
|
|
1260
|
+
readonly fullPasses: number;
|
|
1261
|
+
/** Layouts discarded because the model had already moved on. */
|
|
1262
|
+
readonly staleDiscards: number;
|
|
1263
|
+
/** Cooperative runs abandoned mid-flight for a newer revision. */
|
|
1264
|
+
readonly cancelledRuns: number;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
/**
|
|
1268
|
+
* One live remote-caret label the engine positioned. The host owns its content; the engine
|
|
1269
|
+
* still owns the label's geometry, class, and presence colour, and rebuilds the labels
|
|
1270
|
+
* wholesale on every repaint that moves them.
|
|
1271
|
+
*
|
|
1272
|
+
* @public
|
|
1273
|
+
*/
|
|
1274
|
+
interface RemoteCaretLabelAnchor {
|
|
1275
|
+
readonly element: HTMLElement;
|
|
1276
|
+
readonly selection: CollaborationRemoteSelection;
|
|
1277
|
+
}
|
|
1278
|
+
/**
|
|
1279
|
+
* A host that renders its own content inside the engine's remote-caret labels.
|
|
1280
|
+
*
|
|
1281
|
+
* @public
|
|
1282
|
+
*/
|
|
1283
|
+
interface RemoteCaretLabelHost {
|
|
1284
|
+
/**
|
|
1285
|
+
* Called after every paint that rebuilt the labels, with the current anchors.
|
|
1286
|
+
*
|
|
1287
|
+
* A skipped paint (nothing moved) does not re-publish: the host keeps its last anchors
|
|
1288
|
+
* until the next publish, and elements from a previous publish are dead after the next
|
|
1289
|
+
* one. An empty array is a real publish — every remote caret left the screen.
|
|
1290
|
+
*
|
|
1291
|
+
* Never mutate editor state synchronously from `publish` — a mutation repaints, and the
|
|
1292
|
+
* nested rebuild's publish would arrive before this one returned; only set host state.
|
|
1293
|
+
*/
|
|
1294
|
+
publish(anchors: readonly RemoteCaretLabelAnchor[]): void;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
/**
|
|
1298
|
+
* How a paginated surface opens. Every field is optional.
|
|
1299
|
+
*
|
|
1300
|
+
* `measurer` is the injection seam that keeps layout DOM-free — supply one to lay a document out
|
|
1301
|
+
* on a server, or leave it off in a browser to get the canvas measurer.
|
|
1302
|
+
*/
|
|
1303
|
+
interface PaginatedSurfaceOptions {
|
|
1304
|
+
/** UI labels for shared form controls; omitted keys fall back to English. */
|
|
1305
|
+
readonly translate?: (key: string, params?: Record<string, string | number>) => string;
|
|
1306
|
+
/** Regional conventions for new date input; defaults to en-US. */
|
|
1307
|
+
readonly locale?: string;
|
|
1308
|
+
/**
|
|
1309
|
+
* The collaboration module's replica for this surface's session. Absent,
|
|
1310
|
+
* the surface does not attach, and local store history remains the undo
|
|
1311
|
+
* authority.
|
|
1312
|
+
*/
|
|
1313
|
+
readonly collaborationModel?: CollaborationModuleContribution;
|
|
1314
|
+
/**
|
|
1315
|
+
* How saved field results are edited. `atomic` (the default) keeps every field one unit.
|
|
1316
|
+
* `editable` lets the reader type, delete, and select inside the saved result of a DATE,
|
|
1317
|
+
* MERGEFIELD, HYPERLINK, or similar field. Results must be unnested; simple fields inside
|
|
1318
|
+
* complex field results are not supported. Refused with a {@link collaborationModel}.
|
|
1319
|
+
*/
|
|
1320
|
+
readonly fieldResults?: FieldResultsMode;
|
|
1321
|
+
readonly measurer?: TextMeasurer;
|
|
1322
|
+
/** Ambient author for tracked edits. Required before suggesting can write anything. */
|
|
1323
|
+
readonly author?: string;
|
|
1324
|
+
/** Opening mode; changeable at runtime with `setEditingMode`. */
|
|
1325
|
+
readonly editingMode?: SurfaceEditingMode;
|
|
1326
|
+
/**
|
|
1327
|
+
* Identifies the measurer for cache invalidation.
|
|
1328
|
+
*
|
|
1329
|
+
* Fonts resolve asynchronously, so a host that swaps its measurer must change this or the
|
|
1330
|
+
* cached pre-font layout is served for the rest of the session.
|
|
1331
|
+
*/
|
|
1332
|
+
readonly producer?: string;
|
|
1333
|
+
/**
|
|
1334
|
+
* Maps a document-declared font family to the alias its registered bytes live under, so
|
|
1335
|
+
* painted runs can use embedded glyphs without the file's family name entering the
|
|
1336
|
+
* page-global CSS font namespace.
|
|
1337
|
+
*/
|
|
1338
|
+
readonly fontAlias?: (family: string) => string | undefined;
|
|
1339
|
+
/** Points to CSS pixels. */
|
|
1340
|
+
readonly scale?: number;
|
|
1341
|
+
/**
|
|
1342
|
+
* How revisions project into layout and paint. Omitted keeps the layout default
|
|
1343
|
+
* (`all-markup`). The editor facade passes `proposed` when no review module is
|
|
1344
|
+
* registered — the free tier's final-state rendering; the machinery below this
|
|
1345
|
+
* option is shared either way.
|
|
1346
|
+
*/
|
|
1347
|
+
readonly revisionDisplayMode?: ReviewDisplayMode;
|
|
1348
|
+
/** Authors whose changes open in their accepted view-time projection. */
|
|
1349
|
+
readonly hiddenRevisionAuthors?: readonly string[];
|
|
1350
|
+
/**
|
|
1351
|
+
* When a field's result wears Word's grey shading. Omitted keeps Word's own default,
|
|
1352
|
+
* `when-selected`.
|
|
1353
|
+
*
|
|
1354
|
+
* Applies to ORDINARY fields only. Legacy form fields follow the document's
|
|
1355
|
+
* `w:doNotShadeFormData`, because a form's blanks are the document's own statement about
|
|
1356
|
+
* itself rather than a reader's preference.
|
|
1357
|
+
*
|
|
1358
|
+
* A paint-level option, not a layout one: it changes no geometry, so switching it repaints
|
|
1359
|
+
* without remeasuring a single line.
|
|
1360
|
+
*/
|
|
1361
|
+
readonly fieldShading?: FieldShadingMode;
|
|
1362
|
+
/** Show paragraph-end furniture without changing document content. */
|
|
1363
|
+
readonly showParagraphMarks?: boolean;
|
|
1364
|
+
readonly onToggleParagraphMarks?: () => void;
|
|
1365
|
+
/**
|
|
1366
|
+
* How tracked changes are coloured: by AUTHOR (the default), by kind, or by author with
|
|
1367
|
+
* host-pinned colours. A paint-level option like {@link fieldShading}: it changes no
|
|
1368
|
+
* geometry, so switching it repaints without remeasuring a line. Applies wherever
|
|
1369
|
+
* revision markup paints, whatever the {@link revisionDisplayMode} leaves visible.
|
|
1370
|
+
*/
|
|
1371
|
+
readonly revisionStyles?: RevisionStyles;
|
|
1372
|
+
readonly revisionMarkup?: ResolvedRevisionMarkup;
|
|
1373
|
+
/**
|
|
1374
|
+
* The review module's derivation hooks for this surface's session. Absent,
|
|
1375
|
+
* `session.reviewItems()` is the typed empty queue and every review affordance
|
|
1376
|
+
* built on it stays inert.
|
|
1377
|
+
*/
|
|
1378
|
+
readonly reviewModel?: ReviewModuleContribution;
|
|
1379
|
+
/**
|
|
1380
|
+
* The family a run with no authored font is reported as by `formatting()` AND painted
|
|
1381
|
+
* in — the face the measurer falls back to. Absent, such a run reports
|
|
1382
|
+
* `fontFamily: null` and paints in whatever font the page inherits, which the measurer
|
|
1383
|
+
* did not measure: visible glyphs drift from wrap points and caret geometry.
|
|
1384
|
+
*/
|
|
1385
|
+
readonly defaultFontFamily?: string;
|
|
1386
|
+
/**
|
|
1387
|
+
* Who resolves a pointer to a caret.
|
|
1388
|
+
*
|
|
1389
|
+
* `'engine'` (the default) answers from the layout records, which is what makes a click in
|
|
1390
|
+
* a margin, an indent or a cell's padding land where it was aimed. `'native'` binds no
|
|
1391
|
+
* pointer handlers and leaves the browser's own caret placement in charge.
|
|
1392
|
+
*/
|
|
1393
|
+
readonly pointer?: 'engine' | 'native';
|
|
1394
|
+
readonly onChange?: (state: PaginatedSurfaceState) => void;
|
|
1395
|
+
/**
|
|
1396
|
+
* A plain click on an external (or inert) hyperlink, for a host to open its popover with.
|
|
1397
|
+
*
|
|
1398
|
+
* Absent means such a click does nothing. That is deliberate: a host with no popover
|
|
1399
|
+
* mounted must not have clicks silently opening tabs, and the popover is the only path to
|
|
1400
|
+
* activation (see the navigation module's single `window.open` gate).
|
|
1401
|
+
*/
|
|
1402
|
+
readonly onHyperlinkPopover?: (activation: HyperlinkActivation) => void;
|
|
1403
|
+
readonly onEquationPopover?: (activation: EquationActivation) => void;
|
|
1404
|
+
/**
|
|
1405
|
+
* Ctrl/Cmd+K — Word's Insert Hyperlink. The engine reports the request; the host's chrome
|
|
1406
|
+
* decides what a link dialog looks like. A host that passes nothing leaves the key alone
|
|
1407
|
+
* rather than doing something surprising with it.
|
|
1408
|
+
*/
|
|
1409
|
+
readonly onRequestHyperlink?: () => void;
|
|
1410
|
+
/** Return true when host chrome handles this session. */
|
|
1411
|
+
readonly onRequestTextFormField?: (session: TextFormFieldDialogSession) => boolean;
|
|
1412
|
+
readonly onRequestContentControlWidget?: (session: ContentControlWidgetSession) => boolean;
|
|
1413
|
+
readonly onRequestInvalidTextFormField?: (session: InvalidTextFormFieldSession) => boolean;
|
|
1414
|
+
/**
|
|
1415
|
+
* Localized accessible names for core-owned table insertion furniture.
|
|
1416
|
+
* Defaults to English from `@docx-editor.dev/i18n` when omitted.
|
|
1417
|
+
*/
|
|
1418
|
+
readonly tableInteractionLabel?: (key: 'table.insertRowBelow' | 'table.insertColumnRight') => string;
|
|
1419
|
+
/** Localized drawing refusal labels; defaults to English when omitted. */
|
|
1420
|
+
readonly drawingStrings?: DrawingPaintStrings;
|
|
1421
|
+
/** Override raster decode for package image intents; defaults to browser/headless. */
|
|
1422
|
+
readonly imageDecodePort?: ImageDecodePort;
|
|
1423
|
+
/**
|
|
1424
|
+
* Localized name for a generated TOC, written as the control's `w:alias` on insert.
|
|
1425
|
+
*
|
|
1426
|
+
* The update ACTIONS are not here: they are rows in the host's context menu, which owns
|
|
1427
|
+
* its own labels. The engine paints no menu of its own.
|
|
1428
|
+
*/
|
|
1429
|
+
readonly tocLabels?: {
|
|
1430
|
+
readonly title: string;
|
|
1431
|
+
};
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
/**
|
|
1435
|
+
* What the selection is currently formatted as.
|
|
1436
|
+
*
|
|
1437
|
+
* A value is present only when EVERY span in the selection agrees on it: a selection running
|
|
1438
|
+
* from 11pt into 14pt has no font size, and a toolbar should show a blank rather than pick
|
|
1439
|
+
* one of the two and imply the whole selection is that.
|
|
1440
|
+
*/
|
|
1441
|
+
interface SurfaceFormatting {
|
|
1442
|
+
readonly bold: boolean;
|
|
1443
|
+
readonly italic: boolean;
|
|
1444
|
+
readonly underline: boolean;
|
|
1445
|
+
readonly strikethrough: boolean;
|
|
1446
|
+
readonly superscript: boolean;
|
|
1447
|
+
readonly subscript: boolean;
|
|
1448
|
+
readonly fontFamily: string | null;
|
|
1449
|
+
/** Half-points, the unit OOXML stores and the picker expects. */
|
|
1450
|
+
readonly fontSizeHalfPoints: number | null;
|
|
1451
|
+
readonly color: string | null;
|
|
1452
|
+
readonly highlight: string | null;
|
|
1453
|
+
readonly alignment: 'left' | 'center' | 'right' | 'both' | null;
|
|
1454
|
+
/** Paragraph base direction through the cascade; null when the selection mixes them. */
|
|
1455
|
+
readonly direction: 'ltr' | 'rtl' | null;
|
|
1456
|
+
readonly styleId: string | null;
|
|
1457
|
+
/**
|
|
1458
|
+
* `w:spacing`'s line rule and its value: LINES for `multiple`, points for the other two
|
|
1459
|
+
* (`w:line` is 240ths of a line under `auto` and twentieths of a point otherwise).
|
|
1460
|
+
* Null when the selection's paragraphs disagree, or state no line spacing at all.
|
|
1461
|
+
*/
|
|
1462
|
+
readonly lineSpacing: {
|
|
1463
|
+
readonly rule: 'multiple' | 'exact' | 'atLeast';
|
|
1464
|
+
readonly value: number;
|
|
1465
|
+
} | null;
|
|
1466
|
+
/** `w:spacing/@w:before` and `@w:after` in points, null when the selection disagrees. */
|
|
1467
|
+
readonly spaceBeforePt: number | null;
|
|
1468
|
+
readonly spaceAfterPt: number | null;
|
|
1469
|
+
/**
|
|
1470
|
+
* Effective indent at the selection, in twips, or null with no selection or inside a
|
|
1471
|
+
* table.
|
|
1472
|
+
*
|
|
1473
|
+
* The one field here that does NOT go null on disagreement: the values are the FIRST
|
|
1474
|
+
* touched paragraph's and `mixed` reports the disagreement per field, because a ruler
|
|
1475
|
+
* must draw its handles somewhere and Word draws them at the first selected paragraph.
|
|
1476
|
+
*/
|
|
1477
|
+
readonly indent: IndentFormatting | null;
|
|
1478
|
+
/**
|
|
1479
|
+
* The paragraph flags the Paragraph dialog shows as checkboxes, or null when the
|
|
1480
|
+
* selection's paragraphs disagree about that one.
|
|
1481
|
+
*
|
|
1482
|
+
* `contextualSpacing` is "Don't add space between paragraphs of the same style"; the
|
|
1483
|
+
* other four are its Pagination block. Each is read from the cascade, so a flag a STYLE
|
|
1484
|
+
* sets reads as on — which is what a checkbox has to show.
|
|
1485
|
+
*/
|
|
1486
|
+
readonly paragraphFlags: ParagraphFlags;
|
|
1487
|
+
/**
|
|
1488
|
+
* The paragraph's resolved custom tab stops, cascade included, or null when the selection
|
|
1489
|
+
* disagrees or nothing is loaded. Positions in TWIPS, like every other measurement a
|
|
1490
|
+
* control writes back.
|
|
1491
|
+
*/
|
|
1492
|
+
readonly tabStops: readonly ParagraphTabStop[] | null;
|
|
1493
|
+
/**
|
|
1494
|
+
* Which of the paragraph-level reads above are `null` because the selection DISAGREES,
|
|
1495
|
+
* as opposed to because nothing states them. See {@link ParagraphDisagreements}.
|
|
1496
|
+
*/
|
|
1497
|
+
readonly disagrees: ParagraphDisagreements;
|
|
1498
|
+
}
|
|
1499
|
+
/** How a reveal places its target in the viewport. */
|
|
1500
|
+
interface RevealOptions {
|
|
1501
|
+
/**
|
|
1502
|
+
* `'start'` puts the target near the top (a heading the user jumped to), `'center'`
|
|
1503
|
+
* centres it, `'nearest'` scrolls only when it is out of view — and only far enough to
|
|
1504
|
+
* clear the edge, which parks the target flush against it. `'centerIfNeeded'` is the one
|
|
1505
|
+
* a jump-to-next-thing control wants: silent while the target is already on screen, and
|
|
1506
|
+
* centred when it has to move, so the reader lands looking AT the thing rather than at
|
|
1507
|
+
* the bottom line of the window. Default `'start'`.
|
|
1508
|
+
*/
|
|
1509
|
+
readonly block?: ScrollPlacement;
|
|
1510
|
+
/** Padding above the target, in CSS pixels. Default 24. */
|
|
1511
|
+
readonly offsetPx?: number;
|
|
1512
|
+
readonly behavior?: ScrollBehavior;
|
|
1513
|
+
}
|
|
1514
|
+
/**
|
|
1515
|
+
* How the current selection came to address a drawing — see
|
|
1516
|
+
* {@link PaginatedSurface.drawingSelectionIntent}.
|
|
1517
|
+
*/
|
|
1518
|
+
type DrawingSelectionIntent = {
|
|
1519
|
+
readonly kind: 'none';
|
|
1520
|
+
} | {
|
|
1521
|
+
readonly kind: 'pointer';
|
|
1522
|
+
readonly drawingNodeId: string;
|
|
1523
|
+
} | {
|
|
1524
|
+
readonly kind: 'programmatic';
|
|
1525
|
+
};
|
|
1526
|
+
/**
|
|
1527
|
+
* Everything observable about the surface right now, as one immutable value.
|
|
1528
|
+
*
|
|
1529
|
+
* `revision` is the change token: it moves whenever anything else here does, which is what lets
|
|
1530
|
+
* `snapshot()` hand back the same reference until state actually changes.
|
|
1531
|
+
*/
|
|
1532
|
+
interface PaginatedSurfaceState {
|
|
1533
|
+
readonly revision: number;
|
|
1534
|
+
readonly pageCount: number;
|
|
1535
|
+
readonly selection: SemanticSelection;
|
|
1536
|
+
/**
|
|
1537
|
+
* The rectangle of table cells a drag across cells selected, or null.
|
|
1538
|
+
*
|
|
1539
|
+
* `selection` always holds the equivalent TEXT range, so a reader that does not care about
|
|
1540
|
+
* rectangles needs no branch. This is for the ones that do — the highlight, and table
|
|
1541
|
+
* commands that act on cells rather than characters.
|
|
1542
|
+
*/
|
|
1543
|
+
readonly cellSelection: CellSelection | null;
|
|
1544
|
+
readonly canUndo: boolean;
|
|
1545
|
+
readonly canRedo: boolean;
|
|
1546
|
+
/**
|
|
1547
|
+
* Lifecycle of the attached replica, or `'inactive'` when no collaboration
|
|
1548
|
+
* module is registered on this surface.
|
|
1549
|
+
*/
|
|
1550
|
+
readonly collaborationStatus: CollaborationStatus | 'inactive';
|
|
1551
|
+
readonly lastRejection: string | null;
|
|
1552
|
+
/**
|
|
1553
|
+
* The typing format armed at the caret (Word's stored marks), or null.
|
|
1554
|
+
*
|
|
1555
|
+
* NOT document state — nothing is written until the next characters are typed — but it
|
|
1556
|
+
* IS observable state: `formatting()` reports it, so a host that reflects the toolbar
|
|
1557
|
+
* has to learn when it moves. Reference-stable while unchanged, so a host can compare
|
|
1558
|
+
* it to decide whether to re-derive. See `toggleRunProperty` for the lane itself.
|
|
1559
|
+
*/
|
|
1560
|
+
readonly pendingFormat: readonly {
|
|
1561
|
+
readonly localName: string;
|
|
1562
|
+
}[] | null;
|
|
1563
|
+
/**
|
|
1564
|
+
* Content-control chrome and form-fill mode.
|
|
1565
|
+
*
|
|
1566
|
+
* Surface-owned (not document bytes). Updates report through the same `onChange` path as
|
|
1567
|
+
* selection moves — hosts must not maintain a parallel channel.
|
|
1568
|
+
*/
|
|
1569
|
+
readonly contentControls: ContentControlSurfaceState;
|
|
1570
|
+
/**
|
|
1571
|
+
* The TOC the last right-click landed on, or null.
|
|
1572
|
+
*
|
|
1573
|
+
* A right-click deliberately does not move the caret, and a TOC refuses the caret
|
|
1574
|
+
* entirely, so `selection` can never say which table of contents the user is pointing at.
|
|
1575
|
+
* This is how a host's context menu learns it. Surface chrome, not document state.
|
|
1576
|
+
*/
|
|
1577
|
+
readonly contextTocId: string | null;
|
|
1578
|
+
/**
|
|
1579
|
+
* Format painter arming, and the level of what it holds.
|
|
1580
|
+
*
|
|
1581
|
+
* Surface chrome, not document bytes — the lane `contentControls` above sits in, reported
|
|
1582
|
+
* through the same `onChange` so a toolbar's pressed state has exactly one source.
|
|
1583
|
+
*/
|
|
1584
|
+
readonly formatPainter: FormatPainterSurfaceState;
|
|
1585
|
+
/** Timing and reuse counters for the last pass. Diagnostics, not document state. */
|
|
1586
|
+
readonly perf: PaginatedSurfacePerf;
|
|
1587
|
+
}
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* How an edit is written.
|
|
1591
|
+
*
|
|
1592
|
+
* `'suggest'` is the one that changes what the ops MEAN: the same keystroke becomes a `w:ins`
|
|
1593
|
+
* and the same Backspace becomes a `w:del` over the words it would have removed. `'view'`
|
|
1594
|
+
* refuses edits outright.
|
|
1595
|
+
*/
|
|
1596
|
+
type SurfaceEditingMode = 'edit' | 'suggest' | 'view';
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* Where the section after an inserted break begins — Word's Layout > Breaks menu.
|
|
1600
|
+
*
|
|
1601
|
+
* `evenPage` / `oddPage` sections from a file paginate with their blank parity sheet, but
|
|
1602
|
+
* inserting one is not offered here.
|
|
1603
|
+
*
|
|
1604
|
+
* @public
|
|
1605
|
+
*/
|
|
1606
|
+
type SectionBreakInsertType = 'nextPage' | 'continuous';
|
|
1607
|
+
/**
|
|
1608
|
+
* The mounted, painted, editable document — the layer `createDocxEditor` builds its contract on.
|
|
1609
|
+
*
|
|
1610
|
+
* The painted pages ARE the editable surface: they are `contenteditable`, but the DOM is a
|
|
1611
|
+
* picture. Browser mutations are prevented and re-expressed as tree ops, and selection maps only
|
|
1612
|
+
* through `data-paragraph-id`/`data-start`, never through DOM node identity.
|
|
1613
|
+
*
|
|
1614
|
+
* Every write goes through the guarded mutation path on this object. Reaching past it into
|
|
1615
|
+
* `session` to apply ops directly bypasses the layout invalidation and the caret bookkeeping.
|
|
1616
|
+
*/
|
|
1617
|
+
interface PaginatedSurface {
|
|
1618
|
+
readonly session: TreeDocxSessionView;
|
|
1619
|
+
/** The collaboration replica a `collaborationModule` attached, or null. */
|
|
1620
|
+
collaborationSession(): EditorCollaborationSession | null;
|
|
1621
|
+
storyScope(): StoryScope;
|
|
1622
|
+
imageDecodePort(): ImageDecodePort;
|
|
1623
|
+
applyDrawingOps(ops: readonly DrawingTreeDocOp[]): TreeApplyResult;
|
|
1624
|
+
applyImageProperties(input: ApplyImagePropertiesInput): ImageIntentResult;
|
|
1625
|
+
deleteImage(drawingNodeId: string): ImageIntentResult;
|
|
1626
|
+
insertImage(input: SurfaceInsertImageInput): Promise<ImageIntentResult>;
|
|
1627
|
+
replaceImage(drawingNodeId: string, bytes: Uint8Array, mime: SupportedImageMime, options: {
|
|
1628
|
+
readonly expectedPackageRevision: number;
|
|
1629
|
+
readonly commitGuard?: () => boolean;
|
|
1630
|
+
}): Promise<ImageIntentResult>;
|
|
1631
|
+
layout(): SemanticLayout;
|
|
1632
|
+
state(): PaginatedSurfaceState;
|
|
1633
|
+
/** One-based page at the caret, or at the centre of the mounted viewport. */
|
|
1634
|
+
currentPage(mode?: 'viewport' | 'caret'): number;
|
|
1635
|
+
type(text: string): void;
|
|
1636
|
+
/** Author one explicit tracked text change without changing the editing mode. */
|
|
1637
|
+
proposeTextChange(kind: 'insertion' | 'deletion' | 'replacement', text: string, author?: string): boolean;
|
|
1638
|
+
/**
|
|
1639
|
+
* Queue plain typed text for a batched commit at the caret.
|
|
1640
|
+
*
|
|
1641
|
+
* The DOM input lane's entry: a burst of keystrokes appends here and lands through ONE
|
|
1642
|
+
* `type()` call — one transaction, one undo step, one layout flush — when the queue drains.
|
|
1643
|
+
* Every surface mutation, selection or scope move, geometry read, composition start and
|
|
1644
|
+
* teardown flushes first. Code reading `session` directly sits BELOW the buffer and must
|
|
1645
|
+
* call {@link flushPendingInput}, as save/detach do. `type()` stays synchronous.
|
|
1646
|
+
*/
|
|
1647
|
+
enqueueType(text: string): void;
|
|
1648
|
+
/**
|
|
1649
|
+
* Land any queued typed text now, as its own transaction, AND publish any layout pass a
|
|
1650
|
+
* commit deferred under input pressure — so the caller reads current text and current
|
|
1651
|
+
* geometry at one seam. Both halves are no-ops when nothing is pending, which is the
|
|
1652
|
+
* common case: an isolated commit lays out synchronously in its own tail, and deferral
|
|
1653
|
+
* only happens when the browser reports queued input behind an expensive pass.
|
|
1654
|
+
*/
|
|
1655
|
+
flushPendingInput(): void;
|
|
1656
|
+
/**
|
|
1657
|
+
* Insert text whose newlines are PARAGRAPH BOUNDARIES, in one commit.
|
|
1658
|
+
*
|
|
1659
|
+
* `type` writes its argument into run text verbatim, so a newline reaching it is a
|
|
1660
|
+
* control character the store refuses — which vetoes the whole transaction and makes
|
|
1661
|
+
* the insert do nothing at all. This is the lane for text that arrives from outside the
|
|
1662
|
+
* editor (a paste, a drop), where line breaks are structure rather than characters.
|
|
1663
|
+
*
|
|
1664
|
+
* Plain text only, by construction: no markup is parsed and no DOM is built from the
|
|
1665
|
+
* payload, whatever its origin.
|
|
1666
|
+
*/
|
|
1667
|
+
insertPlainText(text: string): void;
|
|
1668
|
+
deleteBackward(): void;
|
|
1669
|
+
/** Delete forward — the Delete key, and `deleteContentForward` from an IME. */
|
|
1670
|
+
deleteForward(): void;
|
|
1671
|
+
/** Delete to the previous word boundary — Alt/Ctrl+Backspace. */
|
|
1672
|
+
deleteWordBackward(): void;
|
|
1673
|
+
/** Delete to the next word boundary — Alt/Ctrl+Delete. */
|
|
1674
|
+
deleteWordForward(): void;
|
|
1675
|
+
splitParagraph(): void;
|
|
1676
|
+
/** A tab character as a `w:tab` element, not a literal tab in the run text. */
|
|
1677
|
+
insertTab(): void;
|
|
1678
|
+
/** A `w:br` — Shift+Enter, a line break inside the same paragraph. */
|
|
1679
|
+
insertLineBreak(): void;
|
|
1680
|
+
/** A `w:br w:type="page"` — Ctrl+Enter, a hard page break inside the paragraph. */
|
|
1681
|
+
insertPageBreak(): void;
|
|
1682
|
+
/**
|
|
1683
|
+
* Word's Increase/Decrease Indent, over every paragraph the selection touches.
|
|
1684
|
+
*
|
|
1685
|
+
* A NUMBERED or BULLETED paragraph changes LEVEL: `w:numPr/w:ilvl` moves by one, which
|
|
1686
|
+
* re-resolves its marker from `numbering.xml` — so a bullet becomes a hollow circle, a
|
|
1687
|
+
* `1.` becomes an `a.`, exactly as Word demotes a list item. A level the definition
|
|
1688
|
+
* does not declare is DECLARED on the way, with Word's default format for that depth
|
|
1689
|
+
* (its stock bullets and number formats cycle every three levels) — a definition that
|
|
1690
|
+
* stops at `ilvl 0` never blocks the press. Everything else moves its `w:ind/@left` by
|
|
1691
|
+
* one default tab stop, never past the margin.
|
|
1692
|
+
*
|
|
1693
|
+
* Answers whether anything changed, so a caller can fall back (Tab inserting a tab
|
|
1694
|
+
* where there is no list to demote).
|
|
1695
|
+
*/
|
|
1696
|
+
adjustIndent(direction: 'increase' | 'decrease'): boolean;
|
|
1697
|
+
/**
|
|
1698
|
+
* Tab (`increase`) or Shift+Tab (`decrease`) over a selection outside a list: change the
|
|
1699
|
+
* indent and keep the text.
|
|
1700
|
+
*
|
|
1701
|
+
* A selection over two or more paragraphs, or a cell rectangle, steps the left indent of
|
|
1702
|
+
* each paragraph. A selection in one paragraph that starts at the paragraph start, whole or
|
|
1703
|
+
* partial, works on the first line: Tab sets a first-line indent of one default tab stop
|
|
1704
|
+
* (`w:defaultTabStop`), or steps the left indent when the first line already has that
|
|
1705
|
+
* indent or more, or a hanging indent. Shift+Tab clears a first-line indent that the
|
|
1706
|
+
* paragraph states itself, so a style value applies again, and otherwise steps the left
|
|
1707
|
+
* indent back. A paragraph the selection reaches only at its start is not touched by this
|
|
1708
|
+
* rule, unless it is the empty last paragraph of the story.
|
|
1709
|
+
*
|
|
1710
|
+
* Answers true when the selection takes this rule, also when the write is refused or
|
|
1711
|
+
* changes nothing, so the text is never replaced. Answers false for a caret and for a
|
|
1712
|
+
* selection in one paragraph that starts inside the text; there Tab types a tab character
|
|
1713
|
+
* and Shift+Tab steps the left indent.
|
|
1714
|
+
*/
|
|
1715
|
+
indentWithTab(direction: 'increase' | 'decrease'): boolean;
|
|
1716
|
+
/**
|
|
1717
|
+
* Set indent to exact values on every paragraph the selection touches — what a ruler
|
|
1718
|
+
* drag and an indent spinner both need, where {@link adjustIndent} only steps.
|
|
1719
|
+
*
|
|
1720
|
+
* Twips. Omitting a field leaves it as authored; `null` CLEARS it, so the paragraph
|
|
1721
|
+
* falls back to its style — distinct from zero, which blocks the cascade.
|
|
1722
|
+
*
|
|
1723
|
+
* `firstLine` is ONE SIGNED offset, negative for a hanging indent; the two OOXML
|
|
1724
|
+
* spellings are written for it, the unused one as an explicit zero. Answers whether
|
|
1725
|
+
* anything was committed.
|
|
1726
|
+
*/
|
|
1727
|
+
setIndent(update: {
|
|
1728
|
+
readonly left?: number | null;
|
|
1729
|
+
readonly right?: number | null;
|
|
1730
|
+
readonly firstLine?: number | null;
|
|
1731
|
+
}): boolean;
|
|
1732
|
+
/**
|
|
1733
|
+
* Whether Increase/Decrease Indent would do anything right now.
|
|
1734
|
+
*
|
|
1735
|
+
* A list item at level 0 cannot outdent and one at level 8 cannot indent — `w:ilvl`
|
|
1736
|
+
* has nine levels and Word greys the control out at the ends. A missing level
|
|
1737
|
+
* DEFINITION never disables it: `adjustIndent` declares the level as it goes. The one
|
|
1738
|
+
* residue: a `w:numStyleLink` definition missing the level refuses the declaration
|
|
1739
|
+
* (its levels belong to the linked style), so there the press is a safe no-op rather
|
|
1740
|
+
* than a greyed control.
|
|
1741
|
+
*/
|
|
1742
|
+
canAdjustIndent(direction: 'increase' | 'decrease'): boolean;
|
|
1743
|
+
/**
|
|
1744
|
+
* Enter on an empty list item: outdent a level, or leave the list at level 0.
|
|
1745
|
+
*
|
|
1746
|
+
* Answers false when the caret is not on an empty list item, so the caller falls
|
|
1747
|
+
* through to an ordinary paragraph split.
|
|
1748
|
+
*/
|
|
1749
|
+
exitListOnEmptyItem(): boolean;
|
|
1750
|
+
/** Whether the paragraph at the caret is a list item, for Tab's Word-like fallback. */
|
|
1751
|
+
isListParagraph(): boolean;
|
|
1752
|
+
/**
|
|
1753
|
+
* Word's Bullets and Numbering buttons.
|
|
1754
|
+
*
|
|
1755
|
+
* Turns every paragraph the selection touches into a list of `kind`, or takes them all
|
|
1756
|
+
* out when they are already one. The definition is created in `numbering.xml` on first
|
|
1757
|
+
* use — a document that has never carried a list has no numbering part at all.
|
|
1758
|
+
*/
|
|
1759
|
+
toggleList(kind: 'bullet' | 'ordered'): boolean;
|
|
1760
|
+
/** Whether every paragraph the selection touches is already a list of `kind`. */
|
|
1761
|
+
isListActive(kind: 'bullet' | 'ordered'): boolean;
|
|
1762
|
+
/** Select the whole document. */
|
|
1763
|
+
selectAll(): void;
|
|
1764
|
+
/**
|
|
1765
|
+
* Turn the browser's editing affordance on the pages layer on or off.
|
|
1766
|
+
*
|
|
1767
|
+
* The facade's `mode` gates COMMANDS, which stops `exec` but not the keyboard: the pages
|
|
1768
|
+
* layer is `contentEditable` and binds `beforeinput` itself, so a document the facade
|
|
1769
|
+
* called read-only still accepted typing straight into it. Read-only has to reach the
|
|
1770
|
+
* surface to be true.
|
|
1771
|
+
*/
|
|
1772
|
+
setEditable(editable: boolean): void;
|
|
1773
|
+
/**
|
|
1774
|
+
* Scroll a page, or the page a paragraph sits on, into view. Returns whether it
|
|
1775
|
+
* scrolled — false when the target is not laid out, or the surface is not inside a
|
|
1776
|
+
* scroll container, so a caller can tell "no such target" from "done".
|
|
1777
|
+
*
|
|
1778
|
+
* The geometry comes from the LAYOUT, never from the DOM: a page that has not been
|
|
1779
|
+
* materialized yet has no element to measure, and that is exactly the page a reveal is
|
|
1780
|
+
* usually asked for. `revealParagraph` scrolls to the paragraph's own line rather than
|
|
1781
|
+
* the top of its page, so a heading deep in a page lands in view.
|
|
1782
|
+
*/
|
|
1783
|
+
revealPage(pageIndex: number, options?: RevealOptions): boolean;
|
|
1784
|
+
revealParagraph(paragraphId: string, options?: RevealOptions): boolean;
|
|
1785
|
+
/**
|
|
1786
|
+
* Scroll an exact position into view — `revealParagraph` for a caret that is not at
|
|
1787
|
+
* offset 0. Focus-independent and virtualization-safe like every reveal: geometry
|
|
1788
|
+
* comes from the layout and the target page is materialized on the way. Defaults to
|
|
1789
|
+
* `block: 'nearest'`, so an already-visible target never yanks the viewport.
|
|
1790
|
+
*/
|
|
1791
|
+
revealPosition(position: SemanticPosition, options?: RevealOptions): boolean;
|
|
1792
|
+
/** Set the selection directly, for a host driving the surface programmatically. */
|
|
1793
|
+
setSelection(next: SemanticSelection): void;
|
|
1794
|
+
/**
|
|
1795
|
+
* Select one painted drawing at its host paragraph, as a pointer press would.
|
|
1796
|
+
*
|
|
1797
|
+
* False when the layout paints no such drawing on that paragraph, in which case nothing
|
|
1798
|
+
* moves: the caller decides what to do rather than being left mid-way.
|
|
1799
|
+
*/
|
|
1800
|
+
selectDrawing(drawingNodeId: string, hostParagraphId: string): boolean;
|
|
1801
|
+
/**
|
|
1802
|
+
* Select a rectangle of table cells, or clear one with null.
|
|
1803
|
+
*
|
|
1804
|
+
* The equivalent text range is installed alongside it, so `state().selection` stays valid
|
|
1805
|
+
* for every reader that does not know rectangles exist.
|
|
1806
|
+
*/
|
|
1807
|
+
setCellSelection(next: CellSelection | null): void;
|
|
1808
|
+
/**
|
|
1809
|
+
* Toggle a run property over the selection, e.g. `b`, `i`, `u`.
|
|
1810
|
+
*
|
|
1811
|
+
* AT A COLLAPSED CARET this ARMS the property instead of writing it — Word's stored
|
|
1812
|
+
* marks. Nothing reaches the document until the next characters are typed there, and
|
|
1813
|
+
* those take the armed format; the armed state shows in `formatting()` and in
|
|
1814
|
+
* `state().pendingFormat` immediately, so a toolbar reflects the press. It survives the
|
|
1815
|
+
* caret-preserving edits (Backspace, Delete, Enter) and IME composition, and is
|
|
1816
|
+
* discarded when the caret moves elsewhere or the document is undone. A property the
|
|
1817
|
+
* store cannot author is refused at arm time rather than left to poison the keystroke.
|
|
1818
|
+
*/
|
|
1819
|
+
toggleRunProperty(localName: string, attributes?: Record<string, string>): void;
|
|
1820
|
+
/**
|
|
1821
|
+
* SET a run property over the selection, rather than toggling it.
|
|
1822
|
+
*
|
|
1823
|
+
* Font family, size and colour are values, not switches: picking Arial twice must leave
|
|
1824
|
+
* the text in Arial, which a toggle would not. Arms at a collapsed caret on the same
|
|
1825
|
+
* terms as `toggleRunProperty`.
|
|
1826
|
+
*/
|
|
1827
|
+
setRunProperty(localName: string, attributes?: Record<string, string>): void;
|
|
1828
|
+
/**
|
|
1829
|
+
* Set a property on every paragraph the selection touches — alignment, style, spacing.
|
|
1830
|
+
*
|
|
1831
|
+
* `mergeAttributes` keeps the attributes the call does not name, for the properties that
|
|
1832
|
+
* carry several independent settings in one element: `w:spacing` holds the line rule and
|
|
1833
|
+
* the space before and after, so a line-spacing pick must not delete the space-before. A
|
|
1834
|
+
* null-valued attribute removes just that one.
|
|
1835
|
+
*/
|
|
1836
|
+
setParagraphProperty(localName: string, attributes?: Record<string, string | null>, options?: Pick<ParagraphPropertyEdit, 'mergeAttributes' | 'physicalAlignment' | 'paragraphDirection'>): void;
|
|
1837
|
+
/**
|
|
1838
|
+
* Several paragraph properties in ONE transaction, so a dialog is one undo step.
|
|
1839
|
+
*
|
|
1840
|
+
* `setParagraphProperty` is this with a single entry. A dialog that fired one call per
|
|
1841
|
+
* field would leave the user pressing Ctrl+Z five times to undo one OK, and would paint
|
|
1842
|
+
* four intermediate layouts on the way.
|
|
1843
|
+
*/
|
|
1844
|
+
setParagraphProperties(entries: readonly ParagraphPropertyEdit[]): void;
|
|
1845
|
+
/**
|
|
1846
|
+
* The Paragraph dialog as ONE write: alignment, indents, spacing, line spacing and the
|
|
1847
|
+
* five paragraph flags, over every paragraph the selection touches.
|
|
1848
|
+
*
|
|
1849
|
+
* One transaction, so pressing OK is one undo step and the page repaints once. An omitted
|
|
1850
|
+
* field is left as authored; `null` where the type allows it REMOVES the setting so the
|
|
1851
|
+
* style supplies it again. Returns whether anything was written.
|
|
1852
|
+
*/
|
|
1853
|
+
setParagraphFormat(update: SurfaceParagraphFormat): boolean;
|
|
1854
|
+
/**
|
|
1855
|
+
* Word's Clear All Formatting: direct run properties off the selected text, and every
|
|
1856
|
+
* paragraph the selection touches back to the default style with its direct paragraph
|
|
1857
|
+
* properties and mark dropped.
|
|
1858
|
+
*
|
|
1859
|
+
* Only what the document states DIRECTLY — formatting inherited from a style survives, so
|
|
1860
|
+
* the text falls back to its style rather than to nothing. Properties an op cannot name
|
|
1861
|
+
* (`w:rStyle`, `w:lang`, `w:sectPr`, `w:pBdr`) are preserved for the same reason every
|
|
1862
|
+
* other write preserves them.
|
|
1863
|
+
*/
|
|
1864
|
+
clearFormatting(): void;
|
|
1865
|
+
/**
|
|
1866
|
+
* Formatting as it stands at the selection, for a toolbar to reflect.
|
|
1867
|
+
*
|
|
1868
|
+
* With a typing format armed at the caret this reports what the NEXT characters typed
|
|
1869
|
+
* will look like, not what the document holds — which is the answer a toolbar wants and
|
|
1870
|
+
* the one Word gives.
|
|
1871
|
+
*/
|
|
1872
|
+
formatting(): SurfaceFormatting;
|
|
1873
|
+
/**
|
|
1874
|
+
* The section the document declares: page size, margins, columns, orientation.
|
|
1875
|
+
*
|
|
1876
|
+
* What a ruler is made of, and what pagination is measured against.
|
|
1877
|
+
*/
|
|
1878
|
+
sectionProperties(): SectionProperties;
|
|
1879
|
+
/**
|
|
1880
|
+
* The section GOVERNING one paragraph — what a ruler or dialog reflects when the caret sits
|
|
1881
|
+
* in a multi-section document.
|
|
1882
|
+
*
|
|
1883
|
+
* Body content answers for itself, whatever story is open. A header or footer belongs to the
|
|
1884
|
+
* section that names its relationship, and a note to the section holding its reference mark.
|
|
1885
|
+
* An id nothing settles falls back to the FIRST section: the tail is the document-wide answer
|
|
1886
|
+
* and is wrong for everything not on the last page.
|
|
1887
|
+
*/
|
|
1888
|
+
sectionPropertiesAt(paragraphId: string): SectionProperties;
|
|
1889
|
+
/**
|
|
1890
|
+
* How a section-addressed op should name the section `paragraphId` is in.
|
|
1891
|
+
*
|
|
1892
|
+
* `w:sectPr` lives on the body story, so such an op can only name body content — and a caret
|
|
1893
|
+
* in a header or a note is not body content. Passing that caret straight through made every
|
|
1894
|
+
* section write from furniture fail `unknown-paragraph`.
|
|
1895
|
+
*/
|
|
1896
|
+
sectionAnchorParagraphAt(paragraphId: string): SectionAnchor;
|
|
1897
|
+
/**
|
|
1898
|
+
* Write section page-setup fields — size, orientation, margins — as ONE undoable
|
|
1899
|
+
* transaction. Twips throughout; omitted fields are left as authored. With
|
|
1900
|
+
* `anchorParagraphId` only that paragraph's governing section is written (Word's
|
|
1901
|
+
* "Apply to: This section"); without it, every section. Returns whether the write
|
|
1902
|
+
* committed (a hostile value is refused by the op layer).
|
|
1903
|
+
*/
|
|
1904
|
+
setSectionProperties(update: {
|
|
1905
|
+
readonly pageWidthTwips?: number;
|
|
1906
|
+
readonly pageHeightTwips?: number;
|
|
1907
|
+
readonly orientation?: 'portrait' | 'landscape';
|
|
1908
|
+
readonly marginTopTwips?: number;
|
|
1909
|
+
readonly marginRightTwips?: number;
|
|
1910
|
+
readonly marginBottomTwips?: number;
|
|
1911
|
+
readonly marginLeftTwips?: number;
|
|
1912
|
+
readonly anchorParagraphId?: string;
|
|
1913
|
+
}): boolean;
|
|
1914
|
+
/**
|
|
1915
|
+
* Insert a section break at the caret: the paragraph splits, and the head ends a new
|
|
1916
|
+
* section cloning the governing section's page setup — Word's Layout > Breaks. One
|
|
1917
|
+
* undoable step. Returns whether the break committed.
|
|
1918
|
+
*
|
|
1919
|
+
* `breakType` says where the section AFTER the break begins: `'nextPage'` (the default,
|
|
1920
|
+
* Word's Next Page) starts a new sheet, `'continuous'` keeps it on the sheet the
|
|
1921
|
+
* previous section ended, which is how a mid-page column or margin change is authored.
|
|
1922
|
+
*/
|
|
1923
|
+
insertSectionBreak(breakType?: SectionBreakInsertType): boolean;
|
|
1924
|
+
/**
|
|
1925
|
+
* Why {@link insertSectionBreak} would refuse this kind right now, or `null`.
|
|
1926
|
+
*
|
|
1927
|
+
* THE authority for the BREAK's own questions, so `Editor.can` and the write cannot answer
|
|
1928
|
+
* those differently. Both halves are things only the surface knows: the LIVE editing mode
|
|
1929
|
+
* (a document that declares `w:trackRevisions` opens suggesting without anyone passing a
|
|
1930
|
+
* mode, and Review > Track Changes moves it again afterwards), and the paragraph the break
|
|
1931
|
+
* would actually land in — which for a range in suggesting mode is past the struck words,
|
|
1932
|
+
* not the selection's head.
|
|
1933
|
+
*
|
|
1934
|
+
* NOT the deletion's questions. A break replaces the selection first, and that deletion can
|
|
1935
|
+
* cross content a control holds or a region protected some other way; only the store sees
|
|
1936
|
+
* that, and it sees it at write time. So a range whose landing is fine while its deletion
|
|
1937
|
+
* is not answers `null` here and refuses at the press — as every other replacing command in
|
|
1938
|
+
* the engine does, less loudly. Story scope is gated separately again, because a caret in a
|
|
1939
|
+
* header refuses every break kind for a different reason.
|
|
1940
|
+
*/
|
|
1941
|
+
sectionBreakRefusal(breakType?: SectionBreakInsertType): string | null;
|
|
1942
|
+
/** The layout session, so a host or a test can see how much work a pass actually did. */
|
|
1943
|
+
layoutSession(): {
|
|
1944
|
+
readonly stats: {
|
|
1945
|
+
readonly placed: number;
|
|
1946
|
+
readonly total: number;
|
|
1947
|
+
readonly reusedPages: number;
|
|
1948
|
+
};
|
|
1949
|
+
};
|
|
1950
|
+
/**
|
|
1951
|
+
* The hyperlink lane: what link the caret is in, and the insert / retarget / unlink verbs.
|
|
1952
|
+
*
|
|
1953
|
+
* Every verb is one `transact`, so it is one undo step. Targets going IN are host-supplied
|
|
1954
|
+
* and pass the package's own URL allowlist; targets coming OUT are the sanitized
|
|
1955
|
+
* projection, so a caller cannot accidentally hand a refused scheme to a sink.
|
|
1956
|
+
*/
|
|
1957
|
+
readonly hyperlinks: HyperlinkOps;
|
|
1958
|
+
readonly equations: EquationOps;
|
|
1959
|
+
/**
|
|
1960
|
+
* Content-control chrome, form-fill navigation, and value / remove verbs.
|
|
1961
|
+
*
|
|
1962
|
+
* Value and remove commit through `session.applyTreeOps` — the same write path as typing.
|
|
1963
|
+
* Show-all and form-fill are surface chrome and never reflow layout.
|
|
1964
|
+
*/
|
|
1965
|
+
readonly contentControls: ContentControlOps;
|
|
1966
|
+
/** Word's Format Painter: capture, apply, and the transient armed mode. */
|
|
1967
|
+
readonly formatPainter: FormatPainterOps;
|
|
1968
|
+
/** Whether a `rows`×`cols` table can be inserted at the caret. */
|
|
1969
|
+
canInsertTable(rows: number, cols: number): boolean;
|
|
1970
|
+
/**
|
|
1971
|
+
* Insert an empty `rows`×`cols` table at the caret, columns evenly dividing the content
|
|
1972
|
+
* width of the caret's section, and leave the caret in the first cell.
|
|
1973
|
+
*/
|
|
1974
|
+
insertTable(rows: number, cols: number): boolean;
|
|
1975
|
+
/** Whether the addressed (or caret-local) body TOC can be refreshed. */
|
|
1976
|
+
canRefreshToc(tocId?: string): boolean;
|
|
1977
|
+
/** Whether a generated body TOC can be inserted before the caret paragraph. */
|
|
1978
|
+
canInsertToc(): boolean;
|
|
1979
|
+
/** Insert and populate a generated body TOC before the caret paragraph. */
|
|
1980
|
+
insertToc(): boolean;
|
|
1981
|
+
/** Refresh cached TOC entries and/or page numbers through the two-pass layout pipeline. */
|
|
1982
|
+
canEditTextFormField(): boolean;
|
|
1983
|
+
editTextFormField(): boolean;
|
|
1984
|
+
refreshToc(tocId?: string, mode?: 'entire' | 'pageNumbers'): boolean;
|
|
1985
|
+
/**
|
|
1986
|
+
* Rewrite stale REF field results in the body, footnote and endnote stories so a save
|
|
1987
|
+
* exports what the pages paint. Fresh results commit nothing (no transaction, no revision
|
|
1988
|
+
* bump, no undo entry); a rewrite is ONE transaction and ONE undo unit across every stale
|
|
1989
|
+
* part. Viewing, a non-editable session, and a collaborative session write nothing — the
|
|
1990
|
+
* collaboration gate cannot journal the rewrite, so those saves export cached results and
|
|
1991
|
+
* the call returns false.
|
|
1992
|
+
*/
|
|
1993
|
+
refreshRefFieldResults(): boolean;
|
|
1994
|
+
/**
|
|
1995
|
+
* Commit pending form input, refresh REF results, and serialize the document.
|
|
1996
|
+
* Throws an error with code `invalidArgs` for invalid form values, or `invalidState`
|
|
1997
|
+
* during an active edit. Retry after the edit finishes. A destroyed surface throws
|
|
1998
|
+
* with code `destroyed`. Does not change focus.
|
|
1999
|
+
*/
|
|
2000
|
+
save(): Uint8Array;
|
|
2001
|
+
/** Whether a body paragraph belongs to a detected TOC boundary or cached result. */
|
|
2002
|
+
isInsideToc(paragraphId: string): boolean;
|
|
2003
|
+
/**
|
|
2004
|
+
* Bookmark jumps and the ONE external-activation gate. A host's popover "open" action
|
|
2005
|
+
* calls `openExternal`; nothing else in the engine may call `window.open`.
|
|
2006
|
+
*/
|
|
2007
|
+
readonly navigation: SurfaceNavigation;
|
|
2008
|
+
/**
|
|
2009
|
+
* Pin the current selection so it stays VISIBLY selected while focus is elsewhere.
|
|
2010
|
+
*
|
|
2011
|
+
* A document has one selection: the moment a panel focuses an input of its own the browser
|
|
2012
|
+
* takes the highlight off the text, which is when the user most needs to see what the panel
|
|
2013
|
+
* is about to act on. This draws the range on the engine's own overlay instead, so it
|
|
2014
|
+
* survives the focus move. The MODEL selection is untouched — the op the panel finally runs
|
|
2015
|
+
* addresses the same characters it always would.
|
|
2016
|
+
*
|
|
2017
|
+
* The pin releases itself when the caret leaves the range (either edge counts as inside),
|
|
2018
|
+
* which is what lets a host close its panel on "the user clicked somewhere else" without
|
|
2019
|
+
* every adapter reimplementing that comparison.
|
|
2020
|
+
*/
|
|
2021
|
+
retainSelection(): SelectionPin;
|
|
2022
|
+
/** Drop one owned pin. Another owner's pin remains visible. */
|
|
2023
|
+
releaseSelection(pin: SelectionPin): void;
|
|
2024
|
+
/** The pinned range, or null once it was released or escaped. */
|
|
2025
|
+
retainedSelection(): SemanticSelection | null;
|
|
2026
|
+
/**
|
|
2027
|
+
* How edits are written right now.
|
|
2028
|
+
*
|
|
2029
|
+
* Lives on the SURFACE, not on the store. The store's write vocabulary stays explicit —
|
|
2030
|
+
* an op says whether it is tracked — and the surface is the one thing that knows a
|
|
2031
|
+
* keystroke happened, so it is the right place to decide what that keystroke becomes.
|
|
2032
|
+
*/
|
|
2033
|
+
editingMode(): SurfaceEditingMode;
|
|
2034
|
+
setEditingMode(mode: SurfaceEditingMode): void;
|
|
2035
|
+
/** Set the ambient author after buffered text commits under the previous author. */
|
|
2036
|
+
setAuthor(author: string | undefined): void;
|
|
2037
|
+
/** The ambient author tracked edits and review writes record, or undefined. */
|
|
2038
|
+
author(): string | undefined;
|
|
2039
|
+
/** Replace localized drawing labels and repaint materialized pages. */
|
|
2040
|
+
setDrawingStrings(strings: DrawingPaintStrings): void;
|
|
2041
|
+
/** Update shared form-control labels without replacing open dialogs. */
|
|
2042
|
+
setTranslate(translate: PaginatedSurfaceOptions['translate']): void;
|
|
2043
|
+
/** Set regional conventions for subsequent date input without reformatting stored values. */
|
|
2044
|
+
setLocale(locale: string | undefined): void;
|
|
2045
|
+
/** Replace the localized title used by later TOC insertions. */
|
|
2046
|
+
setTocLabels(labels: NonNullable<PaginatedSurfaceOptions['tocLabels']>): void;
|
|
2047
|
+
/**
|
|
2048
|
+
* Every author with a revision in the CURRENT layout, mapped to Word's colour slot by
|
|
2049
|
+
* order of first appearance. One map instance per layout, so a caller can key caches on
|
|
2050
|
+
* its identity.
|
|
2051
|
+
*/
|
|
2052
|
+
revisionAuthors(): ReadonlyMap<string, number>;
|
|
2053
|
+
/** Reviewers currently projected as accepted, without changing the document. */
|
|
2054
|
+
hiddenRevisionAuthors(): ReadonlySet<string>;
|
|
2055
|
+
/** Show one reviewer's markup, or render that reviewer's changes as accepted. */
|
|
2056
|
+
setRevisionAuthorVisible(author: string, visible: boolean): void;
|
|
2057
|
+
/** Show or hide every reviewer in one layout pass. */
|
|
2058
|
+
setAllRevisionAuthorsVisible(visible: boolean): void;
|
|
2059
|
+
/** Clear the reviewer filter in one layout pass. */
|
|
2060
|
+
showAllRevisionAuthors(): void;
|
|
2061
|
+
/** Apply a view-time predicate over complete tracked-change items. */
|
|
2062
|
+
setTrackedChangesFilter(predicate: TrackedChangePredicate | null, mode?: TrackedChangeFilterMode): void;
|
|
2063
|
+
/** The presence colour the caret paints for `name`, sanitized as the paint sink is. */
|
|
2064
|
+
remotePresenceColor(name: string): string | undefined;
|
|
2065
|
+
/**
|
|
2066
|
+
* Replace how tracked changes are coloured, live. Paint-level: the pages repaint without
|
|
2067
|
+
* remeasuring a line, and the caret, selection and undo history stay where they are.
|
|
2068
|
+
*/
|
|
2069
|
+
setRevisionMarkup(settings: ResolvedRevisionMarkup): void;
|
|
2070
|
+
setRevisionStyles(colors: RevisionStyles | undefined): void;
|
|
2071
|
+
/** Toggle paragraph-end furniture without layout or document changes. */
|
|
2072
|
+
setShowParagraphMarks(show: boolean): void;
|
|
2073
|
+
/**
|
|
2074
|
+
* Hand remote-caret label content to the host, or take it back with `null`.
|
|
2075
|
+
*
|
|
2076
|
+
* With a host set, the engine still creates and positions each label (same class, same
|
|
2077
|
+
* presence colour) but leaves it empty, marks it `data-docx-remote-actor`, and calls
|
|
2078
|
+
* {@link RemoteCaretLabelHost.publish} after every paint that rebuilt the labels.
|
|
2079
|
+
* Registration and unregistration repaint immediately, so the first publish fires
|
|
2080
|
+
* without waiting for awareness to move and unregistering restores the default
|
|
2081
|
+
* collaborator-name labels.
|
|
2082
|
+
*/
|
|
2083
|
+
setRemoteCaretLabelHost(host: RemoteCaretLabelHost | null): void;
|
|
2084
|
+
/**
|
|
2085
|
+
* Install the painter for host text highlights, or remove it with `null`. The surface calls
|
|
2086
|
+
* it after every render and once on installation, with the frame it just painted.
|
|
2087
|
+
*/
|
|
2088
|
+
setHighlightPainter(painter: SurfaceOverlayPainter | null): void;
|
|
2089
|
+
/** Call the installed highlight painter against the current frame. */
|
|
2090
|
+
repaintHighlights(): void;
|
|
2091
|
+
/**
|
|
2092
|
+
* Commit ops that came from automation, through the gate a keystroke goes through.
|
|
2093
|
+
*
|
|
2094
|
+
* The narrow entry an automation host writes with, and the reason it needs one: reaching
|
|
2095
|
+
* `session.applyTreeOps` past this skips the editing-mode gate entirely — a document open for
|
|
2096
|
+
* viewing accepts a scripted edit, and a suggesting document records one as a permanent
|
|
2097
|
+
* change with no proposal and no author. Here, viewing refuses, suggesting attributes, the
|
|
2098
|
+
* refusal reason is reported like any other, and the pages repaint from the commit.
|
|
2099
|
+
*
|
|
2100
|
+
* The ops address the story the CALLER named, whatever story the reader is in: the caller
|
|
2101
|
+
* identified its target before calling, so following the caret into a header would write
|
|
2102
|
+
* somewhere else entirely. They default to the body rather than to the reader's story.
|
|
2103
|
+
*
|
|
2104
|
+
* They arrive as a BUILDER, given a way to mint the relationship an external hyperlink names.
|
|
2105
|
+
* That mint changes the package outside the transaction and outside the undo stack, so it must not
|
|
2106
|
+
* happen until the mode has allowed the write — a link minted while the batch was still being
|
|
2107
|
+
* planned left its target in a read-only document's `.rels`. A builder answering null means the
|
|
2108
|
+
* target is one this engine will not author, and the write is refused having changed nothing.
|
|
2109
|
+
*/
|
|
2110
|
+
applyAutomationOps(staged: (relate: (url: string) => string | null) => readonly TreeDocOp[] | null, scope?: StoryScope, packageEdits?: readonly ((pkg: OoxmlPackage) => OoxmlPackage)[], requiresReview?: boolean): TreeApplyResult;
|
|
2111
|
+
/**
|
|
2112
|
+
* Which revision halves this surface is SHOWING.
|
|
2113
|
+
*
|
|
2114
|
+
* Read by the automation adapter so the object model's formatting reaches the same runs the
|
|
2115
|
+
* toolbar does. A range's offsets cover every revision half whatever the view does with
|
|
2116
|
+
* them, so with markup on, a selection over a struck word means one thing to a reader and
|
|
2117
|
+
* would mean another to a script that assumed the resolved result.
|
|
2118
|
+
*/
|
|
2119
|
+
revisionDisplayMode(): ReviewDisplayMode;
|
|
2120
|
+
/** Change the review display without accepting, rejecting, or changing author filters. */
|
|
2121
|
+
setRevisionDisplayMode(mode: ReviewDisplayMode): void;
|
|
2122
|
+
/**
|
|
2123
|
+
* Where a replacement for `[start, end)` of a paragraph lands, or null when the edit would
|
|
2124
|
+
* not be tracked.
|
|
2125
|
+
*
|
|
2126
|
+
* Non-null exactly when suggesting: the struck words stay, so the replacement goes past
|
|
2127
|
+
* them, minus whatever of the range was this author's own pending insertion, which leaves.
|
|
2128
|
+
* The SAME rule every replacing lane of the keyboard reads, exposed so the automation object
|
|
2129
|
+
* model aims a scripted `Replace` where typing does and can answer the span it wrote.
|
|
2130
|
+
*/
|
|
2131
|
+
replacementLanding(paragraphId: string, start: number, end: number): number | null;
|
|
2132
|
+
/**
|
|
2133
|
+
* Commit review ops — accept, reject, a new comment — through the SAME path a keystroke
|
|
2134
|
+
* takes: layout, paint, and a caret clamped to what the document now holds.
|
|
2135
|
+
*
|
|
2136
|
+
* `intent` names WHICH review write this is, so a lane that judges them can tell them apart.
|
|
2137
|
+
* The callback is opaque, and a replica admits only the writes proven to replicate — see
|
|
2138
|
+
* {@link ReviewWriteIntent}.
|
|
2139
|
+
*
|
|
2140
|
+
* Applying them straight to the session skipped all three. Rejecting an insertion left the
|
|
2141
|
+
* pages painting text the tree no longer had, every card anchored where it used to be, and
|
|
2142
|
+
* the caret past the end of the paragraph — after which every keystroke was refused with
|
|
2143
|
+
* `offset-out-of-range` until the user happened to click somewhere else.
|
|
2144
|
+
*/
|
|
2145
|
+
commitReviewOps(run: () => {
|
|
2146
|
+
readonly committed: boolean;
|
|
2147
|
+
readonly reason?: unknown;
|
|
2148
|
+
}, intent?: ReviewWriteIntent): void;
|
|
2149
|
+
/**
|
|
2150
|
+
* The layout as last PUBLISHED, without forcing pending work.
|
|
2151
|
+
*
|
|
2152
|
+
* `layout()` flushes first, which is right for a caller that is about to act on geometry
|
|
2153
|
+
* and wrong for one that merely decorates it. The review rail read through `layout()` and
|
|
2154
|
+
* so forced a synchronous full pass on every keystroke — eleven seconds per read on a
|
|
2155
|
+
* 2432-block document. A card whose anchor is one frame stale is invisible; the paint that
|
|
2156
|
+
* follows the flush republishes it.
|
|
2157
|
+
*/
|
|
2158
|
+
publishedLayout(): SemanticLayout;
|
|
2159
|
+
/**
|
|
2160
|
+
* How the current selection came to address a drawing, if it does at all.
|
|
2161
|
+
*
|
|
2162
|
+
* Word's rule: a caret NEXT TO a floating object is a text caret, never an object selection —
|
|
2163
|
+
* only clicking the object (or a host selection write) selects it. The engine's selection is a
|
|
2164
|
+
* caret at the anchor offset either way, so offsets cannot tell them apart; this is the
|
|
2165
|
+
* discriminator. `none` for a fresh mount (the initial caret routinely coincides with a drawing
|
|
2166
|
+
* anchored at offset zero) and after typing, caret keys, or a press on a non-drawing. `pointer`
|
|
2167
|
+
* names the drawing the press landed on, so a stale press cannot claim a later one.
|
|
2168
|
+
*/
|
|
2169
|
+
drawingSelectionIntent(): DrawingSelectionIntent;
|
|
2170
|
+
/**
|
|
2171
|
+
* Paint-scale coordinate context for overlay chrome.
|
|
2172
|
+
*
|
|
2173
|
+
* Internal seam — not part of the public editor contract. Image overlay uses the same
|
|
2174
|
+
* `zoom * 96/72` scale and per-page horizontal offsets the painter applied.
|
|
2175
|
+
*/
|
|
2176
|
+
overlayCoordinates(): SurfaceOverlayCoordinates;
|
|
2177
|
+
/**
|
|
2178
|
+
* The comment, tracked change or carded custom node the caret is in, as the painted bands
|
|
2179
|
+
* report it. A custom node without `reviewCard` is never the answer: it has no card.
|
|
2180
|
+
*
|
|
2181
|
+
* ONE source for "which item is open". The band under the text and the card beside it are
|
|
2182
|
+
* two views of the same answer, and deriving it twice let them disagree — the card closed
|
|
2183
|
+
* while the text stayed highlighted.
|
|
2184
|
+
*/
|
|
2185
|
+
activeReviewKey(): string | null;
|
|
2186
|
+
/**
|
|
2187
|
+
* Open THIS item, named by key, for as long as `selection` stays the live one.
|
|
2188
|
+
*
|
|
2189
|
+
* Without it the caret is the only evidence of which card is open, and a caret cannot name a
|
|
2190
|
+
* card when two cards cover exactly the same characters: `w:ins` wrapping `w:del` — content
|
|
2191
|
+
* one reviewer added and another struck — gives the insertion and the deletion one identical
|
|
2192
|
+
* range, and every click on either card classified back to whichever the queue happened to
|
|
2193
|
+
* list first. The reader clicked "Deleted" and watched "Added" light up.
|
|
2194
|
+
*
|
|
2195
|
+
* A key, not a position, because the position is precisely what is ambiguous. It holds only
|
|
2196
|
+
* while the selection matches; a pointer or keyboard move hands the answer back to the caret,
|
|
2197
|
+
* which is what lets the reader step out of a card by clicking away from it.
|
|
2198
|
+
*
|
|
2199
|
+
* `selection` is what activation wants installed, and it is installed HERE rather than by a
|
|
2200
|
+
* `setSelection` of the caller's own so that the pin is up before anything is published. The
|
|
2201
|
+
* other order repainted the bands and reported state while the caret was still the only
|
|
2202
|
+
* evidence, so a host saw the wrong twin active for one frame and then a correction. Omit it
|
|
2203
|
+
* to pin against the live selection, which is what a header or note scope has already set.
|
|
2204
|
+
*/
|
|
2205
|
+
activateReview(key: string, selection?: SemanticSelection, options?: {
|
|
2206
|
+
readonly allowExcluded?: boolean;
|
|
2207
|
+
}): void;
|
|
2208
|
+
/**
|
|
2209
|
+
* The key {@link activateReview} pinned, or null once its selection is no longer live.
|
|
2210
|
+
*
|
|
2211
|
+
* Exists so nothing outside the surface keeps its own copy of "the selection came from
|
|
2212
|
+
* opening a card". `selectionPlacement` needs that fact to stay quiet about offering a
|
|
2213
|
+
* comment on text the reader only selected by opening a card over it, and the copy it used to
|
|
2214
|
+
* keep was set on one of activation's three branches, so a header card offered to comment on
|
|
2215
|
+
* itself.
|
|
2216
|
+
*/
|
|
2217
|
+
activatedReviewKey(): string | null;
|
|
2218
|
+
/**
|
|
2219
|
+
* Close the open item until the caret next moves.
|
|
2220
|
+
*
|
|
2221
|
+
* What a click on the canvas means. The caret does not move when someone clicks the grey
|
|
2222
|
+
* around the page, so nothing else would ever put the item away.
|
|
2223
|
+
*/
|
|
2224
|
+
dismissActiveReview(): void;
|
|
2225
|
+
/**
|
|
2226
|
+
* Revision kinds the CARET must not activate, or null for none.
|
|
2227
|
+
*
|
|
2228
|
+
* The review rail filters what it renders (structural and format cards are hidden by
|
|
2229
|
+
* default), but {@link activeReviewKey} used to compute over the unfiltered queue — a
|
|
2230
|
+
* click on tracked text under a format change activated a card the rail does not draw,
|
|
2231
|
+
* and nothing on screen lit up. A host that filters its list tells the surface, so the
|
|
2232
|
+
* band and the visible cards stay one answer.
|
|
2233
|
+
*/
|
|
2234
|
+
setReviewActivationExclusions(kinds: readonly ReviewRevisionKind[] | null, options?: {
|
|
2235
|
+
readonly formattingKinds?: readonly string[];
|
|
2236
|
+
}): void;
|
|
2237
|
+
/**
|
|
2238
|
+
* `bookmarkName -> position` over the current revision, for resolving an internal link.
|
|
2239
|
+
* First in document order wins a duplicate name, matching Word.
|
|
2240
|
+
*/
|
|
2241
|
+
bookmarks(): BookmarkIndex;
|
|
2242
|
+
/** The selected text, for copy and cut. */
|
|
2243
|
+
selectedText(): string;
|
|
2244
|
+
/**
|
|
2245
|
+
* Every clipboard flavour for the current selection: plain text, and the interop HTML
|
|
2246
|
+
* carrying the embedded fragment when the selection is a body-story range. A cell
|
|
2247
|
+
* rectangle answers grid text plus a flattened table; `html` is null where only plain
|
|
2248
|
+
* text should be written. Unsupported object selections return a refusal reason.
|
|
2249
|
+
*/
|
|
2250
|
+
copyFlavours(): {
|
|
2251
|
+
readonly text: string;
|
|
2252
|
+
readonly html: string | null;
|
|
2253
|
+
readonly reason?: 'unsupported-content';
|
|
2254
|
+
};
|
|
2255
|
+
/**
|
|
2256
|
+
* Route one paste payload by fidelity: embedded fragment, then external HTML, then
|
|
2257
|
+
* plain text. Unsupported object fragments refuse without fallback. Other decode, read,
|
|
2258
|
+
* or apply failures can degrade. Suggesting mode, non-body
|
|
2259
|
+
* stories and an armed force-plain all land on the plain lane. False when the payload
|
|
2260
|
+
* landed on no lane at all (nothing to insert).
|
|
2261
|
+
*/
|
|
2262
|
+
pasteRich(text: string, html: string | null): boolean;
|
|
2263
|
+
/** The next paste routes plain, whatever its payload carries (Cmd+Shift+V). */
|
|
2264
|
+
armForcePlainPaste(): void;
|
|
2265
|
+
/** Remove the selection, if any. Returns whether anything was deleted. */
|
|
2266
|
+
deleteSelection(): boolean;
|
|
2267
|
+
navigate(command: NavigationCommand, extend?: boolean): void;
|
|
2268
|
+
/** Reverse the last history entry and put the caret back where it was made. */
|
|
2269
|
+
undo(): void;
|
|
2270
|
+
redo(): void;
|
|
2271
|
+
/**
|
|
2272
|
+
* Refresh table insertion furniture labels without remounting or relayout.
|
|
2273
|
+
*
|
|
2274
|
+
* @public
|
|
2275
|
+
*/
|
|
2276
|
+
refreshTableInteractionLabels(): void;
|
|
2277
|
+
focus(): void;
|
|
2278
|
+
/**
|
|
2279
|
+
* Refresh table insertion furniture labels without remounting the surface.
|
|
2280
|
+
*
|
|
2281
|
+
* @public
|
|
2282
|
+
*/
|
|
2283
|
+
setTableInteractionLabel(resolver: (key: 'table.insertRowBelow' | 'table.insertColumnRight') => string): void;
|
|
2284
|
+
destroy(): void;
|
|
2285
|
+
/**
|
|
2286
|
+
* The section a painted page belongs to, and the page that section starts on.
|
|
2287
|
+
*
|
|
2288
|
+
* Published because opening a furniture story without a page opens it without a section, and
|
|
2289
|
+
* the section is what the ruler clamps to and what a new table's grid is divided from. One
|
|
2290
|
+
* header part can serve several sections, so only the page settles which one the reader is
|
|
2291
|
+
* looking at.
|
|
2292
|
+
*/
|
|
2293
|
+
sectionAtPage(pageIndex: number): {
|
|
2294
|
+
sectionIndex: number;
|
|
2295
|
+
sectionStart: number;
|
|
2296
|
+
};
|
|
2297
|
+
/** Active editing view — body, or an open header/footer story by rId. */
|
|
2298
|
+
activeScope(): ViewScope;
|
|
2299
|
+
/** Activate a view scope. Returns false when a header/footer rId cannot be opened. */
|
|
2300
|
+
setActiveScope(scope: ViewScope): boolean;
|
|
2301
|
+
/**
|
|
2302
|
+
* Open a header/footer story for editing on the painted surface.
|
|
2303
|
+
* Refuses dangling / unknown relationship ids.
|
|
2304
|
+
*/
|
|
2305
|
+
enterHeaderFooter(args: {
|
|
2306
|
+
readonly rId: string;
|
|
2307
|
+
readonly pageIndex?: number;
|
|
2308
|
+
readonly sectionIndex?: number;
|
|
2309
|
+
readonly kind?: 'header' | 'footer';
|
|
2310
|
+
readonly variant?: 'default' | 'first' | 'even';
|
|
2311
|
+
readonly position?: SemanticPosition;
|
|
2312
|
+
}): boolean;
|
|
2313
|
+
/** Leave furniture editing and restore the prior body selection. */
|
|
2314
|
+
exitHeaderFooter(): void;
|
|
2315
|
+
/** Chrome read-model for the open furniture scope, or null when editing the body. */
|
|
2316
|
+
headerFooterState(): {
|
|
2317
|
+
readonly editing: 'header' | 'footer' | null;
|
|
2318
|
+
readonly sectionIndex: number;
|
|
2319
|
+
readonly variant?: 'default' | 'first' | 'even';
|
|
2320
|
+
readonly rId?: string;
|
|
2321
|
+
readonly partName?: string;
|
|
2322
|
+
readonly inherited?: boolean;
|
|
2323
|
+
readonly titlePage?: boolean;
|
|
2324
|
+
readonly evenAndOddHeaders?: boolean;
|
|
2325
|
+
readonly headerDistanceTwips?: number;
|
|
2326
|
+
readonly footerDistanceTwips?: number;
|
|
2327
|
+
} | null;
|
|
2328
|
+
/**
|
|
2329
|
+
* Commit one package-level furniture lifecycle op (create/delete/link/unlink/options).
|
|
2330
|
+
* Flushes layout so the next enter/rebind sees the new resolution.
|
|
2331
|
+
*/
|
|
2332
|
+
applyHeaderFooterLifecycle(op: {
|
|
2333
|
+
readonly op: 'createHeaderFooter' | 'deleteHeaderFooter' | 'linkToPrevious' | 'unlinkFromPrevious' | 'setSectionFurnitureOptions' | 'setDocumentProtection';
|
|
2334
|
+
readonly sectionIndex?: number;
|
|
2335
|
+
/** `setDocumentProtection` only: enforce filling-in-forms protection, or lift it. */
|
|
2336
|
+
readonly enforce?: boolean;
|
|
2337
|
+
readonly kind?: 'header' | 'footer';
|
|
2338
|
+
readonly variant?: 'default' | 'first' | 'even';
|
|
2339
|
+
readonly titlePage?: boolean;
|
|
2340
|
+
readonly evenAndOddHeaders?: boolean;
|
|
2341
|
+
readonly headerDistanceTwips?: number;
|
|
2342
|
+
readonly footerDistanceTwips?: number;
|
|
2343
|
+
}): {
|
|
2344
|
+
readonly ok: true;
|
|
2345
|
+
} | {
|
|
2346
|
+
readonly ok: false;
|
|
2347
|
+
readonly reason: string;
|
|
2348
|
+
};
|
|
2349
|
+
/** Insert an allowlisted page field at the caret in the open HF story. */
|
|
2350
|
+
insertPageField(field: 'PAGE' | 'NUMPAGES' | 'SECTIONPAGES' | 'PAGE_X_OF_Y'): boolean;
|
|
2351
|
+
/** Insert a footnote/endnote at the body caret. */
|
|
2352
|
+
insertNote(noteKind: 'footnote' | 'endnote'): boolean;
|
|
2353
|
+
deleteNote(noteKind: 'footnote' | 'endnote', noteId: number): boolean;
|
|
2354
|
+
convertNote(fromKind: 'footnote' | 'endnote', noteId: number): boolean;
|
|
2355
|
+
convertAllNotes(fromKind: 'footnote' | 'endnote'): boolean;
|
|
2356
|
+
setNoteProperties(args: {
|
|
2357
|
+
readonly scope: 'document' | 'section';
|
|
2358
|
+
readonly sectionIndex?: number;
|
|
2359
|
+
readonly footnote?: {
|
|
2360
|
+
readonly numFmt?: string;
|
|
2361
|
+
readonly numRestart?: string;
|
|
2362
|
+
readonly position?: string;
|
|
2363
|
+
readonly numStart?: number;
|
|
2364
|
+
};
|
|
2365
|
+
readonly endnote?: {
|
|
2366
|
+
readonly numFmt?: string;
|
|
2367
|
+
readonly numRestart?: string;
|
|
2368
|
+
readonly position?: string;
|
|
2369
|
+
readonly numStart?: number;
|
|
2370
|
+
};
|
|
2371
|
+
}): boolean;
|
|
2372
|
+
enterNote(scopeId: string, position?: {
|
|
2373
|
+
paragraphId: string;
|
|
2374
|
+
offset: number;
|
|
2375
|
+
}): boolean;
|
|
2376
|
+
exitNote(): void;
|
|
2377
|
+
/** Resolved/authored note properties for the caret section — chrome read-model. */
|
|
2378
|
+
notePropertiesState(): NotePropertiesStateSnapshot | null;
|
|
2379
|
+
/** Plain-text preview for hover chrome — never returns markup. */
|
|
2380
|
+
notePreviewText(scopeId: string): string | null;
|
|
2381
|
+
/** Commit one table-command plan as a single store transaction. */
|
|
2382
|
+
applyTableCommandPlan(plan: TableCommandPlan): ExecResult;
|
|
2383
|
+
}
|
|
2384
|
+
/**
|
|
2385
|
+
* What opening a document produced: a mounted surface, or a refusal.
|
|
2386
|
+
*
|
|
2387
|
+
* A result rather than a throw, because every refusal here comes from FILE input — a package the
|
|
2388
|
+
* bounded reader rejected, a part that exceeded a limit — and a malformed upload should surface
|
|
2389
|
+
* as a message the host can show rather than an exception it has to catch.
|
|
2390
|
+
*/
|
|
2391
|
+
type OpenPaginatedResult = {
|
|
2392
|
+
readonly ok: true;
|
|
2393
|
+
readonly surface: PaginatedSurface;
|
|
2394
|
+
} | {
|
|
2395
|
+
readonly ok: false;
|
|
2396
|
+
readonly reason: string;
|
|
2397
|
+
readonly detail?: string;
|
|
2398
|
+
};
|
|
2399
|
+
|
|
2400
|
+
/** One URL to fetch and the face it claims to be. */
|
|
2401
|
+
interface FontUrlSource {
|
|
2402
|
+
readonly url: string;
|
|
2403
|
+
readonly family: string;
|
|
2404
|
+
readonly weight: number;
|
|
2405
|
+
readonly style: 'normal' | 'italic';
|
|
2406
|
+
/**
|
|
2407
|
+
* Expected `sha256:` content hash. When present, mismatching bytes are REFUSED —
|
|
2408
|
+
* pin this for any URL not under the app's sole control.
|
|
2409
|
+
*/
|
|
2410
|
+
readonly hash?: string;
|
|
2411
|
+
readonly faceIndex?: number;
|
|
2412
|
+
}
|
|
2413
|
+
/**
|
|
2414
|
+
* What to fetch, and under what limits.
|
|
2415
|
+
*
|
|
2416
|
+
* Only `sources` is required. Each carries its own expected hash, so bytes are trusted by
|
|
2417
|
+
* CONTENT rather than by origin — a swapped asset fails admission even from a trusted host.
|
|
2418
|
+
*/
|
|
2419
|
+
interface LoadFontsRequest {
|
|
2420
|
+
readonly sources: readonly FontUrlSource[];
|
|
2421
|
+
/** Cache API bucket name; default `docx-editor-fonts`. */
|
|
2422
|
+
readonly cacheName?: string;
|
|
2423
|
+
/** Injectable for tests and CSP-constrained hosts; defaults to global `fetch`. */
|
|
2424
|
+
readonly fetcher?: typeof fetch;
|
|
2425
|
+
/** Per-font byte ceiling; defaults to the engine hard maximum. */
|
|
2426
|
+
readonly maxFontBytes?: number;
|
|
2427
|
+
/** Cancels loading with `signal.reason`, without returning per-source failures. */
|
|
2428
|
+
readonly signal?: AbortSignal;
|
|
2429
|
+
}
|
|
2430
|
+
/**
|
|
2431
|
+
* Why one font did not load.
|
|
2432
|
+
*
|
|
2433
|
+
* Distinguished rather than collapsed to "failed" because the responses differ: `networkError`
|
|
2434
|
+
* and `httpError` are worth retrying, while `hashMismatch` and `malformed` mean the bytes were
|
|
2435
|
+
* not what the source claimed and retrying will fetch the same wrong thing.
|
|
2436
|
+
*/
|
|
2437
|
+
type FontLoadFailureReason = 'networkError' | 'httpError' | 'hashMismatch' | 'overLimit' | 'emptyResponse'
|
|
2438
|
+
/** The declared face itself is unusable (empty family, out-of-range weight); nothing was fetched. */
|
|
2439
|
+
| 'invalidRequest'
|
|
2440
|
+
/** The bytes are not a font at all — most often an HTML error page served with 200. */
|
|
2441
|
+
| 'malformed';
|
|
2442
|
+
/**
|
|
2443
|
+
* One face that did not load, with whatever evidence the failure produced.
|
|
2444
|
+
*
|
|
2445
|
+
* Non-fatal: {@link LoadFontsResult} still carries every source that succeeded, and the affected
|
|
2446
|
+
* family falls back to the engine's fixed measurement.
|
|
2447
|
+
*/
|
|
2448
|
+
interface FontLoadFailure {
|
|
2449
|
+
readonly url: string;
|
|
2450
|
+
readonly request: FontFaceRequest;
|
|
2451
|
+
readonly reason: FontLoadFailureReason;
|
|
2452
|
+
/** HTTP status for `httpError`; hashes for `hashMismatch`. */
|
|
2453
|
+
readonly status?: number;
|
|
2454
|
+
readonly expectedHash?: string;
|
|
2455
|
+
readonly actualHash?: string;
|
|
2456
|
+
readonly diagnostic?: string;
|
|
2457
|
+
}
|
|
2458
|
+
/**
|
|
2459
|
+
* What one `loadFonts` call produced: the faces that arrived, plus the ones that did not.
|
|
2460
|
+
*
|
|
2461
|
+
* A `FontConfigurationFragment`, so it composes straight into `composeFontConfiguration`
|
|
2462
|
+
* alongside other font sources. Partial success is the normal case — compose it even with
|
|
2463
|
+
* failures present.
|
|
2464
|
+
*/
|
|
2465
|
+
interface LoadFontsResult extends FontConfigurationFragment {
|
|
2466
|
+
readonly sources: readonly FontSource[];
|
|
2467
|
+
readonly failures: readonly FontLoadFailure[];
|
|
2468
|
+
}
|
|
2469
|
+
/**
|
|
2470
|
+
* Fetch app-specified font URLs into verified, cache-backed `FontSource`s.
|
|
2471
|
+
*
|
|
2472
|
+
* Fetches ONLY the URLs listed — never a default host or engine-chosen CDN — and never
|
|
2473
|
+
* rejects for a per-source failure: the result carries every admitted source and a
|
|
2474
|
+
* typed entry for every drop. Cancellation instead rejects with `signal.reason`. Compose the result with `composeFontConfiguration`.
|
|
2475
|
+
*/
|
|
2476
|
+
declare function loadFonts(request: LoadFontsRequest): Promise<LoadFontsResult>;
|
|
2477
|
+
/**
|
|
2478
|
+
* Turn font bytes you ALREADY hold into a `FontSource` — a file input, IndexedDB, a
|
|
2479
|
+
* bundler import. `loadFonts` covers URLs; this covers everything else, so no caller has
|
|
2480
|
+
* to hand-assemble the record or reach for a hashing helper.
|
|
2481
|
+
*
|
|
2482
|
+
* Returns a typed failure instead of throwing when the descriptor or the bytes are
|
|
2483
|
+
* unusable, matching `loadFonts`: one bad face degrades itself, never its neighbours.
|
|
2484
|
+
*/
|
|
2485
|
+
declare function createFontSource(bytes: Uint8Array, request: FontFaceRequest & {
|
|
2486
|
+
readonly faceIndex?: number;
|
|
2487
|
+
}, options?: {
|
|
2488
|
+
readonly id?: string;
|
|
2489
|
+
readonly maxFontBytes?: number;
|
|
2490
|
+
}): {
|
|
2491
|
+
readonly source: FontSource;
|
|
2492
|
+
} | {
|
|
2493
|
+
readonly failure: FontLoadFailure;
|
|
2494
|
+
};
|
|
2495
|
+
|
|
2496
|
+
/** Options for loading application fonts when the editor resolves its font configuration. @public */
|
|
2497
|
+
interface CustomFontsOptions extends Omit<LoadFontsRequest, 'signal'> {
|
|
2498
|
+
/** Reports each failed face. Defaults to a console warning. Cancellation does not call this handler. */
|
|
2499
|
+
readonly onFailure?: (failure: FontLoadFailure) => void;
|
|
2500
|
+
}
|
|
2501
|
+
/** A font origin that supplies validated application font bytes on demand. @public */
|
|
2502
|
+
type CustomFontsResolver = MarkedFontResolver<(request: FontResolutionRequest) => Promise<LoadFontsResult>>;
|
|
2503
|
+
/**
|
|
2504
|
+
* Supply application fonts without manual resolver wiring.
|
|
2505
|
+
*
|
|
2506
|
+
* Loads all listed faces when the editor resolves fonts, including families the document
|
|
2507
|
+
* does not use yet. This makes company fonts available in the font picker for new documents.
|
|
2508
|
+
* Faces supplied by earlier origins are skipped by family, weight, and style; family
|
|
2509
|
+
* matching ignores case. URLs always come from `sources`, never from document text.
|
|
2510
|
+
*
|
|
2511
|
+
* Uses {@link loadFonts} for validation, optional hash checks, and browser caching.
|
|
2512
|
+
* The editor registers the returned bytes under private aliases. This function does not
|
|
2513
|
+
* change the document's selected fonts or register page-wide family names.
|
|
2514
|
+
*
|
|
2515
|
+
* Constructing the resolver does not fetch. Cancellation of the document load rejects
|
|
2516
|
+
* with `signal.reason`, without warnings or `onFailure` calls. Other face failures are
|
|
2517
|
+
* reported once per resolution, and successful faces remain available to the editor.
|
|
2518
|
+
*
|
|
2519
|
+
* ```ts
|
|
2520
|
+
* const fonts = useFonts(
|
|
2521
|
+
* customFonts({ sources: companyFontFiles, onFailure: reportFontFailure }),
|
|
2522
|
+
* packagedFonts(),
|
|
2523
|
+
* googleFonts(),
|
|
2524
|
+
* );
|
|
2525
|
+
* ```
|
|
2526
|
+
*
|
|
2527
|
+
* Use {@link loadFonts} directly to load every listed face eagerly.
|
|
2528
|
+
* @public
|
|
2529
|
+
*/
|
|
2530
|
+
declare function customFonts(options: CustomFontsOptions): CustomFontsResolver;
|
|
2531
|
+
|
|
2532
|
+
/**
|
|
2533
|
+
* A row that runs one chrome slot.
|
|
2534
|
+
*
|
|
2535
|
+
* @public
|
|
2536
|
+
*/
|
|
2537
|
+
interface ChromeMenuItemEntry {
|
|
2538
|
+
readonly kind: 'item';
|
|
2539
|
+
readonly slot: ChromeSlotId;
|
|
2540
|
+
/**
|
|
2541
|
+
* Plain-label override for this row.
|
|
2542
|
+
*
|
|
2543
|
+
* A slot's own `labelKey` is a TOOLTIP key, and several of them fold the shortcut into
|
|
2544
|
+
* the text (`formattingBar.boldShortcut` is "Bold (Ctrl+B)"). A menu puts the shortcut
|
|
2545
|
+
* in its own right-hand column, so the row needs the bare noun. Both keys already exist
|
|
2546
|
+
* in the catalogue — this points at the plain one rather than minting a duplicate.
|
|
2547
|
+
*/
|
|
2548
|
+
readonly labelKey?: string;
|
|
2549
|
+
/** i18n key of the shortcut shown right-aligned on the row (`toolbar.saveShortcut`). */
|
|
2550
|
+
readonly shortcutKey?: string;
|
|
2551
|
+
/**
|
|
2552
|
+
* The row opens a size PICKER instead of firing on click — Word's insert-table grid.
|
|
2553
|
+
* The slot still owns the label, the icon and the enabled state; only the dispatch
|
|
2554
|
+
* differs, and the picked size is what the host sends.
|
|
2555
|
+
*/
|
|
2556
|
+
readonly picker?: 'tableGrid';
|
|
2557
|
+
}
|
|
2558
|
+
/**
|
|
2559
|
+
* A row that opens a nested panel of rows (Insert › Break).
|
|
2560
|
+
*
|
|
2561
|
+
* It carries its own label and icon rather than a slot, because a submenu PARENT has no
|
|
2562
|
+
* command: clicking it opens the panel. Giving it a slot would mint a public id for a
|
|
2563
|
+
* control that can never be enabled, and `toolbarCommandState` would have to invent an
|
|
2564
|
+
* answer about it.
|
|
2565
|
+
*
|
|
2566
|
+
* @public
|
|
2567
|
+
*/
|
|
2568
|
+
interface ChromeMenuSubmenuEntry {
|
|
2569
|
+
readonly kind: 'submenu';
|
|
2570
|
+
readonly labelKey: string;
|
|
2571
|
+
readonly paths: readonly string[] | null;
|
|
2572
|
+
readonly items: readonly ChromeMenuEntry[];
|
|
2573
|
+
}
|
|
2574
|
+
/** A horizontal rule between groups of rows. @public */
|
|
2575
|
+
interface ChromeMenuSeparatorEntry {
|
|
2576
|
+
readonly kind: 'separator';
|
|
2577
|
+
}
|
|
2578
|
+
/** One row of a chrome menu. @public */
|
|
2579
|
+
type ChromeMenuEntry = ChromeMenuItemEntry | ChromeMenuSubmenuEntry | ChromeMenuSeparatorEntry;
|
|
2580
|
+
/**
|
|
2581
|
+
* Every menu id, as a literal union. Stable public API; renaming one is a breaking change,
|
|
2582
|
+
* exactly like a group or slot id.
|
|
2583
|
+
*
|
|
2584
|
+
* @public
|
|
2585
|
+
*/
|
|
2586
|
+
type ChromeMenuId = 'file' | 'format' | 'insert' | 'review' | 'help';
|
|
2587
|
+
/** One menu of the menu bar. @public */
|
|
2588
|
+
interface ChromeMenu {
|
|
2589
|
+
readonly id: ChromeMenuId;
|
|
2590
|
+
readonly labelKey: string;
|
|
2591
|
+
readonly entries: readonly ChromeMenuEntry[];
|
|
2592
|
+
}
|
|
2593
|
+
|
|
2594
|
+
/**
|
|
2595
|
+
* HOW a control reaches the engine — never WHETHER it is enabled.
|
|
2596
|
+
*
|
|
2597
|
+
* Enabled state has exactly one source: `toolbarCommandState(editor, slot)`, which
|
|
2598
|
+
* asks `Editor.can`. The registry is static data and cannot know what the engine
|
|
2599
|
+
* will honour at this selection, in this document, at this moment.
|
|
2600
|
+
*
|
|
2601
|
+
* There used to be a fourth member, `parityOnly`, meaning "visible but permanently
|
|
2602
|
+
* disabled". It was a second, static answer to the question `Editor.can` already
|
|
2603
|
+
* answers, and it went stale the moment the engine wired underline, strike, the four
|
|
2604
|
+
* alignments, the list commands and the four value slots: the registry still said
|
|
2605
|
+
* parity-only, React ignored it and ran them, and Vue believed it and rendered twelve
|
|
2606
|
+
* WORKING commands permanently disabled. A slot the engine has not wired needs no
|
|
2607
|
+
* registry flag — `commandForSlot` answers null and `toolbarCommandState` disables the
|
|
2608
|
+
* control with the engine's own words ("not wired to an editor command").
|
|
2609
|
+
*/
|
|
2610
|
+
type ChromeControlState =
|
|
2611
|
+
/**
|
|
2612
|
+
* Dispatched as one fixed engine command: enabled when
|
|
2613
|
+
* `Editor.can(commandForSlot(slot))` succeeds, a click runs
|
|
2614
|
+
* `runToolbarCommand(editor, slot)`. The command is resolved from the SLOT id
|
|
2615
|
+
* through `commandForSlot` in toolbar-commands.ts — the one command table both
|
|
2616
|
+
* adapters share. A slot with no row there is simply not wired YET, and says so
|
|
2617
|
+
* through the engine rather than through this descriptor.
|
|
2618
|
+
*/
|
|
2619
|
+
{
|
|
2620
|
+
readonly kind: 'command';
|
|
2621
|
+
}
|
|
2622
|
+
/**
|
|
2623
|
+
* Dispatched with a PICKED value: `commandForSlotValue(slot, value)`. Enabled when
|
|
2624
|
+
* the engine would honour a well-formed value right now (`toolbarCommandState`
|
|
2625
|
+
* probes for exactly that), so the control needs chrome that produces a value — a
|
|
2626
|
+
* font list, a size, a colour — before a click means anything.
|
|
2627
|
+
*
|
|
2628
|
+
* A distinct kind because 'command' cannot describe it: there is no fixed command
|
|
2629
|
+
* to hand `Editor.can`, and a bare click has nothing to send.
|
|
2630
|
+
*/
|
|
2631
|
+
| {
|
|
2632
|
+
readonly kind: 'value';
|
|
2633
|
+
}
|
|
2634
|
+
/** `Editor.save()` — not a command (see `runSave`). */
|
|
2635
|
+
| {
|
|
2636
|
+
readonly kind: 'save';
|
|
2637
|
+
}
|
|
2638
|
+
/**
|
|
2639
|
+
* `Editor.load()` — not a command either, and the exact twin of `save`: bytes cross the
|
|
2640
|
+
* boundary between the host and the engine, and only the host can produce them. The
|
|
2641
|
+
* control needs chrome that reads a file (a picker, a drop target) before a click means
|
|
2642
|
+
* anything, so a bare click has nothing to send — the same reason `save` is not `command`.
|
|
2643
|
+
*
|
|
2644
|
+
* A fourth kind rather than reusing `save` because the two dispatch in opposite
|
|
2645
|
+
* directions, and an adapter branching on `kind` must be able to tell them apart. Unlike
|
|
2646
|
+
* the deleted `parityOnly`, this one IS named by a control (`file.open`).
|
|
2647
|
+
*/
|
|
2648
|
+
| {
|
|
2649
|
+
readonly kind: 'load';
|
|
2650
|
+
}
|
|
2651
|
+
/** Host conversion through `runChromeExport` or `runChromePrint`; not an editing command. */
|
|
2652
|
+
| {
|
|
2653
|
+
readonly kind: 'export';
|
|
2654
|
+
};
|
|
2655
|
+
/**
|
|
2656
|
+
* The SHAPE a control renders as (task M6V.1).
|
|
2657
|
+
*
|
|
2658
|
+
* The legacy toolbar is not a row of uniform icon buttons: it mixes labelled dropdowns
|
|
2659
|
+
* (`Normal`, `Arial`, alignment, line spacing), numeric steppers with visible values
|
|
2660
|
+
* (zoom `- 100% +`, size `- 26 +`), split colour controls (a glyph over a colour swatch
|
|
2661
|
+
* with its own caret), and a mode pill (`Editing`). Rendering all of them as icon
|
|
2662
|
+
* buttons is the difference an owner review called out as "not visual parity" — the
|
|
2663
|
+
* regions were all present and it still did not look like the product.
|
|
2664
|
+
*/
|
|
2665
|
+
/** `modePill` is deliberately absent. It was declared, never used by any control, and
|
|
2666
|
+
* rendered nothing — the editing-mode control below is a `dropdown`, which is what the
|
|
2667
|
+
* legacy product shows. A shape no descriptor names is a branch adapters must implement
|
|
2668
|
+
* and can never exercise. */
|
|
2669
|
+
type ChromeControlShape = 'icon' | 'stepper' | 'dropdown' | 'colorSplit';
|
|
2670
|
+
/**
|
|
2671
|
+
* One toolbar control as the registry describes it — what it renders as, never whether it is
|
|
2672
|
+
* enabled.
|
|
2673
|
+
*
|
|
2674
|
+
* Enabled state has exactly ONE source, `toolbarCommandState`, which asks the engine. A
|
|
2675
|
+
* descriptor carrying its own disabled flag would be a second answer that goes stale the moment
|
|
2676
|
+
* the engine wires the slot.
|
|
2677
|
+
*
|
|
2678
|
+
* @public
|
|
2679
|
+
*/
|
|
2680
|
+
interface ChromeControl<Id extends string = string> {
|
|
2681
|
+
/** Stable control id, unique WITHIN its group. Public API; renames are breaking. */
|
|
2682
|
+
readonly id: Id;
|
|
2683
|
+
/** How it renders. Defaults to `icon`. */
|
|
2684
|
+
readonly shape?: ChromeControlShape;
|
|
2685
|
+
/** Displayed value for a stepper or dropdown (an i18n key, or a literal for numbers). */
|
|
2686
|
+
readonly valueText?: string;
|
|
2687
|
+
/** Swatch colour for a `colorSplit` control. */
|
|
2688
|
+
readonly swatch?: string;
|
|
2689
|
+
/** i18n key for the accessible name and tooltip. Never hardcoded English. */
|
|
2690
|
+
readonly labelKey: string;
|
|
2691
|
+
/** Material Symbols path data, or null for a non-icon control (a picker). */
|
|
2692
|
+
readonly paths: readonly string[] | null;
|
|
2693
|
+
/** For pickers: the i18n key of the placeholder value shown. */
|
|
2694
|
+
readonly valueKey?: string;
|
|
2695
|
+
/** `false` keeps this public slot composable but omits it from the default toolbar. */
|
|
2696
|
+
readonly defaultToolbar?: false;
|
|
2697
|
+
readonly state: ChromeControlState;
|
|
2698
|
+
}
|
|
2699
|
+
/**
|
|
2700
|
+
* One toolbar group: the taxonomy both adapters derive their default arrangement FROM.
|
|
2701
|
+
*
|
|
2702
|
+
* Never hand-list controls in an adapter — a default toolbar is built by walking `CHROME_GROUPS`,
|
|
2703
|
+
* so a slot added here appears in React and Vue without either being edited.
|
|
2704
|
+
*
|
|
2705
|
+
* @public
|
|
2706
|
+
*/
|
|
2707
|
+
interface ChromeGroup<Id extends string = string, ControlId extends string = string> {
|
|
2708
|
+
/** Stable group id. Public API; renames are breaking. */
|
|
2709
|
+
readonly id: Id;
|
|
2710
|
+
readonly labelKey: string;
|
|
2711
|
+
/**
|
|
2712
|
+
* Not part of the DEFAULT toolbar arrangement. The chrome spec shows these
|
|
2713
|
+
* controls only in a context the engine does not model yet (an image or table
|
|
2714
|
+
* selection), or not at all (save belongs in the host's File menu, never in the
|
|
2715
|
+
* bar). Their slots stay public for composition — a host can still place
|
|
2716
|
+
* `image.insert` or `file.save` explicitly — but the default chrome is the
|
|
2717
|
+
* registry's default bar, which ends at the editing-mode picker.
|
|
2718
|
+
*/
|
|
2719
|
+
readonly contextual?: true;
|
|
2720
|
+
readonly controls: readonly ChromeControl<ControlId>[];
|
|
2721
|
+
}
|
|
2722
|
+
/**
|
|
2723
|
+
* The complete chrome, in bar order. Literal-typed (`as const`) so the slot-id
|
|
2724
|
+
* vocabulary below is derived from the data and cannot drift from it.
|
|
2725
|
+
*
|
|
2726
|
+
* Taxonomy taste: ids are short, lowercaseCamel, and never repeat their group's name
|
|
2727
|
+
* (`alignment.left`, not `alignment.alignLeft`; `font.family`, not `font.fontFamily`).
|
|
2728
|
+
*/
|
|
2729
|
+
declare const CHROME_GROUPS: readonly [{
|
|
2730
|
+
readonly id: 'history';
|
|
2731
|
+
readonly labelKey: 'formattingBar.groups.history';
|
|
2732
|
+
readonly controls: readonly [{
|
|
2733
|
+
readonly id: 'undo';
|
|
2734
|
+
readonly labelKey: 'formattingBar.undoShortcut';
|
|
2735
|
+
readonly paths: readonly string[];
|
|
2736
|
+
readonly state: {
|
|
2737
|
+
readonly kind: 'command';
|
|
2738
|
+
};
|
|
2739
|
+
}, {
|
|
2740
|
+
readonly id: 'redo';
|
|
2741
|
+
readonly labelKey: 'formattingBar.redoShortcut';
|
|
2742
|
+
readonly paths: readonly string[];
|
|
2743
|
+
readonly state: {
|
|
2744
|
+
readonly kind: 'command';
|
|
2745
|
+
};
|
|
2746
|
+
}];
|
|
2747
|
+
}, {
|
|
2748
|
+
readonly id: 'zoom';
|
|
2749
|
+
readonly labelKey: 'formattingBar.groups.zoom';
|
|
2750
|
+
readonly controls: readonly [{
|
|
2751
|
+
readonly id: 'level';
|
|
2752
|
+
readonly shape: 'stepper';
|
|
2753
|
+
readonly valueText: '100%';
|
|
2754
|
+
readonly labelKey: 'formattingBar.groups.zoom';
|
|
2755
|
+
readonly paths: null;
|
|
2756
|
+
readonly valueKey: 'zoom.zoomLevel';
|
|
2757
|
+
readonly state: {
|
|
2758
|
+
readonly kind: 'command';
|
|
2759
|
+
};
|
|
2760
|
+
}];
|
|
2761
|
+
}, {
|
|
2762
|
+
readonly id: 'styles';
|
|
2763
|
+
readonly labelKey: 'formattingBar.groups.styles';
|
|
2764
|
+
readonly controls: readonly [{
|
|
2765
|
+
readonly id: 'style';
|
|
2766
|
+
readonly shape: 'dropdown';
|
|
2767
|
+
readonly labelKey: 'styles.selectAriaLabel';
|
|
2768
|
+
readonly paths: null;
|
|
2769
|
+
readonly valueKey: 'styles.normalText';
|
|
2770
|
+
readonly state: {
|
|
2771
|
+
readonly kind: 'value';
|
|
2772
|
+
};
|
|
2773
|
+
}];
|
|
2774
|
+
}, {
|
|
2775
|
+
readonly id: 'font';
|
|
2776
|
+
readonly labelKey: 'formattingBar.groups.font';
|
|
2777
|
+
readonly controls: readonly [{
|
|
2778
|
+
readonly id: 'family';
|
|
2779
|
+
readonly shape: 'dropdown';
|
|
2780
|
+
readonly labelKey: 'font.selectAriaLabel';
|
|
2781
|
+
readonly paths: null;
|
|
2782
|
+
readonly valueKey: 'font.sansSerif';
|
|
2783
|
+
readonly state: {
|
|
2784
|
+
readonly kind: 'value';
|
|
2785
|
+
};
|
|
2786
|
+
}, {
|
|
2787
|
+
readonly id: 'size';
|
|
2788
|
+
readonly shape: 'stepper';
|
|
2789
|
+
readonly valueText: '11';
|
|
2790
|
+
readonly labelKey: 'fontSize.listLabel';
|
|
2791
|
+
readonly paths: null;
|
|
2792
|
+
readonly valueKey: 'fontSize.label';
|
|
2793
|
+
readonly state: {
|
|
2794
|
+
readonly kind: 'value';
|
|
2795
|
+
};
|
|
2796
|
+
}];
|
|
2797
|
+
}, {
|
|
2798
|
+
readonly id: 'text';
|
|
2799
|
+
readonly labelKey: 'formattingBar.groups.textFormatting';
|
|
2800
|
+
readonly controls: readonly [{
|
|
2801
|
+
readonly id: 'bold';
|
|
2802
|
+
readonly labelKey: 'formattingBar.boldShortcut';
|
|
2803
|
+
readonly paths: readonly string[];
|
|
2804
|
+
readonly state: {
|
|
2805
|
+
readonly kind: 'command';
|
|
2806
|
+
};
|
|
2807
|
+
}, {
|
|
2808
|
+
readonly id: 'italic';
|
|
2809
|
+
readonly labelKey: 'formattingBar.italicShortcut';
|
|
2810
|
+
readonly paths: readonly string[];
|
|
2811
|
+
readonly state: {
|
|
2812
|
+
readonly kind: 'command';
|
|
2813
|
+
};
|
|
2814
|
+
}, {
|
|
2815
|
+
readonly id: 'underline';
|
|
2816
|
+
readonly labelKey: 'formattingBar.underlineShortcut';
|
|
2817
|
+
readonly paths: readonly string[];
|
|
2818
|
+
readonly state: {
|
|
2819
|
+
readonly kind: 'command';
|
|
2820
|
+
};
|
|
2821
|
+
}, {
|
|
2822
|
+
readonly id: 'strike';
|
|
2823
|
+
readonly labelKey: 'formattingBar.strikethrough';
|
|
2824
|
+
readonly paths: readonly string[];
|
|
2825
|
+
readonly state: {
|
|
2826
|
+
readonly kind: 'command';
|
|
2827
|
+
};
|
|
2828
|
+
}, {
|
|
2829
|
+
readonly id: 'color';
|
|
2830
|
+
readonly shape: 'colorSplit';
|
|
2831
|
+
readonly swatch: '#ff0000';
|
|
2832
|
+
readonly labelKey: 'formattingBar.fontColor';
|
|
2833
|
+
readonly paths: readonly string[];
|
|
2834
|
+
readonly state: {
|
|
2835
|
+
readonly kind: 'value';
|
|
2836
|
+
};
|
|
2837
|
+
}, {
|
|
2838
|
+
readonly id: 'highlight';
|
|
2839
|
+
readonly shape: 'colorSplit';
|
|
2840
|
+
readonly swatch: '#ffff00';
|
|
2841
|
+
readonly labelKey: 'formattingBar.highlightColor';
|
|
2842
|
+
readonly paths: readonly string[];
|
|
2843
|
+
readonly state: {
|
|
2844
|
+
readonly kind: 'value';
|
|
2845
|
+
};
|
|
2846
|
+
}, {
|
|
2847
|
+
readonly id: 'link';
|
|
2848
|
+
readonly labelKey: 'formattingBar.insertLinkShortcut';
|
|
2849
|
+
readonly paths: readonly string[];
|
|
2850
|
+
readonly state: {
|
|
2851
|
+
readonly kind: 'command';
|
|
2852
|
+
};
|
|
2853
|
+
}];
|
|
2854
|
+
}, {
|
|
2855
|
+
readonly id: 'script';
|
|
2856
|
+
readonly labelKey: 'formattingBar.groups.script';
|
|
2857
|
+
readonly controls: readonly [{
|
|
2858
|
+
readonly id: 'super';
|
|
2859
|
+
readonly labelKey: 'formattingBar.superscript';
|
|
2860
|
+
readonly paths: readonly string[];
|
|
2861
|
+
readonly state: {
|
|
2862
|
+
readonly kind: 'command';
|
|
2863
|
+
};
|
|
2864
|
+
}, {
|
|
2865
|
+
readonly id: 'sub';
|
|
2866
|
+
readonly labelKey: 'formattingBar.subscript';
|
|
2867
|
+
readonly paths: readonly string[];
|
|
2868
|
+
readonly state: {
|
|
2869
|
+
readonly kind: 'command';
|
|
2870
|
+
};
|
|
2871
|
+
}];
|
|
2872
|
+
}, {
|
|
2873
|
+
readonly id: 'alignment';
|
|
2874
|
+
readonly labelKey: 'formattingBar.groups.alignment';
|
|
2875
|
+
readonly controls: readonly [{
|
|
2876
|
+
readonly id: 'left';
|
|
2877
|
+
readonly labelKey: 'alignment.alignLeft';
|
|
2878
|
+
readonly paths: readonly string[];
|
|
2879
|
+
readonly state: {
|
|
2880
|
+
readonly kind: 'command';
|
|
2881
|
+
};
|
|
2882
|
+
}, {
|
|
2883
|
+
readonly id: 'center';
|
|
2884
|
+
readonly labelKey: 'alignment.center';
|
|
2885
|
+
readonly paths: readonly string[];
|
|
2886
|
+
readonly state: {
|
|
2887
|
+
readonly kind: 'command';
|
|
2888
|
+
};
|
|
2889
|
+
}, {
|
|
2890
|
+
readonly id: 'right';
|
|
2891
|
+
readonly labelKey: 'alignment.alignRight';
|
|
2892
|
+
readonly paths: readonly string[];
|
|
2893
|
+
readonly state: {
|
|
2894
|
+
readonly kind: 'command';
|
|
2895
|
+
};
|
|
2896
|
+
}, {
|
|
2897
|
+
readonly id: 'justify';
|
|
2898
|
+
readonly labelKey: 'alignment.justify';
|
|
2899
|
+
readonly paths: readonly string[];
|
|
2900
|
+
readonly state: {
|
|
2901
|
+
readonly kind: 'command';
|
|
2902
|
+
};
|
|
2903
|
+
}];
|
|
2904
|
+
}, {
|
|
2905
|
+
readonly id: 'direction';
|
|
2906
|
+
readonly labelKey: 'formattingBar.groups.direction';
|
|
2907
|
+
readonly contextual: true;
|
|
2908
|
+
readonly controls: readonly [{
|
|
2909
|
+
readonly id: 'ltr';
|
|
2910
|
+
readonly labelKey: 'toolbar.leftToRight';
|
|
2911
|
+
readonly paths: readonly string[];
|
|
2912
|
+
readonly state: {
|
|
2913
|
+
readonly kind: 'command';
|
|
2914
|
+
};
|
|
2915
|
+
}, {
|
|
2916
|
+
readonly id: 'rtl';
|
|
2917
|
+
readonly labelKey: 'toolbar.rightToLeft';
|
|
2918
|
+
readonly paths: readonly string[];
|
|
2919
|
+
readonly state: {
|
|
2920
|
+
readonly kind: 'command';
|
|
2921
|
+
};
|
|
2922
|
+
}];
|
|
2923
|
+
}, {
|
|
2924
|
+
readonly id: 'list';
|
|
2925
|
+
readonly labelKey: 'formattingBar.groups.listFormatting';
|
|
2926
|
+
readonly controls: readonly [{
|
|
2927
|
+
readonly id: 'bullet';
|
|
2928
|
+
readonly labelKey: 'lists.bulletList';
|
|
2929
|
+
readonly paths: readonly string[];
|
|
2930
|
+
readonly state: {
|
|
2931
|
+
readonly kind: 'command';
|
|
2932
|
+
};
|
|
2933
|
+
}, {
|
|
2934
|
+
readonly id: 'numbered';
|
|
2935
|
+
readonly labelKey: 'lists.numberedList';
|
|
2936
|
+
readonly paths: readonly string[];
|
|
2937
|
+
readonly state: {
|
|
2938
|
+
readonly kind: 'command';
|
|
2939
|
+
};
|
|
2940
|
+
}, {
|
|
2941
|
+
readonly id: 'outdent';
|
|
2942
|
+
readonly labelKey: 'lists.decreaseIndent';
|
|
2943
|
+
readonly paths: readonly string[];
|
|
2944
|
+
readonly state: {
|
|
2945
|
+
readonly kind: 'command';
|
|
2946
|
+
};
|
|
2947
|
+
}, {
|
|
2948
|
+
readonly id: 'indent';
|
|
2949
|
+
readonly labelKey: 'lists.increaseIndent';
|
|
2950
|
+
readonly paths: readonly string[];
|
|
2951
|
+
readonly state: {
|
|
2952
|
+
readonly kind: 'command';
|
|
2953
|
+
};
|
|
2954
|
+
}, {
|
|
2955
|
+
readonly id: 'lineSpacing';
|
|
2956
|
+
readonly shape: 'dropdown';
|
|
2957
|
+
readonly labelKey: 'lineSpacing.label';
|
|
2958
|
+
readonly paths: readonly string[];
|
|
2959
|
+
readonly state: {
|
|
2960
|
+
readonly kind: 'command';
|
|
2961
|
+
};
|
|
2962
|
+
}];
|
|
2963
|
+
}, {
|
|
2964
|
+
readonly id: 'format';
|
|
2965
|
+
readonly labelKey: 'formattingBar.groups.format';
|
|
2966
|
+
readonly controls: readonly [{
|
|
2967
|
+
readonly id: 'painter';
|
|
2968
|
+
readonly labelKey: 'formattingBar.formatPainterShortcut';
|
|
2969
|
+
readonly paths: readonly string[];
|
|
2970
|
+
readonly state: {
|
|
2971
|
+
readonly kind: 'command';
|
|
2972
|
+
};
|
|
2973
|
+
}, {
|
|
2974
|
+
readonly id: 'clear';
|
|
2975
|
+
readonly labelKey: 'formattingBar.clearFormatting';
|
|
2976
|
+
readonly paths: readonly string[];
|
|
2977
|
+
readonly state: {
|
|
2978
|
+
readonly kind: 'command';
|
|
2979
|
+
};
|
|
2980
|
+
}];
|
|
2981
|
+
}, {
|
|
2982
|
+
readonly id: 'review';
|
|
2983
|
+
readonly labelKey: 'formattingBar.commentsAndChanges';
|
|
2984
|
+
readonly controls: readonly [{
|
|
2985
|
+
readonly id: 'revisionMarkup';
|
|
2986
|
+
readonly shape: 'icon';
|
|
2987
|
+
readonly labelKey: 'revisionMarkup.title';
|
|
2988
|
+
readonly defaultToolbar: false;
|
|
2989
|
+
readonly paths: readonly string[];
|
|
2990
|
+
readonly state: {
|
|
2991
|
+
readonly kind: 'command';
|
|
2992
|
+
};
|
|
2993
|
+
}, {
|
|
2994
|
+
readonly id: 'simpleMarkup';
|
|
2995
|
+
readonly shape: 'icon';
|
|
2996
|
+
readonly labelKey: 'review.simpleMarkup';
|
|
2997
|
+
readonly defaultToolbar: false;
|
|
2998
|
+
readonly paths: readonly string[];
|
|
2999
|
+
readonly state: {
|
|
3000
|
+
readonly kind: 'command';
|
|
3001
|
+
};
|
|
3002
|
+
}, {
|
|
3003
|
+
readonly id: 'allMarkup';
|
|
3004
|
+
readonly shape: 'icon';
|
|
3005
|
+
readonly labelKey: 'review.allMarkup';
|
|
3006
|
+
readonly defaultToolbar: false;
|
|
3007
|
+
readonly paths: readonly string[];
|
|
3008
|
+
readonly state: {
|
|
3009
|
+
readonly kind: 'command';
|
|
3010
|
+
};
|
|
3011
|
+
}, {
|
|
3012
|
+
readonly id: 'noMarkup';
|
|
3013
|
+
readonly shape: 'icon';
|
|
3014
|
+
readonly labelKey: 'review.noMarkup';
|
|
3015
|
+
readonly defaultToolbar: false;
|
|
3016
|
+
readonly paths: readonly string[];
|
|
3017
|
+
readonly state: {
|
|
3018
|
+
readonly kind: 'command';
|
|
3019
|
+
};
|
|
3020
|
+
}, {
|
|
3021
|
+
readonly id: 'original';
|
|
3022
|
+
readonly shape: 'icon';
|
|
3023
|
+
readonly labelKey: 'review.original';
|
|
3024
|
+
readonly defaultToolbar: false;
|
|
3025
|
+
readonly paths: readonly string[];
|
|
3026
|
+
readonly state: {
|
|
3027
|
+
readonly kind: 'command';
|
|
3028
|
+
};
|
|
3029
|
+
}, {
|
|
3030
|
+
readonly id: 'previousChange';
|
|
3031
|
+
readonly shape: 'icon';
|
|
3032
|
+
readonly labelKey: 'review.previousChange';
|
|
3033
|
+
readonly defaultToolbar: false;
|
|
3034
|
+
readonly paths: readonly string[];
|
|
3035
|
+
readonly state: {
|
|
3036
|
+
readonly kind: 'command';
|
|
3037
|
+
};
|
|
3038
|
+
}, {
|
|
3039
|
+
readonly id: 'nextChange';
|
|
3040
|
+
readonly shape: 'icon';
|
|
3041
|
+
readonly labelKey: 'review.nextChange';
|
|
3042
|
+
readonly defaultToolbar: false;
|
|
3043
|
+
readonly paths: readonly string[];
|
|
3044
|
+
readonly state: {
|
|
3045
|
+
readonly kind: 'command';
|
|
3046
|
+
};
|
|
3047
|
+
}, {
|
|
3048
|
+
readonly id: 'acceptAllChanges';
|
|
3049
|
+
readonly shape: 'icon';
|
|
3050
|
+
readonly labelKey: 'review.acceptAllChanges';
|
|
3051
|
+
readonly defaultToolbar: false;
|
|
3052
|
+
readonly paths: readonly string[];
|
|
3053
|
+
readonly state: {
|
|
3054
|
+
readonly kind: 'command';
|
|
3055
|
+
};
|
|
3056
|
+
}, {
|
|
3057
|
+
readonly id: 'rejectAllChanges';
|
|
3058
|
+
readonly shape: 'icon';
|
|
3059
|
+
readonly labelKey: 'review.rejectAllChanges';
|
|
3060
|
+
readonly defaultToolbar: false;
|
|
3061
|
+
readonly paths: readonly string[];
|
|
3062
|
+
readonly state: {
|
|
3063
|
+
readonly kind: 'command';
|
|
3064
|
+
};
|
|
3065
|
+
}, {
|
|
3066
|
+
readonly id: 'paragraphMarks';
|
|
3067
|
+
readonly shape: 'icon';
|
|
3068
|
+
readonly labelKey: 'formattingBar.paragraphMarks';
|
|
3069
|
+
readonly defaultToolbar: false;
|
|
3070
|
+
readonly paths: readonly string[];
|
|
3071
|
+
readonly state: {
|
|
3072
|
+
readonly kind: 'command';
|
|
3073
|
+
};
|
|
3074
|
+
}, {
|
|
3075
|
+
readonly id: 'protectDocument';
|
|
3076
|
+
readonly shape: 'icon';
|
|
3077
|
+
readonly labelKey: 'review.protectDocument';
|
|
3078
|
+
readonly defaultToolbar: false;
|
|
3079
|
+
readonly paths: readonly string[];
|
|
3080
|
+
readonly state: {
|
|
3081
|
+
readonly kind: 'command';
|
|
3082
|
+
};
|
|
3083
|
+
}, {
|
|
3084
|
+
readonly id: 'comments';
|
|
3085
|
+
readonly shape: 'icon';
|
|
3086
|
+
readonly labelKey: 'formattingBar.commentsAndChanges';
|
|
3087
|
+
readonly paths: readonly string[];
|
|
3088
|
+
readonly state: {
|
|
3089
|
+
readonly kind: 'command';
|
|
3090
|
+
};
|
|
3091
|
+
}, {
|
|
3092
|
+
readonly id: 'addComment';
|
|
3093
|
+
readonly shape: 'icon';
|
|
3094
|
+
readonly labelKey: 'formattingBar.addComment';
|
|
3095
|
+
readonly defaultToolbar: false;
|
|
3096
|
+
readonly paths: readonly string[];
|
|
3097
|
+
readonly state: {
|
|
3098
|
+
readonly kind: 'command';
|
|
3099
|
+
};
|
|
3100
|
+
}, {
|
|
3101
|
+
readonly id: 'authors';
|
|
3102
|
+
readonly shape: 'dropdown';
|
|
3103
|
+
readonly labelKey: 'reviewers.label';
|
|
3104
|
+
readonly paths: readonly string[];
|
|
3105
|
+
readonly defaultToolbar: false;
|
|
3106
|
+
readonly state: {
|
|
3107
|
+
readonly kind: 'command';
|
|
3108
|
+
};
|
|
3109
|
+
}, {
|
|
3110
|
+
readonly id: 'editingMode';
|
|
3111
|
+
readonly shape: 'dropdown';
|
|
3112
|
+
readonly labelKey: 'editingMode.label';
|
|
3113
|
+
readonly valueKey: 'editingMode.editing';
|
|
3114
|
+
readonly paths: readonly string[];
|
|
3115
|
+
readonly state: {
|
|
3116
|
+
readonly kind: 'command';
|
|
3117
|
+
};
|
|
3118
|
+
}];
|
|
3119
|
+
}, {
|
|
3120
|
+
readonly id: 'contentControl';
|
|
3121
|
+
readonly labelKey: 'contentControl.group';
|
|
3122
|
+
readonly contextual: true;
|
|
3123
|
+
readonly controls: readonly [{
|
|
3124
|
+
readonly id: 'showAll';
|
|
3125
|
+
readonly labelKey: 'contentControl.showAll';
|
|
3126
|
+
readonly paths: readonly string[];
|
|
3127
|
+
readonly state: {
|
|
3128
|
+
readonly kind: 'command';
|
|
3129
|
+
};
|
|
3130
|
+
}, {
|
|
3131
|
+
readonly id: 'formFill';
|
|
3132
|
+
readonly labelKey: 'contentControl.formFill';
|
|
3133
|
+
readonly paths: readonly string[];
|
|
3134
|
+
readonly state: {
|
|
3135
|
+
readonly kind: 'command';
|
|
3136
|
+
};
|
|
3137
|
+
}, {
|
|
3138
|
+
readonly id: 'inspector';
|
|
3139
|
+
readonly labelKey: 'contentControl.inspector';
|
|
3140
|
+
readonly paths: readonly string[];
|
|
3141
|
+
readonly state: {
|
|
3142
|
+
readonly kind: 'command';
|
|
3143
|
+
};
|
|
3144
|
+
}, {
|
|
3145
|
+
readonly id: 'remove';
|
|
3146
|
+
readonly labelKey: 'contentControl.remove';
|
|
3147
|
+
readonly paths: readonly string[];
|
|
3148
|
+
readonly state: {
|
|
3149
|
+
readonly kind: 'command';
|
|
3150
|
+
};
|
|
3151
|
+
}];
|
|
3152
|
+
}, {
|
|
3153
|
+
readonly id: 'image';
|
|
3154
|
+
readonly labelKey: 'formattingBar.groups.image';
|
|
3155
|
+
readonly contextual: true;
|
|
3156
|
+
readonly controls: readonly [{
|
|
3157
|
+
readonly id: 'insert';
|
|
3158
|
+
readonly labelKey: 'toolbar.image';
|
|
3159
|
+
readonly paths: readonly string[];
|
|
3160
|
+
readonly state: {
|
|
3161
|
+
readonly kind: 'command';
|
|
3162
|
+
};
|
|
3163
|
+
}, {
|
|
3164
|
+
readonly id: 'properties';
|
|
3165
|
+
readonly labelKey: 'formattingBar.imagePropertiesShortcut';
|
|
3166
|
+
readonly paths: readonly string[];
|
|
3167
|
+
readonly state: {
|
|
3168
|
+
readonly kind: 'command';
|
|
3169
|
+
};
|
|
3170
|
+
}, {
|
|
3171
|
+
readonly id: 'wrap';
|
|
3172
|
+
readonly shape: 'dropdown';
|
|
3173
|
+
readonly labelKey: 'formattingBar.imageWrap';
|
|
3174
|
+
readonly paths: readonly string[];
|
|
3175
|
+
readonly valueKey: 'imageWrap.inline';
|
|
3176
|
+
readonly state: {
|
|
3177
|
+
readonly kind: 'value';
|
|
3178
|
+
};
|
|
3179
|
+
}, {
|
|
3180
|
+
readonly id: 'altText';
|
|
3181
|
+
readonly shape: 'dropdown';
|
|
3182
|
+
readonly labelKey: 'formattingBar.altText';
|
|
3183
|
+
readonly paths: null;
|
|
3184
|
+
readonly valueKey: 'imageProperties.altText';
|
|
3185
|
+
readonly state: {
|
|
3186
|
+
readonly kind: 'value';
|
|
3187
|
+
};
|
|
3188
|
+
}];
|
|
3189
|
+
}, {
|
|
3190
|
+
readonly id: 'table';
|
|
3191
|
+
readonly labelKey: 'formattingBar.groups.table';
|
|
3192
|
+
readonly contextual: true;
|
|
3193
|
+
readonly controls: readonly [{
|
|
3194
|
+
readonly id: 'insert';
|
|
3195
|
+
readonly labelKey: 'toolbar.table';
|
|
3196
|
+
readonly paths: readonly string[];
|
|
3197
|
+
readonly state: {
|
|
3198
|
+
readonly kind: 'command';
|
|
3199
|
+
};
|
|
3200
|
+
}, {
|
|
3201
|
+
readonly id: 'borderTarget';
|
|
3202
|
+
readonly shape: 'dropdown';
|
|
3203
|
+
readonly labelKey: 'table.borders.tooltip';
|
|
3204
|
+
readonly paths: readonly string[];
|
|
3205
|
+
readonly state: {
|
|
3206
|
+
readonly kind: 'value';
|
|
3207
|
+
};
|
|
3208
|
+
}, {
|
|
3209
|
+
readonly id: 'borderColor';
|
|
3210
|
+
readonly shape: 'colorSplit';
|
|
3211
|
+
readonly swatch: '#000000';
|
|
3212
|
+
readonly labelKey: 'table.borderColor';
|
|
3213
|
+
readonly paths: readonly string[];
|
|
3214
|
+
readonly state: {
|
|
3215
|
+
readonly kind: 'value';
|
|
3216
|
+
};
|
|
3217
|
+
}, {
|
|
3218
|
+
readonly id: 'borderStyle';
|
|
3219
|
+
readonly shape: 'dropdown';
|
|
3220
|
+
readonly labelKey: 'table.borders.styleAriaLabel';
|
|
3221
|
+
readonly paths: readonly string[];
|
|
3222
|
+
readonly state: {
|
|
3223
|
+
readonly kind: 'value';
|
|
3224
|
+
};
|
|
3225
|
+
}, {
|
|
3226
|
+
readonly id: 'borderWidth';
|
|
3227
|
+
readonly shape: 'dropdown';
|
|
3228
|
+
readonly labelKey: 'table.borderWidth';
|
|
3229
|
+
readonly paths: readonly string[];
|
|
3230
|
+
readonly state: {
|
|
3231
|
+
readonly kind: 'value';
|
|
3232
|
+
};
|
|
3233
|
+
}, {
|
|
3234
|
+
readonly id: 'cellFill';
|
|
3235
|
+
readonly shape: 'colorSplit';
|
|
3236
|
+
readonly swatch: '#ffffff';
|
|
3237
|
+
readonly labelKey: 'table.cellFillColor';
|
|
3238
|
+
readonly paths: readonly string[];
|
|
3239
|
+
readonly state: {
|
|
3240
|
+
readonly kind: 'value';
|
|
3241
|
+
};
|
|
3242
|
+
}];
|
|
3243
|
+
}, {
|
|
3244
|
+
readonly id: 'paragraph';
|
|
3245
|
+
readonly labelKey: 'dialogs.paragraph.title';
|
|
3246
|
+
readonly contextual: true;
|
|
3247
|
+
readonly controls: readonly [{
|
|
3248
|
+
readonly id: 'dialog';
|
|
3249
|
+
readonly labelKey: 'lineSpacing.options';
|
|
3250
|
+
readonly paths: readonly string[];
|
|
3251
|
+
readonly state: {
|
|
3252
|
+
readonly kind: 'command';
|
|
3253
|
+
};
|
|
3254
|
+
}];
|
|
3255
|
+
}, {
|
|
3256
|
+
readonly id: 'file';
|
|
3257
|
+
readonly labelKey: 'toolbar.file';
|
|
3258
|
+
readonly contextual: true;
|
|
3259
|
+
readonly controls: readonly [{
|
|
3260
|
+
readonly id: 'open';
|
|
3261
|
+
readonly labelKey: 'toolbar.open';
|
|
3262
|
+
readonly paths: readonly string[];
|
|
3263
|
+
readonly state: {
|
|
3264
|
+
readonly kind: 'load';
|
|
3265
|
+
};
|
|
3266
|
+
}, {
|
|
3267
|
+
readonly id: 'save';
|
|
3268
|
+
readonly labelKey: 'toolbar.saveShortcut';
|
|
3269
|
+
readonly paths: readonly string[];
|
|
3270
|
+
readonly state: {
|
|
3271
|
+
readonly kind: 'save';
|
|
3272
|
+
};
|
|
3273
|
+
}, {
|
|
3274
|
+
readonly id: 'exportMarkdown';
|
|
3275
|
+
readonly labelKey: 'toolbar.exportMarkdown';
|
|
3276
|
+
readonly paths: readonly string[];
|
|
3277
|
+
readonly state: {
|
|
3278
|
+
readonly kind: 'export';
|
|
3279
|
+
};
|
|
3280
|
+
}, {
|
|
3281
|
+
readonly id: 'exportPdf';
|
|
3282
|
+
readonly labelKey: 'toolbar.exportPdf';
|
|
3283
|
+
readonly paths: readonly string[];
|
|
3284
|
+
readonly state: {
|
|
3285
|
+
readonly kind: 'export';
|
|
3286
|
+
};
|
|
3287
|
+
}, {
|
|
3288
|
+
readonly id: 'print';
|
|
3289
|
+
readonly labelKey: 'toolbar.print';
|
|
3290
|
+
readonly paths: readonly string[];
|
|
3291
|
+
readonly state: {
|
|
3292
|
+
readonly kind: 'export';
|
|
3293
|
+
};
|
|
3294
|
+
}, {
|
|
3295
|
+
readonly id: 'pageSetup';
|
|
3296
|
+
readonly labelKey: 'toolbar.pageSetup';
|
|
3297
|
+
readonly paths: readonly string[];
|
|
3298
|
+
readonly state: {
|
|
3299
|
+
readonly kind: 'command';
|
|
3300
|
+
};
|
|
3301
|
+
}];
|
|
3302
|
+
}, {
|
|
3303
|
+
readonly id: 'insert';
|
|
3304
|
+
readonly labelKey: 'toolbar.insert';
|
|
3305
|
+
readonly contextual: true;
|
|
3306
|
+
readonly controls: readonly [{
|
|
3307
|
+
readonly id: 'textBox';
|
|
3308
|
+
readonly labelKey: 'toolbar.insertTextBox';
|
|
3309
|
+
readonly paths: readonly string[];
|
|
3310
|
+
readonly state: {
|
|
3311
|
+
readonly kind: 'command';
|
|
3312
|
+
};
|
|
3313
|
+
}, {
|
|
3314
|
+
readonly id: 'footnote';
|
|
3315
|
+
readonly labelKey: 'toolbar.insertFootnote';
|
|
3316
|
+
readonly paths: readonly string[];
|
|
3317
|
+
readonly state: {
|
|
3318
|
+
readonly kind: 'command';
|
|
3319
|
+
};
|
|
3320
|
+
}, {
|
|
3321
|
+
readonly id: 'endnote';
|
|
3322
|
+
readonly labelKey: 'toolbar.insertEndnote';
|
|
3323
|
+
readonly paths: readonly string[];
|
|
3324
|
+
readonly state: {
|
|
3325
|
+
readonly kind: 'command';
|
|
3326
|
+
};
|
|
3327
|
+
}, {
|
|
3328
|
+
readonly id: 'pageNumber';
|
|
3329
|
+
readonly labelKey: 'headerFooter.insertPageNumber';
|
|
3330
|
+
readonly paths: readonly string[];
|
|
3331
|
+
readonly state: {
|
|
3332
|
+
readonly kind: 'command';
|
|
3333
|
+
};
|
|
3334
|
+
}, {
|
|
3335
|
+
readonly id: 'totalPages';
|
|
3336
|
+
readonly labelKey: 'headerFooter.insertTotalPages';
|
|
3337
|
+
readonly paths: readonly string[];
|
|
3338
|
+
readonly state: {
|
|
3339
|
+
readonly kind: 'command';
|
|
3340
|
+
};
|
|
3341
|
+
}, {
|
|
3342
|
+
readonly id: 'sectionPages';
|
|
3343
|
+
readonly labelKey: 'headerFooter.insertSectionPages';
|
|
3344
|
+
readonly paths: readonly string[];
|
|
3345
|
+
readonly state: {
|
|
3346
|
+
readonly kind: 'command';
|
|
3347
|
+
};
|
|
3348
|
+
}, {
|
|
3349
|
+
readonly id: 'pageXofY';
|
|
3350
|
+
readonly labelKey: 'headerFooter.insertPageXofY';
|
|
3351
|
+
readonly paths: readonly string[];
|
|
3352
|
+
readonly state: {
|
|
3353
|
+
readonly kind: 'command';
|
|
3354
|
+
};
|
|
3355
|
+
}, {
|
|
3356
|
+
readonly id: 'pageBreak';
|
|
3357
|
+
readonly labelKey: 'toolbar.pageBreak';
|
|
3358
|
+
readonly paths: readonly string[];
|
|
3359
|
+
readonly state: {
|
|
3360
|
+
readonly kind: 'command';
|
|
3361
|
+
};
|
|
3362
|
+
}, {
|
|
3363
|
+
readonly id: 'sectionBreakNextPage';
|
|
3364
|
+
readonly labelKey: 'toolbar.sectionBreakNextPage';
|
|
3365
|
+
readonly paths: readonly string[];
|
|
3366
|
+
readonly state: {
|
|
3367
|
+
readonly kind: 'command';
|
|
3368
|
+
};
|
|
3369
|
+
}, {
|
|
3370
|
+
readonly id: 'sectionBreakContinuous';
|
|
3371
|
+
readonly labelKey: 'toolbar.sectionBreakContinuous';
|
|
3372
|
+
readonly paths: readonly string[];
|
|
3373
|
+
readonly state: {
|
|
3374
|
+
readonly kind: 'command';
|
|
3375
|
+
};
|
|
3376
|
+
}, {
|
|
3377
|
+
readonly id: 'toc';
|
|
3378
|
+
readonly labelKey: 'toolbar.tableOfContents';
|
|
3379
|
+
readonly paths: readonly string[];
|
|
3380
|
+
readonly state: {
|
|
3381
|
+
readonly kind: 'command';
|
|
3382
|
+
};
|
|
3383
|
+
}];
|
|
3384
|
+
}];
|
|
3385
|
+
/**
|
|
3386
|
+
* Every group id in the chrome, as a literal union. Stable public API; renaming a group
|
|
3387
|
+
* id is a breaking change.
|
|
3388
|
+
*
|
|
3389
|
+
* @public
|
|
3390
|
+
*/
|
|
3391
|
+
type ChromeGroupId = 'history' | 'zoom' | 'styles' | 'font' | 'text' | 'script' | 'alignment' | 'direction' | 'list' | 'format' | 'review' | 'contentControl' | 'image' | 'table' | 'paragraph' | 'file' | 'insert';
|
|
3392
|
+
/**
|
|
3393
|
+
* The public slot vocabulary: `${groupId}.${controlId}` for every control that actually
|
|
3394
|
+
* exists — `text.bold`, `font.family`, `alignment.left`. THE stable contract a host
|
|
3395
|
+
* composes against and `commandForSlot` resolves; renaming a slot is a breaking change.
|
|
3396
|
+
*
|
|
3397
|
+
* @public
|
|
3398
|
+
*/
|
|
3399
|
+
type ChromeSlotId = 'history.undo' | 'history.redo' | 'zoom.level' | 'styles.style' | 'font.family' | 'font.size' | 'text.bold' | 'text.italic' | 'text.underline' | 'text.strike' | 'text.color' | 'text.highlight' | 'text.link' | 'script.super' | 'script.sub' | 'alignment.left' | 'alignment.center' | 'alignment.right' | 'alignment.justify' | 'direction.ltr' | 'direction.rtl' | 'list.bullet' | 'list.numbered' | 'list.outdent' | 'list.indent' | 'list.lineSpacing' | 'format.painter' | 'format.clear' | 'review.revisionMarkup' | 'review.comments' | 'review.addComment' | 'review.paragraphMarks' | 'review.protectDocument' | 'review.simpleMarkup' | 'review.allMarkup' | 'review.noMarkup' | 'review.original' | 'review.previousChange' | 'review.nextChange' | 'review.acceptAllChanges' | 'review.rejectAllChanges' | 'review.authors' | 'review.editingMode' | 'contentControl.showAll' | 'contentControl.formFill' | 'contentControl.inspector' | 'contentControl.remove' | 'image.insert' | 'image.properties' | 'image.wrap' | 'image.altText' | 'table.insert' | 'table.borderTarget' | 'table.borderColor' | 'table.borderStyle' | 'table.borderWidth' | 'table.cellFill' | 'file.open' | 'file.save' | 'file.exportMarkdown' | 'file.exportPdf' | 'file.print' | 'paragraph.dialog' | 'file.pageSetup' | 'insert.textBox' | 'insert.footnote' | 'insert.endnote' | 'insert.pageNumber' | 'insert.totalPages' | 'insert.sectionPages' | 'insert.pageXofY' | 'insert.pageBreak' | 'insert.sectionBreakNextPage' | 'insert.sectionBreakContinuous' | 'insert.toc';
|
|
3400
|
+
/**
|
|
3401
|
+
* Every control id in the chrome, as a literal union. Unique WITHIN a group, not
|
|
3402
|
+
* globally (`image.insert` / `table.insert`) — key consumers on {@link ChromeSlotId}.
|
|
3403
|
+
*
|
|
3404
|
+
* @public
|
|
3405
|
+
*/
|
|
3406
|
+
type ChromeControlId = ChromeSlotId extends `${string}.${infer C}` ? C : never;
|
|
3407
|
+
/**
|
|
3408
|
+
* The slot id of one control within its group. Only meaningful for entries of
|
|
3409
|
+
* `CHROME_GROUPS` — the cast is sound because every group/control pair in the registry
|
|
3410
|
+
* is, by construction, a member of the `ChromeSlotId` union.
|
|
3411
|
+
*
|
|
3412
|
+
* @public
|
|
3413
|
+
*/
|
|
3414
|
+
declare function chromeSlotId(group: {
|
|
3415
|
+
readonly id: string;
|
|
3416
|
+
}, control: {
|
|
3417
|
+
readonly id: string;
|
|
3418
|
+
}): ChromeSlotId;
|
|
3419
|
+
/**
|
|
3420
|
+
* The groups of the DEFAULT toolbar arrangement, in bar order: every group that is
|
|
3421
|
+
* not `contextual`. This is the registry's default bar — undo/redo through the
|
|
3422
|
+
* editing-mode picker — and what both adapters render when the host composes
|
|
3423
|
+
* nothing. Contextual slots (`image.*`, `table.insert`, `file.save`) remain
|
|
3424
|
+
* available for explicit composition.
|
|
3425
|
+
*
|
|
3426
|
+
* @public
|
|
3427
|
+
*/
|
|
3428
|
+
declare function defaultChromeGroups(): readonly ChromeGroup[];
|
|
3429
|
+
/**
|
|
3430
|
+
* The formatting-bar groups for one editor snapshot: the default bar, plus the
|
|
3431
|
+
* contextual `image` group when a drawing is selected. Insertion without a selection
|
|
3432
|
+
* lives in the packaged Insert menu (`CHROME_MENUS`), not in the bar — a host that wants
|
|
3433
|
+
* a bar button places `DocxEditor.Toolbar.ImageInsert` itself.
|
|
3434
|
+
*
|
|
3435
|
+
* @public
|
|
3436
|
+
*/
|
|
3437
|
+
declare function formattingBarChromeGroups(image: ImageContext | null): readonly ChromeGroup[];
|
|
3438
|
+
|
|
3439
|
+
/**
|
|
3440
|
+
* The menu bar the chrome shows above the toolbar, in bar order: File, Format, Insert, Review,
|
|
3441
|
+
* Help.
|
|
3442
|
+
*
|
|
3443
|
+
* @public
|
|
3444
|
+
*/
|
|
3445
|
+
declare const CHROME_MENUS: readonly ChromeMenu[];
|
|
3446
|
+
/**
|
|
3447
|
+
* Every slot a menu places, in menu order, submenus flattened. What a parity test asserts
|
|
3448
|
+
* against, and what a host enumerates to know which capabilities the menu bar reaches.
|
|
3449
|
+
*
|
|
3450
|
+
* @public
|
|
3451
|
+
*/
|
|
3452
|
+
declare function chromeMenuSlots(): readonly ChromeSlotId[];
|
|
3453
|
+
/** Total controls, so a parity test can assert none were dropped. */
|
|
3454
|
+
declare function chromeControlCount(): number;
|
|
3455
|
+
/** Tooltip for adapter controls without a picker; command refusals use engine reasons. */
|
|
3456
|
+
declare const CHROME_UNAVAILABLE_KEY = "formattingBar.unavailableInPreview";
|
|
3457
|
+
|
|
3458
|
+
/** Material Symbol name → SVG path data (viewBox "0 -960 960 960"). */
|
|
3459
|
+
declare const GENERATED_ICON_PATHS: Readonly<Record<string, readonly string[]>>;
|
|
3460
|
+
|
|
3461
|
+
/** Border target picker value — concrete scopes plus clear (`none`). */
|
|
3462
|
+
type TableBorderTargetValue = TableBorderEdgeTarget | 'none';
|
|
3463
|
+
/** UI draft: last active edge scope and the complete border spec to reapply. */
|
|
3464
|
+
interface TableChromeDraft {
|
|
3465
|
+
readonly activeTarget: TableBorderEdgeTarget;
|
|
3466
|
+
readonly spec: TableBorderSpec;
|
|
3467
|
+
}
|
|
3468
|
+
/** The draft a table's border chrome starts from: a 1pt black single border on every edge. */
|
|
3469
|
+
declare const DEFAULT_TABLE_CHROME_DRAFT: TableChromeDraft;
|
|
3470
|
+
/**
|
|
3471
|
+
* The chrome slots that only exist while the caret is inside a table.
|
|
3472
|
+
*
|
|
3473
|
+
* A subset of `ChromeSlotId`, so these names are public API on the same terms — renaming one is
|
|
3474
|
+
* a breaking change.
|
|
3475
|
+
*/
|
|
3476
|
+
type TableChromeSlotId = 'table.borderTarget' | 'table.borderColor' | 'table.borderStyle' | 'table.borderWidth' | 'table.cellFill';
|
|
3477
|
+
/** Every {@link TableChromeSlotId}, for iteration and for {@link isTableChromeSlot}. */
|
|
3478
|
+
declare const TABLE_CHROME_SLOT_IDS: readonly TableChromeSlotId[];
|
|
3479
|
+
/** Furniture insertion controls (Task 8) share this label seam. */
|
|
3480
|
+
type TableInteractionLabelKey = 'table.insertRowBelow' | 'table.insertColumnRight';
|
|
3481
|
+
/**
|
|
3482
|
+
* The English label for a furniture-insertion control.
|
|
3483
|
+
*
|
|
3484
|
+
* The FALLBACK, for a host that has not wired its own translator — adapters pass their
|
|
3485
|
+
* `useTranslation` result instead so the control follows the app's locale.
|
|
3486
|
+
*/
|
|
3487
|
+
declare function defaultTableLabel(key: TableInteractionLabelKey): string;
|
|
3488
|
+
/** Whether a chrome slot is one of the table-only ones. Narrows the type. */
|
|
3489
|
+
declare function isTableChromeSlot(slot: ChromeSlotId): slot is TableChromeSlotId;
|
|
3490
|
+
/** Contextual table chrome is visible when the engine reports table context. */
|
|
3491
|
+
declare function tableChromeVisible(table: TableContext | null | undefined): boolean;
|
|
3492
|
+
/** One entry in the border-target picker: which edges it addresses, its icon, and its label key. */
|
|
3493
|
+
interface TableBorderTargetOption {
|
|
3494
|
+
readonly value: TableBorderTargetValue;
|
|
3495
|
+
readonly icon: keyof typeof GENERATED_ICON_PATHS;
|
|
3496
|
+
/** i18n key, never a literal string — both adapters translate it themselves. */
|
|
3497
|
+
readonly labelKey: string;
|
|
3498
|
+
}
|
|
3499
|
+
/** The border-target picker's entries, in Word's own order, ending with clear. */
|
|
3500
|
+
declare const TABLE_BORDER_TARGET_OPTIONS: readonly TableBorderTargetOption[];
|
|
3501
|
+
/** One entry in the border-style picker, with the CSS class that draws its preview line. */
|
|
3502
|
+
interface TableBorderStyleOption {
|
|
3503
|
+
readonly value: TableBorderStyle;
|
|
3504
|
+
readonly labelKey: string;
|
|
3505
|
+
/** Class on the preview swatch. Defined in the core stylesheet, which both adapters import. */
|
|
3506
|
+
readonly previewClass: string;
|
|
3507
|
+
}
|
|
3508
|
+
/** The border-style picker's entries. */
|
|
3509
|
+
declare const TABLE_BORDER_STYLE_OPTIONS: readonly TableBorderStyleOption[];
|
|
3510
|
+
/** One entry in the border-width picker. */
|
|
3511
|
+
interface TableBorderWidthOption {
|
|
3512
|
+
/** `w:sz` — eighths of a point, as OOXML stores border widths. */
|
|
3513
|
+
readonly size: number;
|
|
3514
|
+
readonly labelKey: string;
|
|
3515
|
+
/** Points, for drawing the preview swatch. `size / 8`. */
|
|
3516
|
+
readonly previewThickness: number;
|
|
3517
|
+
}
|
|
3518
|
+
/** Widths in eighths of a point — Word-like presets. */
|
|
3519
|
+
declare const TABLE_BORDER_WIDTH_OPTIONS: readonly TableBorderWidthOption[];
|
|
3520
|
+
/**
|
|
3521
|
+
* What one table-chrome selection produced: the command to run, and the draft to remember.
|
|
3522
|
+
*
|
|
3523
|
+
* Both halves matter. A border picker is stateful — choosing "dashed" and then "outside" must
|
|
3524
|
+
* apply a dashed outside border — so each pick returns the COMPLETE spec to execute alongside the
|
|
3525
|
+
* draft the next pick builds on.
|
|
3526
|
+
*/
|
|
3527
|
+
interface TableChromePick {
|
|
3528
|
+
readonly command: EditorCommand;
|
|
3529
|
+
readonly nextDraft: TableChromeDraft;
|
|
3530
|
+
}
|
|
3531
|
+
/**
|
|
3532
|
+
* Build the engine command for one table chrome pick and the draft state after it.
|
|
3533
|
+
* Target picks apply the current complete spec; `none` clears the active target only.
|
|
3534
|
+
*/
|
|
3535
|
+
declare function applyTableChromePick(draft: TableChromeDraft, slot: TableChromeSlotId, value: unknown): TableChromePick | null;
|
|
3536
|
+
/** Probe command for `Editor.can` — uses the draft's active target and a well-formed value. */
|
|
3537
|
+
declare function probeTableChromeCommand(slot: TableChromeSlotId, draft?: TableChromeDraft): EditorCommand | null;
|
|
3538
|
+
/**
|
|
3539
|
+
* The i18n key naming one border target, for a trigger that shows the active scope.
|
|
3540
|
+
*
|
|
3541
|
+
* Falls back to the "all" key rather than throwing: a label is chrome, and a missing one should
|
|
3542
|
+
* not take the toolbar down.
|
|
3543
|
+
*/
|
|
3544
|
+
declare function tableChromeLabelKeyForTarget(target: TableBorderEdgeTarget): string;
|
|
3545
|
+
/** Material Symbol paths for one table chrome icon name. */
|
|
3546
|
+
declare function tableChromeIconPaths(name: keyof typeof GENERATED_ICON_PATHS): readonly string[];
|
|
3547
|
+
|
|
3548
|
+
/** Value types accepted by toolbar controls. Font size uses half-points. @public */
|
|
3549
|
+
interface ToolbarValueMap {
|
|
3550
|
+
'font.family': string;
|
|
3551
|
+
'font.size': number;
|
|
3552
|
+
'text.color': string;
|
|
3553
|
+
'text.highlight': string;
|
|
3554
|
+
'styles.style': string;
|
|
3555
|
+
'list.lineSpacing': number;
|
|
3556
|
+
'image.wrap': ImageWrapTarget;
|
|
3557
|
+
'image.altText': string;
|
|
3558
|
+
'review.editingMode': 'editing' | 'suggesting' | 'viewing';
|
|
3559
|
+
}
|
|
3560
|
+
/** @public */
|
|
3561
|
+
type ToolbarValueSlot = keyof ToolbarValueMap | TableChromeSlotId;
|
|
3562
|
+
/** @public */
|
|
3563
|
+
type ToolbarSlotValue<K extends ToolbarValueSlot> = K extends keyof ToolbarValueMap ? ToolbarValueMap[K] : unknown;
|
|
3564
|
+
/** A command hook keeps its nullary event-handler form and accepts explicit options. @public */
|
|
3565
|
+
interface EditorCommandExecute {
|
|
3566
|
+
(): boolean;
|
|
3567
|
+
(options: EditorExecOptions): boolean;
|
|
3568
|
+
}
|
|
3569
|
+
/** Ignore framework events passed to a command used directly as an event handler. */
|
|
3570
|
+
declare function commandExecOptions(value: unknown): EditorExecOptions | undefined;
|
|
3571
|
+
|
|
3572
|
+
/**
|
|
3573
|
+
* The probe a slot uses to ask "would the engine honour this right now?" when its real
|
|
3574
|
+
* command needs an argument the slot itself cannot supply.
|
|
3575
|
+
*
|
|
3576
|
+
* `text.link` is the case: whether this selection could become a link is the engine's
|
|
3577
|
+
* question, but WHICH link is a URL field's. Chrome that owns a link UI (React's
|
|
3578
|
+
* `ToolbarLink`) asks with this and dispatches through that UI.
|
|
3579
|
+
*
|
|
3580
|
+
* DELIBERATELY NOT in `SLOT_COMMANDS`. Enabled state has one source, and putting the probe
|
|
3581
|
+
* there would enable the control in EVERY adapter — including Vue, which has grown no link
|
|
3582
|
+
* UI, where the result is an enabled button whose click can only be refused. A dead button
|
|
3583
|
+
* is the worse lie: `file.save` was a disabled control for a capability that works, and this
|
|
3584
|
+
* would be an enabled control for one that is not reachable. Vue's slot therefore keeps
|
|
3585
|
+
* reporting the honest "not wired to an editor command" until its popover lands.
|
|
3586
|
+
*
|
|
3587
|
+
* @public
|
|
3588
|
+
*/
|
|
3589
|
+
declare function chromeProbeForSlot(slotId: ChromeSlotId): EditorCommand | null;
|
|
3590
|
+
/**
|
|
3591
|
+
* The public editor command behind one chrome slot, or `null` when the slot is
|
|
3592
|
+
* not wired to a command yet (parity-only chrome, or save — which is not a
|
|
3593
|
+
* command). The single source of command truth for both adapters.
|
|
3594
|
+
*
|
|
3595
|
+
* @public
|
|
3596
|
+
*/
|
|
3597
|
+
declare function commandForSlot(slotId: ChromeSlotId): EditorCommand | null;
|
|
3598
|
+
|
|
3599
|
+
/**
|
|
3600
|
+
* Build an engine command for one table chrome slot using the caller's draft state.
|
|
3601
|
+
*
|
|
3602
|
+
* @public
|
|
3603
|
+
*/
|
|
3604
|
+
declare function commandForTableChromeSlotValue(slotId: TableChromeSlotId, value: unknown, draft: TableChromeDraft): EditorCommand | null;
|
|
3605
|
+
/**
|
|
3606
|
+
* The engine command for a VALUE-TYPED slot carrying the picked value, or `null` for a
|
|
3607
|
+
* slot that does not take a value.
|
|
3608
|
+
*
|
|
3609
|
+
* Two families: the run-property pickers (`font.family`, `font.size`, `text.color`,
|
|
3610
|
+
* `text.highlight`) resolve to `setMarkAttr`, and `styles.style` resolves to
|
|
3611
|
+
* `setParagraphStyle` — a paragraph styleId, not a mark. Either way the value is
|
|
3612
|
+
* validated by the engine's own gate (`can` refuses a malformed one with `invalidArgs`;
|
|
3613
|
+
* a styleId the document does not define is refused at `exec`), so a host can pass user
|
|
3614
|
+
* input through unmodified.
|
|
3615
|
+
*
|
|
3616
|
+
* @public
|
|
3617
|
+
*/
|
|
3618
|
+
declare function commandForSlotValue(slotId: ChromeSlotId, value: unknown): EditorCommand | null;
|
|
3619
|
+
/**
|
|
3620
|
+
* Whether one control is enabled, and the engine's reason when it is not.
|
|
3621
|
+
*
|
|
3622
|
+
* @public
|
|
3623
|
+
*/
|
|
3624
|
+
interface ToolbarCommandState {
|
|
3625
|
+
readonly id: ChromeSlotId;
|
|
3626
|
+
readonly enabled: boolean;
|
|
3627
|
+
/** The engine's reason when disabled — surfaced as a tooltip, never invented. */
|
|
3628
|
+
readonly disabledReason: string | null;
|
|
3629
|
+
/**
|
|
3630
|
+
* What the control currently SHOWS, for the slots whose answer is a value rather than a
|
|
3631
|
+
* pressed state — the editing-mode pill, and image wrap when it lands.
|
|
3632
|
+
*
|
|
3633
|
+
* `active` cannot express this: "the mode is Suggesting" is not a boolean about one
|
|
3634
|
+
* command, and a parallel channel for it would be a second place a control could read its
|
|
3635
|
+
* own state from. Absent for every slot whose state really is just pressed-or-not.
|
|
3636
|
+
*/
|
|
3637
|
+
readonly value?: string;
|
|
3638
|
+
/** Whether the command is currently APPLIED at the selection, from `Editor.isActive` —
|
|
3639
|
+
* derived in the engine for marks and alignment, honest-false elsewhere. */
|
|
3640
|
+
readonly active: boolean;
|
|
3641
|
+
}
|
|
3642
|
+
/**
|
|
3643
|
+
* Enabled state for one table chrome slot using explicit draft state.
|
|
3644
|
+
*
|
|
3645
|
+
* @public
|
|
3646
|
+
*/
|
|
3647
|
+
declare function tableChromeToolbarState(editor: Editor | null, slot: TableChromeSlotId, draft?: TableChromeDraft): ToolbarCommandState;
|
|
3648
|
+
/**
|
|
3649
|
+
* Ask the engine whether one control should be enabled.
|
|
3650
|
+
*
|
|
3651
|
+
* @public
|
|
3652
|
+
*/
|
|
3653
|
+
declare function toolbarCommandState(editor: Editor | null, id: ChromeSlotId): ToolbarCommandState;
|
|
3654
|
+
/**
|
|
3655
|
+
* Whether a slot's control renders as a TOGGLE — pressed or not — so it carries
|
|
3656
|
+
* `aria-pressed`.
|
|
3657
|
+
*
|
|
3658
|
+
* Shared rather than derived per adapter, because it is not derivable from the command table
|
|
3659
|
+
* alone: the format painter has no fixed command (a press captures, arms, locks or stands
|
|
3660
|
+
* down, which no single `EditorCommand` describes), so a rule that only read `commandForSlot`
|
|
3661
|
+
* left it announcing nothing at all to a screen reader while it was armed.
|
|
3662
|
+
*
|
|
3663
|
+
* @public
|
|
3664
|
+
*/
|
|
3665
|
+
declare function chromeSlotIsToggle(slotId: ChromeSlotId): boolean;
|
|
3666
|
+
/**
|
|
3667
|
+
* Enabled state for several controls in one pass.
|
|
3668
|
+
*
|
|
3669
|
+
* @public
|
|
3670
|
+
*/
|
|
3671
|
+
declare function toolbarCommandStates(editor: Editor | null, ids: readonly ChromeSlotId[]): readonly ToolbarCommandState[];
|
|
3672
|
+
/**
|
|
3673
|
+
* Result of {@link runTableChromeCommand}: engine outcome plus post-pick draft on success.
|
|
3674
|
+
*
|
|
3675
|
+
* @public
|
|
3676
|
+
*/
|
|
3677
|
+
interface RunTableChromeCommandResult {
|
|
3678
|
+
readonly result: ExecResult;
|
|
3679
|
+
readonly nextDraft: TableChromeDraft | null;
|
|
3680
|
+
}
|
|
3681
|
+
/**
|
|
3682
|
+
* Run one table chrome pick with explicit draft state; returns the post-pick draft on success.
|
|
3683
|
+
*
|
|
3684
|
+
* @public
|
|
3685
|
+
*/
|
|
3686
|
+
declare function runTableChromeCommand(editor: Editor | null, slot: TableChromeSlotId, value: unknown, draft: TableChromeDraft): RunTableChromeCommandResult;
|
|
3687
|
+
/**
|
|
3688
|
+
* Run a toolbar control: `can` first, then `exec` only if it said yes. Returns
|
|
3689
|
+
* the engine's refusal untouched when it said no, so a caller cannot mistake a
|
|
3690
|
+
* declined command for a no-op.
|
|
3691
|
+
*
|
|
3692
|
+
* @public
|
|
3693
|
+
*/
|
|
3694
|
+
declare function runToolbarCommand(editor: Editor | null, id: ChromeSlotId): ExecResult;
|
|
3695
|
+
/** @public */
|
|
3696
|
+
declare function runToolbarCommand(editor: Editor | null, id: Exclude<ChromeSlotId, ToolbarValueSlot>, options: EditorExecOptions): ExecResult;
|
|
3697
|
+
/** @public */
|
|
3698
|
+
declare function runToolbarCommand<K extends keyof ToolbarValueMap>(editor: Editor | null, id: K, value: ToolbarValueMap[NoInfer<K>], options?: EditorExecOptions): ExecResult;
|
|
3699
|
+
/** @public */
|
|
3700
|
+
declare function runToolbarCommand(editor: Editor | null, id: TableChromeSlotId, value: unknown, options?: EditorExecOptions): ExecResult;
|
|
3701
|
+
/** @public */
|
|
3702
|
+
declare function runToolbarCommand(editor: Editor | null, id: ChromeSlotId, value: undefined, options: EditorExecOptions): ExecResult;
|
|
3703
|
+
/**
|
|
3704
|
+
* Save goes straight to `Editor.save()` — it is not a command.
|
|
3705
|
+
*
|
|
3706
|
+
* @public
|
|
3707
|
+
*/
|
|
3708
|
+
declare function runSave(editor: Editor | null): Promise<ArrayBuffer>;
|
|
3709
|
+
/**
|
|
3710
|
+
* Enabled state for a table command when the caller holds the paginated surface.
|
|
3711
|
+
*
|
|
3712
|
+
* Uses the same planner-backed `tableCommandState` as `Editor.can`/`gateTableCommand`.
|
|
3713
|
+
* Chrome slot mapping for table controls is Task 9 — this helper is the shared
|
|
3714
|
+
* can-before-exec seam for arbitrary table commands.
|
|
3715
|
+
*
|
|
3716
|
+
* @public
|
|
3717
|
+
*/
|
|
3718
|
+
declare function tableCommandToolbarState(surface: PaginatedSurface | null, command: EditorCommand): Pick<ToolbarCommandState, 'enabled' | 'disabledReason'>;
|
|
3719
|
+
/**
|
|
3720
|
+
* Run a table command: planner-backed `can` first, then `exec` only when allowed.
|
|
3721
|
+
*
|
|
3722
|
+
* @public
|
|
3723
|
+
*/
|
|
3724
|
+
declare function runTableCommand(editor: Editor | null, command: EditorCommand, options?: EditorExecOptions): ExecResult;
|
|
3725
|
+
|
|
3726
|
+
/**
|
|
3727
|
+
* Build an editor: the full `Editor` contract over a paginated surface.
|
|
3728
|
+
*
|
|
3729
|
+
* Construction is separate from mounting. Pass a `container` and the document mounts
|
|
3730
|
+
* immediately; omit it and nothing touches the DOM until `attach(el)` — the provider-first
|
|
3731
|
+
* shape. `detach()` remounts from the saved bytes, which resets undo and the caret.
|
|
3732
|
+
*
|
|
3733
|
+
* `snapshot()` is version-cached: the same reference until state actually moves, with
|
|
3734
|
+
* reference-stable sub-objects, so it is safe as a `useSyncExternalStore` source.
|
|
3735
|
+
*
|
|
3736
|
+
* @example
|
|
3737
|
+
* ```ts
|
|
3738
|
+
* const editor = createDocxEditor({ document: bytes, modules: [reviewModule()] });
|
|
3739
|
+
* editor.attach(element);
|
|
3740
|
+
* editor.on('change', () => setDirty(true));
|
|
3741
|
+
* ```
|
|
3742
|
+
*
|
|
3743
|
+
* @public
|
|
3744
|
+
*/
|
|
3745
|
+
declare function createDocxEditor(config: DocxEditorConfig): DocxEditorInstance;
|
|
3746
|
+
|
|
3747
|
+
/** Native event policy for one continuous control gesture. @public */
|
|
3748
|
+
interface HistoryGroupBindingOptions {
|
|
3749
|
+
readonly kind: 'native-color' | 'range' | 'repeat' | 'keyboard';
|
|
3750
|
+
}
|
|
3751
|
+
/** Dispose when the element or editor changes. @public */
|
|
3752
|
+
interface HistoryGroupBinding {
|
|
3753
|
+
/** Options for the next synchronous formatting command. */
|
|
3754
|
+
options(): EditorExecOptions;
|
|
3755
|
+
/** Close the gesture and remove every listener; does not revert edits. */
|
|
3756
|
+
dispose(): void;
|
|
3757
|
+
}
|
|
3758
|
+
/**
|
|
3759
|
+
* Bind native gesture events. Framework change handlers apply values; this binding ends groups.
|
|
3760
|
+
* Native color `change` means value commitment, not portable popup closure. Controls without
|
|
3761
|
+
* a terminal change event end on the next activation, Escape, blur, or disposal.
|
|
3762
|
+
* Range/repeat controls end on pointer release/cancel or keyup, including outside releases.
|
|
3763
|
+
* Terminal events close after propagation so the final value can use the same handle.
|
|
3764
|
+
* @public
|
|
3765
|
+
*/
|
|
3766
|
+
declare function bindHistoryGroup(editor: Editor, element: HTMLElement, config: HistoryGroupBindingOptions): HistoryGroupBinding;
|
|
3767
|
+
|
|
3768
|
+
/** File menu conversion formats. @public */
|
|
3769
|
+
type ChromeExportFormat = 'markdown' | 'pdf';
|
|
3770
|
+
/** Viewer settings captured before PDF conversion. @public */
|
|
3771
|
+
interface ChromeExportView {
|
|
3772
|
+
readonly displayMode: ReviewDisplayMode;
|
|
3773
|
+
readonly revisionMarkup: ResolvedRevisionMarkup;
|
|
3774
|
+
/** Stable session slots, including gaps left by removed authors. */
|
|
3775
|
+
readonly revisionAuthorSlots?: Readonly<Record<string, number>>;
|
|
3776
|
+
}
|
|
3777
|
+
/**
|
|
3778
|
+
* Conversion handlers for File > Export. Install the corresponding converter package.
|
|
3779
|
+
* Use `exportMarkdown` for Markdown. PDF requires `exportPdf` on a Node.js server.
|
|
3780
|
+
* Browser hosts supply a PDF handler that calls that server after the user selects Export.
|
|
3781
|
+
* @public
|
|
3782
|
+
*/
|
|
3783
|
+
interface ChromeExportHandlers {
|
|
3784
|
+
/** Returns continuous document Markdown. Page output is not downloaded. */
|
|
3785
|
+
readonly markdown?: (source: Uint8Array) => Promise<{
|
|
3786
|
+
readonly markdown: string;
|
|
3787
|
+
}>;
|
|
3788
|
+
/** Returns PDF bytes from `@docx-editor.dev/docx-to-pdf` on Node.js. */
|
|
3789
|
+
readonly pdf?: (source: Uint8Array, view?: ChromeExportView) => Promise<{
|
|
3790
|
+
readonly bytes: Uint8Array;
|
|
3791
|
+
}>;
|
|
3792
|
+
}
|
|
3793
|
+
/** Download data from a completed conversion. @public */
|
|
3794
|
+
interface ChromeExportResult {
|
|
3795
|
+
readonly bytes: Uint8Array;
|
|
3796
|
+
readonly extension: 'md' | 'pdf';
|
|
3797
|
+
readonly mimeType: string;
|
|
3798
|
+
}
|
|
3799
|
+
/** An export has no configured converter. @public */
|
|
3800
|
+
declare class ChromeExportError extends Error {
|
|
3801
|
+
readonly format: ChromeExportFormat;
|
|
3802
|
+
readonly code = "missing-exporter";
|
|
3803
|
+
constructor(format: ChromeExportFormat);
|
|
3804
|
+
}
|
|
3805
|
+
/**
|
|
3806
|
+
* Saves the current document and converts those bytes through the configured handler.
|
|
3807
|
+
* Missing handlers fail before saving. Conversion never changes the editor document.
|
|
3808
|
+
* @public
|
|
3809
|
+
*/
|
|
3810
|
+
declare function runChromeExport(editor: Pick<Editor, 'save'> & Partial<Pick<DocxEditorInstance, 'snapshot' | 'getReviewAuthors'>>, format: ChromeExportFormat, handlers?: ChromeExportHandlers): Promise<ChromeExportResult>;
|
|
3811
|
+
|
|
3812
|
+
/** Why the browser could not print the converted PDF. @public */
|
|
3813
|
+
type ChromePrintErrorCode = 'pdf-viewer-unavailable' | 'pdf-load-failed' | 'print-refused' | 'print-ended';
|
|
3814
|
+
/**
|
|
3815
|
+
* The browser could not print the converted PDF. The PDF at `ChromePrintJob.url` is still
|
|
3816
|
+
* available, so the user can open it and print from the PDF viewer.
|
|
3817
|
+
* @public
|
|
3818
|
+
*/
|
|
3819
|
+
declare class ChromePrintError extends Error {
|
|
3820
|
+
/** Why the browser could not print. */
|
|
3821
|
+
readonly code: ChromePrintErrorCode;
|
|
3822
|
+
constructor(code: ChromePrintErrorCode);
|
|
3823
|
+
}
|
|
3824
|
+
/**
|
|
3825
|
+
* True for the print shortcut: Cmd+P on Apple platforms, Ctrl+P elsewhere. On macOS,
|
|
3826
|
+
* Ctrl+P moves the caret to the previous line, so it is not a print shortcut there. The P
|
|
3827
|
+
* key matches by `code` too when it types no Latin letter, as on Cyrillic or Hebrew layouts.
|
|
3828
|
+
* @public
|
|
3829
|
+
*/
|
|
3830
|
+
declare function isChromePrintShortcut(event: KeyboardEvent): boolean;
|
|
3831
|
+
/** Options for `ChromePrintJob.print`. @public */
|
|
3832
|
+
interface ChromePrintOptions {
|
|
3833
|
+
/**
|
|
3834
|
+
* Runs after the PDF loads and before the print dialog opens. Close any modal dialog
|
|
3835
|
+
* here: a modal dialog makes the rest of the page, including the print frame, inert.
|
|
3836
|
+
*/
|
|
3837
|
+
readonly beforePrint?: () => void | Promise<void>;
|
|
3838
|
+
}
|
|
3839
|
+
/**
|
|
3840
|
+
* A converted PDF, ready for the browser print dialog.
|
|
3841
|
+
* Call `dispose()` when the job ends: it removes the print frame and revokes `url`.
|
|
3842
|
+
* @public
|
|
3843
|
+
*/
|
|
3844
|
+
interface ChromePrintJob {
|
|
3845
|
+
/** An object URL for the PDF. It stays valid until `dispose()`. */
|
|
3846
|
+
readonly url: string;
|
|
3847
|
+
/**
|
|
3848
|
+
* Opens the browser print dialog for the PDF from a hidden frame.
|
|
3849
|
+
* Rejects with `ChromePrintError` when the browser has no PDF viewer, the frame cannot
|
|
3850
|
+
* load the PDF, or the job has ended. A browser without a PDF viewer would download the
|
|
3851
|
+
* PDF instead of loading it, so the frame is not created in that case.
|
|
3852
|
+
*/
|
|
3853
|
+
print(options?: ChromePrintOptions): Promise<void>;
|
|
3854
|
+
/** Removes the print frame and revokes `url`. Later `print()` calls reject. */
|
|
3855
|
+
dispose(): void;
|
|
3856
|
+
}
|
|
3857
|
+
/**
|
|
3858
|
+
* Saves the current document, converts it with the configured PDF handler, and prepares
|
|
3859
|
+
* the result for printing. Uses the same handler and checks as File > Export > PDF, so a
|
|
3860
|
+
* missing handler rejects with `ChromeExportError` before the document is saved.
|
|
3861
|
+
* Saving commits pending form input and can refresh field results with an undo step.
|
|
3862
|
+
* `container` receives the hidden print frame. For an editor inside a modal dialog,
|
|
3863
|
+
* pass an element inside that dialog.
|
|
3864
|
+
* @public
|
|
3865
|
+
*/
|
|
3866
|
+
declare function runChromePrint(editor: Pick<Editor, 'save'> & Partial<Pick<Editor, 'snapshot'>>, handlers?: ChromeExportHandlers, container?: Document | Element): Promise<ChromePrintJob>;
|
|
3867
|
+
|
|
3868
|
+
export { IMAGE_OVERLAY_NUDGE_SHIFT_PT as $, CHROME_GROUPS as C, DEFAULT_TABLE_CHROME_DRAFT as F, EMU_PER_POINT as I, IMAGE_OVERLAY_NUDGE_PT as _, createFontSource as a$, applyTableChromePick as aJ, bindHistoryGroup as aK, blankDocumentBytes as aL, canExecuteImageCommand as aM, captureImageMutationPreconditions as aN, chromeControlCount as aO, chromeMenuSlots as aP, chromeProbeForSlot as aQ, chromeSlotId as aR, chromeSlotIsToggle as aS, commandExecOptions as aT, commandForSlot as aU, commandForSlotValue as aV, commandForTableChromeSlotValue as aW, computeImageResizeResult as aX, computeMovedImagePosition as aY, computeResizedImageExtentEmu as aZ, createDocxEditor as a_, TABLE_BORDER_STYLE_OPTIONS as ar, TABLE_BORDER_TARGET_OPTIONS as as, TABLE_BORDER_WIDTH_OPTIONS as at, TABLE_CHROME_SLOT_IDS as au, CHROME_MENUS as b, createImageOverlayScrollPort as b0, cssPixelsToLayoutPoints as b1, customFonts as b2, defaultChromeGroups as b3, defaultTableLabel as b4, emuToOverlayPoints as b5, equationAtPosition as b6, executeImageCommand as b7, finalizeImageOverlayInteraction as b8, formattingBarChromeGroups as b9, isChromePrintShortcut as ba, isStaleImageInteractionCommit as bb, isTableChromeSlot as bc, layoutPointsToCssPixels as bd, loadFonts as be, overlayFrameToSheetCssPixels as bf, overlayHostOrigin as bg, pointsToEmu as bh, probeTableChromeCommand as bi, resizePreservesAspect as bj, runChromeExport as bk, runChromePrint as bl, runSave as bm, runTableChromeCommand as bn, runTableCommand as bo, runToolbarCommand as bp, selectedDrawingOverlayTargetOf as bq, selectedImageStateOf as br, surfacePaintScale as bs, tableChromeIconPaths as bt, tableChromeLabelKeyForTarget as bu, tableChromeToolbarState as bv, tableChromeVisible as bw, tableCommandToolbarState as bx, toolbarCommandState as by, toolbarCommandStates as bz, CHROME_UNAVAILABLE_KEY as c, ChromeExportError as g, ChromePrintError as t };
|
|
3869
|
+
export type { AnchorFrameOrigin as A, CustomFontsOptions as B, DocxEditorInstance as D, CustomFontsResolver as E, DocxEditorConfig as G, DrawingSelectionIntent as H, EditorCommandExecute as J, EquationActivation as K, EquationChromeHandlers as L, EquationOps as M, FinalizedImageOverlayInteraction as N, OpenPaginatedResult as O, PaginatedSurfaceOptions as P, FontLoadFailure as Q, FontLoadFailureReason as R, FontMeasurementState as S, TableCommandPlan as T, FontUrlSource as U, HistoryGroupBinding as V, HistoryGroupBindingOptions as W, HyperlinkActivation as X, HyperlinkChromeHandlers as Y, HyperlinkOps as Z, PaginatedSurface as a, ImageInteractionSession as a0, ImageOverlayScrollPort as a1, ImageResizeHandle as a2, ImageResizeResult as a3, InvalidTextFormFieldChromeHandlers as a4, InvalidTextFormFieldSession as a5, LoadFontsRequest as a6, LoadFontsResult as a7, OpeningIndicatorHost as a8, OverlayFrameRect as a9, TableChromePick as aA, TableChromeSlotId as aB, TableInteractionLabelKey as aC, TextFormFieldChromeHandlers as aD, TextFormFieldDialogSession as aE, ToolbarCommandState as aF, ToolbarSlotValue as aG, ToolbarValueMap as aH, ToolbarValueSlot as aI, PaginatedSurfaceState as aa, ParagraphPropertyEdit as ab, PopupChromeRegistrationOptions as ac, RemoteCaretLabelAnchor as ad, RemoteCaretLabelHost as ae, ReviewWriteIntent as af, RunTableChromeCommandResult as ag, SectionAnchor as ah, SectionBreakInsertType as ai, SelectedDrawingOverlayTarget as aj, SurfaceEquation as ak, SurfaceFormatting as al, SurfaceHyperlink as am, SurfaceInsertImageInput as an, SurfaceNavigation as ao, SurfaceOverlayCoordinates as ap, SurfaceParagraphFormat as aq, TableBorderStyleOption as av, TableBorderTargetOption as aw, TableBorderTargetValue as ax, TableBorderWidthOption as ay, TableChromeDraft as az, ChromeControl as d, ChromeControlId as e, ChromeControlState as f, ChromeExportFormat as h, ChromeExportHandlers as i, ChromeExportResult as j, ChromeExportView as k, ChromeGroup as l, ChromeGroupId as m, ChromeMenu as n, ChromeMenuEntry as o, ChromeMenuId as p, ChromeMenuItemEntry as q, ChromeMenuSeparatorEntry as r, ChromeMenuSubmenuEntry as s, ChromePrintErrorCode as u, ChromePrintJob as v, ChromePrintOptions as w, ChromeSlotId as x, ContentControlWidgetChromeHandlers as y, ContentControlWidgetSession as z };
|