@zeke-02/docx-editor 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/dist/{KeyboardShortcutsDialog-5D_FoAp6.d.ts → KeyboardShortcutsDialog-B0UFuR4w.d.ts} +2 -2
  2. package/dist/{KeyboardShortcutsDialog-D7ihAj18.d.mts → KeyboardShortcutsDialog-t6JKL4Aj.d.mts} +2 -2
  3. package/dist/PageSetupDialog-642IAVG2.js +1 -1
  4. package/dist/PageSetupDialog-ERUQDHAY.mjs +1 -1
  5. package/dist/PluginHost-HS31VIuo.d.mts +16 -0
  6. package/dist/PluginHost-zILZO7zX.d.ts +16 -0
  7. package/dist/{agentApi-D4AZmNfB.d.ts → agentApi-B2Y7kexW.d.ts} +1 -1
  8. package/dist/{agentApi-C41hiW-n.d.mts → agentApi-BzUJ_kao.d.mts} +1 -1
  9. package/dist/{chunk-E6MQXELR.js → chunk-HXDMASAR.js} +1 -1
  10. package/dist/chunk-JFRDFK7V.mjs +260 -0
  11. package/dist/{chunk-LUJ6HCMH.mjs → chunk-LWOHVYKW.mjs} +1 -1
  12. package/dist/chunk-MDTA25AN.mjs +60 -0
  13. package/dist/chunk-NOLMVQNN.mjs +40 -0
  14. package/dist/chunk-SGTUE33R.js +260 -0
  15. package/dist/chunk-WO3FIV4B.js +40 -0
  16. package/dist/{chunk-ONNHQWAX.mjs → chunk-XGJ2EORY.mjs} +1 -1
  17. package/dist/{chunk-AYMGSTNG.js → chunk-Y3SEHWZ2.js} +1 -1
  18. package/dist/chunk-YBEVHQCT.js +60 -0
  19. package/dist/{content-B2MzIMwA.d.mts → content-REFGFfEH.d.mts} +1 -1
  20. package/dist/{content-B2MzIMwA.d.ts → content-REFGFfEH.d.ts} +1 -1
  21. package/dist/dialogs.d.mts +4 -4
  22. package/dist/dialogs.d.ts +4 -4
  23. package/dist/dialogs.js +1 -1
  24. package/dist/dialogs.mjs +1 -1
  25. package/dist/{document-Di1qGqLS.d.mts → document-Cu2vq_wS.d.mts} +1 -1
  26. package/dist/{document-DZ_ZeZEH.d.ts → document-CxOagoLQ.d.ts} +1 -1
  27. package/dist/executor-WBHID2RK.mjs +1 -0
  28. package/dist/{executor-EPEB53SJ.js → executor-Y5VUOAHY.js} +1 -1
  29. package/dist/{findReplace-pkMskVJU.d.ts → findReplace-Bue0JaXh.d.ts} +1 -1
  30. package/dist/{findReplace-CpIoILbP.d.mts → findReplace-shXbOjFQ.d.mts} +1 -1
  31. package/dist/fork.css +1 -0
  32. package/dist/fork.d.mts +535 -0
  33. package/dist/fork.d.ts +535 -0
  34. package/dist/fork.js +1 -0
  35. package/dist/fork.mjs +1 -0
  36. package/dist/hooks.d.mts +6 -6
  37. package/dist/hooks.d.ts +6 -6
  38. package/dist/hooks.js +1 -1
  39. package/dist/hooks.mjs +1 -1
  40. package/dist/index-B5A-J9GC.d.ts +1119 -0
  41. package/dist/index-bw-PaozF.d.mts +1119 -0
  42. package/dist/index.d.mts +11 -1120
  43. package/dist/index.d.ts +11 -1120
  44. package/dist/index.js +1 -40
  45. package/dist/index.mjs +1 -40
  46. package/dist/plugin-api.d.mts +5 -16
  47. package/dist/plugin-api.d.ts +5 -16
  48. package/dist/plugin-api.js +1 -260
  49. package/dist/plugin-api.mjs +1 -260
  50. package/dist/{types-DZUhB7Ao.d.mts → types-BF48VxkC.d.mts} +1 -1
  51. package/dist/{types-DZUhB7Ao.d.ts → types-BF48VxkC.d.ts} +1 -1
  52. package/dist/{types-Bd_YzkhG.d.mts → types-BnIs4sE7.d.mts} +1 -1
  53. package/dist/{types-Bd_YzkhG.d.ts → types-BnIs4sE7.d.ts} +1 -1
  54. package/dist/{types-DcxHFUSc.d.ts → types-CW6HFAX6.d.ts} +1 -1
  55. package/dist/{types-CkfDgB0O.d.mts → types-DIsDCwTG.d.mts} +1 -1
  56. package/dist/ui.d.mts +9 -9
  57. package/dist/ui.d.ts +9 -9
  58. package/dist/ui.js +1 -1
  59. package/dist/ui.mjs +1 -1
  60. package/dist/{useFindReplace-eyhMSZZf.d.ts → useFindReplace-DKy-s3gS.d.ts} +2 -2
  61. package/dist/{useFindReplace-DDs533b-.d.mts → useFindReplace-vuoKpDKE.d.mts} +2 -2
  62. package/package.json +7 -7
  63. package/dist/chunk-47VJOBJD.mjs +0 -60
  64. package/dist/chunk-IP5NAYHL.js +0 -60
  65. package/dist/executor-TVJ6K6MW.mjs +0 -1
package/dist/index.d.mts CHANGED
@@ -1,1122 +1,13 @@
1
- import * as React from 'react';
2
- import { ReactNode, CSSProperties } from 'react';
3
- import * as prosemirror_view from 'prosemirror-view';
4
- import { EditorView } from 'prosemirror-view';
5
- import * as prosemirror_state from 'prosemirror-state';
6
- import { EditorState, Transaction } from 'prosemirror-state';
7
- import { D as Document, T as Theme } from './document-Di1qGqLS.mjs';
8
- import { S as StyleInfo, A as AgentContext, P as Position, R as Range, a as AgentCommand, F as FontOption, b as PrintOptions } from './agentApi-C41hiW-n.mjs';
9
- import { R as RenderedDomContext, a as ReactSidebarItem } from './types-Bd_YzkhG.mjs';
10
- import { T as TextFormatting, P as ParagraphFormatting, C as Comment } from './content-B2MzIMwA.mjs';
11
- import { T as Translations, a as TranslationKey } from './types-DZUhB7Ao.mjs';
12
- export { L as LocaleStrings, P as PartialLocaleStrings } from './types-DZUhB7Ao.mjs';
13
- import { E as EditorHandle } from './types-CkfDgB0O.mjs';
14
- import * as react_jsx_runtime from 'react/jsx-runtime';
1
+ export { b as DocxEditor, c as DocxEditorHandle, d as DocxEditorProps, e as DocxEditorRef, E as EditorMode, L as LocaleProvider, f as LocaleProviderProps, R as RenderAsyncOptions, V as VERSION, r as renderAsync, u as useTranslation } from './index-bw-PaozF.mjs';
2
+ export { L as LocaleStrings, P as PartialLocaleStrings, T as TranslationKey, a as Translations } from './types-BF48VxkC.mjs';
3
+ import 'react';
4
+ import 'prosemirror-view';
5
+ import 'prosemirror-state';
6
+ import './document-Cu2vq_wS.mjs';
7
+ import './content-REFGFfEH.mjs';
8
+ import './agentApi-BzUJ_kao.mjs';
9
+ import './types-BnIs4sE7.mjs';
15
10
  import 'prosemirror-model';
11
+ import './types-DIsDCwTG.mjs';
12
+ import 'react/jsx-runtime';
16
13
  import '@eigenpal/docx-editor-i18n/en.json';
17
-
18
- interface LocaleProviderProps {
19
- i18n?: Translations;
20
- children: ReactNode;
21
- }
22
- declare function LocaleProvider({ i18n, children }: LocaleProviderProps): react_jsx_runtime.JSX.Element;
23
- declare function useTranslation(): {
24
- t: (key: TranslationKey, vars?: Record<string, string | number>) => string;
25
- };
26
-
27
- /**
28
- * Selective Save Module
29
- *
30
- * Orchestrates selective XML patching for the save flow.
31
- * Serializes full document.xml, validates patch safety, builds patched XML,
32
- * and calls applyUpdatesToZip() to produce the final DOCX.
33
- *
34
- * Returns null on any failure, signaling the caller to fall back to full repack.
35
- */
36
-
37
- interface SelectiveSaveOptions {
38
- /** Changed paragraph IDs to selectively patch */
39
- changedParaIds: Set<string>;
40
- /** Whether structural changes occurred (paragraph add/delete) */
41
- structuralChange: boolean;
42
- /** Whether any changes affected paragraphs without paraId */
43
- hasUntrackedChanges: boolean;
44
- }
45
-
46
- /**
47
- * Flexible input types for DOCX documents.
48
- *
49
- * Accepts any common binary format so consumers don't need to manually
50
- * convert before passing data to the editor or parser.
51
- */
52
- /**
53
- * Any binary representation of a DOCX file that the editor can consume.
54
- *
55
- * - `ArrayBuffer` — from `FileReader.readAsArrayBuffer()` or `fetch().arrayBuffer()`
56
- * - `Uint8Array` — from Node.js `fs.readFile()` or streaming APIs
57
- * - `Blob` — from drag-and-drop or `<input type="file">`
58
- * - `File` — subclass of Blob, from `<input type="file">`
59
- */
60
- type DocxInput = ArrayBuffer | Uint8Array | Blob | File;
61
-
62
- /**
63
- * DocumentAgent - High-level fluent API for programmatic document manipulation
64
- *
65
- * Provides a convenient interface for:
66
- * - Reading document content and metadata
67
- * - Editing text with formatting
68
- * - Inserting tables, images, and hyperlinks
69
- * - Managing template variables
70
- * - Exporting to DOCX buffer
71
- *
72
- * All operations are immutable - they return a new DocumentAgent instance
73
- * or don't modify the underlying document.
74
- */
75
-
76
- /**
77
- * Options for inserting text
78
- */
79
- interface InsertTextOptions {
80
- /** Text formatting */
81
- formatting?: TextFormatting;
82
- }
83
- /**
84
- * Options for inserting table
85
- */
86
- interface InsertTableOptions {
87
- /** Table data (2D array of strings) */
88
- data?: string[][];
89
- /** Whether first row is a header */
90
- hasHeader?: boolean;
91
- }
92
- /**
93
- * Options for inserting image
94
- */
95
- interface InsertImageOptions {
96
- /** Image width in pixels */
97
- width?: number;
98
- /** Image height in pixels */
99
- height?: number;
100
- /** Alt text for accessibility */
101
- alt?: string;
102
- }
103
- /**
104
- * Options for inserting hyperlink
105
- */
106
- interface InsertHyperlinkOptions {
107
- /** Display text (overrides selected text) */
108
- displayText?: string;
109
- /** Tooltip on hover */
110
- tooltip?: string;
111
- }
112
- /**
113
- * Formatted text segment
114
- */
115
- interface FormattedTextSegment {
116
- /** Text content */
117
- text: string;
118
- /** Applied formatting */
119
- formatting?: TextFormatting;
120
- /** Is part of a hyperlink */
121
- isHyperlink?: boolean;
122
- /** Hyperlink URL if applicable */
123
- hyperlinkUrl?: string;
124
- }
125
- /**
126
- * DocumentAgent provides a fluent API for document manipulation
127
- *
128
- * @example
129
- * ```ts
130
- * const agent = new DocumentAgent(buffer);
131
- *
132
- * // Read operations
133
- * const text = agent.getText();
134
- * const wordCount = agent.getWordCount();
135
- * const variables = agent.getVariables();
136
- *
137
- * // Write operations (returns new agent)
138
- * const newAgent = agent
139
- * .insertText({ paragraphIndex: 0, offset: 0 }, 'Hello ', { formatting: { bold: true } })
140
- * .applyStyle({ paragraphIndex: 0, offset: 0 }, { paragraphIndex: 0, offset: 5 }, 'Heading1');
141
- *
142
- * // Export
143
- * const newBuffer = await newAgent.toBuffer();
144
- * ```
145
- */
146
- declare class DocumentAgent {
147
- private _document;
148
- private _pendingVariables;
149
- /**
150
- * Create a new DocumentAgent
151
- *
152
- * @param source - Document object or ArrayBuffer to parse
153
- */
154
- constructor(source: Document | ArrayBuffer);
155
- /**
156
- * Create a DocumentAgent from a DOCX buffer (async)
157
- *
158
- * @param buffer - DOCX file as ArrayBuffer, Uint8Array, Blob, or File
159
- * @returns Promise resolving to DocumentAgent
160
- */
161
- static fromBuffer(buffer: DocxInput): Promise<DocumentAgent>;
162
- /**
163
- * Create a DocumentAgent from a Document object
164
- *
165
- * @param document - Parsed Document
166
- * @returns DocumentAgent
167
- */
168
- static fromDocument(document: Document): DocumentAgent;
169
- /**
170
- * Get the underlying document
171
- */
172
- getDocument(): Document;
173
- /**
174
- * Get plain text content of the document
175
- *
176
- * @returns All document text concatenated
177
- */
178
- getText(): string;
179
- /**
180
- * Get formatted text segments
181
- *
182
- * @returns Array of text segments with formatting info
183
- */
184
- getFormattedText(): FormattedTextSegment[];
185
- /**
186
- * Get detected template variables
187
- *
188
- * @returns Array of variable names (without braces)
189
- */
190
- getVariables(): string[];
191
- /**
192
- * Get available styles from the document
193
- *
194
- * @returns Array of style info
195
- */
196
- getStyles(): StyleInfo[];
197
- /**
198
- * Get approximate page count
199
- *
200
- * Note: This is an estimate based on content length.
201
- * Actual page count requires full layout computation.
202
- *
203
- * @returns Estimated page count
204
- */
205
- getPageCount(): number;
206
- /**
207
- * Get word count
208
- *
209
- * @returns Number of words in the document
210
- */
211
- getWordCount(): number;
212
- /**
213
- * Get character count
214
- *
215
- * @param includeSpaces - Whether to include whitespace
216
- * @returns Number of characters
217
- */
218
- getCharacterCount(includeSpaces?: boolean): number;
219
- /**
220
- * Get paragraph count
221
- *
222
- * @returns Number of paragraphs
223
- */
224
- getParagraphCount(): number;
225
- /**
226
- * Get table count
227
- *
228
- * @returns Number of tables
229
- */
230
- getTableCount(): number;
231
- /**
232
- * Get document context for AI agents
233
- *
234
- * @param outlineMaxChars - Max characters per paragraph in outline
235
- * @returns Agent context
236
- */
237
- getAgentContext(outlineMaxChars?: number): AgentContext;
238
- /**
239
- * Insert text at a position
240
- *
241
- * @param position - Where to insert
242
- * @param text - Text to insert
243
- * @param options - Insert options
244
- * @returns New DocumentAgent with text inserted
245
- */
246
- insertText(position: Position, text: string, options?: InsertTextOptions): DocumentAgent;
247
- /**
248
- * Replace text in a range
249
- *
250
- * @param range - Range to replace
251
- * @param text - Replacement text
252
- * @param options - Replace options
253
- * @returns New DocumentAgent with text replaced
254
- */
255
- replaceRange(range: Range, text: string, options?: InsertTextOptions): DocumentAgent;
256
- /**
257
- * Delete text in a range
258
- *
259
- * @param range - Range to delete
260
- * @returns New DocumentAgent with text deleted
261
- */
262
- deleteRange(range: Range): DocumentAgent;
263
- /**
264
- * Apply text formatting to a range
265
- *
266
- * @param range - Range to format
267
- * @param formatting - Formatting to apply
268
- * @returns New DocumentAgent with formatting applied
269
- */
270
- applyFormatting(range: Range, formatting: Partial<TextFormatting>): DocumentAgent;
271
- /**
272
- * Apply a named style to a paragraph
273
- *
274
- * @param paragraphIndex - Index of the paragraph
275
- * @param styleId - Style ID to apply
276
- * @returns New DocumentAgent with style applied
277
- */
278
- applyStyle(paragraphIndex: number, styleId: string): DocumentAgent;
279
- /**
280
- * Apply paragraph formatting
281
- *
282
- * @param paragraphIndex - Index of the paragraph
283
- * @param formatting - Formatting to apply
284
- * @returns New DocumentAgent with formatting applied
285
- */
286
- applyParagraphFormatting(paragraphIndex: number, formatting: Partial<ParagraphFormatting>): DocumentAgent;
287
- /**
288
- * Insert a table at a position
289
- *
290
- * @param position - Where to insert the table
291
- * @param rows - Number of rows
292
- * @param cols - Number of columns
293
- * @param options - Table options
294
- * @returns New DocumentAgent with table inserted
295
- */
296
- insertTable(position: Position, rows: number, cols: number, options?: InsertTableOptions): DocumentAgent;
297
- /**
298
- * Insert an image at a position
299
- *
300
- * @param position - Where to insert the image
301
- * @param src - Image source (base64 data URL or URL)
302
- * @param options - Image options
303
- * @returns New DocumentAgent with image inserted
304
- */
305
- insertImage(position: Position, src: string, options?: InsertImageOptions): DocumentAgent;
306
- /**
307
- * Insert a hyperlink
308
- *
309
- * @param range - Range to make into a hyperlink
310
- * @param url - URL of the hyperlink
311
- * @param options - Hyperlink options
312
- * @returns New DocumentAgent with hyperlink inserted
313
- */
314
- insertHyperlink(range: Range, url: string, options?: InsertHyperlinkOptions): DocumentAgent;
315
- /**
316
- * Remove a hyperlink but keep the text
317
- *
318
- * @param range - Range containing the hyperlink
319
- * @returns New DocumentAgent with hyperlink removed
320
- */
321
- removeHyperlink(range: Range): DocumentAgent;
322
- /**
323
- * Insert a paragraph break
324
- *
325
- * @param position - Where to break the paragraph
326
- * @returns New DocumentAgent with paragraph broken
327
- */
328
- insertParagraphBreak(position: Position): DocumentAgent;
329
- /**
330
- * Merge consecutive paragraphs
331
- *
332
- * @param startParagraphIndex - First paragraph index
333
- * @param count - Number of paragraphs to merge with the first
334
- * @returns New DocumentAgent with paragraphs merged
335
- */
336
- mergeParagraphs(startParagraphIndex: number, count: number): DocumentAgent;
337
- /**
338
- * Set a template variable value
339
- *
340
- * Note: Variables are not applied until `applyVariables()` is called
341
- *
342
- * @param name - Variable name (without braces)
343
- * @param value - Variable value
344
- * @returns This DocumentAgent (for chaining)
345
- */
346
- setVariable(name: string, value: string): DocumentAgent;
347
- /**
348
- * Set multiple template variables
349
- *
350
- * @param variables - Map of variable names to values
351
- * @returns This DocumentAgent (for chaining)
352
- */
353
- setVariables(variables: Record<string, string>): DocumentAgent;
354
- /**
355
- * Get pending variable values
356
- *
357
- * @returns Map of pending variable values
358
- */
359
- getPendingVariables(): Record<string, string>;
360
- /**
361
- * Clear pending variables
362
- *
363
- * @returns This DocumentAgent (for chaining)
364
- */
365
- clearPendingVariables(): DocumentAgent;
366
- /**
367
- * Apply all pending template variables
368
- *
369
- * Uses docxtemplater to substitute variables while preserving formatting.
370
- *
371
- * @param variables - Optional additional variables (merged with pending)
372
- * @returns New DocumentAgent with variables applied
373
- */
374
- applyVariables(variables?: Record<string, string>): Promise<DocumentAgent>;
375
- /**
376
- * Export document to DOCX ArrayBuffer
377
- *
378
- * @returns Promise resolving to DOCX file as ArrayBuffer
379
- */
380
- toBuffer(options?: {
381
- selective?: SelectiveSaveOptions;
382
- }): Promise<ArrayBuffer>;
383
- /**
384
- * Export document to Blob
385
- *
386
- * @param mimeType - MIME type for the blob
387
- * @returns Promise resolving to DOCX file as Blob
388
- */
389
- toBlob(mimeType?: string): Promise<Blob>;
390
- /**
391
- * Execute multiple commands in sequence
392
- *
393
- * @param commands - Commands to execute
394
- * @returns New DocumentAgent with all commands applied
395
- */
396
- executeCommands(commands: AgentCommand[]): DocumentAgent;
397
- /**
398
- * Execute a single command and return new agent
399
- */
400
- private _executeCommand;
401
- /**
402
- * Get plain text from document body
403
- */
404
- private _getBodyText;
405
- /**
406
- * Get plain text from a paragraph
407
- */
408
- private _getParagraphText;
409
- /**
410
- * Get plain text from a run
411
- */
412
- private _getRunText;
413
- /**
414
- * Get plain text from a hyperlink
415
- */
416
- private _getHyperlinkText;
417
- /**
418
- * Get plain text from a table
419
- */
420
- private _getTableText;
421
- /**
422
- * Extract formatted text segments from a paragraph
423
- */
424
- private _extractParagraphSegments;
425
- /**
426
- * Parse heading level from style ID
427
- */
428
- private _parseHeadingLevel;
429
- /**
430
- * Check if document has images
431
- */
432
- private _hasImages;
433
- /**
434
- * Check if document has hyperlinks
435
- */
436
- private _hasHyperlinks;
437
- }
438
-
439
- /**
440
- * Selection State Utilities
441
- *
442
- * Extracts selection state from ProseMirror for toolbar integration.
443
- */
444
-
445
- /**
446
- * Selection state for toolbar integration
447
- */
448
- interface SelectionState {
449
- /** Whether there's an active selection (not just cursor) */
450
- hasSelection: boolean;
451
- /** Whether selection spans multiple paragraphs */
452
- isMultiParagraph: boolean;
453
- /** Current text formatting at selection/cursor */
454
- textFormatting: TextFormatting;
455
- /** Current paragraph formatting */
456
- paragraphFormatting: ParagraphFormatting;
457
- /** Current paragraph style ID (e.g., 'Heading1', 'Normal') */
458
- styleId: string | null;
459
- /** Start paragraph index */
460
- startParagraphIndex: number;
461
- /** End paragraph index */
462
- endParagraphIndex: number;
463
- }
464
-
465
- /**
466
- * Layout Engine Types
467
- *
468
- * Core types for the paginated layout engine.
469
- * Converts document blocks + measurements into positioned fragments on pages.
470
- */
471
- /**
472
- * Unique identifier for a block in the document.
473
- * Format: typically `${index}-${type}` or just the block index.
474
- */
475
- type BlockId = string | number;
476
- /**
477
- * Base fragment properties common to all fragment types.
478
- */
479
- type FragmentBase = {
480
- /** Block ID this fragment belongs to. */
481
- blockId: BlockId;
482
- /** X position on page (relative to page left). */
483
- x: number;
484
- /** Y position on page (relative to page top). */
485
- y: number;
486
- /** Width of the fragment. */
487
- width: number;
488
- /** ProseMirror start position (for click mapping). */
489
- pmStart?: number;
490
- /** ProseMirror end position (for click mapping). */
491
- pmEnd?: number;
492
- };
493
- /**
494
- * A paragraph fragment positioned on a page.
495
- * May span only part of the paragraph's lines if split across pages.
496
- */
497
- type ParagraphFragment = FragmentBase & {
498
- kind: 'paragraph';
499
- /** First line index (inclusive) from the measure. */
500
- fromLine: number;
501
- /** Last line index (exclusive) from the measure. */
502
- toLine: number;
503
- /** Height of this fragment. */
504
- height: number;
505
- /** True if this continues from a previous page. */
506
- continuesFromPrev?: boolean;
507
- /** True if this continues onto the next page. */
508
- continuesOnNext?: boolean;
509
- };
510
- /**
511
- * A table fragment positioned on a page.
512
- * May span only part of the table's rows if split across pages.
513
- */
514
- type TableFragment = FragmentBase & {
515
- kind: 'table';
516
- /** First row index (inclusive). */
517
- fromRow: number;
518
- /** Last row index (exclusive). */
519
- toRow: number;
520
- /** Height of this fragment. */
521
- height: number;
522
- /** True if this is a floating table. */
523
- isFloating?: boolean;
524
- /** True if this continues from a previous page. */
525
- continuesFromPrev?: boolean;
526
- /** True if this continues onto the next page. */
527
- continuesOnNext?: boolean;
528
- /** Number of header rows prepended to this continuation fragment (0 or undefined for first fragment). */
529
- headerRowCount?: number;
530
- };
531
- /**
532
- * An image fragment positioned on a page.
533
- */
534
- type ImageFragment = FragmentBase & {
535
- kind: 'image';
536
- /** Height of the image. */
537
- height: number;
538
- /** True if this is an anchored/floating image. */
539
- isAnchored?: boolean;
540
- /** Z-index for layering. */
541
- zIndex?: number;
542
- };
543
- /**
544
- * A text box fragment positioned on a page.
545
- */
546
- type TextBoxFragment = FragmentBase & {
547
- kind: 'textBox';
548
- /** Height of the text box. */
549
- height: number;
550
- /** True when positioned outside normal document flow. */
551
- isFloating?: boolean;
552
- /** Stack order hint for anchored text boxes. */
553
- zIndex?: number;
554
- };
555
- /**
556
- * Union of all fragment types.
557
- */
558
- type Fragment = ParagraphFragment | TableFragment | ImageFragment | TextBoxFragment;
559
- /**
560
- * Page margin configuration.
561
- */
562
- type PageMargins = {
563
- top: number;
564
- right: number;
565
- bottom: number;
566
- left: number;
567
- /** Distance from page top to header content. */
568
- header?: number;
569
- /** Distance from page bottom to footer content. */
570
- footer?: number;
571
- };
572
- /**
573
- * A rendered page containing positioned fragments.
574
- */
575
- type Page = {
576
- /** Page number (1-indexed). */
577
- number: number;
578
- /** Fragments positioned on this page. */
579
- fragments: Fragment[];
580
- /** Page margins. */
581
- margins: PageMargins;
582
- /** Page size (width, height). */
583
- size: {
584
- w: number;
585
- h: number;
586
- };
587
- /** Page orientation. */
588
- orientation?: 'portrait' | 'landscape';
589
- /** Section index this page belongs to. */
590
- sectionIndex?: number;
591
- /** Header/footer references for this page. */
592
- headerFooterRefs?: {
593
- headerDefault?: string;
594
- headerFirst?: string;
595
- headerEven?: string;
596
- footerDefault?: string;
597
- footerFirst?: string;
598
- footerEven?: string;
599
- };
600
- /** Footnote IDs that appear on this page (for rendering). */
601
- footnoteIds?: number[];
602
- /** Height reserved for the footnote area at page bottom (pixels). */
603
- footnoteReservedHeight?: number;
604
- /** Column layout for this page (if multi-column). */
605
- columns?: ColumnLayout;
606
- };
607
- /**
608
- * Column layout configuration.
609
- */
610
- type ColumnLayout = {
611
- count: number;
612
- gap: number;
613
- equalWidth?: boolean;
614
- /** Draw vertical separator line between columns (w:sep). */
615
- separator?: boolean;
616
- };
617
- /**
618
- * Header/footer layout for a specific type.
619
- */
620
- type HeaderFooterLayout = {
621
- height: number;
622
- fragments: Fragment[];
623
- };
624
- /**
625
- * Final layout output ready for rendering/painting.
626
- */
627
- type Layout = {
628
- /** Default page size for the document. */
629
- pageSize: {
630
- w: number;
631
- h: number;
632
- };
633
- /** All rendered pages with positioned fragments. */
634
- pages: Page[];
635
- /** Column configuration (if multi-column). */
636
- columns?: ColumnLayout;
637
- /** Header layouts by type (default, first, even). */
638
- headers?: Record<string, HeaderFooterLayout>;
639
- /** Footer layouts by type (default, first, even). */
640
- footers?: Record<string, HeaderFooterLayout>;
641
- /** Gap between pages in pixels (for rendering). */
642
- pageGap?: number;
643
- };
644
-
645
- interface PagedEditorRef {
646
- /** Get the current document. */
647
- getDocument(): Document | null;
648
- /** Get the ProseMirror EditorState. */
649
- getState(): EditorState | null;
650
- /** Get the ProseMirror EditorView. */
651
- getView(): EditorView | null;
652
- /** Focus the editor. */
653
- focus(): void;
654
- /** Blur the editor. */
655
- blur(): void;
656
- /** Check if focused. */
657
- isFocused(): boolean;
658
- /** Dispatch a transaction. */
659
- dispatch(tr: Transaction): void;
660
- /** Undo. */
661
- undo(): boolean;
662
- /** Redo. */
663
- redo(): boolean;
664
- /** Set selection by PM position. */
665
- setSelection(anchor: number, head?: number): void;
666
- /** Get current layout. */
667
- getLayout(): Layout | null;
668
- /** Force re-layout. */
669
- relayout(): void;
670
- /** Scroll the visible pages to bring a PM position into view. */
671
- scrollToPosition(pmPos: number): void;
672
- /**
673
- * Scroll to the paragraph identified by Word `w14:paraId` / PM `paraId`.
674
- * @returns whether a matching paragraph was found
675
- */
676
- scrollToParaId(paraId: string): boolean;
677
- /**
678
- * Scroll the paginated view so `pageNumber` (1-indexed) is in view.
679
- * No-op if the layout isn't ready yet or pageNumber is out of range.
680
- */
681
- scrollToPage(pageNumber: number): void;
682
- }
683
-
684
- /**
685
- * DocxEditor props
686
- */
687
- interface DocxEditorProps {
688
- /** Document data — ArrayBuffer, Uint8Array, Blob, or File */
689
- documentBuffer?: DocxInput | null;
690
- /** Pre-parsed document (alternative to documentBuffer) */
691
- document?: Document | null;
692
- /** Callback when document is saved */
693
- onSave?: (buffer: ArrayBuffer) => void;
694
- /** Author name used for comments and track changes */
695
- author?: string;
696
- /** Callback when document changes */
697
- onChange?: (document: Document) => void;
698
- /** Callback when selection changes */
699
- onSelectionChange?: (state: SelectionState | null) => void;
700
- /** Callback on error */
701
- onError?: (error: Error) => void;
702
- /** Callback when fonts are loaded */
703
- onFontsLoaded?: () => void;
704
- /** External ProseMirror plugins (from PluginHost) */
705
- externalPlugins?: prosemirror_state.Plugin[];
706
- /**
707
- * When true, the editor treats the `document` prop as a schema seed only and
708
- * does not load it into ProseMirror on mount. Content is expected to come from
709
- * external sources — typically `externalPlugins` such as `ySyncPlugin` from
710
- * `y-prosemirror`, but also any code that dispatches transactions directly.
711
- *
712
- * You must still pass a `document` prop (e.g., `createEmptyDocument()`) so the
713
- * editor can build its schema and render the shell.
714
- */
715
- externalContent?: boolean;
716
- /** Callback when editor view is ready (for PluginHost) */
717
- onEditorViewReady?: (view: prosemirror_view.EditorView) => void;
718
- /** Theme for styling */
719
- theme?: Theme | null;
720
- /** Whether to show toolbar (default: true) */
721
- showToolbar?: boolean;
722
- /** Whether to show zoom control (default: true) */
723
- showZoomControl?: boolean;
724
- /** Whether to show page margin guides/boundaries (default: false) */
725
- showMarginGuides?: boolean;
726
- /** Color for margin guides (default: '#c0c0c0') */
727
- marginGuideColor?: string;
728
- /** Whether to show horizontal ruler (default: false) */
729
- showRuler?: boolean;
730
- /** Unit for ruler display (default: 'inch') */
731
- rulerUnit?: 'inch' | 'cm';
732
- /** Initial zoom level (default: 1.0) */
733
- initialZoom?: number;
734
- /** Whether the editor is read-only. When true, hides toolbar and rulers */
735
- readOnly?: boolean;
736
- /**
737
- * When true, the editor does not intercept Cmd/Ctrl+F or Cmd/Ctrl+H.
738
- * This lets the browser or host app handle native find/history shortcuts.
739
- */
740
- disableFindReplaceShortcuts?: boolean;
741
- /** Custom toolbar actions */
742
- toolbarExtra?: ReactNode;
743
- /** Additional CSS class name */
744
- className?: string;
745
- /** Additional inline styles */
746
- style?: CSSProperties;
747
- /** Placeholder when no document */
748
- placeholder?: ReactNode;
749
- /** Loading indicator */
750
- loadingIndicator?: ReactNode;
751
- /** Whether to show the document outline sidebar (default: false) */
752
- showOutline?: boolean;
753
- /** Whether to show the floating outline toggle button (default: true) */
754
- showOutlineButton?: boolean;
755
- /**
756
- * Custom list of fonts shown in the toolbar's font-family dropdown.
757
- * Strings render in the "Other" group; pass `FontOption[]` for category
758
- * grouping and CSS fallback chains. Omit to use the built-in 12-font
759
- * default. An empty array renders an empty (but enabled) dropdown.
760
- *
761
- * Pass a stable reference (memoized or module-level) — inline arrays
762
- * create a new identity per render and invalidate the picker's memo.
763
- *
764
- * @example fontFamilies={['Arial', 'Roboto']}
765
- * @example fontFamilies={[{ name: 'Roboto', fontFamily: 'Roboto, sans-serif', category: 'sans-serif' }]}
766
- */
767
- fontFamilies?: ReadonlyArray<string | FontOption>;
768
- /** Whether to show print button in toolbar (default: true) */
769
- showPrintButton?: boolean;
770
- /** Whether to show the editing mode switcher (Editing/Suggesting/Viewing) in toolbar (default: true) */
771
- showModeSwitcher?: boolean;
772
- /** Whether to show the comments sidebar toggle button in toolbar (default: true) */
773
- showCommentsSidebarToggle?: boolean;
774
- /** Print options for print preview */
775
- printOptions?: PrintOptions;
776
- /**
777
- * Callback when print is triggered. Pass it to enable the `File > Print`
778
- * menu entry; omit to hide. The imperative `ref.current.print()` also
779
- * invokes this callback.
780
- */
781
- onPrint?: () => void;
782
- /** Callback when content is copied */
783
- onCopy?: () => void;
784
- /** Callback when content is cut */
785
- onCut?: () => void;
786
- /** Callback when content is pasted */
787
- onPaste?: () => void;
788
- /** Editor mode: 'editing' (direct edits), 'suggesting' (track changes), or 'viewing' (read-only). Default: 'editing' */
789
- mode?: EditorMode;
790
- /** Callback when the editing mode changes */
791
- onModeChange?: (mode: EditorMode) => void;
792
- /** Callback when a comment is added via the UI */
793
- onCommentAdd?: (comment: Comment) => void;
794
- /** Callback when a comment is resolved via the UI */
795
- onCommentResolve?: (comment: Comment) => void;
796
- /** Callback when a comment is deleted via the UI */
797
- onCommentDelete?: (comment: Comment) => void;
798
- /** Callback when a reply is added to a comment via the UI */
799
- onCommentReply?: (reply: Comment, parent: Comment) => void;
800
- /**
801
- * Controlled comments array. When provided, the editor reads comment thread
802
- * metadata (text, author, replies, resolved status) from this prop instead
803
- * of internal state, and emits every change through `onCommentsChange`.
804
- *
805
- * Use this with collaboration backends (Yjs, Liveblocks, Automerge, …) so
806
- * comment threads sync across peers — the PM document only carries the
807
- * range markers; thread metadata lives outside the doc and needs its own
808
- * sync channel.
809
- *
810
- * If omitted, the editor falls back to internal state (current behavior).
811
- * The granular `onCommentAdd`/`onCommentResolve`/`onCommentDelete`/
812
- * `onCommentReply` callbacks fire in both modes.
813
- */
814
- comments?: Comment[];
815
- /** Fires whenever the comments array changes (controlled mode). */
816
- onCommentsChange?: (comments: Comment[]) => void;
817
- /**
818
- * Callback when rendered DOM context is ready (for plugin overlays).
819
- * Used by PluginHost to get access to the rendered page DOM for positioning.
820
- */
821
- onRenderedDomContextReady?: (context: RenderedDomContext) => void;
822
- /**
823
- * Plugin overlays to render inside the editor viewport.
824
- * Passed from PluginHost to render plugin-specific overlays.
825
- */
826
- pluginOverlays?: ReactNode;
827
- /** Sidebar items from plugins (passed from PluginHost). */
828
- pluginSidebarItems?: ReactSidebarItem[];
829
- /** Rendered DOM context from PluginHost (for sidebar position resolution). */
830
- pluginRenderedDomContext?: RenderedDomContext | null;
831
- /** Custom logo/icon for the title bar */
832
- renderLogo?: () => ReactNode;
833
- /** Document name shown in the title bar */
834
- documentName?: string;
835
- /** Callback when document name changes */
836
- onDocumentNameChange?: (name: string) => void;
837
- /** Whether the document name is editable (default: true) */
838
- documentNameEditable?: boolean;
839
- /** Custom right-side actions for the title bar */
840
- renderTitleBarRight?: () => ReactNode;
841
- /** Translation overrides. Import a locale JSON file and pass it directly. */
842
- i18n?: Translations;
843
- /**
844
- * Mount a controllable agent panel on the right side of the editor. The
845
- * panel is the chrome (header, close button, drag-resize); the consumer
846
- * supplies whatever content goes inside via `render` — typically a chat
847
- * UI from `@ai-sdk/react`'s `useChat`, `assistant-ui`, or any other
848
- * framework. We do not ship message bubbles, a composer, or a chat engine.
849
- *
850
- * Three control patterns:
851
- * - **Uncontrolled**: `agentPanel={{ render }}` — toolbar button + panel
852
- * close button toggle the panel. Width persists to localStorage.
853
- * - **Controlled**: `agentPanel={{ render, open, onOpenChange }}` — the
854
- * consumer owns open state (e.g. tied to a global menu).
855
- * - **Headless**: omit `agentPanel`, use the toolkit directly via
856
- * `useDocxAgentTools` — render the panel anywhere you want.
857
- */
858
- agentPanel?: {
859
- /** Render-prop returning the panel content. Called only when open. */
860
- render: (ctx: {
861
- close: () => void;
862
- }) => ReactNode;
863
- /** Controlled open state. Omit for uncontrolled. */
864
- open?: boolean;
865
- /** Fires when toolbar button or panel close button is clicked. */
866
- onOpenChange?: (open: boolean) => void;
867
- /** Show the toolbar toggle button. Default: true. */
868
- showToolbarButton?: boolean;
869
- /** Optional badge / dot on the toolbar button. */
870
- toolbarBadge?: ReactNode;
871
- /** Optional panel title. Default: t('agentPanel.defaultTitle'). */
872
- title?: string;
873
- /** Optional panel header icon. Default: sparkle. */
874
- icon?: ReactNode;
875
- /** Initial panel width in px (uncontrolled). Default: 360. */
876
- defaultWidth?: number;
877
- /** Min drag width. Default: 280. */
878
- minWidth?: number;
879
- /** Max drag width. Default: 600. */
880
- maxWidth?: number;
881
- };
882
- }
883
- /**
884
- * DocxEditor ref interface
885
- */
886
- interface DocxEditorRef {
887
- /** Get the DocumentAgent for programmatic access */
888
- getAgent: () => DocumentAgent | null;
889
- /** Get the current document */
890
- getDocument: () => Document | null;
891
- /** Get the editor ref */
892
- getEditorRef: () => PagedEditorRef | null;
893
- /** Save the document to buffer. Pass { selective: false } to force full repack. */
894
- save: (options?: {
895
- selective?: boolean;
896
- }) => Promise<ArrayBuffer | null>;
897
- /** Set zoom level */
898
- setZoom: (zoom: number) => void;
899
- /** Get current zoom level */
900
- getZoom: () => number;
901
- /** Focus the editor */
902
- focus: () => void;
903
- /** Get current page number */
904
- getCurrentPage: () => number;
905
- /** Get total page count */
906
- getTotalPages: () => number;
907
- /**
908
- * Scroll the paginated view so the given page is in view.
909
- * Page numbers are 1-indexed (matches `getCurrentPage` / `getTotalPages`).
910
- * No-op for out-of-range or non-integer values.
911
- * @example ref.current?.scrollToPage(2)
912
- */
913
- scrollToPage: (pageNumber: number) => void;
914
- /**
915
- * Scroll the paginated view to the paragraph with the given Word `w14:paraId`.
916
- * @returns whether a matching paragraph exists in the ProseMirror document
917
- * @example ref.current?.scrollToParaId('1A2B3C4D')
918
- */
919
- scrollToParaId: (paraId: string) => boolean;
920
- /**
921
- * Scroll the paginated view to a specific ProseMirror document position.
922
- * Use this when you have a raw PM offset; for Word `w14:paraId` use
923
- * `scrollToParaId` instead.
924
- * @example ref.current?.scrollToPosition(42)
925
- */
926
- scrollToPosition: (pmPos: number) => void;
927
- /** Open print preview */
928
- openPrintPreview: () => void;
929
- /** Print the document directly */
930
- print: () => void;
931
- /** Load a pre-parsed document programmatically */
932
- loadDocument: (doc: Document) => void;
933
- /** Load a DOCX buffer programmatically (ArrayBuffer, Uint8Array, Blob, or File) */
934
- loadDocumentBuffer: (buffer: DocxInput) => Promise<void>;
935
- /**
936
- * Apply document changes from a DocumentAgent while preserving undo history.
937
- * This dispatches a PM transaction that replaces the document content,
938
- * allowing undo/redo to work with agent-made changes.
939
- *
940
- * @param doc - The modified Document from an agent
941
- * @returns true if the changes were applied, false if the editor is not ready
942
- *
943
- * @example
944
- * ```ts
945
- * const agent = EnhancedDocumentAgent.fromDocument(editorRef.current.getDocument());
946
- * const updated = agent.toggleBulletList([0, 1, 2]).getDocument();
947
- * editorRef.current.applyDocumentChanges(updated);
948
- * // Ctrl+Z will undo the bullet list changes
949
- * ```
950
- */
951
- applyDocumentChanges: (doc: Document) => boolean;
952
- /** Add a comment programmatically. Anchored by Word `w14:paraId` so
953
- * it survives unrelated edits. Returns the comment ID, or null if
954
- * the paraId is unknown or the search text isn't found / is ambiguous. */
955
- addComment: (options: {
956
- paraId: string;
957
- text: string;
958
- author: string;
959
- /** Optional: anchor to a specific phrase within the paragraph (must be unique). */
960
- search?: string;
961
- }) => number | null;
962
- /** Reply to an existing comment. Returns the reply comment ID. */
963
- replyToComment: (commentId: number, text: string, author: string) => number | null;
964
- /** Resolve (mark as done) a comment. */
965
- resolveComment: (commentId: number) => void;
966
- /** Suggest a tracked change. Pass `replaceWith: ''` to delete the matched text;
967
- * pass `search: ''` to insert at paragraph end. Returns false on missing paraId,
968
- * missing/ambiguous search, or attempt to layer on an existing tracked change. */
969
- proposeChange: (options: {
970
- paraId: string;
971
- search: string;
972
- replaceWith: string;
973
- author: string;
974
- }) => boolean;
975
- /** Locate every paragraph containing `query` (case-insensitive substring).
976
- * Returns a stable handle (paraId + the matched phrase) the agent can pass
977
- * back to `addComment` / `proposeChange`. */
978
- findInDocument: (query: string, options?: {
979
- caseSensitive?: boolean;
980
- limit?: number;
981
- }) => Array<{
982
- paraId: string;
983
- match: string;
984
- before: string;
985
- after: string;
986
- }>;
987
- /**
988
- * Apply character formatting (bold / italic / color / size / font / etc.)
989
- * to a paragraph or to a unique phrase within it. This is a direct edit,
990
- * not a tracked change. Returns false on missing paraId or ambiguous search.
991
- */
992
- applyFormatting: (options: {
993
- paraId: string;
994
- search?: string;
995
- marks: {
996
- bold?: boolean;
997
- italic?: boolean;
998
- underline?: boolean | {
999
- style?: string;
1000
- };
1001
- strike?: boolean;
1002
- color?: {
1003
- rgb?: string;
1004
- themeColor?: string;
1005
- };
1006
- highlight?: string;
1007
- fontSize?: number;
1008
- fontFamily?: {
1009
- ascii?: string;
1010
- hAnsi?: string;
1011
- };
1012
- };
1013
- }) => boolean;
1014
- /**
1015
- * Apply a paragraph style by styleId (e.g. `'Heading1'`, `'Quote'`).
1016
- * Direct edit, not a tracked change. Returns false if paraId is unknown.
1017
- */
1018
- setParagraphStyle: (options: {
1019
- paraId: string;
1020
- styleId: string;
1021
- }) => boolean;
1022
- /**
1023
- * Read the contents of a single page. 1-indexed; returns null if the page
1024
- * does not exist. Each paragraph is returned with its stable paraId so the
1025
- * agent can comment on or modify it without an extra round-trip.
1026
- */
1027
- getPageContent: (pageNumber: number) => {
1028
- pageNumber: number;
1029
- text: string;
1030
- paragraphs: Array<{
1031
- paraId: string;
1032
- text: string;
1033
- styleId?: string;
1034
- }>;
1035
- } | null;
1036
- /** Read the user's current cursor / selection — what's highlighted right now. */
1037
- getSelectionInfo: () => {
1038
- paraId: string | null;
1039
- selectedText: string;
1040
- paragraphText: string;
1041
- before: string;
1042
- after: string;
1043
- } | null;
1044
- /** Get all comments. */
1045
- getComments: () => Comment[];
1046
- /** Subscribe to document changes. Fires after every committed edit. Returns unsubscribe. */
1047
- onContentChange: (listener: (document: Document) => void) => () => void;
1048
- /** Subscribe to selection changes (cursor moves / selection changes). Returns unsubscribe. */
1049
- onSelectionChange: (listener: (selection: SelectionState | null) => void) => () => void;
1050
- }
1051
- type EditorMode = 'editing' | 'suggesting' | 'viewing';
1052
- /**
1053
- * DocxEditor - Complete DOCX editor component
1054
- */
1055
- declare const DocxEditor: React.ForwardRefExoticComponent<DocxEditorProps & React.RefAttributes<DocxEditorRef>>;
1056
-
1057
- /**
1058
- * Simple imperative API for rendering a DOCX editor into a DOM element.
1059
- *
1060
- * Returns an `EditorHandle` (from @eigenpal/docx-editor-core) that works with
1061
- * any framework implementation.
1062
- *
1063
- * Usage:
1064
- * ```ts
1065
- * import { renderAsync } from '@eigenpal/docx-editor-react';
1066
- *
1067
- * const editor = await renderAsync(docxBlob, document.getElementById('container'), {
1068
- * readOnly: false,
1069
- * showToolbar: true,
1070
- * });
1071
- *
1072
- * // Save the edited document
1073
- * const blob = await editor.save();
1074
- *
1075
- * // Clean up
1076
- * editor.destroy();
1077
- * ```
1078
- */
1079
-
1080
- /**
1081
- * Options for {@link renderAsync}. A subset of DocxEditorProps minus
1082
- * `documentBuffer` / `document` (passed as the first argument instead).
1083
- */
1084
- type RenderAsyncOptions = Omit<DocxEditorProps, 'documentBuffer' | 'document'>;
1085
- /**
1086
- * React-specific handle that extends the framework-agnostic EditorHandle
1087
- * with zoom control.
1088
- */
1089
- interface DocxEditorHandle extends EditorHandle {
1090
- /** Set zoom level (1.0 = 100%). */
1091
- setZoom: (zoom: number) => void;
1092
- /** Scroll to a body paragraph by Word `w14:paraId`. */
1093
- scrollToParaId: (paraId: string) => boolean;
1094
- /** Scroll to a raw ProseMirror document position. */
1095
- scrollToPosition: (pmPos: number) => void;
1096
- }
1097
- /**
1098
- * Render a DOCX editor into a container element.
1099
- *
1100
- * @param input - DOCX data as ArrayBuffer, Uint8Array, Blob, or File
1101
- * @param container - DOM element to render into
1102
- * @param options - Editor configuration (toolbar, readOnly, callbacks, etc.)
1103
- * @returns A handle with save / destroy / getDocument methods
1104
- */
1105
- declare function renderAsync(input: DocxInput, container: HTMLElement, options?: RenderAsyncOptions): Promise<DocxEditorHandle>;
1106
-
1107
- /**
1108
- * @eigenpal/docx-editor-react
1109
- *
1110
- * Curated root entry for the documented React editor API. Advanced surfaces
1111
- * stay public through explicit subpaths:
1112
- * - `@eigenpal/docx-editor-react/ui`
1113
- * - `@eigenpal/docx-editor-react/dialogs`
1114
- * - `@eigenpal/docx-editor-react/hooks`
1115
- * - `@eigenpal/docx-editor-react/plugin-api`
1116
- *
1117
- * Framework-agnostic document utilities live in `@eigenpal/docx-editor-core`.
1118
- * Agent/MCP surfaces live in `@eigenpal/docx-editor-agents`.
1119
- */
1120
- declare const VERSION = "0.0.2";
1121
-
1122
- export { DocxEditor, type DocxEditorHandle, type DocxEditorProps, type DocxEditorRef, type EditorMode, LocaleProvider, type LocaleProviderProps, type RenderAsyncOptions, TranslationKey, Translations, VERSION, renderAsync, useTranslation };