ooxml-ui 1.8.5 → 1.10.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.
Files changed (167) hide show
  1. package/dist/{chunk-SNV6YKPC.js → chunk-HZSYGNNB.js} +2 -1
  2. package/dist/{chunk-SUHT5S2P.js → chunk-IXLJNVUD.js} +1 -1
  3. package/dist/{chunk-CTPXTRDT.js → chunk-WMGMZIMM.js} +1 -1
  4. package/dist/docx/columns-dialog.d.ts +1 -1
  5. package/dist/docx/editor-core.d.ts +2 -0
  6. package/dist/docx/page-controller.d.ts +3 -2
  7. package/dist/docx/print-border-width.d.ts +2 -0
  8. package/dist/docx/print-drag-scroll.d.ts +7 -0
  9. package/dist/docx/print-editing-geometry.d.ts +2 -0
  10. package/dist/docx/print-editing-index.d.ts +30 -0
  11. package/dist/docx/print-editing.d.ts +12 -0
  12. package/dist/docx/print-keyboard-navigation.d.ts +18 -0
  13. package/dist/docx/print-layout-view.d.ts +6 -10
  14. package/dist/docx/print-layout.d.ts +2 -2
  15. package/dist/docx/print-picture.d.ts +1 -0
  16. package/dist/docx/print-table.d.ts +1 -1
  17. package/dist/docx.js +770 -28
  18. package/dist/index.js +3 -3
  19. package/dist/pptx/ai/index.cjs +2 -2
  20. package/dist/pptx/ai/index.mjs +1 -1
  21. package/dist/pptx/{chunk-VRFNAF3Q.mjs → chunk-5AD3V3PA.mjs} +10 -0
  22. package/dist/pptx/{chunk-BPAA5FSB.mjs → chunk-6B3UUVRS.mjs} +1 -1
  23. package/dist/pptx/{chunk-W7LT3EOB.mjs → chunk-6NFW2AQA.mjs} +976 -498
  24. package/dist/pptx/chunk-EYPNQ3FG.cjs +59 -0
  25. package/dist/pptx/chunk-FFIYFHBO.mjs +55 -0
  26. package/dist/pptx/{chunk-HWW2UVUP.cjs → chunk-JRCK6CFI.cjs} +19 -9
  27. package/dist/pptx/{chunk-MKVKISFW.mjs → chunk-OBRLAW6C.mjs} +1 -1
  28. package/dist/pptx/{chunk-7EMTVQSC.cjs → chunk-OCNECNJS.cjs} +1104 -563
  29. package/dist/pptx/{chunk-Y4LTLCQP.cjs → chunk-OJFD3SHS.cjs} +26 -47
  30. package/dist/pptx/{chunk-7KPDES3X.mjs → chunk-PMURSMHH.mjs} +6 -35
  31. package/dist/pptx/{chunk-PKDISDDZ.cjs → chunk-TSSWTBJQ.cjs} +2 -2
  32. package/dist/pptx/{chunk-SABFKDRM.mjs → chunk-WFEN6SHA.mjs} +19 -10
  33. package/dist/pptx/{chunk-UEF4BFW4.cjs → chunk-XFQ2RD4I.cjs} +7 -7
  34. package/dist/pptx/{chunk-SM3CWDIQ.cjs → chunk-Y7CDPPMZ.cjs} +10 -0
  35. package/dist/pptx/dom/elements/image.d.ts.map +1 -1
  36. package/dist/pptx/dom/elements/text-shape.d.ts.map +1 -1
  37. package/dist/pptx/dom/index.cjs +244 -226
  38. package/dist/pptx/dom/index.mjs +47 -29
  39. package/dist/pptx/dom/load-presentation.d.ts +1 -0
  40. package/dist/pptx/dom/load-presentation.d.ts.map +1 -1
  41. package/dist/pptx/i18n/index.cjs +6 -6
  42. package/dist/pptx/i18n/index.mjs +1 -1
  43. package/dist/pptx/i18n/translations-en-galleries.d.ts.map +1 -1
  44. package/dist/pptx/i18n/translations-en.d.ts.map +1 -1
  45. package/dist/pptx/index.cjs +2928 -2812
  46. package/dist/pptx/index.mjs +7 -7
  47. package/dist/pptx/render/animation-after-effect-authoring.d.ts +1 -38
  48. package/dist/pptx/render/animation-after-effect-authoring.d.ts.map +1 -1
  49. package/dist/pptx/render/animation-after-effect.d.ts +2 -2
  50. package/dist/pptx/render/animation-after-effect.d.ts.map +1 -1
  51. package/dist/pptx/render/animation-authoring.cjs +39 -39
  52. package/dist/pptx/render/animation-authoring.d.ts +2 -11
  53. package/dist/pptx/render/animation-authoring.d.ts.map +1 -1
  54. package/dist/pptx/render/animation-authoring.mjs +1 -1
  55. package/dist/pptx/render/animation-opacity-playback.d.ts +9 -0
  56. package/dist/pptx/render/animation-opacity-playback.d.ts.map +1 -0
  57. package/dist/pptx/render/animation-opacity-style.d.ts +6 -0
  58. package/dist/pptx/render/animation-opacity-style.d.ts.map +1 -0
  59. package/dist/pptx/render/animation-playback-engine.d.ts +1 -1
  60. package/dist/pptx/render/animation-playback-engine.d.ts.map +1 -1
  61. package/dist/pptx/render/animation-playback-seek.d.ts.map +1 -1
  62. package/dist/pptx/render/animation-playback-steps.d.ts.map +1 -1
  63. package/dist/pptx/render/animation-timeline-engine.d.ts +4 -0
  64. package/dist/pptx/render/animation-timeline-engine.d.ts.map +1 -1
  65. package/dist/pptx/render/animation-timeline-group.d.ts +2 -0
  66. package/dist/pptx/render/animation-timeline-group.d.ts.map +1 -1
  67. package/dist/pptx/render/animation-timeline-regular-step.d.ts.map +1 -1
  68. package/dist/pptx/render/animation-timeline-rows.d.ts.map +1 -1
  69. package/dist/pptx/render/animation-timeline-sequence-builder.d.ts.map +1 -1
  70. package/dist/pptx/render/animation-timeline-step-effect.d.ts +2 -1
  71. package/dist/pptx/render/animation-timeline-step-effect.d.ts.map +1 -1
  72. package/dist/pptx/render/animation-timeline-step.d.ts +3 -1
  73. package/dist/pptx/render/animation-timeline-step.d.ts.map +1 -1
  74. package/dist/pptx/render/background-animation-layers.d.ts +12 -0
  75. package/dist/pptx/render/background-animation-layers.d.ts.map +1 -0
  76. package/dist/pptx/render/customization/customization-resolve-ribbon.d.ts.map +1 -1
  77. package/dist/pptx/render/customization/ribbon-control-catalog-tail.d.ts +6 -0
  78. package/dist/pptx/render/customization/ribbon-control-catalog-tail.d.ts.map +1 -1
  79. package/dist/pptx/render/customization/ribbon-control-catalog.d.ts +6 -0
  80. package/dist/pptx/render/customization/ribbon-control-catalog.d.ts.map +1 -1
  81. package/dist/pptx/render/field-context.d.ts +2 -0
  82. package/dist/pptx/render/field-context.d.ts.map +1 -1
  83. package/dist/pptx/render/find-replace.d.ts +1 -1
  84. package/dist/pptx/render/find-replace.d.ts.map +1 -1
  85. package/dist/pptx/render/font-family-update.d.ts +45 -0
  86. package/dist/pptx/render/font-family-update.d.ts.map +1 -0
  87. package/dist/pptx/render/format-painter.cjs +6 -6
  88. package/dist/pptx/render/format-painter.mjs +3 -3
  89. package/dist/pptx/render/index.d.ts +6 -0
  90. package/dist/pptx/render/index.d.ts.map +1 -1
  91. package/dist/pptx/render/inline-selection-utils.d.ts +2 -1
  92. package/dist/pptx/render/inline-selection-utils.d.ts.map +1 -1
  93. package/dist/pptx/render/inspector-helpers.cjs +17 -13
  94. package/dist/pptx/render/inspector-helpers.d.ts +8 -0
  95. package/dist/pptx/render/inspector-helpers.d.ts.map +1 -1
  96. package/dist/pptx/render/inspector-helpers.mjs +2 -2
  97. package/dist/pptx/render/inspector-number.d.ts +15 -0
  98. package/dist/pptx/render/inspector-number.d.ts.map +1 -0
  99. package/dist/pptx/render/picture-frame.d.ts +72 -0
  100. package/dist/pptx/render/picture-frame.d.ts.map +1 -0
  101. package/dist/pptx/render/ribbon-animations-state.cjs +6 -6
  102. package/dist/pptx/render/ribbon-animations-state.mjs +2 -2
  103. package/dist/pptx/render/ribbon-galleries/gallery-placements.d.ts +3 -3
  104. package/dist/pptx/render/ribbon-galleries/gallery-placements.d.ts.map +1 -1
  105. package/dist/pptx/render/ribbon-galleries/table-style-tile-svg.d.ts +21 -6
  106. package/dist/pptx/render/ribbon-galleries/table-style-tile-svg.d.ts.map +1 -1
  107. package/dist/pptx/render/ribbon-galleries/table-styles-gallery.d.ts +3 -1
  108. package/dist/pptx/render/ribbon-galleries/table-styles-gallery.d.ts.map +1 -1
  109. package/dist/pptx/render/ribbon-home-crop.d.ts +37 -0
  110. package/dist/pptx/render/ribbon-home-crop.d.ts.map +1 -0
  111. package/dist/pptx/render/ribbon-home-families-objects.d.ts +5 -2
  112. package/dist/pptx/render/ribbon-home-families-objects.d.ts.map +1 -1
  113. package/dist/pptx/render/ribbon-home-spec.d.ts +1 -1
  114. package/dist/pptx/render/ribbon-home-spec.d.ts.map +1 -1
  115. package/dist/pptx/render/ribbon-home-state-extras.d.ts.map +1 -1
  116. package/dist/pptx/render/ribbon-home-state.d.ts +1 -0
  117. package/dist/pptx/render/ribbon-home-state.d.ts.map +1 -1
  118. package/dist/pptx/render/share-session.d.ts.map +1 -1
  119. package/dist/pptx/render/slide-operations.d.ts +2 -1
  120. package/dist/pptx/render/slide-operations.d.ts.map +1 -1
  121. package/dist/pptx/render/slide-package-clipboard.d.ts +31 -0
  122. package/dist/pptx/render/slide-package-clipboard.d.ts.map +1 -0
  123. package/dist/pptx/render/slide-sorter-context-menu.d.ts +3 -5
  124. package/dist/pptx/render/slide-sorter-context-menu.d.ts.map +1 -1
  125. package/dist/pptx/render/slide-sorter-state.d.ts +8 -1
  126. package/dist/pptx/render/slide-sorter-state.d.ts.map +1 -1
  127. package/dist/pptx/render/text-block-style.d.ts.map +1 -1
  128. package/dist/pptx/render/text-field-substitution.d.ts +12 -0
  129. package/dist/pptx/render/text-field-substitution.d.ts.map +1 -1
  130. package/dist/pptx/render/text-style-update.d.ts.map +1 -1
  131. package/dist/pptx/render/update-text-segment-style.d.ts +7 -1
  132. package/dist/pptx/render/update-text-segment-style.d.ts.map +1 -1
  133. package/dist/pptx/web-components/index.d.ts +2 -0
  134. package/dist/pptx/web-components/index.d.ts.map +1 -1
  135. package/dist/pptx/web-components/ribbon-home-styles.d.ts +1 -1
  136. package/dist/pptx/web-components/ribbon-home-styles.d.ts.map +1 -1
  137. package/dist/pptx/web-components/ribbon-home.d.ts +2 -0
  138. package/dist/pptx/web-components/ribbon-home.d.ts.map +1 -1
  139. package/dist/pptx/web-components/slide-clipboard.d.ts +14 -0
  140. package/dist/pptx/web-components/slide-clipboard.d.ts.map +1 -0
  141. package/dist/{presentation-preview-HF3GZ2VD.js → presentation-preview-VIIU7E2S.js} +1 -1
  142. package/dist/teams.js +2 -2
  143. package/dist/visio/format-pane-fields.d.ts +2 -0
  144. package/dist/visio/page-setup-action.d.ts +1 -1
  145. package/dist/visio/page-setup-dialog-form.d.ts +1 -1
  146. package/dist/visio/ribbon-action.d.ts +1 -1
  147. package/dist/visio/viewer-accessibility.d.ts +17 -0
  148. package/dist/visio/viewer-insert-dialog.d.ts +2 -1
  149. package/dist/visio/viewer-review.d.ts +2 -0
  150. package/dist/visio.js +304 -14
  151. package/dist/xlsx/commands/pivots.d.ts +2 -0
  152. package/dist/xlsx/commands/sparklines.d.ts +2 -0
  153. package/dist/xlsx/dialogs/help-dialogs.d.ts +2 -2
  154. package/dist/xlsx/dialogs/page-header.d.ts +4 -0
  155. package/dist/xlsx/dialogs/page-setup-tabs.d.ts +6 -1
  156. package/dist/xlsx/dialogs/pivot-values.d.ts +10 -0
  157. package/dist/xlsx/dialogs/pivots.d.ts +2 -0
  158. package/dist/xlsx/dialogs/print-preview.d.ts +2 -0
  159. package/dist/xlsx/dialogs/sparklines.d.ts +4 -0
  160. package/dist/xlsx/print-cell.d.ts +4 -0
  161. package/dist/xlsx/print-header.d.ts +7 -0
  162. package/dist/xlsx/print-pages.d.ts +4 -0
  163. package/dist/xlsx/print.d.ts +4 -12
  164. package/dist/xlsx.js +1214 -288
  165. package/package.json +3 -3
  166. package/dist/pptx/chunk-CENGE3TZ.mjs +0 -10
  167. package/dist/pptx/chunk-OGJRSAGH.cjs +0 -12
package/dist/docx.js CHANGED
@@ -10,14 +10,14 @@ import './chunk-SPNWHKSR.js';
10
10
  import { normalizeLocale, SUPPORTED_OFFICE_LOCALES, interpolate } from 'ooxml-core/i18n';
11
11
  import { createDocument, saveDocx, sectionsFromLayout, sectionLayoutJson, sectionsOf, pageSizeOf, columnPreset, applyPageSetup, withSection, computeListLabels, numberNotesInOrder, tocEntries, tableOfFiguresInstruction, findTableOfContents, ensureListDefinition, resolveNumberingLevel, equalColumnDraft, readColumnDraft, PAGE_SIZE_OPTIONS, PAGE_SIZES, readPageSetup, isRunHiddenForReview, resolveTableStyleFormatting, resolveParagraphFormatting, displayListLabel, setTitlePage, setLineNumbering, setVerticalAlign, setPageNumbering, ST_NumberFormat, unequalColumnPreset, setColumns, setOrientation, setPageSize, setMargins, lineSpacingLabel, formatNoteNumber, reviewDocumentFormatting, reviewFormattingWarnings, listRevisions, plainText, tocHyperlinks, DEFAULT_TOC_INSTRUCTION, tocBookmarks, buildTableOfContents, tocCaptionLabel, isFieldLocked, twips as twips$1, signedTwips, formatListNumber, columnTextWidth, validColumnDraft, validatePageSetup, presetOf, LIGATURE_VALUES, isLigatures, reviewRunFormatting, resolveRunFormatting, reviewParagraphFormatting, resolveThemeColorReference, lineSpacingValue, isStHighlightColor, transformCase, DEFAULT_TABLE_BORDERS, parseLineSpacingValue, twipsAttr, twipsFromPixels, headingLevel, isValidLanguageTag, WORD, isHeadingListKind, fieldName, lineSpacingOptions, halfPointsFromPoints, changeColumnWidth, changeColumnGap, createListDefinition, linkStylesToList, headingListLevels, documentStats } from 'ooxml-core/docx';
12
12
  import { Schema, DOMSerializer, Fragment } from 'prosemirror-model';
13
- import { markSpecs, imageNodeSpec, fieldMarkerNodeSpec, noteReferenceNodeSpec, pageBreakNodeSpec, hardBreakNodeSpec, commentHistoryAttributes, tableCellStyle, tableStyle, createToggleFormat, expectDefined, paragraphBoxCss, themeToCssVars, lightTheme, darkTheme, normalizeThemeMode, applyThemeColors, refreshWordYjsPresence, normalizeRibbonActions, DirtyState, isWordYjsRemoteTransaction, REMOTE_TRANSACTION_META, repairCollaborativeDocumentIds, HEADER_FOOTER_INPUT, restoreSectionParts, commentThreadsFromDoc, restoreNoteParts, CollaborationClient, createCollaborationIdGenerator, WordYjsCollaboration, sectionPartsJson, NotePartsStep, notePartsJson, SectionPartsStep, fitZoomPercent, hasChangeAtCursor, hasAnyChange, commentIdsAtSelection, commentAnchors, countWords, fieldGuardPlugin, trackChangesPlugin, wordYjsPresencePlugin, chartNodeSpec, placementClass, removeCommentThread, removeCommentAnchor, deleteComment, updateCommentThreads, addComment, toggleTrackChanges, goToNextChange, goToPreviousChange, rejectAllChanges, acceptAllChanges, rejectChangeAtCursor, acceptChangeAtCursor, goToComment, appendInlineNode, sameJson, sameRuns, PARAGRAPH_KEEP_KEYS, paragraphFromAttrs, parseBordersJson, isNavigableHref, wordYjsPluginKey, setReviewRecordingPreferences, nodeNumbering, paragraphFormattingRevision, inlineNodeRun, formattingRevision, insertWordHardBreak, paragraphAttrs, resolveCellVisuals, themeDrawing, ribbonActionIdForLabel, removeWordLink, fieldResultRanges, wordLinkRangeAt, ligatureCss as ligatureCss$1, wordYjsRedo, wordYjsUndo, runToInlineNodes as runToInlineNodes$1, backstageFocus, applyRunFormattingPatch, clearDirectRunFormatting, applyWordLink, ligatureStyle, wordHighlightColors, swatchColor, cssBorderSide, deleteFieldSelection, resolveComment, replyToComment, CollaborationAuthority } from 'ooxml-core/docx/ui';
13
+ import { markSpecs, imageNodeSpec, fieldMarkerNodeSpec, noteReferenceNodeSpec, pageBreakNodeSpec, hardBreakNodeSpec, commentHistoryAttributes, tableCellStyle, tableStyle, createToggleFormat, expectDefined, paragraphBoxCss, themeToCssVars, lightTheme, darkTheme, normalizeThemeMode, applyThemeColors, refreshWordYjsPresence, normalizeRibbonActions, DirtyState, isWordYjsRemoteTransaction, REMOTE_TRANSACTION_META, repairCollaborativeDocumentIds, HEADER_FOOTER_INPUT, restoreSectionParts, commentThreadsFromDoc, restoreNoteParts, CollaborationClient, createCollaborationIdGenerator, WordYjsCollaboration, sectionPartsJson, NotePartsStep, notePartsJson, SectionPartsStep, fitZoomPercent, hasChangeAtCursor, hasAnyChange, commentIdsAtSelection, commentAnchors, countWords, fieldGuardPlugin, tableStructureGuardPlugin, trackChangesPlugin, wordYjsPresencePlugin, chartNodeSpec, placementClass, removeCommentThread, removeCommentAnchor, deleteComment, updateCommentThreads, addComment, toggleTrackChanges, goToNextChange, goToPreviousChange, rejectAllChanges, acceptAllChanges, rejectChangeAtCursor, acceptChangeAtCursor, goToComment, appendInlineNode, sameJson, sameRuns, PARAGRAPH_KEEP_KEYS, paragraphFromAttrs, parseBordersJson, isNavigableHref, wordYjsPluginKey, setReviewRecordingPreferences, nodeNumbering, paragraphFormattingRevision, inlineNodeRun, formattingRevision, insertWordHardBreak, paragraphAttrs, resolveCellVisuals, themeDrawing, ribbonActionIdForLabel, removeWordLink, fieldResultRanges, wordLinkRangeAt, ligatureCss as ligatureCss$1, wordYjsRedo, wordYjsUndo, runToInlineNodes as runToInlineNodes$1, backstageFocus, applyRunFormattingPatch, clearDirectRunFormatting, applyWordLink, ligatureStyle, wordHighlightColors, swatchColor, cssBorderSide, deleteFieldSelection, resolveComment, replyToComment, CollaborationAuthority } from 'ooxml-core/docx/ui';
14
14
  export { CollaborationAuthority, CollaborationClient, RIBBON_ACTION_IDS, RIBBON_ACTION_LABELS, createCollaborationIdGenerator, darkTheme, isRibbonActionId, lightTheme, normalizeRibbonActions, repairCollaborativeDocumentIds, themeToCssVars } from 'ooxml-core/docx/ui';
15
15
  import { parseOmml, convertOmmlToLatex, convertOmmlToMathMl } from 'ooxml-core/math';
16
16
  import { PluginKey, EditorState, Plugin, NodeSelection, TextSelection, Selection } from 'prosemirror-state';
17
17
  import { EditorView, Decoration, DecorationSet } from 'prosemirror-view';
18
18
  import { loadDocument } from 'ooxml-core/docx/load';
19
19
  import { closeHistory, undo, redo, history } from 'prosemirror-history';
20
- import { layoutDocumentModel, pageNumbers, createFakeMeasurer, ligatureCss, cssFontStack, pageNumberValues, sectionPageCounts, headerFooterForPage, tokenizeRun, paragraphFloats, floatPosition, placeTab, DEFAULT_FONT_SIZE_PT, fieldDisplayText } from 'ooxml-core/docx/layout';
20
+ import { layoutDocumentModel, pageNumbers, createFakeMeasurer, ligatureCss, cssFontStack, pageNumberValues, sectionPageCounts, headerFooterForPage, tokenizeRun, paragraphFloats, floatPosition, placeTab, cellVerticalOffset, DEFAULT_FONT_SIZE_PT, fieldDisplayText } from 'ooxml-core/docx/layout';
21
21
  import { sendableSteps, getVersion } from 'prosemirror-collab';
22
22
  import { sanitizeColor, sanitizeUserName, SequenceTracker, isValidId, classifyVersion, validateDisplayName } from 'ooxml-core/collab';
23
23
  import { keymap } from 'prosemirror-keymap';
@@ -11528,6 +11528,7 @@ function createDropCapDialog(getView) {
11528
11528
  function createColumnsDialog(host) {
11529
11529
  const element = createDialogShell("Columns", "dve-format-dialog");
11530
11530
  const count = numberInput(1, 45, 1);
11531
+ const footnoteCount = numberInput(0, 2147483647, 1);
11531
11532
  const gap = numberInput(0, 22, 0.01);
11532
11533
  const width = document.createElement("output");
11533
11534
  const equal = checkbox("Equal column width");
@@ -11544,6 +11545,7 @@ function createColumnsDialog(host) {
11544
11545
  fieldset(
11545
11546
  "Columns",
11546
11547
  labelled("Number of columns", count),
11548
+ labelled("Footnote columns (0 matches section)", footnoteCount),
11547
11549
  row2(labelled("Column width (inches)", width), labelled("Column spacing (inches)", gap)),
11548
11550
  equal.wrapper,
11549
11551
  separator.wrapper,
@@ -11565,7 +11567,7 @@ function createColumnsDialog(host) {
11565
11567
  const spacing = Math.round(Number(gap.value) * 1440);
11566
11568
  const size = (total() - spacing * (number - 1)) / number;
11567
11569
  width.value = equal.input.checked && Number.isFinite(size) ? (size / 1440).toFixed(3) : "\u2014";
11568
- const valid = validCount() && (equal.input.checked ? gap.value !== "" && Number.isFinite(spacing) && spacing >= 0 && spacing <= 31680 && size >= 720 : draft.widths.length === number && validColumnDraft(draft, total()) && controls.every((control) => control.width.value !== "" && control.gap.value !== ""));
11570
+ const valid = validCount() && footnoteCount.value !== "" && Number.isInteger(Number(footnoteCount.value)) && Number(footnoteCount.value) >= 0 && Number(footnoteCount.value) <= 2147483647 && (equal.input.checked ? gap.value !== "" && Number.isFinite(spacing) && spacing >= 0 && spacing <= 31680 && size >= 720 : draft.widths.length === number && validColumnDraft(draft, total()) && controls.every((control) => control.width.value !== "" && control.gap.value !== ""));
11569
11571
  message.textContent = valid ? "" : "Enter whole columns and spacing that leaves at least 0.5 inch for each column.";
11570
11572
  localizeElement(message, locale);
11571
11573
  ok.disabled = !valid;
@@ -11623,6 +11625,7 @@ function createColumnsDialog(host) {
11623
11625
  validate();
11624
11626
  });
11625
11627
  gap.addEventListener("input", validate);
11628
+ footnoteCount.addEventListener("input", validate);
11626
11629
  equal.input.addEventListener("change", () => {
11627
11630
  if (!equal.input.checked && validCount()) {
11628
11631
  draft = equalColumnDraft(total(), Number(count.value), Math.round(Number(gap.value) * 1440));
@@ -11650,7 +11653,8 @@ function createColumnsDialog(host) {
11650
11653
  widthTwips: twips$1(value),
11651
11654
  ...i < draft.widths.length - 1 ? { spacingTwips: twips$1(draft.gaps[i]) } : {}
11652
11655
  }))
11653
- }
11656
+ },
11657
+ ...source.footnoteColumns === void 0 && Number(footnoteCount.value) === 0 ? [] : [Number(footnoteCount.value)]
11654
11658
  );
11655
11659
  hide();
11656
11660
  };
@@ -11678,6 +11682,7 @@ function createColumnsDialog(host) {
11678
11682
  element.replaceChildren(...content);
11679
11683
  localizeDialog(element, locale);
11680
11684
  count.value = String(source.columns.count);
11685
+ footnoteCount.value = String(source.footnoteColumns ?? 0);
11681
11686
  gap.value = String((source.columns.spacingTwips ?? 720) / 1440);
11682
11687
  equal.input.checked = source.columns.equalWidth;
11683
11688
  separator.input.checked = Boolean(source.columns.separator);
@@ -15365,12 +15370,16 @@ var PageController = class {
15365
15370
  this.dispatchSections(applyPageSetup(model, currentSectionIndex(view, model), values2));
15366
15371
  }
15367
15372
  /** Layout > More Columns, recorded as one undoable section edit. */
15368
- applyColumns(columns) {
15373
+ applyColumns(columns, footnoteColumns) {
15369
15374
  const view = this.host.view();
15370
15375
  if (!view?.editable || !this.host.canEditOutsideBody()) return;
15371
15376
  const model = this.host.model();
15372
15377
  this.dispatchSections(
15373
- withSection(model, currentSectionIndex(view, model), (section3) => ({ ...section3, columns }))
15378
+ withSection(model, currentSectionIndex(view, model), (section3) => ({
15379
+ ...section3,
15380
+ columns,
15381
+ ...footnoteColumns === void 0 ? {} : { footnoteColumns }
15382
+ }))
15374
15383
  );
15375
15384
  }
15376
15385
  /** Layout > Line Numbers options, recorded as one undoable section edit. */
@@ -15528,13 +15537,14 @@ var PageController = class {
15528
15537
  select2.value = String(percent);
15529
15538
  this.host.statusBar()?.setZoom(percent);
15530
15539
  }
15531
- /** Switches between the continuous editing surface and the paginated Print Layout render. */
15540
+ /** Switches between continuous and paginated presentations of the existing editor. */
15532
15541
  setViewMode(mode) {
15533
15542
  this.viewMode = mode;
15534
15543
  const printLayout = this.host.printLayout();
15535
15544
  printLayout?.setActive(mode === "print");
15536
15545
  const paper = this.host.paper();
15537
- if (paper) paper.hidden = mode === "print";
15546
+ if (paper) paper.hidden = false;
15547
+ this.host.printEditing?.(mode === "print");
15538
15548
  paper?.parentElement?.toggleAttribute("data-print-view", mode === "print");
15539
15549
  const toolbar = this.host.toolbar();
15540
15550
  const select2 = toolbar && findLocalizedControl(toolbar, "Layout view");
@@ -16226,7 +16236,7 @@ var EditorCore = class {
16226
16236
  columns: {
16227
16237
  section: () => this.pages.currentSection(),
16228
16238
  canEdit: () => !this.readOnly && !this.collab.active,
16229
- apply: (columns) => this.pages.applyColumns(columns)
16239
+ apply: (columns, footnoteColumns) => this.pages.applyColumns(columns, footnoteColumns)
16230
16240
  }
16231
16241
  });
16232
16242
  this.imageMedia = new ImageMediaCache(
@@ -16264,6 +16274,7 @@ var EditorCore = class {
16264
16274
  toolbar: () => this.shell.toolbar,
16265
16275
  statusBar: () => this.shell.chrome?.statusBar,
16266
16276
  printLayout: () => this.shell.printLayout,
16277
+ printEditing: (active) => this.shell.printEditing?.setActive(active),
16267
16278
  refreshControls: () => this.refreshControls()
16268
16279
  });
16269
16280
  }
@@ -16374,7 +16385,10 @@ var EditorCore = class {
16374
16385
  const { searchPanel, printLayout, review, chrome, toolbar } = this.shell;
16375
16386
  searchPanel?.refresh();
16376
16387
  if (review?.commentsOpen) review.commentsPanel.refresh();
16377
- if (this.pages.viewMode === "print") printLayout?.refreshCurrentPage();
16388
+ if (this.pages.viewMode === "print") {
16389
+ printLayout?.refreshCurrentPage();
16390
+ this.shell.printEditing?.refresh();
16391
+ }
16378
16392
  const status = refreshEditorControls(
16379
16393
  toolbar,
16380
16394
  this.targetView(),
@@ -16432,7 +16446,7 @@ var ribbon_polish_default = "/* Ribbon polish: distinct pressed state and Word's
16432
16446
  var document_default = ".dve-revision-insert {\n color: var(--dve-revision-color, inherit);\n text-decoration: underline;\n text-decoration-color: var(--dve-revision-color, currentColor);\n}\n.dve-revision-delete {\n color: var(--dve-revision-color, inherit);\n text-decoration: line-through;\n text-decoration-color: var(--dve-revision-color, currentColor);\n}\n/* Moved text, like Word: green, double underline at the destination, double strike at the source. */\n.dve-revision-move {\n --dve-revision-color: #2e7d32;\n text-decoration-style: double;\n}\n.ProseMirror .dve-revision-hidden {\n /* Review visibility takes precedence over picture/equation node-view display rules. */\n display: none !important;\n}\n[data-review-display]:not([data-review-display='all']) .dve-revision-insert,\n[data-review-display]:not([data-review-display='all']) .dve-revision-delete {\n color: inherit;\n text-decoration: none;\n}\n[data-review-display]:not([data-review-display='all']) .dve-comment-range {\n background: transparent;\n}\n.dve-revision-format-markup {\n outline: 1px dotted currentColor;\n outline-offset: 2px;\n}\n.dve-comment-range {\n background: rgba(255, 212, 0, 0.28);\n}\n.dve-paper {\n box-sizing: border-box;\n position: relative;\n flex: none;\n margin: 0 auto;\n background: var(--dve-page-color, #fff);\n color: #202124;\n box-shadow:\n 0 1px 3px #20212430,\n 0 4px 12px #20212420;\n outline: none;\n /* Single spacing and no paragraph gap unless the document's styles set them, as in Word. */\n font:\n 11pt/1.2 Calibri,\n Carlito,\n Arial,\n sans-serif;\n zoom: var(--dve-zoom, 1);\n}\n.dve-paper p {\n min-height: 1.2em;\n margin: 0;\n white-space: pre-wrap;\n}\n.dve-paper p:last-child {\n margin-bottom: 0;\n}\n/* The caret marks focus in the document, as in Word; no ring around the editable area. */\n.dve-paper .ProseMirror:focus,\n.dve-paper .ProseMirror:focus-visible {\n outline: none;\n}\n.dve-paper:focus {\n box-shadow:\n 0 1px 3px #20212430,\n 0 4px 12px #20212420,\n 0 0 0 1px var(--blue);\n}\n/* Columns follow the table's grid and cell widths (equal when it has none), as Word lays them out;\n tables add no space around themselves. */\n.dve-paper table {\n width: 100%;\n table-layout: fixed;\n border-collapse: collapse;\n margin: 0;\n}\n.dve-paper td {\n min-width: 44px;\n border: var(--dve-cell-border, 1px dashed #c8c6c4);\n vertical-align: top;\n}\n.dve-paper td p {\n margin: 0;\n}\n.dve-paper p[data-list-label]::before {\n content: attr(data-list-label);\n white-space: pre;\n user-select: none;\n}\n.dve-paper p[data-list-marker]:not([data-list-marker=''])::before {\n content: attr(data-list-marker);\n position: absolute;\n left: var(--dve-marker-left);\n text-indent: 0;\n font-family: var(--dve-marker-family);\n font-size: var(--dve-marker-size);\n font-weight: var(--dve-marker-weight);\n font-style: var(--dve-marker-style);\n color: var(--dve-marker-color);\n}\n.multilingual-controls {\n flex: 1 1 100%;\n align-items: flex-start;\n gap: 9px 14px;\n}\n.multilingual-language-control {\n display: grid;\n grid-template-columns: minmax(145px, 180px);\n gap: 4px;\n color: var(--muted);\n font-size: 11px;\n}\n.multilingual-language-control select,\n.multilingual-language-control input {\n box-sizing: border-box;\n width: 180px;\n}\n.multilingual-language-control input {\n height: 26px;\n border: 1px solid var(--line);\n border-radius: 3px;\n background: var(--surface);\n padding: 0 7px;\n color: var(--ink);\n font:\n 11px 'Segoe UI',\n Arial,\n sans-serif;\n}\n.multilingual-note {\n align-self: end;\n max-width: 240px;\n color: var(--muted);\n font-size: 11px;\n}\n@media (max-width: 650px) {\n .ribbon-panel {\n min-height: 96px;\n padding: 6px;\n gap: 4px;\n }\n .ribbon-group {\n padding-right: 7px;\n }\n .ribbon-panel[data-panel='Home'] .ribbon-group[data-label='Font'] {\n width: 340px;\n }\n .ribbon-panel[data-panel='Home'] .ribbon-group[data-label='Paragraph'] {\n width: 280px;\n }\n .ribbon-panel[data-panel='Home'] .ribbon-group[data-label='Editing'] {\n width: auto;\n }\n .ribbon-group button {\n min-width: 34px;\n min-height: 34px;\n }\n .ribbon-group select {\n max-width: min(150px, 42vw);\n }\n .dve-canvas {\n padding: 18px 8px 38px;\n align-items: flex-start;\n }\n .ribbon-group select.font-family-select {\n width: 120px;\n max-width: 38vw;\n }\n .ribbon-group select.font-size-select {\n width: 56px;\n }\n .ribbon-group select.spacing-select {\n width: min(128px, 36vw);\n }\n .ribbon-group select.line-spacing-select {\n width: min(112px, 32vw);\n }\n}\n.dve-break-marker {\n display: block;\n margin: 0.4em 0;\n padding: 2px 0;\n border-top: 1px dashed var(--muted);\n border-bottom: 1px dashed var(--muted);\n color: var(--muted);\n font-size: 10px;\n text-align: center;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n user-select: none;\n}\n.dve-note-reference {\n color: var(--blue);\n cursor: default;\n}\n.dve-header,\n.dve-footer {\n box-sizing: border-box;\n width: 816px;\n max-width: 100%;\n margin: 0 auto;\n padding: 10px clamp(16px, 5vw, 70px);\n background: var(--surface);\n color: var(--muted);\n font:\n 10pt/1.35 Calibri,\n Arial,\n sans-serif;\n}\n.dve-header {\n border-bottom: 1px dashed var(--line);\n}\n.dve-footer {\n border-top: 1px dashed var(--line);\n}\n.dve-header-footer-label {\n margin-bottom: 2px;\n color: var(--muted);\n font-size: 10px;\n text-transform: uppercase;\n letter-spacing: 0.04em;\n}\n.dve-notes-container {\n box-sizing: border-box;\n width: 816px;\n max-width: 100%;\n margin: 12px auto 0;\n}\n.dve-notes {\n box-sizing: border-box;\n padding: 10px clamp(16px, 5vw, 70px);\n background: var(--surface);\n border-top: 1px solid var(--line);\n font:\n 10pt/1.35 Calibri,\n Arial,\n sans-serif;\n}\n.dve-notes-heading {\n margin: 0 0 6px;\n color: var(--ink);\n font-size: 12px;\n}\n.dve-note-list {\n margin: 0;\n padding: 0;\n list-style: none;\n}\n.dve-note-list li {\n display: flex;\n gap: 4px;\n align-items: baseline;\n margin-bottom: 4px;\n}\n.dve-note-marker {\n flex: none;\n color: var(--muted);\n}\n@media (prefers-reduced-motion: reduce) {\n * {\n scroll-behavior: auto !important;\n }\n}\n\n/* Print Layout: a read-only, paginated render kept beside the continuous\n editing surface (see print-layout.ts / print-layout-view.ts). */\n";
16433
16447
 
16434
16448
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/docx/styles/print.css?raw
16435
- var print_default = ".dve-print-pages {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 24px;\n margin: 0 auto;\n zoom: var(--dve-zoom, 1);\n}\n.dve-print-pages[hidden] {\n display: none;\n}\n.dve-print-page {\n position: relative;\n flex: none;\n background: var(--dve-page-color, #fff);\n color: #202124;\n box-shadow:\n 0 1px 3px #20212430,\n 0 4px 12px #20212420;\n overflow: hidden;\n}\n.dve-print-column {\n position: absolute;\n z-index: 1;\n}\n/* Floating pictures sit in front of text unless anchored behind it (wp:anchor/@behindDoc). */\n.dve-print-float {\n z-index: 2;\n}\n.dve-print-float-behind {\n z-index: 0;\n}\n.dve-print-picture-missing {\n box-sizing: border-box;\n border: 1px dashed #8a8886;\n background: #f3f2f1;\n}\n.dve-print-chart {\n overflow: hidden;\n background: #fff;\n}\n.dve-print-chart > svg {\n display: block;\n width: 100%;\n height: 100%;\n}\n.dve-print-chart-frame {\n display: grid;\n place-items: center;\n color: #605e5c;\n font-size: 11px;\n}\n.dve-print-block {\n position: absolute;\n left: 0;\n width: 100%;\n}\n.dve-print-line {\n position: absolute;\n left: 0;\n width: 100%;\n font:\n 11pt/1.2 Calibri,\n Arial,\n sans-serif;\n cursor: text;\n}\n.dve-print-line span {\n position: absolute;\n top: 0;\n}\n.dve-print-row {\n position: absolute;\n left: 0;\n width: 100%;\n}\n/* Cells sit at their grid positions; borders come from the document (Word prints no gridlines). */\n.dve-print-cell {\n position: absolute;\n top: 0;\n box-sizing: border-box;\n}\n.dve-print-cell-content {\n position: absolute;\n bottom: 0;\n}\n@media print {\n .dve-ribbon,\n .dve-status,\n .multilingual-controls {\n display: none !important;\n }\n .dve-canvas {\n overflow: visible !important;\n padding: 0 !important;\n }\n .dve-paper {\n display: none !important;\n }\n .dve-print-pages {\n gap: 0 !important;\n zoom: 1 !important;\n }\n .dve-print-page {\n /* Like Word, page colours are not printed unless asked for. */\n background: #fff !important;\n box-shadow: none !important;\n break-after: page;\n }\n}\n.dve-print-header,\n.dve-print-footer {\n position: absolute;\n color: var(--ink);\n font-size: 11pt;\n pointer-events: none;\n}\n.dve-print-header p,\n.dve-print-footer p {\n margin: 0;\n}\n.dve-print-header table,\n.dve-print-footer table {\n width: 100%;\n border-collapse: collapse;\n}\n\n/* Complex field begin/code/separate/end markers: kept in the document, never shown. */\n.dve-field-marker {\n display: inline;\n font-size: 0;\n}\n\n/* TOC entries link to hidden _Toc bookmarks; Word draws them in the entry's style, not as links. */\na.dve-link[data-anchor^='_Toc'] {\n color: inherit;\n text-decoration: none;\n}\n\n/* Tabs sized to Word's tab stops by tab-stops-view.ts; leaders fill the tab's width. */\n.dve-tab {\n display: inline-block;\n overflow: hidden;\n white-space: pre;\n vertical-align: baseline;\n text-indent: 0;\n}\n.dve-tab-leader-dot,\n.dve-tab-leader-middleDot {\n background-image: radial-gradient(circle, currentColor 0.8px, transparent 1.1px);\n background-size: 4px 4px;\n background-repeat: repeat-x;\n background-position: right 0 bottom 0.25em;\n}\n.dve-tab-leader-hyphen {\n background-image: linear-gradient(to right, currentColor 50%, transparent 50%);\n background-size: 6px 1px;\n background-repeat: repeat-x;\n background-position: right 0 bottom 0.4em;\n}\n.dve-tab-leader-underscore,\n.dve-tab-leader-heavy {\n border-bottom: 1px solid currentColor;\n}\n.dve-tab-leader-heavy {\n border-bottom-width: 2px;\n}\n\n/* Footnotes above the bottom margin; the separator is Word's 2-inch rule. */\n.dve-print-footnotes {\n position: absolute;\n z-index: 1;\n}\n.dve-print-footnote-separator {\n position: absolute;\n top: -7px;\n left: 0;\n width: 192px;\n border-top: 1px solid currentColor;\n}\n.dve-print-footnote {\n position: absolute;\n left: 0;\n width: 100%;\n}\n\n[data-print-view] .dve-notes-container {\n display: none;\n}\n\n/* Word draws superscript and subscript at about two thirds size without growing the line. */\n.dve-paper sup,\n.dve-paper sub {\n font-size: 0.65em;\n line-height: 0;\n}\n/* Exact-height rows clip content that does not fit, as Word does. */\n.dve-print-cell {\n overflow: hidden;\n}\n.dve-print-paragraph-frame {\n position: absolute;\n top: 0;\n box-sizing: border-box;\n}\n\n/* View > Multiple Pages: Print Layout's sheets sit side by side and wrap, instead of one column. */\n.dve-canvas[data-multipage] .dve-print-pages {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: center;\n}\n\n/* Layout > Line Numbers: numbers in the left margin, one per printed line. */\n.dve-print-line-number {\n position: absolute;\n width: 40px;\n text-align: right;\n font:\n 10px 'Segoe UI',\n Arial,\n sans-serif;\n color: #444;\n pointer-events: none;\n}\n";
16449
+ var print_default = ".dve-print-pages {\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 24px;\n margin: 0 auto;\n zoom: var(--dve-zoom, 1);\n}\n.dve-print-pages[hidden] {\n display: none;\n}\n.dve-print-page {\n position: relative;\n flex: none;\n background: var(--dve-page-color, #fff);\n color: #202124;\n box-shadow:\n 0 1px 3px #20212430,\n 0 4px 12px #20212420;\n overflow: hidden;\n}\n.dve-print-column {\n position: absolute;\n z-index: 1;\n}\n/* Floating pictures sit in front of text unless anchored behind it (wp:anchor/@behindDoc). */\n.dve-print-float {\n z-index: 2;\n}\n.dve-print-float-behind {\n z-index: 0;\n}\n.dve-print-picture-missing {\n box-sizing: border-box;\n border: 1px dashed #8a8886;\n background: #f3f2f1;\n}\n.dve-print-chart {\n overflow: hidden;\n background: #fff;\n}\n.dve-print-chart > svg {\n display: block;\n width: 100%;\n height: 100%;\n}\n.dve-print-chart-frame {\n display: grid;\n place-items: center;\n color: #605e5c;\n font-size: 11px;\n}\n.dve-print-block {\n position: absolute;\n left: 0;\n width: 100%;\n}\n.dve-print-line {\n position: absolute;\n left: 0;\n width: 100%;\n font:\n 11pt/1.2 Calibri,\n Arial,\n sans-serif;\n cursor: text;\n}\n.dve-print-line span {\n position: absolute;\n top: 0;\n}\n.dve-print-row {\n position: absolute;\n left: 0;\n width: 100%;\n}\n/* Cells sit at their grid positions; borders come from the document (Word prints no gridlines). */\n.dve-print-cell {\n position: absolute;\n top: 0;\n box-sizing: border-box;\n}\n.dve-print-cell-content {\n position: absolute;\n bottom: 0;\n}\n@media print {\n .dve-ribbon,\n .dve-status,\n .multilingual-controls {\n display: none !important;\n }\n .dve-canvas {\n overflow: visible !important;\n padding: 0 !important;\n }\n .dve-paper {\n display: none !important;\n }\n .dve-print-pages {\n gap: 0 !important;\n zoom: 1 !important;\n }\n .dve-print-page {\n /* Like Word, page colours are not printed unless asked for. */\n background: #fff !important;\n box-shadow: none !important;\n break-after: page;\n }\n}\n.dve-print-header,\n.dve-print-footer {\n position: absolute;\n color: var(--ink);\n font-size: 11pt;\n pointer-events: none;\n}\n.dve-print-header p,\n.dve-print-footer p {\n margin: 0;\n}\n.dve-print-header table,\n.dve-print-footer table {\n width: 100%;\n border-collapse: collapse;\n}\n\n/* Complex field begin/code/separate/end markers: kept in the document, never shown. */\n.dve-field-marker {\n display: inline;\n font-size: 0;\n}\n\n/* TOC entries link to hidden _Toc bookmarks; Word draws them in the entry's style, not as links. */\na.dve-link[data-anchor^='_Toc'] {\n color: inherit;\n text-decoration: none;\n}\n\n/* Tabs sized to Word's tab stops by tab-stops-view.ts; leaders fill the tab's width. */\n.dve-tab {\n display: inline-block;\n overflow: hidden;\n white-space: pre;\n vertical-align: baseline;\n text-indent: 0;\n}\n.dve-tab-leader-dot,\n.dve-tab-leader-middleDot {\n background-image: radial-gradient(circle, currentColor 0.8px, transparent 1.1px);\n background-size: 4px 4px;\n background-repeat: repeat-x;\n background-position: right 0 bottom 0.25em;\n}\n.dve-tab-leader-hyphen {\n background-image: linear-gradient(to right, currentColor 50%, transparent 50%);\n background-size: 6px 1px;\n background-repeat: repeat-x;\n background-position: right 0 bottom 0.4em;\n}\n.dve-tab-leader-underscore,\n.dve-tab-leader-heavy {\n border-bottom: 1px solid currentColor;\n}\n.dve-tab-leader-heavy {\n border-bottom-width: 2px;\n}\n\n/* Footnotes above the bottom margin; the separator is Word's 2-inch rule. */\n.dve-print-footnotes {\n position: absolute;\n z-index: 1;\n}\n.dve-print-footnote-separator {\n position: absolute;\n top: -7px;\n left: 0;\n width: 192px;\n border-top: 1px solid currentColor;\n}\n.dve-print-footnote-continuation-separator {\n width: 100%;\n}\n.dve-print-footnote {\n position: absolute;\n left: 0;\n width: 100%;\n}\n\n[data-print-view] .dve-notes-container {\n display: none;\n}\n\n/* Word draws superscript and subscript at about two thirds size without growing the line. */\n.dve-paper sup,\n.dve-paper sub {\n font-size: 0.65em;\n line-height: 0;\n}\n/* Exact-height rows clip content that does not fit, as Word does. */\n.dve-print-cell {\n overflow: hidden;\n}\n.dve-print-paragraph-frame {\n position: absolute;\n top: 0;\n box-sizing: border-box;\n}\n\n/* View > Multiple Pages: Print Layout's sheets sit side by side and wrap, instead of one column. */\n.dve-canvas[data-multipage] .dve-print-pages {\n flex-direction: row;\n flex-wrap: wrap;\n align-items: flex-start;\n justify-content: center;\n}\n\n/* Layout > Line Numbers: numbers in the left margin, one per printed line. */\n.dve-print-line-number {\n position: absolute;\n width: 40px;\n text-align: right;\n font:\n 10px 'Segoe UI',\n Arial,\n sans-serif;\n color: #444;\n pointer-events: none;\n}\n\n/* Native input stays mounted while page geometry supplies the visible selection. */\n.dve-paper.dve-print-input {\n position: fixed;\n top: 0;\n left: 0;\n margin: 0;\n opacity: 0;\n max-height: 1px;\n overflow: hidden;\n pointer-events: none;\n z-index: -1;\n}\n.dve-print-pages {\n position: relative;\n}\n.dve-print-selection-layer {\n position: absolute;\n inset: 0;\n pointer-events: none;\n z-index: 3;\n}\n.dve-print-caret,\n.dve-print-selection {\n position: absolute;\n pointer-events: none;\n}\n.dve-print-caret {\n background: currentColor;\n animation: dve-print-caret-blink 1s step-end infinite;\n}\n.dve-print-selection {\n background: Highlight;\n opacity: 0.3;\n}\n@keyframes dve-print-caret-blink {\n 50% {\n opacity: 0;\n }\n}\n@media print {\n .dve-print-input,\n .dve-print-selection-layer {\n display: none !important;\n }\n}\n";
16436
16450
 
16437
16451
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/docx/styles/chrome-titlebar.css?raw
16438
16452
  var chrome_titlebar_default = ".dve-frame {\n position: relative;\n border: 0;\n box-shadow: none;\n}\n.dve-icon {\n flex: none;\n}\n.dve-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n min-width: 28px;\n height: 28px;\n padding: 0 6px;\n border: 0;\n border-radius: 4px;\n background: none;\n color: inherit;\n cursor: pointer;\n}\n.dve-icon-button:hover:not(:disabled),\n.dve-icon-button[aria-pressed='true'] {\n background: var(--word-soft);\n}\n.dve-icon-button:disabled {\n opacity: 0.4;\n cursor: default;\n}\n\n/* Title bar: drawn by the shared office-ui-title-bar; these colour it. */\n.dve-titlebar {\n flex: none;\n --office-title-bar-height: 40px;\n --office-title-bar-background: var(--chrome);\n --office-title-bar-border: var(--line);\n --office-title-bar-mark-background: var(--word);\n --office-title-bar-mark-foreground: var(--dve-primary-foreground);\n}\n";
@@ -16817,7 +16831,45 @@ function createSearchPanel(options, initialLocale = "en") {
16817
16831
  };
16818
16832
  }
16819
16833
 
16820
- // src/docx/print-table.ts
16834
+ // src/docx/print-border-width.ts
16835
+ var widths = /* @__PURE__ */ new WeakMap();
16836
+ function measuredBorderWidth(css, fallback) {
16837
+ if (!css || fallback === 0) return 0;
16838
+ const view = document.defaultView;
16839
+ if (!view) return fallback;
16840
+ let cache = widths.get(document);
16841
+ if (!cache) {
16842
+ cache = /* @__PURE__ */ new Map();
16843
+ widths.set(document, cache);
16844
+ }
16845
+ const key2 = `${view.devicePixelRatio}|${css}`;
16846
+ const cached = cache.get(key2);
16847
+ if (cached !== void 0) return cached;
16848
+ const probe = document.createElement("span");
16849
+ probe.dataset.printBorderProbe = "true";
16850
+ probe.setAttribute("aria-hidden", "true");
16851
+ Object.assign(probe.style, {
16852
+ position: "fixed",
16853
+ visibility: "hidden",
16854
+ pointerEvents: "none",
16855
+ left: "-10000px",
16856
+ top: "0px",
16857
+ width: "0px",
16858
+ height: "0px",
16859
+ borderLeft: css
16860
+ });
16861
+ const parent = document.body ?? document.documentElement;
16862
+ if (!parent) return fallback;
16863
+ parent.append(probe);
16864
+ try {
16865
+ const actual = Number.parseFloat(view.getComputedStyle(probe).borderLeftWidth);
16866
+ const width = Number.isFinite(actual) ? actual : fallback;
16867
+ cache.set(key2, width);
16868
+ return width;
16869
+ } finally {
16870
+ probe.remove();
16871
+ }
16872
+ }
16821
16873
  var cssBorder = (border) => border ? `${border.widthPx}px ${border.style} ${border.color}` : "";
16822
16874
  function geometryOf(row3, index, widthPx) {
16823
16875
  const given = row3.geometry?.[index];
@@ -16836,6 +16888,7 @@ function renderTable(box2, columnWidthPx, renderParagraph) {
16836
16888
  table.className = "dve-print-block dve-print-table";
16837
16889
  table.style.top = `${box2.yPx}px`;
16838
16890
  table.style.height = `${box2.heightPx}px`;
16891
+ if (box2.widthPx !== void 0) table.style.width = `${box2.widthPx}px`;
16839
16892
  if (box2.xPx) table.style.left = `${box2.xPx}px`;
16840
16893
  box2.rows.forEach((row3, rowIndex) => {
16841
16894
  const rowEl = document.createElement("div");
@@ -16844,6 +16897,8 @@ function renderTable(box2, columnWidthPx, renderParagraph) {
16844
16897
  rowEl.style.height = `${row3.heightPx}px`;
16845
16898
  if (row3.repeated) rowEl.dataset.repeated = "true";
16846
16899
  const lastRow = rowIndex === box2.rows.length - 1;
16900
+ rowEl.style.isolation = "isolate";
16901
+ const frameLayers = [];
16847
16902
  row3.cells.forEach((paragraphs, cellIndex) => {
16848
16903
  const geometry = geometryOf(row3, cellIndex, columnWidthPx);
16849
16904
  const cell = document.createElement("div");
@@ -16861,17 +16916,61 @@ function renderTable(box2, columnWidthPx, renderParagraph) {
16861
16916
  if (lastRow) cell.style.borderBottom = cssBorder(borders?.bottom);
16862
16917
  const content = document.createElement("div");
16863
16918
  content.className = "dve-print-cell-content";
16864
- const free = Math.max(0, row3.heightPx - geometry.contentHeightPx);
16865
- const offset = geometry.verticalAlign === "center" ? free / 2 : geometry.verticalAlign === "bottom" ? free : 0;
16919
+ content.style.zIndex = "2";
16920
+ const offset = cellVerticalOffset(geometry, row3.heightPx);
16866
16921
  Object.assign(content.style, {
16867
- left: `${geometry.paddingLeftPx}px`,
16868
- right: `${geometry.paddingRightPx}px`,
16869
- top: `${offset}px`
16922
+ left: `${geometry.paddingLeftPx - (geometry.borderInsetsReserved ? measuredBorderWidth(cssBorder(borders?.left), borders?.left?.widthPx ?? 0) : 0)}px`,
16923
+ right: `${geometry.paddingRightPx - (geometry.borderInsetsReserved && cellIndex === row3.cells.length - 1 ? measuredBorderWidth(cssBorder(borders?.right), borders?.right?.widthPx ?? 0) : 0)}px`,
16924
+ top: `${offset - (geometry.borderInsetsReserved ? measuredBorderWidth(cssBorder(borders?.top), borders?.top?.widthPx ?? 0) : 0)}px`
16870
16925
  });
16871
- for (const paragraph2 of paragraphs) content.append(renderParagraph(paragraph2));
16926
+ const nestedTables = row3.cellTables?.[cellIndex] ?? [];
16927
+ if (nestedTables.length) {
16928
+ const layer = document.createElement("div");
16929
+ layer.className = "dve-print-cell-frame-layer";
16930
+ layer.setAttribute("aria-hidden", "true");
16931
+ Object.assign(layer.style, {
16932
+ position: "absolute",
16933
+ left: `${geometry.xPx}px`,
16934
+ top: "0px",
16935
+ width: `${geometry.widthPx}px`,
16936
+ height: `${row3.heightPx}px`,
16937
+ overflowX: "visible",
16938
+ overflowY: "clip",
16939
+ pointerEvents: "none",
16940
+ zIndex: "1"
16941
+ });
16942
+ if (!geometry.borderInsetsReserved) {
16943
+ layer.style.boxSizing = "border-box";
16944
+ layer.style.borderLeft = cssBorder(borders?.left);
16945
+ layer.style.borderTop = cssBorder(borders?.top);
16946
+ layer.style.borderLeftColor = "transparent";
16947
+ layer.style.borderTopColor = "transparent";
16948
+ }
16949
+ const origin = document.createElement("div");
16950
+ origin.className = "dve-print-cell-frame-origin";
16951
+ Object.assign(origin.style, {
16952
+ position: "absolute",
16953
+ left: `${geometry.paddingLeftPx}px`,
16954
+ top: `${offset}px`
16955
+ });
16956
+ for (const nested of nestedTables) {
16957
+ const frame = renderTable(nested, nested.widthPx ?? geometry.widthPx, () => null);
16958
+ frame.classList.add("dve-print-nested-table");
16959
+ frame.setAttribute("aria-hidden", "true");
16960
+ frame.style.pointerEvents = "none";
16961
+ origin.append(frame);
16962
+ }
16963
+ layer.append(origin);
16964
+ frameLayers.push(layer);
16965
+ }
16966
+ for (const paragraph2 of paragraphs) {
16967
+ const element = renderParagraph(paragraph2);
16968
+ if (element) content.append(element);
16969
+ }
16872
16970
  cell.append(content);
16873
16971
  rowEl.append(cell);
16874
16972
  });
16973
+ rowEl.append(...frameLayers);
16875
16974
  table.append(rowEl);
16876
16975
  });
16877
16976
  return table;
@@ -17013,6 +17112,17 @@ function chartElement(chart) {
17013
17112
  return element;
17014
17113
  }
17015
17114
  function pictureElement(object, pictureUrl) {
17115
+ if (object.noteSeparator) {
17116
+ const rule = document.createElement("span");
17117
+ rule.className = "dve-print-note-rule";
17118
+ Object.assign(rule.style, {
17119
+ position: "absolute",
17120
+ width: `${object.widthPx}px`,
17121
+ height: "1px",
17122
+ borderTop: "1px solid currentColor"
17123
+ });
17124
+ return rule;
17125
+ }
17016
17126
  if (object.chart) {
17017
17127
  const element2 = chartElement(object.chart);
17018
17128
  element2.classList.add("dve-print-picture");
@@ -17089,20 +17199,28 @@ function styleFragment(el, fragment) {
17089
17199
  function renderLine(line, blockId, hitboxes, pictureUrl) {
17090
17200
  const lineEl = document.createElement("div");
17091
17201
  lineEl.className = "dve-print-line";
17202
+ lineEl.dataset.blockId = blockId;
17203
+ lineEl.dataset.sourceStart = String(line.sourceStart);
17204
+ lineEl.dataset.sourceEnd = String(line.sourceEnd);
17092
17205
  lineEl.style.top = `${line.yPx}px`;
17093
17206
  lineEl.style.height = `${line.heightPx}px`;
17094
17207
  const fragments = [];
17095
17208
  for (const fragment of line.fragments) {
17096
17209
  if (fragment.object) {
17097
17210
  const picture = pictureElement(fragment.object, pictureUrl);
17211
+ if (fragment.color) picture.style.color = fragment.color;
17098
17212
  picture.style.left = `${fragment.xPx}px`;
17099
17213
  picture.style.top = `${fragment.topPx ?? 0}px`;
17214
+ picture.dataset.sourceStart = String(fragment.sourceStart ?? 0);
17215
+ picture.dataset.sourceEnd = String(fragment.sourceEnd ?? 0);
17100
17216
  lineEl.append(picture);
17101
17217
  fragments.push({ element: picture, fragment });
17102
17218
  continue;
17103
17219
  }
17104
17220
  if (fragment.leader) {
17105
17221
  const leader = leaderElement(fragment);
17222
+ leader.dataset.sourceStart = String(fragment.sourceStart ?? 0);
17223
+ leader.dataset.sourceEnd = String(fragment.sourceEnd ?? 0);
17106
17224
  lineEl.append(leader);
17107
17225
  fragments.push({ element: leader, fragment });
17108
17226
  continue;
@@ -17110,6 +17228,8 @@ function renderLine(line, blockId, hitboxes, pictureUrl) {
17110
17228
  if (!fragment.text && fragment.widthPx === 0) continue;
17111
17229
  const span = document.createElement("span");
17112
17230
  styleFragment(span, fragment);
17231
+ span.dataset.sourceStart = String(fragment.sourceStart ?? 0);
17232
+ span.dataset.sourceEnd = String(fragment.sourceEnd ?? 0);
17113
17233
  lineEl.append(span);
17114
17234
  fragments.push({ element: span, fragment });
17115
17235
  }
@@ -17144,6 +17264,12 @@ function renderBlock(box2, hitboxes, pictureUrl, columnWidthPx) {
17144
17264
  el.className = "dve-print-block";
17145
17265
  el.style.top = `${box2.yPx}px`;
17146
17266
  el.style.height = `${box2.heightPx}px`;
17267
+ if (box2.xPx !== void 0) el.style.left = `${box2.xPx}px`;
17268
+ if (box2.widthPx !== void 0) el.style.width = `${box2.widthPx}px`;
17269
+ if (box2.readOnly) {
17270
+ el.dataset.readOnly = "true";
17271
+ el.title = "Read-only nested table content";
17272
+ }
17147
17273
  if (box2.frame) el.append(paragraphFrame(box2.frame, box2.heightPx));
17148
17274
  for (const line of box2.lines) el.append(renderLine(line, box2.blockId, hitboxes, pictureUrl));
17149
17275
  return el;
@@ -17156,7 +17282,7 @@ function renderBlock(box2, hitboxes, pictureUrl, columnWidthPx) {
17156
17282
  }
17157
17283
  function footnoteArea(page2, hitboxes, pictureUrl) {
17158
17284
  const notes = page2.footnotes ?? [];
17159
- const heightPx = notes.reduce((sum, note) => sum + note.heightPx, 0);
17285
+ const heightPx = page2.footnoteHeightPx ?? notes.reduce((sum, note) => sum + note.heightPx, 0);
17160
17286
  const widthPx = page2.widthPx - page2.marginLeftPx - page2.marginRightPx;
17161
17287
  const area = document.createElement("div");
17162
17288
  area.className = "dve-print-footnotes";
@@ -17167,16 +17293,54 @@ function footnoteArea(page2, hitboxes, pictureUrl) {
17167
17293
  top: `${page2.heightPx - page2.marginBottomPx - heightPx}px`,
17168
17294
  height: `${heightPx}px`
17169
17295
  });
17170
- const separator = document.createElement("div");
17171
- separator.className = "dve-print-footnote-separator";
17172
- area.append(separator);
17296
+ const appendSeparator = (story, x, y, width, continued) => {
17297
+ const separator = document.createElement("div");
17298
+ if (story) {
17299
+ separator.className = "dve-print-custom-footnote-separator";
17300
+ Object.assign(separator.style, {
17301
+ position: "absolute",
17302
+ left: `${x}px`,
17303
+ top: `${y - story.heightPx}px`,
17304
+ width: `${width}px`,
17305
+ height: `${story.heightPx}px`
17306
+ });
17307
+ for (const paragraph2 of story.paragraphs)
17308
+ separator.append(renderBlock(paragraph2, [], pictureUrl, width));
17309
+ } else {
17310
+ separator.className = "dve-print-footnote-separator";
17311
+ if (continued) separator.classList.add("dve-print-footnote-continuation-separator");
17312
+ Object.assign(separator.style, {
17313
+ left: `${x}px`,
17314
+ top: `${y - 7}px`,
17315
+ width: `${continued ? width : Math.min(192, width)}px`
17316
+ });
17317
+ }
17318
+ area.append(separator);
17319
+ };
17320
+ if (page2.footnoteColumnAreas) {
17321
+ for (const column of page2.footnoteColumnAreas)
17322
+ appendSeparator(column.separator, column.xPx, column.yPx, column.widthPx, column.continued);
17323
+ } else
17324
+ appendSeparator(
17325
+ page2.footnoteSeparator,
17326
+ 0,
17327
+ 0,
17328
+ widthPx,
17329
+ notes.some((note) => note.continued)
17330
+ );
17173
17331
  for (const note of notes) {
17174
17332
  const noteEl = document.createElement("div");
17175
17333
  noteEl.className = "dve-print-footnote";
17176
17334
  noteEl.dataset.noteId = note.id;
17177
- Object.assign(noteEl.style, { top: `${note.yPx}px`, height: `${note.heightPx}px` });
17335
+ if (note.continued) noteEl.dataset.continued = "true";
17336
+ Object.assign(noteEl.style, {
17337
+ left: `${note.xPx ?? 0}px`,
17338
+ width: `${note.widthPx ?? widthPx}px`,
17339
+ top: `${note.yPx}px`,
17340
+ height: `${note.heightPx}px`
17341
+ });
17178
17342
  for (const paragraph2 of note.paragraphs)
17179
- noteEl.append(renderBlock(paragraph2, hitboxes, pictureUrl, widthPx));
17343
+ noteEl.append(renderBlock(paragraph2, hitboxes, pictureUrl, note.widthPx ?? widthPx));
17180
17344
  area.append(noteEl);
17181
17345
  }
17182
17346
  return area;
@@ -17268,7 +17432,7 @@ function renderPrintLayout(result, pictureUrl, options = {}) {
17268
17432
 
17269
17433
  // src/docx/print-layout-view.ts
17270
17434
  var RELAYOUT_DEBOUNCE_MS = 150;
17271
- function createPrintLayoutController(scrollContainer, onRequestCursor, pictureUrl, onLayout, getReviewMode = () => "all") {
17435
+ function createPrintLayoutController(scrollContainer, onRequestCursor, pictureUrl, onLayout, getReviewMode = () => "all", isEditing = () => false) {
17272
17436
  let measurer = createCanvasMeasurer();
17273
17437
  let lastModel = null;
17274
17438
  const fonts = typeof document === "undefined" ? void 0 : document.fonts;
@@ -17325,7 +17489,7 @@ function createPrintLayoutController(scrollContainer, onRequestCursor, pictureUr
17325
17489
  onLayout?.();
17326
17490
  }
17327
17491
  function onClick(event) {
17328
- if (!handle || !(event.target instanceof Element)) return;
17492
+ if (isEditing() || !handle || !(event.target instanceof Element)) return;
17329
17493
  const hit = handle.resolveClick(event.target, event.clientX);
17330
17494
  if (hit) onRequestCursor(hit.blockId, hit.offset);
17331
17495
  }
@@ -17350,6 +17514,7 @@ function createPrintLayoutController(scrollContainer, onRequestCursor, pictureUr
17350
17514
  }
17351
17515
  return {
17352
17516
  element,
17517
+ resolveClick: (target, clientX) => handle?.resolveClick(target, clientX) ?? null,
17353
17518
  setActive(active) {
17354
17519
  element.hidden = !active;
17355
17520
  },
@@ -17399,6 +17564,562 @@ function printLayoutResult(result, note) {
17399
17564
  window.print();
17400
17565
  style.remove();
17401
17566
  }
17567
+
17568
+ // src/docx/print-editing-geometry.ts
17569
+ function glyphRect(element, from2, to = from2) {
17570
+ const start = Number(element.dataset.sourceStart);
17571
+ const end = Number(element.dataset.sourceEnd);
17572
+ const text = element.firstChild;
17573
+ const box2 = element.getBoundingClientRect();
17574
+ if (text?.nodeType === Node.TEXT_NODE && end > start) {
17575
+ const length = text.textContent?.length ?? 0;
17576
+ const offset = (value) => Math.max(0, Math.min(length, Math.round((value - start) * length / (end - start))));
17577
+ const range = element.ownerDocument.createRange();
17578
+ range.setStart(text, offset(from2));
17579
+ range.setEnd(text, offset(to));
17580
+ if (typeof range.getBoundingClientRect === "function") {
17581
+ const measured = range.getBoundingClientRect();
17582
+ if (measured.height) return measured;
17583
+ }
17584
+ }
17585
+ const ratio = end > start ? Math.max(0, Math.min(1, (from2 - start) / (end - start))) : 0;
17586
+ const width = end > start ? box2.width * Math.max(0, Math.min(1, (to - from2) / (end - start))) : box2.width;
17587
+ return new DOMRect(box2.left + box2.width * ratio, box2.top, from2 === to ? 0 : width, box2.height);
17588
+ }
17589
+ function caretRect(line, offset) {
17590
+ const fragments = [...line.querySelectorAll("[data-source-start]")];
17591
+ const fragment = fragments.find(
17592
+ (el) => Number(el.dataset.sourceStart) <= offset && Number(el.dataset.sourceEnd) >= offset
17593
+ ) ?? fragments.at(-1);
17594
+ const rect = fragment ? glyphRect(fragment, offset) : line.getBoundingClientRect();
17595
+ const lineRect = line.getBoundingClientRect();
17596
+ return new DOMRect(fragment ? rect.left : lineRect.left, lineRect.top, 0, lineRect.height);
17597
+ }
17598
+
17599
+ // src/docx/print-keyboard-navigation.ts
17600
+ function printKeyboardNavigation(options) {
17601
+ const {
17602
+ active,
17603
+ getView,
17604
+ index,
17605
+ position,
17606
+ select: select2,
17607
+ resolveHit,
17608
+ scrollContainer,
17609
+ preferredPage,
17610
+ setPreferredPage
17611
+ } = options;
17612
+ let verticalX;
17613
+ return (event) => {
17614
+ const pageKey = event.key === "PageUp" || event.key === "PageDown";
17615
+ const boundaryKey = event.ctrlKey && (event.key === "Home" || event.key === "End");
17616
+ if (!active() || event.altKey || event.metaKey || event.ctrlKey && !pageKey && !boundaryKey || event.isComposing)
17617
+ return;
17618
+ const view = getView();
17619
+ if (!view || view.composing) return;
17620
+ if (boundaryKey) {
17621
+ index.update(view.state.doc);
17622
+ const boundary = (event.key === "Home" ? TextSelection.atStart(view.state.doc) : TextSelection.atEnd(view.state.doc)).head;
17623
+ const paragraph3 = index.at(boundary);
17624
+ if (paragraph3 && select2(paragraph3.id, boundary - paragraph3.start, event.shiftKey))
17625
+ event.preventDefault();
17626
+ return;
17627
+ }
17628
+ const keys2 = ["ArrowUp", "ArrowDown", "Home", "End", "PageUp", "PageDown"];
17629
+ if (!keys2.includes(event.key)) {
17630
+ verticalX = void 0;
17631
+ return;
17632
+ }
17633
+ index.update(view.state.doc);
17634
+ const head = view.state.selection.head;
17635
+ const paragraph2 = index.at(head);
17636
+ if (!paragraph2) return;
17637
+ const matches = index.block(paragraph2.id).filter(
17638
+ (line2) => head >= paragraph2.start + Number(line2.dataset.sourceStart) && head <= paragraph2.start + Number(line2.dataset.sourceEnd)
17639
+ );
17640
+ const line = matches.filter(
17641
+ (el) => el.closest(".dve-print-page")?.dataset.pageIndex === preferredPage()
17642
+ ).at(-1) ?? matches.at(-1);
17643
+ if (!line) return;
17644
+ let target = line;
17645
+ let offset;
17646
+ if (event.key === "Home" || event.key === "End") {
17647
+ verticalX = void 0;
17648
+ offset = event.key === "Home" ? Number(line.dataset.sourceStart) : Math.max(
17649
+ Number(line.dataset.sourceStart),
17650
+ ...[...line.querySelectorAll("[data-source-end]")].map(
17651
+ (fragment) => Number(fragment.dataset.sourceEnd)
17652
+ )
17653
+ );
17654
+ } else if (pageKey) {
17655
+ const direction = event.key === "PageUp" ? -1 : 1;
17656
+ verticalX ??= caretRect(line, head - paragraph2.start).left;
17657
+ if (event.ctrlKey) {
17658
+ target = index.pageStep(line, direction);
17659
+ offset = Number(target.dataset.sourceStart);
17660
+ } else {
17661
+ const viewport = scrollContainer.getBoundingClientRect(), caret = caretRect(line, head - paragraph2.start);
17662
+ const top = Math.max(0, viewport.top), bottom = Math.min(window.innerHeight, viewport.bottom);
17663
+ const y = event.shiftKey ? direction < 0 ? top + 1 : bottom - 1 : caret.top + direction * (bottom - top);
17664
+ target = index.nearest(verticalX, y) ?? line;
17665
+ offset = resolveHit(target, verticalX)?.offset ?? Number(target.dataset.sourceStart);
17666
+ if (!event.shiftKey) scrollContainer.scrollTop += direction * (bottom - top);
17667
+ }
17668
+ } else {
17669
+ const base = position(line.dataset.blockId, 0);
17670
+ verticalX ??= caretRect(line, head - base).left;
17671
+ target = index.adjacent(line, event.key === "ArrowUp" ? -1 : 1);
17672
+ offset = resolveHit(target, verticalX)?.offset ?? Number(target.dataset.sourceStart);
17673
+ }
17674
+ setPreferredPage(target.closest(".dve-print-page")?.dataset.pageIndex);
17675
+ if (select2(target.dataset.blockId, offset, event.shiftKey)) {
17676
+ event.preventDefault();
17677
+ target.scrollIntoView?.({ block: "nearest", inline: "nearest" });
17678
+ }
17679
+ };
17680
+ }
17681
+
17682
+ // src/docx/print-drag-scroll.ts
17683
+ function createPrintDragScroll(viewport, selectAt) {
17684
+ let frame, point, lastTime = 0, destroyed = false;
17685
+ function bounds() {
17686
+ const rect = viewport.getBoundingClientRect();
17687
+ return {
17688
+ left: rect.left,
17689
+ right: rect.right,
17690
+ top: Math.max(0, rect.top),
17691
+ bottom: Math.min(window.innerHeight, rect.bottom)
17692
+ };
17693
+ }
17694
+ function velocity(y, top, bottom) {
17695
+ const band = Math.min(32, (bottom - top) / 3);
17696
+ if (band <= 0) return 0;
17697
+ if (y < top + band) return -Math.min(24, 24 * (top + band - y) / band);
17698
+ if (y > bottom - band) return Math.min(24, 24 * (y - bottom + band) / band);
17699
+ return 0;
17700
+ }
17701
+ function tick(time) {
17702
+ frame = void 0;
17703
+ if (!point || destroyed) return;
17704
+ const box2 = bounds(), speed = velocity(point.y, box2.top, box2.bottom);
17705
+ if (!speed) return;
17706
+ const elapsed = lastTime ? Math.min(64, time - lastTime) : 16;
17707
+ lastTime = time;
17708
+ const old = viewport.scrollTop, max = Math.max(0, viewport.scrollHeight - viewport.clientHeight);
17709
+ viewport.scrollTop = Math.max(0, Math.min(max, old + speed * elapsed / 16));
17710
+ if (viewport.scrollTop === old) return;
17711
+ selectAt(
17712
+ Math.max(box2.left + 1, Math.min(box2.right - 1, point.x)),
17713
+ Math.max(box2.top + 1, Math.min(box2.bottom - 1, point.y))
17714
+ );
17715
+ frame = requestAnimationFrame(tick);
17716
+ }
17717
+ return {
17718
+ update(x, y) {
17719
+ if (destroyed) return;
17720
+ point = { x, y };
17721
+ const box2 = bounds();
17722
+ if (frame === void 0 && velocity(y, box2.top, box2.bottom)) {
17723
+ lastTime = 0;
17724
+ frame = requestAnimationFrame(tick);
17725
+ }
17726
+ },
17727
+ stop() {
17728
+ point = void 0;
17729
+ lastTime = 0;
17730
+ if (frame !== void 0) cancelAnimationFrame(frame);
17731
+ frame = void 0;
17732
+ },
17733
+ destroy() {
17734
+ this.stop();
17735
+ destroyed = true;
17736
+ }
17737
+ };
17738
+ }
17739
+
17740
+ // src/docx/print-editing-index.ts
17741
+ var PrintEditingIndex = class {
17742
+ constructor(pages) {
17743
+ this.pages = pages;
17744
+ }
17745
+ pages;
17746
+ doc;
17747
+ root;
17748
+ paragraphs = [];
17749
+ positions = /* @__PURE__ */ new Map();
17750
+ byBlock = /* @__PURE__ */ new Map();
17751
+ lines = [];
17752
+ renderedLines = [];
17753
+ pageLines = /* @__PURE__ */ new Map();
17754
+ linePositions = /* @__PURE__ */ new Map();
17755
+ update(doc) {
17756
+ const documentChanged = this.doc !== doc;
17757
+ if (documentChanged) {
17758
+ this.doc = doc;
17759
+ this.paragraphs = [];
17760
+ this.positions.clear();
17761
+ doc.descendants((node, pos) => {
17762
+ if (node.type.name !== "paragraph") return true;
17763
+ const paragraph2 = {
17764
+ id: String(node.attrs.id),
17765
+ start: pos + 1,
17766
+ end: pos + 1 + node.content.size
17767
+ };
17768
+ this.paragraphs.push(paragraph2);
17769
+ if (!this.positions.has(paragraph2.id)) this.positions.set(paragraph2.id, paragraph2);
17770
+ return false;
17771
+ });
17772
+ }
17773
+ const root = this.pages.firstElementChild;
17774
+ if (!documentChanged && root === this.root) return;
17775
+ if (root !== this.root)
17776
+ this.renderedLines = [
17777
+ ...this.pages.querySelectorAll(".dve-print-line[data-block-id]")
17778
+ ];
17779
+ this.root = root;
17780
+ this.byBlock.clear();
17781
+ this.pageLines.clear();
17782
+ this.linePositions.clear();
17783
+ this.lines = [];
17784
+ for (const line of this.renderedLines) {
17785
+ const id = line.dataset.blockId;
17786
+ if (!this.positions.has(id)) continue;
17787
+ const block = this.byBlock.get(id) ?? [];
17788
+ block.push(line);
17789
+ this.byBlock.set(id, block);
17790
+ const page2 = line.closest(".dve-print-page") ?? this.pages;
17791
+ const pageRows = this.pageLines.get(page2) ?? [];
17792
+ pageRows.push(line);
17793
+ this.pageLines.set(page2, pageRows);
17794
+ this.linePositions.set(line, this.lines.length);
17795
+ this.lines.push(line);
17796
+ }
17797
+ }
17798
+ position(id, offset) {
17799
+ const paragraph2 = this.positions.get(id);
17800
+ return paragraph2 ? paragraph2.start + Math.max(0, Math.min(offset, paragraph2.end - paragraph2.start)) : void 0;
17801
+ }
17802
+ firstEndingAtOrAfter(pos) {
17803
+ let low = 0, high = this.paragraphs.length;
17804
+ while (low < high) {
17805
+ const mid = low + high >>> 1;
17806
+ if (this.paragraphs[mid].end < pos) low = mid + 1;
17807
+ else high = mid;
17808
+ }
17809
+ return low;
17810
+ }
17811
+ *between(from2, to) {
17812
+ for (let i = this.firstEndingAtOrAfter(from2); i < this.paragraphs.length; i++) {
17813
+ const paragraph2 = this.paragraphs[i];
17814
+ if (paragraph2.start > to) break;
17815
+ yield paragraph2;
17816
+ }
17817
+ }
17818
+ at(pos) {
17819
+ const paragraph2 = this.paragraphs[this.firstEndingAtOrAfter(pos)];
17820
+ return paragraph2 && paragraph2.start <= pos ? paragraph2 : void 0;
17821
+ }
17822
+ block(id) {
17823
+ return this.byBlock.get(id) ?? [];
17824
+ }
17825
+ adjacent(line, direction) {
17826
+ return this.lines[(this.linePositions.get(line) ?? -1) + direction] ?? line;
17827
+ }
17828
+ pageStep(line, direction) {
17829
+ const page2 = line.closest(".dve-print-page") ?? this.pages;
17830
+ const pages = [...this.pageLines.keys()];
17831
+ return this.pageLines.get(pages[pages.indexOf(page2) + direction])?.[0] ?? line;
17832
+ }
17833
+ nearest(x, y) {
17834
+ const distance = (rect) => Math.hypot(
17835
+ Math.max(rect.left - x, x - rect.right, 0),
17836
+ Math.max(rect.top - y, y - rect.bottom, 0)
17837
+ );
17838
+ let bestPage, bestDistance = Infinity;
17839
+ for (const page2 of this.pageLines.keys()) {
17840
+ const score = distance(page2.getBoundingClientRect());
17841
+ if (score < bestDistance) {
17842
+ bestPage = page2;
17843
+ bestDistance = score;
17844
+ }
17845
+ }
17846
+ let best;
17847
+ bestDistance = Infinity;
17848
+ for (const line of this.pageLines.get(bestPage) ?? []) {
17849
+ const score = distance(line.getBoundingClientRect());
17850
+ if (score < bestDistance) {
17851
+ best = line;
17852
+ bestDistance = score;
17853
+ }
17854
+ }
17855
+ return best;
17856
+ }
17857
+ clear() {
17858
+ this.doc = void 0;
17859
+ this.root = void 0;
17860
+ this.paragraphs = [];
17861
+ this.positions.clear();
17862
+ this.pageLines.clear();
17863
+ this.byBlock.clear();
17864
+ this.lines = [];
17865
+ this.renderedLines = [];
17866
+ this.linePositions.clear();
17867
+ }
17868
+ };
17869
+ function createPrintEditingBridge(pages, paper, getView, resolveHit, scrollContainer = pages.parentElement ?? pages) {
17870
+ let active = false;
17871
+ let destroyed = false;
17872
+ const listeners = new AbortController();
17873
+ const index = new PrintEditingIndex(pages);
17874
+ const dragScroll = createPrintDragScroll(scrollContainer, extendAt);
17875
+ let nativeX = 0;
17876
+ let nativeY = 0;
17877
+ let dragging = false;
17878
+ let previousDoc;
17879
+ let previousHead = -1;
17880
+ let preferredPage;
17881
+ const overlay = document.createElement("div");
17882
+ overlay.className = "dve-print-selection-layer";
17883
+ overlay.setAttribute("aria-hidden", "true");
17884
+ let frame;
17885
+ function position(blockId, offset) {
17886
+ const view = getView();
17887
+ if (!view || view.isDestroyed || destroyed) return void 0;
17888
+ index.update(view.state.doc);
17889
+ return index.position(blockId, offset);
17890
+ }
17891
+ function addBox(rect, caret = false) {
17892
+ const parent = pages.getBoundingClientRect();
17893
+ const element = document.createElement("div");
17894
+ element.className = caret ? "dve-print-caret" : "dve-print-selection";
17895
+ const scale = pages.offsetWidth ? parent.width / pages.offsetWidth : 1;
17896
+ Object.assign(element.style, {
17897
+ left: `${(rect.left - parent.left) / (scale || 1)}px`,
17898
+ top: `${(rect.top - parent.top) / (scale || 1)}px`,
17899
+ width: `${caret ? 1 : rect.width / (scale || 1)}px`,
17900
+ height: `${rect.height / (scale || 1)}px`
17901
+ });
17902
+ overlay.append(element);
17903
+ return element;
17904
+ }
17905
+ function draw() {
17906
+ frame = void 0;
17907
+ overlay.replaceChildren();
17908
+ if (destroyed || !active || pages.hidden) return;
17909
+ const view = getView();
17910
+ if (!view || view.isDestroyed) return;
17911
+ if (!overlay.isConnected) pages.append(overlay);
17912
+ if (!view.dom.hasAttribute("tabindex")) {
17913
+ view.dom.tabIndex = 0;
17914
+ view.dom.dataset.printTabstop = "true";
17915
+ }
17916
+ const { from: from2, to, head, empty } = view.state.selection;
17917
+ let caret;
17918
+ index.update(view.state.doc);
17919
+ for (const { id, start, end } of index.between(from2, to)) {
17920
+ const block = index.block(id);
17921
+ if (head >= start && head <= end) {
17922
+ const offset = head - start;
17923
+ const candidates = block.filter(
17924
+ (el) => Number(el.dataset.sourceStart) <= offset && Number(el.dataset.sourceEnd) >= offset
17925
+ );
17926
+ const line = candidates.filter(
17927
+ (el) => el.closest(".dve-print-page")?.dataset.pageIndex === preferredPage
17928
+ ).at(-1) ?? candidates.at(-1);
17929
+ if (line) caret = caretRect(line, offset);
17930
+ }
17931
+ if (!empty && from2 <= end && to >= start) {
17932
+ for (const line of block) {
17933
+ const a = Math.max(from2 - start, Number(line.dataset.sourceStart));
17934
+ const b = Math.min(to - start, Number(line.dataset.sourceEnd));
17935
+ if (b <= a) continue;
17936
+ for (const fragment of line.querySelectorAll("[data-source-start]")) {
17937
+ const low = Math.max(a, Number(fragment.dataset.sourceStart));
17938
+ const high = Math.min(b, Number(fragment.dataset.sourceEnd));
17939
+ if (high > low) addBox(glyphRect(fragment, low, high));
17940
+ }
17941
+ }
17942
+ }
17943
+ }
17944
+ if (caret && view.hasFocus()) {
17945
+ const marker = addBox(caret, true);
17946
+ if (!empty) {
17947
+ marker.style.background = "transparent";
17948
+ marker.style.animation = "none";
17949
+ }
17950
+ if (!dragging && !view.composing && (previousDoc !== view.state.doc || previousHead !== head))
17951
+ marker.scrollIntoView?.({ block: "nearest", inline: "nearest" });
17952
+ previousDoc = view.state.doc;
17953
+ previousHead = head;
17954
+ if (!view.composing) {
17955
+ try {
17956
+ const source = view.coordsAtPos(head);
17957
+ const inputScale = paper.offsetWidth ? paper.getBoundingClientRect().width / paper.offsetWidth : 1;
17958
+ nativeX += (caret.left - source.left) / (inputScale || 1);
17959
+ nativeY += (caret.top - source.top) / (inputScale || 1);
17960
+ paper.style.translate = `${nativeX}px ${nativeY}px`;
17961
+ } catch {
17962
+ }
17963
+ }
17964
+ }
17965
+ }
17966
+ function refresh() {
17967
+ if (destroyed) return;
17968
+ if (frame !== void 0) cancelAnimationFrame(frame);
17969
+ frame = requestAnimationFrame(draw);
17970
+ }
17971
+ function select2(blockId, offset, extend = false) {
17972
+ const view = getView(), target = position(blockId, offset);
17973
+ if (!view || target === void 0) return false;
17974
+ view.dispatch(
17975
+ view.state.tr.setSelection(
17976
+ TextSelection.create(view.state.doc, extend ? view.state.selection.anchor : target, target)
17977
+ )
17978
+ );
17979
+ if (!view.dom.hasAttribute("tabindex")) {
17980
+ view.dom.tabIndex = 0;
17981
+ view.dom.dataset.printTabstop = "true";
17982
+ }
17983
+ view.focus();
17984
+ refresh();
17985
+ return true;
17986
+ }
17987
+ function hit(event) {
17988
+ const root = pages.getRootNode();
17989
+ const target = root.elementFromPoint?.(event.clientX, event.clientY);
17990
+ const line = target?.closest(".dve-print-line[data-block-id]");
17991
+ if (!line || !pages.contains(line)) return void 0;
17992
+ preferredPage = line.closest(".dve-print-page")?.dataset.pageIndex;
17993
+ return resolveHit(target, event.clientX) ?? void 0;
17994
+ }
17995
+ function extendAt(x, y) {
17996
+ const view = getView();
17997
+ if (!view || view.isDestroyed) return;
17998
+ index.update(view.state.doc);
17999
+ const line = index.nearest(x, y);
18000
+ if (!line) return;
18001
+ const target = resolveHit(line, x);
18002
+ if (!target) return;
18003
+ preferredPage = line.closest(".dve-print-page")?.dataset.pageIndex;
18004
+ select2(target.blockId, target.offset, true);
18005
+ }
18006
+ function move(event) {
18007
+ if (!dragging) return;
18008
+ extendAt(event.clientX, event.clientY);
18009
+ dragScroll.update(event.clientX, event.clientY);
18010
+ }
18011
+ function up() {
18012
+ dragging = false;
18013
+ dragScroll.stop();
18014
+ window.removeEventListener("pointermove", move);
18015
+ window.removeEventListener("pointerup", up);
18016
+ window.removeEventListener("pointercancel", up);
18017
+ window.removeEventListener("blur", up);
18018
+ }
18019
+ pages.addEventListener(
18020
+ "pointerdown",
18021
+ (event) => {
18022
+ if (!active || event.button !== 0) return;
18023
+ if (event.target instanceof Element && event.target.closest('[data-read-only="true"]')) {
18024
+ getView()?.dom.blur();
18025
+ return;
18026
+ }
18027
+ const target = hit(event);
18028
+ if (!target || !select2(target.blockId, target.offset, event.shiftKey)) return;
18029
+ event.preventDefault();
18030
+ dragging = true;
18031
+ window.addEventListener("pointermove", move);
18032
+ window.addEventListener("pointerup", up);
18033
+ window.addEventListener("pointercancel", up);
18034
+ window.addEventListener("blur", up);
18035
+ dragScroll.update(event.clientX, event.clientY);
18036
+ },
18037
+ { signal: listeners.signal }
18038
+ );
18039
+ paper.addEventListener(
18040
+ "keydown",
18041
+ printKeyboardNavigation({
18042
+ active: () => active,
18043
+ getView,
18044
+ index,
18045
+ position,
18046
+ select: select2,
18047
+ resolveHit,
18048
+ scrollContainer,
18049
+ preferredPage: () => preferredPage,
18050
+ setPreferredPage: (page2) => {
18051
+ preferredPage = page2;
18052
+ }
18053
+ }),
18054
+ { capture: true, signal: listeners.signal }
18055
+ );
18056
+ pages.addEventListener(
18057
+ "dblclick",
18058
+ (event) => {
18059
+ if (!active || !(event.target instanceof Element)) return;
18060
+ const target = resolveHit(event.target, event.clientX);
18061
+ const view = getView();
18062
+ const pos = target ? position(target.blockId, target.offset) : void 0;
18063
+ if (!view || pos === void 0) return;
18064
+ const resolved = view.state.doc.resolve(pos);
18065
+ const text = resolved.parent.textBetween(0, resolved.parent.content.size, "", "\uFFFC");
18066
+ const word = [...new Intl.Segmenter(void 0, { granularity: "word" }).segment(text)].find(
18067
+ (part) => part.isWordLike && resolved.parentOffset >= part.index && resolved.parentOffset <= part.index + part.segment.length
18068
+ );
18069
+ if (!word) return;
18070
+ view.dispatch(
18071
+ view.state.tr.setSelection(
18072
+ TextSelection.create(
18073
+ view.state.doc,
18074
+ resolved.start() + word.index,
18075
+ resolved.start() + word.index + word.segment.length
18076
+ )
18077
+ )
18078
+ );
18079
+ view.focus();
18080
+ refresh();
18081
+ event.preventDefault();
18082
+ },
18083
+ { signal: listeners.signal }
18084
+ );
18085
+ paper.addEventListener("focusin", refresh, { signal: listeners.signal });
18086
+ paper.addEventListener("focusout", refresh, { signal: listeners.signal });
18087
+ paper.addEventListener("compositionend", refresh, { signal: listeners.signal });
18088
+ return {
18089
+ setActive(value) {
18090
+ if (destroyed) return;
18091
+ active = value;
18092
+ paper.classList.toggle("dve-print-input", value);
18093
+ if (!value) {
18094
+ up();
18095
+ paper.style.translate = "";
18096
+ nativeX = 0;
18097
+ nativeY = 0;
18098
+ overlay.remove();
18099
+ const view = getView();
18100
+ if (view?.dom.dataset.printTabstop) {
18101
+ view.dom.removeAttribute("tabindex");
18102
+ delete view.dom.dataset.printTabstop;
18103
+ }
18104
+ }
18105
+ refresh();
18106
+ },
18107
+ destroy() {
18108
+ if (destroyed) return;
18109
+ this.setActive(false);
18110
+ destroyed = true;
18111
+ if (frame !== void 0) cancelAnimationFrame(frame);
18112
+ frame = void 0;
18113
+ up();
18114
+ listeners.abort();
18115
+ index.clear();
18116
+ dragScroll.destroy();
18117
+ previousDoc = void 0;
18118
+ },
18119
+ refresh,
18120
+ select: select2
18121
+ };
18122
+ }
17402
18123
  function moveCursorToBlock(view, blockId, offset) {
17403
18124
  let target;
17404
18125
  view.state.doc.descendants((node, pos) => {
@@ -20104,7 +20825,10 @@ function createChrome(core, api) {
20104
20825
  }
20105
20826
  function buildShell(core, api) {
20106
20827
  const { element, shell } = core;
20107
- if (shell.toolbar) return;
20828
+ if (shell.toolbar) {
20829
+ attachPrintEditing(core);
20830
+ return;
20831
+ }
20108
20832
  element.classList.add("dve-host");
20109
20833
  const root = element.attachShadow({ mode: "open" });
20110
20834
  const style = document.createElement("style");
@@ -20126,7 +20850,8 @@ function buildShell(core, api) {
20126
20850
  },
20127
20851
  (partName, contentType) => core.imageMedia.urlFor(partName, contentType),
20128
20852
  () => core.refreshControls(),
20129
- () => core.reviewDisplayMode
20853
+ () => core.reviewDisplayMode,
20854
+ () => core.pages.viewMode === "print"
20130
20855
  );
20131
20856
  canvas.append(printLayout.element);
20132
20857
  canvas.addEventListener("scroll", () => {
@@ -20202,6 +20927,7 @@ function buildShell(core, api) {
20202
20927
  if (core.pendingFileName) chrome.fileName = core.pendingFileName;
20203
20928
  root.append(style, frame);
20204
20929
  Object.assign(shell, { toolbar, canvas, paper });
20930
+ attachPrintEditing(core);
20205
20931
  applyRibbonAddIns(core);
20206
20932
  chrome.setLocale(core.locale);
20207
20933
  applyViewOptions(core);
@@ -20216,6 +20942,18 @@ function applyRibbonAddIns(core) {
20216
20942
  syncRibbonAddIns(toolbar, core.ribbonAddIns, { panelClass: "ribbon-panel" });
20217
20943
  if (toolbar.querySelector("[data-add-in]") !== before) refitRibbon(toolbar);
20218
20944
  }
20945
+ function attachPrintEditing(core) {
20946
+ const { shell } = core;
20947
+ if (shell.printEditing || !shell.printLayout || !shell.paper) return;
20948
+ shell.printEditing = createPrintEditingBridge(
20949
+ shell.printLayout.element,
20950
+ shell.paper,
20951
+ () => core.view,
20952
+ shell.printLayout.resolveClick,
20953
+ shell.canvas
20954
+ );
20955
+ shell.printEditing.setActive(core.pages.viewMode === "print");
20956
+ }
20219
20957
  var key = new PluginKey("dve-tab-stops");
20220
20958
  var MAX_PASSES = 4;
20221
20959
  var stopsOf = (paragraph2) => (paragraph2.attrs.tabStops ?? []).map((stop) => ({
@@ -20349,6 +21087,7 @@ function bodyPlugins(host) {
20349
21087
  noteNumberingPlugin(),
20350
21088
  sectionBreaksPlugin(),
20351
21089
  fieldGuardPlugin(),
21090
+ tableStructureGuardPlugin(),
20352
21091
  reviewRunMarksPlugin(() => host.reviewDisplayMode()),
20353
21092
  tabStopsPlugin(),
20354
21093
  keymap({
@@ -20478,6 +21217,7 @@ function renderDocument(core) {
20478
21217
  core.view = new EditorView(paper, {
20479
21218
  state,
20480
21219
  editable: () => core.canEditBody(),
21220
+ handleScrollToSelection: () => core.pages.viewMode === "print",
20481
21221
  dispatchTransaction(transaction) {
20482
21222
  const view = this;
20483
21223
  if (view.isDestroyed) return;
@@ -20812,6 +21552,8 @@ var DocxEditorElement = class extends DocxEditorApi {
20812
21552
  }
20813
21553
  disconnectedCallback() {
20814
21554
  const { core } = this;
21555
+ core.shell.printEditing?.destroy();
21556
+ delete core.shell.printEditing;
20815
21557
  core.collab.presence?.leave();
20816
21558
  core.detachedState = core.view?.state;
20817
21559
  core.view?.destroy();