@eigenpal/docx-js-editor 0.0.2 → 0.0.3

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/index.d.cts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as prosemirror_view from 'prosemirror-view';
2
2
  import { EditorView, DecorationSet } from 'prosemirror-view';
3
3
  import * as prosemirror_state from 'prosemirror-state';
4
- import { EditorState, Command, Plugin, PluginKey } from 'prosemirror-state';
4
+ import { Plugin, EditorState, Transaction, PluginKey } from 'prosemirror-state';
5
5
  import * as React$1 from 'react';
6
6
  import React__default, { CSSProperties, ReactNode, Component, ErrorInfo } from 'react';
7
- import { T as TextFormatting, e as Paragraph, f as Table, a1 as SectionProperties, an as HeaderFooter, h as Document, ab as Theme, U as ParagraphFormatting, a2 as SelectionContext, a8 as TableCell, ao as ParagraphAlignment, a4 as Style, A as AIAction, l as AgentResponse, ap as StyleType, aq as BorderSpec, ar as ShadingProperties, R as Run, as as BreakContent, $ as RunContent } from './types-BJXChtaM.cjs';
7
+ import { T as TextFormatting, e as Paragraph, f as Table, a1 as SectionProperties, an as HeaderFooter, h as Document, ab as Theme, U as ParagraphFormatting, a8 as TableCell, ao as ParagraphAlignment, a4 as Style, a2 as SelectionContext, A as AIAction, l as AgentResponse, ap as StyleType, aq as BorderSpec, ar as ShadingProperties, R as Run, as as BreakContent, $ as RunContent } from './types-BJXChtaM.cjs';
8
8
  export { i as AIActionRequest, j as AgentCommand, k as AgentContext, m as ApplyStyleCommand, B as BlockContent, at as BookmarkEnd, au as BookmarkStart, C as CorePlugin, q as DeleteTextCommand, D as DocumentBody, r as DocxPackage, E as Endnote, av as Field, aw as FooterReference, F as Footnote, t as FormatTextCommand, ax as HeaderReference, H as Hyperlink, I as Image, u as InsertHyperlinkCommand, v as InsertImageCommand, w as InsertTableCommand, x as InsertTextCommand, L as ListLevel, d as McpSession, M as McpToolDefinition, N as McpToolHandler, O as McpToolResult, Q as NumberingDefinitions, S as ParagraphContext, g as Position, Y as Range, Z as Relationship, _ as ReplaceTextCommand, a3 as SetVariableCommand, ay as Shape, a5 as StyleDefinitions, a7 as SuggestedAction, a9 as TableRow, az as TextBox, aa as TextContent, aA as ThemeColorScheme, aB as ThemeFont, aC as ThemeFontScheme } from './types-BJXChtaM.cjs';
9
9
  import { D as DocumentAgent } from './colorResolver-C-tITrbI.cjs';
10
10
  export { A as AgentContextOptions, C as CreateEmptyDocumentOptions, E as ExtendedSelectionContext, P as ProcessTemplateOptions, e as ProcessTemplateResult, f as SelectionContextOptions, g as blendColors, h as buildExtendedSelectionContext, i as buildSelectionContext, k as colorsEqual, n as createDocumentWithText, o as createEmptyDocument, p as createRgbColor, r as createThemeColor, s as darkenColor, t as emuToPixels, u as emuToTwips, v as executeCommand, w as executeCommands, x as formatPx, y as getAgentContext, z as getContrastingColor, B as getDocumentSummary, J as getTemplateTags, K as halfPointsToPixels, L as isBlack, M as isWhite, N as lightenColor, O as parseColorString, Q as parseDocx, R as pixelsToEmu, U as pixelsToTwips, V as pointsToPixels, X as processTemplate, Z as processTemplateAsBlob, _ as processTemplateDetailed, $ as resolveColor, a0 as resolveHighlightColor, a1 as resolveShadingColor, a2 as serializeDocumentBody, a3 as serializeDocx, a4 as serializeSectionProperties, a5 as twipsToEmu, a6 as twipsToPixels, a7 as validateTemplate } from './colorResolver-C-tITrbI.cjs';
@@ -245,7 +245,7 @@ interface Line {
245
245
  /**
246
246
  * A laid out page
247
247
  */
248
- interface Page {
248
+ interface Page$1 {
249
249
  /** Page number (1-indexed) */
250
250
  pageNumber: number;
251
251
  /** Section this page belongs to */
@@ -303,7 +303,7 @@ interface PageContent {
303
303
  */
304
304
  interface PageLayoutResult {
305
305
  /** All pages */
306
- pages: Page[];
306
+ pages: Page$1[];
307
307
  /** Total page count */
308
308
  totalPages: number;
309
309
  /** Page number field values by location */
@@ -429,6 +429,12 @@ declare function formatPageRange(range: {
429
429
  */
430
430
  declare function isPrintSupported(): boolean;
431
431
 
432
+ /**
433
+ * Selection State Utilities
434
+ *
435
+ * Extracts selection state from ProseMirror for toolbar integration.
436
+ */
437
+
432
438
  /**
433
439
  * Selection state for toolbar integration
434
440
  */
@@ -448,39 +454,162 @@ interface SelectionState {
448
454
  /** End paragraph index */
449
455
  endParagraphIndex: number;
450
456
  }
457
+
451
458
  /**
452
- * Ref interface for external control
459
+ * Layout Engine Types
460
+ *
461
+ * Core types for the paginated layout engine.
462
+ * Converts document blocks + measurements into positioned fragments on pages.
453
463
  */
454
- interface ProseMirrorEditorRef {
455
- /** Focus the editor */
456
- focus: () => void;
457
- /** Blur the editor */
458
- blur: () => void;
459
- /** Get the current ProseMirror state */
460
- getState: () => EditorState | null;
461
- /** Get the current ProseMirror view */
462
- getView: () => EditorView | null;
463
- /** Undo the last change */
464
- undo: () => boolean;
465
- /** Redo the last undone change */
466
- redo: () => boolean;
467
- /** Check if undo is available */
468
- canUndo: () => boolean;
469
- /** Check if redo is available */
470
- canRedo: () => boolean;
471
- /** Execute a ProseMirror command */
472
- executeCommand: (command: Command) => boolean;
473
- /** Toggle bold mark */
474
- toggleBold: () => boolean;
475
- /** Toggle italic mark */
476
- toggleItalic: () => boolean;
477
- /** Toggle underline mark */
478
- toggleUnderline: () => boolean;
479
- /** Get the current Document from PM state */
480
- getDocument: () => Document | null;
481
- /** Get selection context for AI features */
482
- getSelectionContext: () => SelectionContext | null;
483
- }
464
+ /**
465
+ * Unique identifier for a block in the document.
466
+ * Format: typically `${index}-${type}` or just the block index.
467
+ */
468
+ type BlockId = string | number;
469
+ /**
470
+ * Base fragment properties common to all fragment types.
471
+ */
472
+ type FragmentBase = {
473
+ /** Block ID this fragment belongs to. */
474
+ blockId: BlockId;
475
+ /** X position on page (relative to page left). */
476
+ x: number;
477
+ /** Y position on page (relative to page top). */
478
+ y: number;
479
+ /** Width of the fragment. */
480
+ width: number;
481
+ /** ProseMirror start position (for click mapping). */
482
+ pmStart?: number;
483
+ /** ProseMirror end position (for click mapping). */
484
+ pmEnd?: number;
485
+ };
486
+ /**
487
+ * A paragraph fragment positioned on a page.
488
+ * May span only part of the paragraph's lines if split across pages.
489
+ */
490
+ type ParagraphFragment = FragmentBase & {
491
+ kind: 'paragraph';
492
+ /** First line index (inclusive) from the measure. */
493
+ fromLine: number;
494
+ /** Last line index (exclusive) from the measure. */
495
+ toLine: number;
496
+ /** Height of this fragment. */
497
+ height: number;
498
+ /** True if this continues from a previous page. */
499
+ continuesFromPrev?: boolean;
500
+ /** True if this continues onto the next page. */
501
+ continuesOnNext?: boolean;
502
+ };
503
+ /**
504
+ * A table fragment positioned on a page.
505
+ * May span only part of the table's rows if split across pages.
506
+ */
507
+ type TableFragment = FragmentBase & {
508
+ kind: 'table';
509
+ /** First row index (inclusive). */
510
+ fromRow: number;
511
+ /** Last row index (exclusive). */
512
+ toRow: number;
513
+ /** Height of this fragment. */
514
+ height: number;
515
+ /** True if this continues from a previous page. */
516
+ continuesFromPrev?: boolean;
517
+ /** True if this continues onto the next page. */
518
+ continuesOnNext?: boolean;
519
+ };
520
+ /**
521
+ * An image fragment positioned on a page.
522
+ */
523
+ type ImageFragment = FragmentBase & {
524
+ kind: 'image';
525
+ /** Height of the image. */
526
+ height: number;
527
+ /** True if this is an anchored/floating image. */
528
+ isAnchored?: boolean;
529
+ /** Z-index for layering. */
530
+ zIndex?: number;
531
+ };
532
+ /**
533
+ * Union of all fragment types.
534
+ */
535
+ type Fragment = ParagraphFragment | TableFragment | ImageFragment;
536
+ /**
537
+ * Page margin configuration.
538
+ */
539
+ type PageMargins = {
540
+ top: number;
541
+ right: number;
542
+ bottom: number;
543
+ left: number;
544
+ /** Distance from page top to header content. */
545
+ header?: number;
546
+ /** Distance from page bottom to footer content. */
547
+ footer?: number;
548
+ };
549
+ /**
550
+ * A rendered page containing positioned fragments.
551
+ */
552
+ type Page = {
553
+ /** Page number (1-indexed). */
554
+ number: number;
555
+ /** Fragments positioned on this page. */
556
+ fragments: Fragment[];
557
+ /** Page margins. */
558
+ margins: PageMargins;
559
+ /** Page size (width, height). */
560
+ size: {
561
+ w: number;
562
+ h: number;
563
+ };
564
+ /** Page orientation. */
565
+ orientation?: 'portrait' | 'landscape';
566
+ /** Section index this page belongs to. */
567
+ sectionIndex?: number;
568
+ /** Header/footer references for this page. */
569
+ headerFooterRefs?: {
570
+ headerDefault?: string;
571
+ headerFirst?: string;
572
+ headerEven?: string;
573
+ footerDefault?: string;
574
+ footerFirst?: string;
575
+ footerEven?: string;
576
+ };
577
+ };
578
+ /**
579
+ * Column layout configuration.
580
+ */
581
+ type ColumnLayout = {
582
+ count: number;
583
+ gap: number;
584
+ equalWidth?: boolean;
585
+ };
586
+ /**
587
+ * Header/footer layout for a specific type.
588
+ */
589
+ type HeaderFooterLayout = {
590
+ height: number;
591
+ fragments: Fragment[];
592
+ };
593
+ /**
594
+ * Final layout output ready for rendering/painting.
595
+ */
596
+ type Layout = {
597
+ /** Default page size for the document. */
598
+ pageSize: {
599
+ w: number;
600
+ h: number;
601
+ };
602
+ /** All rendered pages with positioned fragments. */
603
+ pages: Page[];
604
+ /** Column configuration (if multi-column). */
605
+ columns?: ColumnLayout;
606
+ /** Header layouts by type (default, first, even). */
607
+ headers?: Record<string, HeaderFooterLayout>;
608
+ /** Footer layouts by type (default, first, even). */
609
+ footers?: Record<string, HeaderFooterLayout>;
610
+ /** Gap between pages in pixels (for rendering). */
611
+ pageGap?: number;
612
+ };
484
613
 
485
614
  /**
486
615
  * Generic Plugin Interface for the DOCX Editor
@@ -711,6 +840,49 @@ interface PluginHostRef {
711
840
  refreshPluginStates: () => void;
712
841
  }
713
842
 
843
+ /**
844
+ * PagedEditor Component
845
+ *
846
+ * Main paginated editing component that integrates:
847
+ * - HiddenProseMirror: off-screen editor for keyboard input
848
+ * - Layout engine: computes page layout from PM state
849
+ * - DOM painter: renders pages to visible DOM
850
+ * - Selection overlay: renders caret and selection highlights
851
+ *
852
+ * Architecture:
853
+ * 1. User clicks on visible pages → hit test → update PM selection
854
+ * 2. User types → hidden PM receives input → PM transaction
855
+ * 3. PM transaction → convert to blocks → measure → layout → paint
856
+ * 4. Selection changes → compute rects → update overlay
857
+ */
858
+
859
+ interface PagedEditorRef {
860
+ /** Get the current document. */
861
+ getDocument(): Document | null;
862
+ /** Get the ProseMirror EditorState. */
863
+ getState(): EditorState | null;
864
+ /** Get the ProseMirror EditorView. */
865
+ getView(): EditorView | null;
866
+ /** Focus the editor. */
867
+ focus(): void;
868
+ /** Blur the editor. */
869
+ blur(): void;
870
+ /** Check if focused. */
871
+ isFocused(): boolean;
872
+ /** Dispatch a transaction. */
873
+ dispatch(tr: Transaction): void;
874
+ /** Undo. */
875
+ undo(): boolean;
876
+ /** Redo. */
877
+ redo(): boolean;
878
+ /** Set selection by PM position. */
879
+ setSelection(anchor: number, head?: number): void;
880
+ /** Get current layout. */
881
+ getLayout(): Layout | null;
882
+ /** Force re-layout. */
883
+ relayout(): void;
884
+ }
885
+
714
886
  /**
715
887
  * DocxEditor props
716
888
  */
@@ -787,12 +959,6 @@ interface DocxEditorProps {
787
959
  onCut?: () => void;
788
960
  /** Callback when content is pasted */
789
961
  onPaste?: () => void;
790
- /**
791
- * Use paginated editor mode (experimental).
792
- * When enabled, shows true paginated editing with visible page breaks.
793
- * When disabled (default), uses standard ProseMirror editor.
794
- */
795
- usePaginatedEditor?: boolean;
796
962
  /**
797
963
  * Callback when rendered DOM context is ready (for plugin overlays).
798
964
  * Used by PluginHost to get access to the rendered page DOM for positioning.
@@ -812,8 +978,8 @@ interface DocxEditorRef {
812
978
  getAgent: () => DocumentAgent | null;
813
979
  /** Get the current document */
814
980
  getDocument: () => Document | null;
815
- /** Get the ProseMirror editor ref */
816
- getEditorRef: () => ProseMirrorEditorRef | null;
981
+ /** Get the editor ref */
982
+ getEditorRef: () => PagedEditorRef | null;
817
983
  /** Save the document to buffer */
818
984
  save: () => Promise<ArrayBuffer | null>;
819
985
  /** Set zoom level */
@@ -1380,7 +1546,7 @@ interface DocumentViewerProps {
1380
1546
  /** Callback when page becomes visible */
1381
1547
  onPageVisible?: (pageNumber: number) => void;
1382
1548
  /** Callback when document is clicked */
1383
- onDocumentClick?: (e: React__default.MouseEvent, page: Page | null) => void;
1549
+ onDocumentClick?: (e: React__default.MouseEvent, page: Page$1 | null) => void;
1384
1550
  /** Additional CSS class name */
1385
1551
  className?: string;
1386
1552
  /** Additional inline styles */
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as prosemirror_view from 'prosemirror-view';
2
2
  import { EditorView, DecorationSet } from 'prosemirror-view';
3
3
  import * as prosemirror_state from 'prosemirror-state';
4
- import { EditorState, Command, Plugin, PluginKey } from 'prosemirror-state';
4
+ import { Plugin, EditorState, Transaction, PluginKey } from 'prosemirror-state';
5
5
  import * as React$1 from 'react';
6
6
  import React__default, { CSSProperties, ReactNode, Component, ErrorInfo } from 'react';
7
- import { T as TextFormatting, e as Paragraph, f as Table, a1 as SectionProperties, an as HeaderFooter, h as Document, ab as Theme, U as ParagraphFormatting, a2 as SelectionContext, a8 as TableCell, ao as ParagraphAlignment, a4 as Style, A as AIAction, l as AgentResponse, ap as StyleType, aq as BorderSpec, ar as ShadingProperties, R as Run, as as BreakContent, $ as RunContent } from './types-BJXChtaM.js';
7
+ import { T as TextFormatting, e as Paragraph, f as Table, a1 as SectionProperties, an as HeaderFooter, h as Document, ab as Theme, U as ParagraphFormatting, a8 as TableCell, ao as ParagraphAlignment, a4 as Style, a2 as SelectionContext, A as AIAction, l as AgentResponse, ap as StyleType, aq as BorderSpec, ar as ShadingProperties, R as Run, as as BreakContent, $ as RunContent } from './types-BJXChtaM.js';
8
8
  export { i as AIActionRequest, j as AgentCommand, k as AgentContext, m as ApplyStyleCommand, B as BlockContent, at as BookmarkEnd, au as BookmarkStart, C as CorePlugin, q as DeleteTextCommand, D as DocumentBody, r as DocxPackage, E as Endnote, av as Field, aw as FooterReference, F as Footnote, t as FormatTextCommand, ax as HeaderReference, H as Hyperlink, I as Image, u as InsertHyperlinkCommand, v as InsertImageCommand, w as InsertTableCommand, x as InsertTextCommand, L as ListLevel, d as McpSession, M as McpToolDefinition, N as McpToolHandler, O as McpToolResult, Q as NumberingDefinitions, S as ParagraphContext, g as Position, Y as Range, Z as Relationship, _ as ReplaceTextCommand, a3 as SetVariableCommand, ay as Shape, a5 as StyleDefinitions, a7 as SuggestedAction, a9 as TableRow, az as TextBox, aa as TextContent, aA as ThemeColorScheme, aB as ThemeFont, aC as ThemeFontScheme } from './types-BJXChtaM.js';
9
9
  import { D as DocumentAgent } from './colorResolver-Yakhydrt.js';
10
10
  export { A as AgentContextOptions, C as CreateEmptyDocumentOptions, E as ExtendedSelectionContext, P as ProcessTemplateOptions, e as ProcessTemplateResult, f as SelectionContextOptions, g as blendColors, h as buildExtendedSelectionContext, i as buildSelectionContext, k as colorsEqual, n as createDocumentWithText, o as createEmptyDocument, p as createRgbColor, r as createThemeColor, s as darkenColor, t as emuToPixels, u as emuToTwips, v as executeCommand, w as executeCommands, x as formatPx, y as getAgentContext, z as getContrastingColor, B as getDocumentSummary, J as getTemplateTags, K as halfPointsToPixels, L as isBlack, M as isWhite, N as lightenColor, O as parseColorString, Q as parseDocx, R as pixelsToEmu, U as pixelsToTwips, V as pointsToPixels, X as processTemplate, Z as processTemplateAsBlob, _ as processTemplateDetailed, $ as resolveColor, a0 as resolveHighlightColor, a1 as resolveShadingColor, a2 as serializeDocumentBody, a3 as serializeDocx, a4 as serializeSectionProperties, a5 as twipsToEmu, a6 as twipsToPixels, a7 as validateTemplate } from './colorResolver-Yakhydrt.js';
@@ -245,7 +245,7 @@ interface Line {
245
245
  /**
246
246
  * A laid out page
247
247
  */
248
- interface Page {
248
+ interface Page$1 {
249
249
  /** Page number (1-indexed) */
250
250
  pageNumber: number;
251
251
  /** Section this page belongs to */
@@ -303,7 +303,7 @@ interface PageContent {
303
303
  */
304
304
  interface PageLayoutResult {
305
305
  /** All pages */
306
- pages: Page[];
306
+ pages: Page$1[];
307
307
  /** Total page count */
308
308
  totalPages: number;
309
309
  /** Page number field values by location */
@@ -429,6 +429,12 @@ declare function formatPageRange(range: {
429
429
  */
430
430
  declare function isPrintSupported(): boolean;
431
431
 
432
+ /**
433
+ * Selection State Utilities
434
+ *
435
+ * Extracts selection state from ProseMirror for toolbar integration.
436
+ */
437
+
432
438
  /**
433
439
  * Selection state for toolbar integration
434
440
  */
@@ -448,39 +454,162 @@ interface SelectionState {
448
454
  /** End paragraph index */
449
455
  endParagraphIndex: number;
450
456
  }
457
+
451
458
  /**
452
- * Ref interface for external control
459
+ * Layout Engine Types
460
+ *
461
+ * Core types for the paginated layout engine.
462
+ * Converts document blocks + measurements into positioned fragments on pages.
453
463
  */
454
- interface ProseMirrorEditorRef {
455
- /** Focus the editor */
456
- focus: () => void;
457
- /** Blur the editor */
458
- blur: () => void;
459
- /** Get the current ProseMirror state */
460
- getState: () => EditorState | null;
461
- /** Get the current ProseMirror view */
462
- getView: () => EditorView | null;
463
- /** Undo the last change */
464
- undo: () => boolean;
465
- /** Redo the last undone change */
466
- redo: () => boolean;
467
- /** Check if undo is available */
468
- canUndo: () => boolean;
469
- /** Check if redo is available */
470
- canRedo: () => boolean;
471
- /** Execute a ProseMirror command */
472
- executeCommand: (command: Command) => boolean;
473
- /** Toggle bold mark */
474
- toggleBold: () => boolean;
475
- /** Toggle italic mark */
476
- toggleItalic: () => boolean;
477
- /** Toggle underline mark */
478
- toggleUnderline: () => boolean;
479
- /** Get the current Document from PM state */
480
- getDocument: () => Document | null;
481
- /** Get selection context for AI features */
482
- getSelectionContext: () => SelectionContext | null;
483
- }
464
+ /**
465
+ * Unique identifier for a block in the document.
466
+ * Format: typically `${index}-${type}` or just the block index.
467
+ */
468
+ type BlockId = string | number;
469
+ /**
470
+ * Base fragment properties common to all fragment types.
471
+ */
472
+ type FragmentBase = {
473
+ /** Block ID this fragment belongs to. */
474
+ blockId: BlockId;
475
+ /** X position on page (relative to page left). */
476
+ x: number;
477
+ /** Y position on page (relative to page top). */
478
+ y: number;
479
+ /** Width of the fragment. */
480
+ width: number;
481
+ /** ProseMirror start position (for click mapping). */
482
+ pmStart?: number;
483
+ /** ProseMirror end position (for click mapping). */
484
+ pmEnd?: number;
485
+ };
486
+ /**
487
+ * A paragraph fragment positioned on a page.
488
+ * May span only part of the paragraph's lines if split across pages.
489
+ */
490
+ type ParagraphFragment = FragmentBase & {
491
+ kind: 'paragraph';
492
+ /** First line index (inclusive) from the measure. */
493
+ fromLine: number;
494
+ /** Last line index (exclusive) from the measure. */
495
+ toLine: number;
496
+ /** Height of this fragment. */
497
+ height: number;
498
+ /** True if this continues from a previous page. */
499
+ continuesFromPrev?: boolean;
500
+ /** True if this continues onto the next page. */
501
+ continuesOnNext?: boolean;
502
+ };
503
+ /**
504
+ * A table fragment positioned on a page.
505
+ * May span only part of the table's rows if split across pages.
506
+ */
507
+ type TableFragment = FragmentBase & {
508
+ kind: 'table';
509
+ /** First row index (inclusive). */
510
+ fromRow: number;
511
+ /** Last row index (exclusive). */
512
+ toRow: number;
513
+ /** Height of this fragment. */
514
+ height: number;
515
+ /** True if this continues from a previous page. */
516
+ continuesFromPrev?: boolean;
517
+ /** True if this continues onto the next page. */
518
+ continuesOnNext?: boolean;
519
+ };
520
+ /**
521
+ * An image fragment positioned on a page.
522
+ */
523
+ type ImageFragment = FragmentBase & {
524
+ kind: 'image';
525
+ /** Height of the image. */
526
+ height: number;
527
+ /** True if this is an anchored/floating image. */
528
+ isAnchored?: boolean;
529
+ /** Z-index for layering. */
530
+ zIndex?: number;
531
+ };
532
+ /**
533
+ * Union of all fragment types.
534
+ */
535
+ type Fragment = ParagraphFragment | TableFragment | ImageFragment;
536
+ /**
537
+ * Page margin configuration.
538
+ */
539
+ type PageMargins = {
540
+ top: number;
541
+ right: number;
542
+ bottom: number;
543
+ left: number;
544
+ /** Distance from page top to header content. */
545
+ header?: number;
546
+ /** Distance from page bottom to footer content. */
547
+ footer?: number;
548
+ };
549
+ /**
550
+ * A rendered page containing positioned fragments.
551
+ */
552
+ type Page = {
553
+ /** Page number (1-indexed). */
554
+ number: number;
555
+ /** Fragments positioned on this page. */
556
+ fragments: Fragment[];
557
+ /** Page margins. */
558
+ margins: PageMargins;
559
+ /** Page size (width, height). */
560
+ size: {
561
+ w: number;
562
+ h: number;
563
+ };
564
+ /** Page orientation. */
565
+ orientation?: 'portrait' | 'landscape';
566
+ /** Section index this page belongs to. */
567
+ sectionIndex?: number;
568
+ /** Header/footer references for this page. */
569
+ headerFooterRefs?: {
570
+ headerDefault?: string;
571
+ headerFirst?: string;
572
+ headerEven?: string;
573
+ footerDefault?: string;
574
+ footerFirst?: string;
575
+ footerEven?: string;
576
+ };
577
+ };
578
+ /**
579
+ * Column layout configuration.
580
+ */
581
+ type ColumnLayout = {
582
+ count: number;
583
+ gap: number;
584
+ equalWidth?: boolean;
585
+ };
586
+ /**
587
+ * Header/footer layout for a specific type.
588
+ */
589
+ type HeaderFooterLayout = {
590
+ height: number;
591
+ fragments: Fragment[];
592
+ };
593
+ /**
594
+ * Final layout output ready for rendering/painting.
595
+ */
596
+ type Layout = {
597
+ /** Default page size for the document. */
598
+ pageSize: {
599
+ w: number;
600
+ h: number;
601
+ };
602
+ /** All rendered pages with positioned fragments. */
603
+ pages: Page[];
604
+ /** Column configuration (if multi-column). */
605
+ columns?: ColumnLayout;
606
+ /** Header layouts by type (default, first, even). */
607
+ headers?: Record<string, HeaderFooterLayout>;
608
+ /** Footer layouts by type (default, first, even). */
609
+ footers?: Record<string, HeaderFooterLayout>;
610
+ /** Gap between pages in pixels (for rendering). */
611
+ pageGap?: number;
612
+ };
484
613
 
485
614
  /**
486
615
  * Generic Plugin Interface for the DOCX Editor
@@ -711,6 +840,49 @@ interface PluginHostRef {
711
840
  refreshPluginStates: () => void;
712
841
  }
713
842
 
843
+ /**
844
+ * PagedEditor Component
845
+ *
846
+ * Main paginated editing component that integrates:
847
+ * - HiddenProseMirror: off-screen editor for keyboard input
848
+ * - Layout engine: computes page layout from PM state
849
+ * - DOM painter: renders pages to visible DOM
850
+ * - Selection overlay: renders caret and selection highlights
851
+ *
852
+ * Architecture:
853
+ * 1. User clicks on visible pages → hit test → update PM selection
854
+ * 2. User types → hidden PM receives input → PM transaction
855
+ * 3. PM transaction → convert to blocks → measure → layout → paint
856
+ * 4. Selection changes → compute rects → update overlay
857
+ */
858
+
859
+ interface PagedEditorRef {
860
+ /** Get the current document. */
861
+ getDocument(): Document | null;
862
+ /** Get the ProseMirror EditorState. */
863
+ getState(): EditorState | null;
864
+ /** Get the ProseMirror EditorView. */
865
+ getView(): EditorView | null;
866
+ /** Focus the editor. */
867
+ focus(): void;
868
+ /** Blur the editor. */
869
+ blur(): void;
870
+ /** Check if focused. */
871
+ isFocused(): boolean;
872
+ /** Dispatch a transaction. */
873
+ dispatch(tr: Transaction): void;
874
+ /** Undo. */
875
+ undo(): boolean;
876
+ /** Redo. */
877
+ redo(): boolean;
878
+ /** Set selection by PM position. */
879
+ setSelection(anchor: number, head?: number): void;
880
+ /** Get current layout. */
881
+ getLayout(): Layout | null;
882
+ /** Force re-layout. */
883
+ relayout(): void;
884
+ }
885
+
714
886
  /**
715
887
  * DocxEditor props
716
888
  */
@@ -787,12 +959,6 @@ interface DocxEditorProps {
787
959
  onCut?: () => void;
788
960
  /** Callback when content is pasted */
789
961
  onPaste?: () => void;
790
- /**
791
- * Use paginated editor mode (experimental).
792
- * When enabled, shows true paginated editing with visible page breaks.
793
- * When disabled (default), uses standard ProseMirror editor.
794
- */
795
- usePaginatedEditor?: boolean;
796
962
  /**
797
963
  * Callback when rendered DOM context is ready (for plugin overlays).
798
964
  * Used by PluginHost to get access to the rendered page DOM for positioning.
@@ -812,8 +978,8 @@ interface DocxEditorRef {
812
978
  getAgent: () => DocumentAgent | null;
813
979
  /** Get the current document */
814
980
  getDocument: () => Document | null;
815
- /** Get the ProseMirror editor ref */
816
- getEditorRef: () => ProseMirrorEditorRef | null;
981
+ /** Get the editor ref */
982
+ getEditorRef: () => PagedEditorRef | null;
817
983
  /** Save the document to buffer */
818
984
  save: () => Promise<ArrayBuffer | null>;
819
985
  /** Set zoom level */
@@ -1380,7 +1546,7 @@ interface DocumentViewerProps {
1380
1546
  /** Callback when page becomes visible */
1381
1547
  onPageVisible?: (pageNumber: number) => void;
1382
1548
  /** Callback when document is clicked */
1383
- onDocumentClick?: (e: React__default.MouseEvent, page: Page | null) => void;
1549
+ onDocumentClick?: (e: React__default.MouseEvent, page: Page$1 | null) => void;
1384
1550
  /** Additional CSS class name */
1385
1551
  className?: string;
1386
1552
  /** Additional inline styles */