@sqren/docx-editor-react 1.7.0-fork.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +122 -0
- package/dist/FindReplaceDialog-HM63BMXE.js +1 -0
- package/dist/FindReplaceDialog-KU5TEIBJ.mjs +1 -0
- package/dist/FootnotePropertiesDialog-TV2BGQDC.js +1 -0
- package/dist/FootnotePropertiesDialog-W3YHM4BV.mjs +1 -0
- package/dist/HyperlinkDialog-7MEQJIYP.js +1 -0
- package/dist/HyperlinkDialog-ZYH7ZHRF.mjs +1 -0
- package/dist/ImagePositionDialog-HEWYR6Q3.mjs +1 -0
- package/dist/ImagePositionDialog-LSCCQORZ.js +1 -0
- package/dist/ImagePropertiesDialog-RAB47C6M.mjs +1 -0
- package/dist/ImagePropertiesDialog-Z4M6XKFG.js +1 -0
- package/dist/KeyboardShortcutsDialog-B-h3NAat.d.mts +415 -0
- package/dist/KeyboardShortcutsDialog-B-h3NAat.d.ts +415 -0
- package/dist/PageSetupDialog-AIGIXO3E.mjs +1 -0
- package/dist/PageSetupDialog-LWYOYKEU.js +1 -0
- package/dist/PrintPreview-DEhwRBC_.d.mts +93 -0
- package/dist/PrintPreview-DEhwRBC_.d.ts +93 -0
- package/dist/SplitCellDialog-45W7SDPY.js +1 -0
- package/dist/SplitCellDialog-IFBKYCD6.mjs +1 -0
- package/dist/TablePropertiesDialog-TMLKGOOW.mjs +1 -0
- package/dist/TablePropertiesDialog-VCDCPM3R.js +1 -0
- package/dist/WatermarkDialog-KRL7WMIS.mjs +1 -0
- package/dist/WatermarkDialog-XGLAH3TK.js +1 -0
- package/dist/chunk-4Y4JFAPY.mjs +2 -0
- package/dist/chunk-74OM4KEH.js +2 -0
- package/dist/chunk-7VWJSV3T.js +2 -0
- package/dist/chunk-BABMU5KA.mjs +2 -0
- package/dist/chunk-BJ5RZW6Y.js +1 -0
- package/dist/chunk-BMBP5UFA.mjs +1 -0
- package/dist/chunk-BZO4G5M6.js +1 -0
- package/dist/chunk-GM2S2WMT.mjs +1 -0
- package/dist/chunk-GNIO6SOS.js +1 -0
- package/dist/chunk-GWXEFL3H.js +1 -0
- package/dist/chunk-IVFYCMAM.mjs +1 -0
- package/dist/chunk-J72K2BOS.mjs +2 -0
- package/dist/chunk-L4MDZW2J.js +1 -0
- package/dist/chunk-LNONBJQM.js +1 -0
- package/dist/chunk-NIBCC7WQ.js +1 -0
- package/dist/chunk-O6M2HAIZ.mjs +1 -0
- package/dist/chunk-OCA7BO3G.mjs +1 -0
- package/dist/chunk-OHNO4NRQ.mjs +1 -0
- package/dist/chunk-P5ZOUQIK.mjs +1 -0
- package/dist/chunk-P6METJHI.mjs +2 -0
- package/dist/chunk-PSBO3UDN.js +1 -0
- package/dist/chunk-QD7BVJV3.js +2 -0
- package/dist/chunk-WFGAQC2B.mjs +1 -0
- package/dist/chunk-WNWY6WX7.js +2 -0
- package/dist/chunk-YY52FSUR.js +1 -0
- package/dist/chunk-ZFZJRL2R.mjs +1 -0
- package/dist/dialogs.d.mts +40 -0
- package/dist/dialogs.d.ts +40 -0
- package/dist/dialogs.js +1 -0
- package/dist/dialogs.mjs +1 -0
- package/dist/hooks.d.mts +513 -0
- package/dist/hooks.d.ts +513 -0
- package/dist/hooks.js +1 -0
- package/dist/hooks.mjs +1 -0
- package/dist/index.d.mts +683 -0
- package/dist/index.d.ts +683 -0
- package/dist/index.js +32 -0
- package/dist/index.mjs +32 -0
- package/dist/plugin-api.d.mts +90 -0
- package/dist/plugin-api.d.ts +90 -0
- package/dist/plugin-api.js +246 -0
- package/dist/plugin-api.mjs +246 -0
- package/dist/styles.css +1 -0
- package/dist/styles.d.mts +13 -0
- package/dist/styles.d.ts +13 -0
- package/dist/styles.js +1 -0
- package/dist/styles.mjs +1 -0
- package/dist/types-D35gNE-_.d.mts +106 -0
- package/dist/types-D35gNE-_.d.ts +106 -0
- package/dist/ui.d.mts +1568 -0
- package/dist/ui.d.ts +1568 -0
- package/dist/ui.js +111 -0
- package/dist/ui.mjs +111 -0
- package/dist/useFindReplace-Bc2ubEeV.d.mts +219 -0
- package/dist/useFindReplace-Bc2ubEeV.d.ts +219 -0
- package/package.json +137 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,683 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @eigenpal/docx-editor-react
|
|
3
|
+
*
|
|
4
|
+
* Curated root entry for the documented React editor API. Advanced surfaces
|
|
5
|
+
* stay public through explicit subpaths:
|
|
6
|
+
* - `@eigenpal/docx-editor-react/ui`
|
|
7
|
+
* - `@eigenpal/docx-editor-react/dialogs`
|
|
8
|
+
* - `@eigenpal/docx-editor-react/hooks`
|
|
9
|
+
* - `@eigenpal/docx-editor-react/plugin-api`
|
|
10
|
+
*
|
|
11
|
+
* Framework-agnostic document utilities live in `@eigenpal/docx-editor-core`.
|
|
12
|
+
* Agent/MCP surfaces live in `@eigenpal/docx-editor-agents`.
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
import * as React from 'react';
|
|
18
|
+
import { ReactNode, CSSProperties } from 'react';
|
|
19
|
+
import * as prosemirror_view from 'prosemirror-view';
|
|
20
|
+
import { EditorView } from 'prosemirror-view';
|
|
21
|
+
import * as prosemirror_state from 'prosemirror-state';
|
|
22
|
+
import { EditorState, Transaction } from 'prosemirror-state';
|
|
23
|
+
import { Document, HeaderFooter, Theme } from '@eigenpal/docx-editor-core/types/document';
|
|
24
|
+
import { FontOption } from '@eigenpal/docx-editor-core/utils/fontOptions';
|
|
25
|
+
import { R as ReactSidebarItem } from './types-D35gNE-_.mjs';
|
|
26
|
+
import { Comment } from '@eigenpal/docx-editor-core/types/content';
|
|
27
|
+
import { Translations, TFunction } from '@eigenpal/docx-editor-i18n';
|
|
28
|
+
import { P as PrintOptions } from './PrintPreview-DEhwRBC_.mjs';
|
|
29
|
+
import { DocumentAgent, ContentControlFilter, ContentControlValue } from '@eigenpal/docx-editor-core/agent';
|
|
30
|
+
import { DocxInput, FontDefinition } from '@eigenpal/docx-editor-core/utils';
|
|
31
|
+
import { SelectionState, PMContentControl } from '@eigenpal/docx-editor-core/prosemirror';
|
|
32
|
+
import { Layout } from '@eigenpal/docx-editor-core/layout-engine';
|
|
33
|
+
import { RenderedDomContext } from '@eigenpal/docx-editor-core/plugin-api';
|
|
34
|
+
import { EditorHandle } from '@eigenpal/docx-editor-core';
|
|
35
|
+
export { CreateEmptyDocumentOptions, createDocumentWithText, createEmptyDocument } from '@eigenpal/docx-editor-core';
|
|
36
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Options for the agent panel mount on the right side of the editor.
|
|
40
|
+
*
|
|
41
|
+
* Three control patterns:
|
|
42
|
+
* - **Uncontrolled**: `agentPanel={{ render }}` — toolbar button + panel
|
|
43
|
+
* close button toggle the panel. Width persists to localStorage.
|
|
44
|
+
* - **Controlled**: `agentPanel={{ render, open, onOpenChange }}` — the
|
|
45
|
+
* consumer owns open state (e.g. tied to a global menu).
|
|
46
|
+
* - **Headless**: omit `agentPanel`, use the toolkit directly via
|
|
47
|
+
* `useDocxAgentTools` — render the panel anywhere you want.
|
|
48
|
+
*/
|
|
49
|
+
interface AgentPanelOptions {
|
|
50
|
+
/** Render-prop returning the panel content. Called only when open. */
|
|
51
|
+
render: (ctx: {
|
|
52
|
+
close: () => void;
|
|
53
|
+
}) => ReactNode;
|
|
54
|
+
/** Controlled open state. Omit for uncontrolled. */
|
|
55
|
+
open?: boolean;
|
|
56
|
+
/** Fires when toolbar button or panel close button is clicked. */
|
|
57
|
+
onOpenChange?: (open: boolean) => void;
|
|
58
|
+
/** Show the toolbar toggle button. Default: true. */
|
|
59
|
+
showToolbarButton?: boolean;
|
|
60
|
+
/** Optional badge / dot on the toolbar button. */
|
|
61
|
+
toolbarBadge?: ReactNode;
|
|
62
|
+
/** Optional panel title. Default: t('agentPanel.defaultTitle'). */
|
|
63
|
+
title?: string;
|
|
64
|
+
/** Optional panel header icon. Default: sparkle. */
|
|
65
|
+
icon?: ReactNode;
|
|
66
|
+
/** Initial panel width in px (uncontrolled). Default: 360. */
|
|
67
|
+
defaultWidth?: number;
|
|
68
|
+
/** Min drag width. Default: 280. */
|
|
69
|
+
minWidth?: number;
|
|
70
|
+
/** Max drag width. Default: 600. */
|
|
71
|
+
maxWidth?: number;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface PagedEditorRef {
|
|
75
|
+
/** Get the current document. */
|
|
76
|
+
getDocument(): Document | null;
|
|
77
|
+
/** Get the ProseMirror EditorState. */
|
|
78
|
+
getState(): EditorState | null;
|
|
79
|
+
/** Get the ProseMirror EditorView. */
|
|
80
|
+
getView(): EditorView | null;
|
|
81
|
+
/** Focus the editor. */
|
|
82
|
+
focus(): void;
|
|
83
|
+
/** Blur the editor. */
|
|
84
|
+
blur(): void;
|
|
85
|
+
/** Check if focused. */
|
|
86
|
+
isFocused(): boolean;
|
|
87
|
+
/** Dispatch a transaction. */
|
|
88
|
+
dispatch(tr: Transaction): void;
|
|
89
|
+
/** Undo. */
|
|
90
|
+
undo(): boolean;
|
|
91
|
+
/** Redo. */
|
|
92
|
+
redo(): boolean;
|
|
93
|
+
/** Set selection by PM position. */
|
|
94
|
+
setSelection(anchor: number, head?: number): void;
|
|
95
|
+
/** Get current layout. */
|
|
96
|
+
getLayout(): Layout | null;
|
|
97
|
+
/** Force re-layout. */
|
|
98
|
+
relayout(): void;
|
|
99
|
+
/** Scroll the visible pages to bring a PM position into view. */
|
|
100
|
+
scrollToPosition(pmPos: number): void;
|
|
101
|
+
/**
|
|
102
|
+
* Scroll to the paragraph identified by Word `w14:paraId` / PM `paraId`.
|
|
103
|
+
* @returns whether a matching paragraph was found
|
|
104
|
+
*/
|
|
105
|
+
scrollToParaId(paraId: string): boolean;
|
|
106
|
+
/**
|
|
107
|
+
* Scroll the paginated view so `pageNumber` (1-indexed) is in view.
|
|
108
|
+
* No-op if the layout isn't ready yet or pageNumber is out of range.
|
|
109
|
+
*/
|
|
110
|
+
scrollToPage(pageNumber: number): void;
|
|
111
|
+
/**
|
|
112
|
+
* Scroll to the comment identified by `commentId` and select its range so
|
|
113
|
+
* the selection overlay highlights it. Resolves the id → PM range via the
|
|
114
|
+
* live comment marks; returns `false` (not a throw, not a silent no-op)
|
|
115
|
+
* when the id no longer resolves so the caller can surface a "location no
|
|
116
|
+
* longer exists" affordance.
|
|
117
|
+
*/
|
|
118
|
+
scrollToCommentId(commentId: number): boolean;
|
|
119
|
+
/**
|
|
120
|
+
* Scroll to the tracked change identified by `revisionId` and select its
|
|
121
|
+
* range so the selection overlay highlights it. Resolves the id → PM range
|
|
122
|
+
* via the live tracked-change marks; returns `false` when the id no longer
|
|
123
|
+
* resolves (the change was accepted/rejected/deleted).
|
|
124
|
+
*/
|
|
125
|
+
scrollToChangeId(revisionId: number): boolean;
|
|
126
|
+
/**
|
|
127
|
+
* Select the PM position range `[from, to]` so the selection overlay
|
|
128
|
+
* highlights it, and scroll its start into view. No-op for a malformed
|
|
129
|
+
* range or a `from` past the document end; `to` is clamped to the document
|
|
130
|
+
* size (raw caller positions, so out-of-range must not throw).
|
|
131
|
+
*/
|
|
132
|
+
highlightRange(from: number, to: number): void;
|
|
133
|
+
/**
|
|
134
|
+
* Look up the persistent hidden HF PM EditorView for a given HeaderFooter
|
|
135
|
+
* instance. Returns null when none is mounted (no document, or `hf` is not
|
|
136
|
+
* present in `Document.package.headers/footers`). Phase 2 of the HF
|
|
137
|
+
* unification: the inline overlay uses this to replicate edits into the
|
|
138
|
+
* persistent PM so the painter — which reads from the persistent PM per
|
|
139
|
+
* phase 1 — re-renders live during typing. Phase 5 deletes the inline
|
|
140
|
+
* overlay's PM and this method's only remaining caller is the click /
|
|
141
|
+
* focus router (phase 3).
|
|
142
|
+
*/
|
|
143
|
+
getHfPmView(hf: HeaderFooter): EditorView | null;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* EditorMode union + the catalog the editing-mode dropdown renders.
|
|
148
|
+
* Lives next to DocxEditor.tsx so the dropdown component and the parent
|
|
149
|
+
* forwardRef body share one source of truth.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
type EditorMode = 'editing' | 'suggesting' | 'viewing';
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* DocxEditor props
|
|
156
|
+
*/
|
|
157
|
+
interface DocxEditorProps {
|
|
158
|
+
/** Document data — ArrayBuffer, Uint8Array, Blob, or File */
|
|
159
|
+
documentBuffer?: DocxInput | null;
|
|
160
|
+
/** Pre-parsed document (alternative to documentBuffer) */
|
|
161
|
+
document?: Document | null;
|
|
162
|
+
/** Callback when document is saved */
|
|
163
|
+
onSave?: (buffer: ArrayBuffer) => void;
|
|
164
|
+
/** Author name used for comments and track changes */
|
|
165
|
+
author?: string;
|
|
166
|
+
/** Callback when document changes */
|
|
167
|
+
onChange?: (document: Document) => void;
|
|
168
|
+
/** Callback when selection changes */
|
|
169
|
+
onSelectionChange?: (state: SelectionState | null) => void;
|
|
170
|
+
/** Callback on error */
|
|
171
|
+
onError?: (error: Error) => void;
|
|
172
|
+
/** Callback when fonts are loaded */
|
|
173
|
+
onFontsLoaded?: () => void;
|
|
174
|
+
/** External ProseMirror plugins (from PluginHost) */
|
|
175
|
+
externalPlugins?: prosemirror_state.Plugin[];
|
|
176
|
+
/**
|
|
177
|
+
* When true, the editor treats the `document` prop as a schema seed only and
|
|
178
|
+
* does not load it into ProseMirror on mount. Content is expected to come from
|
|
179
|
+
* external sources — typically `externalPlugins` such as `ySyncPlugin` from
|
|
180
|
+
* `y-prosemirror`, but also any code that dispatches transactions directly.
|
|
181
|
+
*
|
|
182
|
+
* You must still pass a `document` prop (e.g., `createEmptyDocument()`) so the
|
|
183
|
+
* editor can build its schema and render the shell.
|
|
184
|
+
*/
|
|
185
|
+
externalContent?: boolean;
|
|
186
|
+
/** Callback when editor view is ready (for PluginHost) */
|
|
187
|
+
onEditorViewReady?: (view: prosemirror_view.EditorView) => void;
|
|
188
|
+
/** Color theme mode for UI styling. `'system'` follows the OS preference. */
|
|
189
|
+
colorMode?: 'light' | 'dark' | 'system';
|
|
190
|
+
/** Document theme schema object */
|
|
191
|
+
theme?: Theme | null;
|
|
192
|
+
/** Whether to show toolbar (default: true) */
|
|
193
|
+
showToolbar?: boolean;
|
|
194
|
+
/** Whether to show zoom control (default: true) */
|
|
195
|
+
showZoomControl?: boolean;
|
|
196
|
+
/** Whether to show page margin guides/boundaries (default: false) */
|
|
197
|
+
showMarginGuides?: boolean;
|
|
198
|
+
/** Color for margin guides (default: '#c0c0c0') */
|
|
199
|
+
marginGuideColor?: string;
|
|
200
|
+
/** Whether to show horizontal ruler (default: false) */
|
|
201
|
+
showRuler?: boolean;
|
|
202
|
+
/** Unit for ruler display (default: 'inch') */
|
|
203
|
+
rulerUnit?: 'inch' | 'cm';
|
|
204
|
+
/** Initial zoom level (default: 1.0) */
|
|
205
|
+
initialZoom?: number;
|
|
206
|
+
/** Whether the editor is read-only. When true, hides toolbar and rulers */
|
|
207
|
+
readOnly?: boolean;
|
|
208
|
+
/**
|
|
209
|
+
* When true, the editor does not intercept Cmd/Ctrl+F or Cmd/Ctrl+H.
|
|
210
|
+
* This lets the browser or host app handle native find/history shortcuts.
|
|
211
|
+
*/
|
|
212
|
+
disableFindReplaceShortcuts?: boolean;
|
|
213
|
+
/** Custom toolbar actions */
|
|
214
|
+
toolbarExtra?: ReactNode;
|
|
215
|
+
/** Additional CSS class name */
|
|
216
|
+
className?: string;
|
|
217
|
+
/** Additional inline styles */
|
|
218
|
+
style?: CSSProperties;
|
|
219
|
+
/** Placeholder when no document */
|
|
220
|
+
placeholder?: ReactNode;
|
|
221
|
+
/** Loading indicator */
|
|
222
|
+
loadingIndicator?: ReactNode;
|
|
223
|
+
/** Whether to show the document outline sidebar (default: false) */
|
|
224
|
+
showOutline?: boolean;
|
|
225
|
+
/** Whether to show the floating outline toggle button (default: true) */
|
|
226
|
+
showOutlineButton?: boolean;
|
|
227
|
+
/**
|
|
228
|
+
* Custom list of fonts shown in the toolbar's font-family dropdown.
|
|
229
|
+
* Strings render in the "Other" group; pass `FontOption[]` for category
|
|
230
|
+
* grouping and CSS fallback chains. Omit to use the built-in 12-font
|
|
231
|
+
* default. An empty array renders an empty (but enabled) dropdown.
|
|
232
|
+
*
|
|
233
|
+
* Pass a stable reference (memoized or module-level) — inline arrays
|
|
234
|
+
* create a new identity per render and invalidate the picker's memo.
|
|
235
|
+
*
|
|
236
|
+
* @example fontFamilies={['Arial', 'Roboto']}
|
|
237
|
+
* @example fontFamilies={[{ name: 'Roboto', fontFamily: 'Roboto, sans-serif', category: 'sans-serif' }]}
|
|
238
|
+
*/
|
|
239
|
+
fontFamilies?: ReadonlyArray<string | FontOption>;
|
|
240
|
+
/**
|
|
241
|
+
* Custom font faces to register with the browser before the editor measures
|
|
242
|
+
* text. Each entry injects an `@font-face` rule. Pass a URL (woff2/woff/
|
|
243
|
+
* ttf/otf), an ArrayBuffer, or omit `src` to load by name from Google Fonts.
|
|
244
|
+
* Multiple entries can share `family` to register different weights/styles.
|
|
245
|
+
*
|
|
246
|
+
* Pass a stable reference — inline arrays re-register faces on each render
|
|
247
|
+
* (the loader dedupes by `family|weight|style`, so it's harmless but wastes
|
|
248
|
+
* work).
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* fonts={[
|
|
252
|
+
* { family: 'Custom Sans', src: '/fonts/CustomSans-Regular.woff2' },
|
|
253
|
+
* { family: 'Custom Sans', src: '/fonts/CustomSans-Bold.woff2', weight: 700 },
|
|
254
|
+
* ]}
|
|
255
|
+
*/
|
|
256
|
+
fonts?: ReadonlyArray<FontDefinition>;
|
|
257
|
+
/**
|
|
258
|
+
* Text-watermark presets shown in the watermark dialog's preset dropdown.
|
|
259
|
+
* Omit to use the built-in MS Word phrases (`DEFAULT_WATERMARK_PRESETS`:
|
|
260
|
+
* CONFIDENTIAL, DRAFT, DO NOT COPY, SAMPLE, URGENT, ASAP). Pass an empty
|
|
261
|
+
* array to hide the preset dropdown and require custom text.
|
|
262
|
+
*
|
|
263
|
+
* @example watermarkPresets={['INTERNAL', 'PROPRIETARY', 'COPY']}
|
|
264
|
+
*/
|
|
265
|
+
watermarkPresets?: readonly string[];
|
|
266
|
+
/** Print options for print preview */
|
|
267
|
+
printOptions?: PrintOptions;
|
|
268
|
+
/**
|
|
269
|
+
* Callback when print is triggered. Pass it to enable the `File > Print`
|
|
270
|
+
* menu entry; omit to hide. The imperative `ref.current.print()` also
|
|
271
|
+
* invokes this callback.
|
|
272
|
+
*/
|
|
273
|
+
onPrint?: () => void;
|
|
274
|
+
/** Callback when content is copied */
|
|
275
|
+
onCopy?: () => void;
|
|
276
|
+
/** Callback when content is cut */
|
|
277
|
+
onCut?: () => void;
|
|
278
|
+
/** Callback when content is pasted */
|
|
279
|
+
onPaste?: () => void;
|
|
280
|
+
/** Editor mode: 'editing' (direct edits), 'suggesting' (track changes), or 'viewing' (read-only). Default: 'editing' */
|
|
281
|
+
mode?: EditorMode;
|
|
282
|
+
/** Callback when the editing mode changes */
|
|
283
|
+
onModeChange?: (mode: EditorMode) => void;
|
|
284
|
+
/** Callback when a comment is added via the UI */
|
|
285
|
+
onCommentAdd?: (comment: Comment) => void;
|
|
286
|
+
/** Callback when a comment is resolved via the UI */
|
|
287
|
+
onCommentResolve?: (comment: Comment) => void;
|
|
288
|
+
/** Callback when a comment is deleted via the UI */
|
|
289
|
+
onCommentDelete?: (comment: Comment) => void;
|
|
290
|
+
/** Callback when a reply is added to a comment via the UI */
|
|
291
|
+
onCommentReply?: (reply: Comment, parent: Comment) => void;
|
|
292
|
+
/**
|
|
293
|
+
* Controlled comments array. When provided, the editor reads comment thread
|
|
294
|
+
* metadata (text, author, replies, resolved status) from this prop instead
|
|
295
|
+
* of internal state, and emits every change through `onCommentsChange`.
|
|
296
|
+
*
|
|
297
|
+
* Use this with collaboration backends (Yjs, Liveblocks, Automerge, …) so
|
|
298
|
+
* comment threads sync across peers — the PM document only carries the
|
|
299
|
+
* range markers; thread metadata lives outside the doc and needs its own
|
|
300
|
+
* sync channel.
|
|
301
|
+
*
|
|
302
|
+
* If omitted, the editor falls back to internal state (current behavior).
|
|
303
|
+
* The granular `onCommentAdd`/`onCommentResolve`/`onCommentDelete`/
|
|
304
|
+
* `onCommentReply` callbacks fire in both modes.
|
|
305
|
+
*/
|
|
306
|
+
comments?: Comment[];
|
|
307
|
+
/** Fires whenever the comments array changes (controlled mode). */
|
|
308
|
+
onCommentsChange?: (comments: Comment[]) => void;
|
|
309
|
+
/**
|
|
310
|
+
* Callback when rendered DOM context is ready (for plugin overlays).
|
|
311
|
+
* Used by PluginHost to get access to the rendered page DOM for positioning.
|
|
312
|
+
*/
|
|
313
|
+
onRenderedDomContextReady?: (context: RenderedDomContext) => void;
|
|
314
|
+
/**
|
|
315
|
+
* Plugin overlays to render inside the editor viewport.
|
|
316
|
+
* Passed from PluginHost to render plugin-specific overlays.
|
|
317
|
+
*/
|
|
318
|
+
pluginOverlays?: ReactNode;
|
|
319
|
+
/** Sidebar items from plugins (passed from PluginHost). */
|
|
320
|
+
pluginSidebarItems?: ReactSidebarItem[];
|
|
321
|
+
/** Rendered DOM context from PluginHost (for sidebar position resolution). */
|
|
322
|
+
pluginRenderedDomContext?: RenderedDomContext | null;
|
|
323
|
+
/** Custom logo/icon for the title bar */
|
|
324
|
+
renderLogo?: () => ReactNode;
|
|
325
|
+
/** Document name shown in the title bar */
|
|
326
|
+
documentName?: string;
|
|
327
|
+
/** Callback when document name changes */
|
|
328
|
+
onDocumentNameChange?: (name: string) => void;
|
|
329
|
+
/** Whether the document name is editable (default: true) */
|
|
330
|
+
documentNameEditable?: boolean;
|
|
331
|
+
/** Custom right-side actions for the title bar */
|
|
332
|
+
renderTitleBarRight?: () => ReactNode;
|
|
333
|
+
/** Translation overrides. Import a locale JSON file and pass it directly. */
|
|
334
|
+
i18n?: Translations;
|
|
335
|
+
/**
|
|
336
|
+
* Mount a controllable agent panel on the right side of the editor. The
|
|
337
|
+
* panel is the chrome (header, close button, drag-resize); the consumer
|
|
338
|
+
* supplies whatever content goes inside via `render` — typically a chat
|
|
339
|
+
* UI from `@ai-sdk/react`'s `useChat`, `assistant-ui`, or any other
|
|
340
|
+
* framework. We do not ship message bubbles, a composer, or a chat engine.
|
|
341
|
+
*
|
|
342
|
+
* Three control patterns:
|
|
343
|
+
* - **Uncontrolled**: `agentPanel={{ render }}` — toolbar button + panel
|
|
344
|
+
* close button toggle the panel. Width persists to localStorage.
|
|
345
|
+
* - **Controlled**: `agentPanel={{ render, open, onOpenChange }}` — the
|
|
346
|
+
* consumer owns open state (e.g. tied to a global menu).
|
|
347
|
+
* - **Headless**: omit `agentPanel`, use the toolkit directly via
|
|
348
|
+
* `useDocxAgentTools` — render the panel anywhere you want.
|
|
349
|
+
*/
|
|
350
|
+
agentPanel?: AgentPanelOptions;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* DocxEditor ref interface
|
|
354
|
+
*/
|
|
355
|
+
interface DocxEditorRef {
|
|
356
|
+
/** Get the DocumentAgent for programmatic access */
|
|
357
|
+
getAgent: () => DocumentAgent | null;
|
|
358
|
+
/** Get the current document */
|
|
359
|
+
getDocument: () => Document | null;
|
|
360
|
+
/** Get the editor ref */
|
|
361
|
+
getEditorRef: () => PagedEditorRef | null;
|
|
362
|
+
/** Save the document to buffer. Pass { selective: false } to force full repack. */
|
|
363
|
+
save: (options?: {
|
|
364
|
+
selective?: boolean;
|
|
365
|
+
}) => Promise<ArrayBuffer | null>;
|
|
366
|
+
/** Set zoom level */
|
|
367
|
+
setZoom: (zoom: number) => void;
|
|
368
|
+
/** Get current zoom level */
|
|
369
|
+
getZoom: () => number;
|
|
370
|
+
/** Focus the editor */
|
|
371
|
+
focus: () => void;
|
|
372
|
+
/** Get current page number */
|
|
373
|
+
getCurrentPage: () => number;
|
|
374
|
+
/** Get total page count */
|
|
375
|
+
getTotalPages: () => number;
|
|
376
|
+
/**
|
|
377
|
+
* Scroll the paginated view so the given page is in view.
|
|
378
|
+
* Page numbers are 1-indexed (matches `getCurrentPage` / `getTotalPages`).
|
|
379
|
+
* No-op for out-of-range or non-integer values.
|
|
380
|
+
* @example ref.current?.scrollToPage(2)
|
|
381
|
+
*/
|
|
382
|
+
scrollToPage: (pageNumber: number) => void;
|
|
383
|
+
/**
|
|
384
|
+
* Scroll the paginated view to the paragraph with the given Word `w14:paraId`.
|
|
385
|
+
* @returns whether a matching paragraph exists in the ProseMirror document
|
|
386
|
+
* @example ref.current?.scrollToParaId('1A2B3C4D')
|
|
387
|
+
*/
|
|
388
|
+
scrollToParaId: (paraId: string) => boolean;
|
|
389
|
+
/**
|
|
390
|
+
* Scroll the paginated view to a specific ProseMirror document position.
|
|
391
|
+
* Use this when you have a raw PM offset; for Word `w14:paraId` use
|
|
392
|
+
* `scrollToParaId` instead.
|
|
393
|
+
* @example ref.current?.scrollToPosition(42)
|
|
394
|
+
*/
|
|
395
|
+
scrollToPosition: (pmPos: number) => void;
|
|
396
|
+
/**
|
|
397
|
+
* Scroll the paginated view to the comment with the given id and select its
|
|
398
|
+
* anchored range so the selection overlay highlights it. Resolves the id
|
|
399
|
+
* against the live comment marks at call time.
|
|
400
|
+
* @returns `false` when the id no longer resolves (the comment was deleted
|
|
401
|
+
* or its anchored text removed between render and click), so the caller
|
|
402
|
+
* can surface a "location no longer exists" affordance rather than
|
|
403
|
+
* silently no-op'ing.
|
|
404
|
+
* @example ref.current?.scrollToCommentId(3)
|
|
405
|
+
*/
|
|
406
|
+
scrollToCommentId: (commentId: number) => boolean;
|
|
407
|
+
/**
|
|
408
|
+
* Scroll the paginated view to the tracked change with the given Word
|
|
409
|
+
* revision `w:id` and select its range so the selection overlay highlights
|
|
410
|
+
* it. Resolves the id against the live tracked-change marks at call time
|
|
411
|
+
* (matching coalesced revisions the way the changes sidebar does).
|
|
412
|
+
* @returns `false` when the id no longer resolves (the change was
|
|
413
|
+
* accepted, rejected, or deleted between render and click).
|
|
414
|
+
* @example ref.current?.scrollToChangeId(42)
|
|
415
|
+
*/
|
|
416
|
+
scrollToChangeId: (revisionId: number) => boolean;
|
|
417
|
+
/**
|
|
418
|
+
* Select the ProseMirror position range `[from, to]` so the selection
|
|
419
|
+
* overlay highlights it, and scroll its start into view. The selection
|
|
420
|
+
* persists until it next changes (there is no auto-clearing flash). No-op
|
|
421
|
+
* for a malformed range or a `from` past the document end; `to` is clamped
|
|
422
|
+
* to the document size.
|
|
423
|
+
* @example ref.current?.highlightRange(10, 24)
|
|
424
|
+
*/
|
|
425
|
+
highlightRange: (from: number, to: number) => void;
|
|
426
|
+
/** Open print preview */
|
|
427
|
+
openPrintPreview: () => void;
|
|
428
|
+
/** Print the document directly */
|
|
429
|
+
print: () => void;
|
|
430
|
+
/** Load a pre-parsed document programmatically */
|
|
431
|
+
loadDocument: (doc: Document) => void;
|
|
432
|
+
/** Load a DOCX buffer programmatically (ArrayBuffer, Uint8Array, Blob, or File) */
|
|
433
|
+
loadDocumentBuffer: (buffer: DocxInput) => Promise<void>;
|
|
434
|
+
/** Add a comment programmatically. Anchored by Word `w14:paraId` so
|
|
435
|
+
* it survives unrelated edits. Returns the comment ID, or null if
|
|
436
|
+
* the paraId is unknown or the search text isn't found / is ambiguous. */
|
|
437
|
+
addComment: (options: {
|
|
438
|
+
paraId: string;
|
|
439
|
+
text: string;
|
|
440
|
+
author: string;
|
|
441
|
+
/** Optional: anchor to a specific phrase within the paragraph (must be unique). */
|
|
442
|
+
search?: string;
|
|
443
|
+
}) => number | null;
|
|
444
|
+
/** Reply to an existing comment. Returns the reply comment ID. */
|
|
445
|
+
replyToComment: (commentId: number, text: string, author: string) => number | null;
|
|
446
|
+
/** Resolve (mark as done) a comment. */
|
|
447
|
+
resolveComment: (commentId: number) => void;
|
|
448
|
+
/** Suggest a tracked change. Pass `replaceWith: ''` to delete the matched text;
|
|
449
|
+
* pass `search: ''` to insert at paragraph end. Returns false on missing paraId,
|
|
450
|
+
* missing/ambiguous search, or attempt to layer on an existing tracked change. */
|
|
451
|
+
proposeChange: (options: {
|
|
452
|
+
paraId: string;
|
|
453
|
+
search: string;
|
|
454
|
+
replaceWith: string;
|
|
455
|
+
author: string;
|
|
456
|
+
}) => boolean;
|
|
457
|
+
/** Locate every paragraph containing `query` (case-insensitive substring).
|
|
458
|
+
* Returns a stable handle (paraId + the matched phrase) the agent can pass
|
|
459
|
+
* back to `addComment` / `proposeChange`. */
|
|
460
|
+
findInDocument: (query: string, options?: {
|
|
461
|
+
caseSensitive?: boolean;
|
|
462
|
+
limit?: number;
|
|
463
|
+
}) => Array<{
|
|
464
|
+
paraId: string;
|
|
465
|
+
match: string;
|
|
466
|
+
before: string;
|
|
467
|
+
after: string;
|
|
468
|
+
}>;
|
|
469
|
+
/**
|
|
470
|
+
* Apply character formatting (bold / italic / color / size / font / etc.)
|
|
471
|
+
* to a paragraph or to a unique phrase within it. This is a direct edit,
|
|
472
|
+
* not a tracked change. Returns false on missing paraId or ambiguous search.
|
|
473
|
+
*/
|
|
474
|
+
applyFormatting: (options: {
|
|
475
|
+
paraId: string;
|
|
476
|
+
search?: string;
|
|
477
|
+
marks: {
|
|
478
|
+
bold?: boolean;
|
|
479
|
+
italic?: boolean;
|
|
480
|
+
underline?: boolean | {
|
|
481
|
+
style?: string;
|
|
482
|
+
};
|
|
483
|
+
strike?: boolean;
|
|
484
|
+
color?: {
|
|
485
|
+
rgb?: string;
|
|
486
|
+
themeColor?: string;
|
|
487
|
+
};
|
|
488
|
+
highlight?: string;
|
|
489
|
+
fontSize?: number;
|
|
490
|
+
fontFamily?: {
|
|
491
|
+
ascii?: string;
|
|
492
|
+
hAnsi?: string;
|
|
493
|
+
};
|
|
494
|
+
};
|
|
495
|
+
}) => boolean;
|
|
496
|
+
/**
|
|
497
|
+
* Apply a paragraph style by styleId (e.g. `'Heading1'`, `'Quote'`).
|
|
498
|
+
* Direct edit, not a tracked change. Returns false if paraId is unknown.
|
|
499
|
+
*/
|
|
500
|
+
setParagraphStyle: (options: {
|
|
501
|
+
paraId: string;
|
|
502
|
+
styleId: string;
|
|
503
|
+
}) => boolean;
|
|
504
|
+
/**
|
|
505
|
+
* Insert a page or section break after the paragraph identified by `paraId`.
|
|
506
|
+
* `'page'` adds a page break; `'sectionNextPage'` / `'sectionContinuous'`
|
|
507
|
+
* start a new section on a new page / the same page. Direct edit, not a
|
|
508
|
+
* tracked change. Returns false if paraId is unknown.
|
|
509
|
+
*/
|
|
510
|
+
insertBreak: (options: {
|
|
511
|
+
paraId: string;
|
|
512
|
+
type: 'page' | 'sectionNextPage' | 'sectionContinuous';
|
|
513
|
+
}) => boolean;
|
|
514
|
+
/**
|
|
515
|
+
* Read the contents of a single page. 1-indexed; returns null if the page
|
|
516
|
+
* does not exist. Each paragraph is returned with its stable paraId so the
|
|
517
|
+
* agent can comment on or modify it without an extra round-trip.
|
|
518
|
+
*/
|
|
519
|
+
getPageContent: (pageNumber: number) => {
|
|
520
|
+
pageNumber: number;
|
|
521
|
+
text: string;
|
|
522
|
+
paragraphs: Array<{
|
|
523
|
+
paraId: string;
|
|
524
|
+
text: string;
|
|
525
|
+
styleId?: string;
|
|
526
|
+
}>;
|
|
527
|
+
} | null;
|
|
528
|
+
/** Read the user's current cursor / selection — what's highlighted right now. */
|
|
529
|
+
getSelectionInfo: () => {
|
|
530
|
+
paraId: string | null;
|
|
531
|
+
selectedText: string;
|
|
532
|
+
paragraphText: string;
|
|
533
|
+
before: string;
|
|
534
|
+
after: string;
|
|
535
|
+
} | null;
|
|
536
|
+
/** Get all comments. */
|
|
537
|
+
getComments: () => Comment[];
|
|
538
|
+
/**
|
|
539
|
+
* List content controls (SDTs) in the live document, optionally filtered by
|
|
540
|
+
* `tag`/`alias`/`id`/`type`. Reaches block AND inline controls wherever they
|
|
541
|
+
* live (body, table cells, mid-paragraph). Each result includes the control's
|
|
542
|
+
* text and PM position. Anchors for templates and document automation.
|
|
543
|
+
*/
|
|
544
|
+
getContentControls: (filter?: ContentControlFilter) => PMContentControl[];
|
|
545
|
+
/** Scroll the first content control matching `filter` into view. Returns false if none. */
|
|
546
|
+
scrollToContentControl: (filter: ContentControlFilter) => boolean;
|
|
547
|
+
/**
|
|
548
|
+
* Replace the content of the first control matching `filter` with `text`
|
|
549
|
+
* (newlines become paragraphs). Returns false if no match. Throws if the
|
|
550
|
+
* control is content-locked unless `{ force: true }`.
|
|
551
|
+
*/
|
|
552
|
+
setContentControlContent: (filter: ContentControlFilter, text: string, options?: {
|
|
553
|
+
force?: boolean;
|
|
554
|
+
}) => boolean;
|
|
555
|
+
/**
|
|
556
|
+
* Remove the first control matching `filter`. With `{ keepContent: true }`
|
|
557
|
+
* the inner blocks are unwrapped in place. Returns false if no match. Throws
|
|
558
|
+
* if the control is deletion-locked unless `{ force: true }`.
|
|
559
|
+
*/
|
|
560
|
+
removeContentControl: (filter: ContentControlFilter, options?: {
|
|
561
|
+
force?: boolean;
|
|
562
|
+
keepContent?: boolean;
|
|
563
|
+
}) => boolean;
|
|
564
|
+
/**
|
|
565
|
+
* Set a typed value on the first control matching `filter`: a dropdown
|
|
566
|
+
* selection (`{ kind: 'dropdown', value }`), checkbox (`{ kind: 'checkbox',
|
|
567
|
+
* checked }`), or date (`{ kind: 'date', date }`). Updates the visible
|
|
568
|
+
* content and structured state. Returns false if no match; throws if
|
|
569
|
+
* content-locked (unless `force`) or the value doesn't fit the control type.
|
|
570
|
+
*/
|
|
571
|
+
setContentControlValue: (filter: ContentControlFilter, value: ContentControlValue, options?: {
|
|
572
|
+
force?: boolean;
|
|
573
|
+
}) => boolean;
|
|
574
|
+
/**
|
|
575
|
+
* Plant a NEW inline content control around an occurrence-precise placeholder
|
|
576
|
+
* span — the create side of the template-fill pipeline. `locator` selects the
|
|
577
|
+
* span by `text` + 0-based `occurrence` (within the `paraId` paragraph if
|
|
578
|
+
* given, else the whole document in reading order); `props.tag` is the stable
|
|
579
|
+
* id that later resolves the control for filling. Returns `wrapped` with the
|
|
580
|
+
* tag, or `not-found` / `crosses-inline-boundary` (the span spans a paragraph
|
|
581
|
+
* or un-splittable inline content). One undoable edit.
|
|
582
|
+
*/
|
|
583
|
+
wrapContentControl: (locator: {
|
|
584
|
+
text: string;
|
|
585
|
+
occurrence?: number;
|
|
586
|
+
paraId?: string;
|
|
587
|
+
}, props: {
|
|
588
|
+
tag: string;
|
|
589
|
+
alias?: string;
|
|
590
|
+
sdtType?: 'richText' | 'plainText';
|
|
591
|
+
}) => {
|
|
592
|
+
status: 'wrapped' | 'not-found' | 'crosses-inline-boundary';
|
|
593
|
+
tag?: string;
|
|
594
|
+
};
|
|
595
|
+
/** Subscribe to document changes. Fires after every committed edit. Returns unsubscribe. */
|
|
596
|
+
onContentChange: (listener: (document: Document) => void) => () => void;
|
|
597
|
+
/** Subscribe to selection changes (cursor moves / selection changes). Returns unsubscribe. */
|
|
598
|
+
onSelectionChange: (listener: (selection: SelectionState | null) => void) => () => void;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* DocxEditor - Complete DOCX editor component
|
|
603
|
+
*/
|
|
604
|
+
declare const DocxEditor: React.ForwardRefExoticComponent<DocxEditorProps & React.RefAttributes<DocxEditorRef>>;
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Simple imperative API for rendering a DOCX editor into a DOM element.
|
|
608
|
+
*
|
|
609
|
+
* Returns an `EditorHandle` (from @eigenpal/docx-editor-core) that works with
|
|
610
|
+
* any framework implementation.
|
|
611
|
+
*
|
|
612
|
+
* Usage:
|
|
613
|
+
* ```ts
|
|
614
|
+
* import { renderAsync } from '@eigenpal/docx-editor-react';
|
|
615
|
+
*
|
|
616
|
+
* const editor = await renderAsync(docxBlob, document.getElementById('container'), {
|
|
617
|
+
* readOnly: false,
|
|
618
|
+
* showToolbar: true,
|
|
619
|
+
* });
|
|
620
|
+
*
|
|
621
|
+
* // Save the edited document
|
|
622
|
+
* const blob = await editor.save();
|
|
623
|
+
*
|
|
624
|
+
* // Clean up
|
|
625
|
+
* editor.destroy();
|
|
626
|
+
* ```
|
|
627
|
+
*/
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Options for {@link renderAsync}. A subset of DocxEditorProps minus
|
|
631
|
+
* `documentBuffer` / `document` (passed as the first argument instead).
|
|
632
|
+
*/
|
|
633
|
+
type RenderAsyncOptions = Omit<DocxEditorProps, 'documentBuffer' | 'document'>;
|
|
634
|
+
/**
|
|
635
|
+
* React-specific handle that extends the framework-agnostic EditorHandle
|
|
636
|
+
* with zoom control.
|
|
637
|
+
*/
|
|
638
|
+
interface DocxEditorHandle extends EditorHandle {
|
|
639
|
+
/** Set zoom level (1.0 = 100%). */
|
|
640
|
+
setZoom: (zoom: number) => void;
|
|
641
|
+
/** Scroll to a body paragraph by Word `w14:paraId`. */
|
|
642
|
+
scrollToParaId: (paraId: string) => boolean;
|
|
643
|
+
/** Scroll to a raw ProseMirror document position. */
|
|
644
|
+
scrollToPosition: (pmPos: number) => void;
|
|
645
|
+
}
|
|
646
|
+
/**
|
|
647
|
+
* Render a DOCX editor into a container element.
|
|
648
|
+
*
|
|
649
|
+
* @param input - DOCX data as ArrayBuffer, Uint8Array, Blob, or File
|
|
650
|
+
* @param container - DOM element to render into
|
|
651
|
+
* @param options - Editor configuration (toolbar, readOnly, callbacks, etc.)
|
|
652
|
+
* @returns A handle with save / destroy / getDocument methods
|
|
653
|
+
*/
|
|
654
|
+
declare function renderAsync(input: DocxInput, container: HTMLElement, options?: RenderAsyncOptions): Promise<DocxEditorHandle>;
|
|
655
|
+
|
|
656
|
+
interface LocaleProviderProps {
|
|
657
|
+
i18n?: Translations;
|
|
658
|
+
children: ReactNode;
|
|
659
|
+
}
|
|
660
|
+
declare function LocaleProvider({ i18n, children }: LocaleProviderProps): react_jsx_runtime.JSX.Element;
|
|
661
|
+
declare function useTranslation(): {
|
|
662
|
+
t: TFunction;
|
|
663
|
+
};
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* @eigenpal/docx-editor-react
|
|
667
|
+
*
|
|
668
|
+
* Curated root entry for the documented React editor API. Advanced surfaces
|
|
669
|
+
* stay public through explicit subpaths:
|
|
670
|
+
* - `@eigenpal/docx-editor-react/ui`
|
|
671
|
+
* - `@eigenpal/docx-editor-react/dialogs`
|
|
672
|
+
* - `@eigenpal/docx-editor-react/hooks`
|
|
673
|
+
* - `@eigenpal/docx-editor-react/plugin-api`
|
|
674
|
+
*
|
|
675
|
+
* Framework-agnostic document utilities live in `@eigenpal/docx-editor-core`.
|
|
676
|
+
* Agent/MCP surfaces live in `@eigenpal/docx-editor-agents`.
|
|
677
|
+
*
|
|
678
|
+
* @packageDocumentation
|
|
679
|
+
* @public
|
|
680
|
+
*/
|
|
681
|
+
declare const VERSION = "0.0.2";
|
|
682
|
+
|
|
683
|
+
export { DocxEditor, type DocxEditorHandle, type DocxEditorProps, type DocxEditorRef, type EditorMode, LocaleProvider, type LocaleProviderProps, type RenderAsyncOptions, VERSION, renderAsync, useTranslation };
|