ooxml-ui 1.22.0 → 1.23.1

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 (186) hide show
  1. package/dist/{chunk-REJECZGV.js → chunk-6RCASLEC.js} +1 -1
  2. package/dist/{chunk-DRBAJ5UO.js → chunk-FX6CF43K.js} +2 -1
  3. package/dist/chunk-HTIJ2EAA.js +364 -0
  4. package/dist/docx/backstage-pages.d.ts +5 -0
  5. package/dist/docx/backstage.d.ts +7 -0
  6. package/dist/docx/component.d.ts +1 -0
  7. package/dist/docx/context-menu.d.ts +6 -0
  8. package/dist/docx/customization-apply.d.ts +12 -0
  9. package/dist/docx/customization.d.ts +52 -0
  10. package/dist/docx/editor-chrome.d.ts +19 -0
  11. package/dist/docx/editor-core.d.ts +23 -1
  12. package/dist/docx/element-api.d.ts +18 -0
  13. package/dist/docx/events.d.ts +13 -2
  14. package/dist/docx/file-commands.d.ts +12 -6
  15. package/dist/docx/index.d.ts +3 -0
  16. package/dist/docx/keyboard.d.ts +2 -0
  17. package/dist/docx/shortcut-help.d.ts +2 -1
  18. package/dist/docx/title-bar.d.ts +2 -0
  19. package/dist/docx/view-options.d.ts +5 -0
  20. package/dist/docx.js +355 -108
  21. package/dist/embedding/host-backstage.d.ts +33 -0
  22. package/dist/embedding/host-menu.d.ts +33 -0
  23. package/dist/embedding/index.d.ts +3 -0
  24. package/dist/embedding/region-host.d.ts +38 -0
  25. package/dist/embedding/region-host.d.ts.map +1 -0
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.js +3 -3
  28. package/dist/parse-worker.js +3 -1
  29. package/dist/pptx/ai/index.cjs +4 -5
  30. package/dist/pptx/ai/index.mjs +2 -3
  31. package/dist/pptx/{chart-3d-view-scene-6LQRJAM3.mjs → chart-3d-view-scene-CDIMM5T3.mjs} +0 -1
  32. package/dist/pptx/{chart-3d-view-scene-FAKI4QKT.cjs → chart-3d-view-scene-RYL7F65H.cjs} +0 -1
  33. package/dist/pptx/{chat-history-idb-FJWHIDOK.cjs → chat-history-idb-PGLJPVOI.cjs} +2 -3
  34. package/dist/pptx/{chat-history-idb-XWRFLX2R.mjs → chat-history-idb-XXPB3Q4U.mjs} +1 -2
  35. package/dist/pptx/{chunk-C22MU5CA.cjs → chunk-43NFRLCD.cjs} +2 -2
  36. package/dist/pptx/{chunk-72NIN6QF.cjs → chunk-6DQCBVYA.cjs} +592 -7108
  37. package/dist/pptx/{chunk-3IN66FIL.mjs → chunk-72P6AWRA.mjs} +1 -1
  38. package/dist/pptx/{chunk-ANKJE2PT.mjs → chunk-7DIZOCO4.mjs} +5 -9
  39. package/dist/pptx/{chunk-G2LGZNTI.cjs → chunk-A5MANNJR.cjs} +1 -1
  40. package/dist/pptx/{chunk-T34B6TZT.cjs → chunk-B4GBGPNL.cjs} +35 -29
  41. package/dist/pptx/{chunk-75S3RTSS.mjs → chunk-B5FR65LB.mjs} +2 -2
  42. package/dist/pptx/{chunk-LLENQTWZ.mjs → chunk-LVDF75JU.mjs} +1 -1
  43. package/dist/pptx/{chunk-VGOIAVPA.mjs → chunk-M43GZY6N.mjs} +612 -7163
  44. package/dist/pptx/{chunk-W7CBPO77.cjs → chunk-ZO43VVWQ.cjs} +2 -2
  45. package/dist/pptx/dom/index.cjs +220 -221
  46. package/dist/pptx/dom/index.mjs +5 -6
  47. package/dist/pptx/export/canvas-color-fix.cjs +0 -1
  48. package/dist/pptx/export/canvas-color-fix.mjs +0 -1
  49. package/dist/pptx/export/handout-layout.cjs +0 -1
  50. package/dist/pptx/export/handout-layout.mjs +0 -1
  51. package/dist/pptx/export/handout-master-chrome.cjs +0 -1
  52. package/dist/pptx/export/handout-master-chrome.mjs +0 -1
  53. package/dist/pptx/export/html-escape.cjs +0 -1
  54. package/dist/pptx/export/html-escape.mjs +0 -1
  55. package/dist/pptx/export/html2canvas-clone.cjs +2 -3
  56. package/dist/pptx/export/html2canvas-clone.mjs +1 -2
  57. package/dist/pptx/export/index.d.ts +1 -0
  58. package/dist/pptx/export/index.d.ts.map +1 -1
  59. package/dist/pptx/export/pdf-page-size.cjs +0 -1
  60. package/dist/pptx/export/pdf-page-size.mjs +0 -1
  61. package/dist/pptx/export/presentation-save.d.ts +40 -0
  62. package/dist/pptx/export/presentation-save.d.ts.map +1 -0
  63. package/dist/pptx/export/print-document.cjs +0 -1
  64. package/dist/pptx/export/print-document.mjs +0 -1
  65. package/dist/pptx/export/video-plan.cjs +0 -1
  66. package/dist/pptx/export/video-plan.mjs +0 -1
  67. package/dist/pptx/i18n/index.cjs +0 -1
  68. package/dist/pptx/i18n/index.mjs +0 -1
  69. package/dist/pptx/index.cjs +3039 -2952
  70. package/dist/pptx/index.mjs +4 -5
  71. package/dist/pptx/loader/index.cjs +0 -1
  72. package/dist/pptx/loader/index.mjs +0 -1
  73. package/dist/pptx/render/account.d.ts +8 -3
  74. package/dist/pptx/render/account.d.ts.map +1 -1
  75. package/dist/pptx/render/animation-authoring.cjs +0 -1
  76. package/dist/pptx/render/animation-authoring.mjs +0 -1
  77. package/dist/pptx/render/animation-preset-labels.cjs +0 -1
  78. package/dist/pptx/render/animation-preset-labels.mjs +0 -1
  79. package/dist/pptx/render/autosave-host-store.d.ts +28 -0
  80. package/dist/pptx/render/autosave-host-store.d.ts.map +1 -0
  81. package/dist/pptx/render/autosave-maintenance.d.ts +18 -0
  82. package/dist/pptx/render/autosave-maintenance.d.ts.map +1 -0
  83. package/dist/pptx/render/autosave-recovery.d.ts +5 -3
  84. package/dist/pptx/render/autosave-recovery.d.ts.map +1 -1
  85. package/dist/pptx/render/autosave-store.d.ts +9 -11
  86. package/dist/pptx/render/autosave-store.d.ts.map +1 -1
  87. package/dist/pptx/render/backstage.d.ts +3 -2
  88. package/dist/pptx/render/backstage.d.ts.map +1 -1
  89. package/dist/pptx/render/chart-combo-stock.cjs +0 -1
  90. package/dist/pptx/render/chart-combo-stock.mjs +0 -1
  91. package/dist/pptx/render/chart-overlays.cjs +0 -1
  92. package/dist/pptx/render/chart-overlays.mjs +0 -1
  93. package/dist/pptx/render/chart-surface-treemap.cjs +0 -1
  94. package/dist/pptx/render/chart-surface-treemap.mjs +0 -1
  95. package/dist/pptx/render/chart-view-model.cjs +0 -1
  96. package/dist/pptx/render/chart-view-model.mjs +0 -1
  97. package/dist/pptx/render/chart-waterfall-map.cjs +0 -1
  98. package/dist/pptx/render/chart-waterfall-map.mjs +0 -1
  99. package/dist/pptx/render/content-part-strokes.cjs +0 -1
  100. package/dist/pptx/render/content-part-strokes.mjs +0 -1
  101. package/dist/pptx/render/context-menu-target.cjs +0 -1
  102. package/dist/pptx/render/context-menu-target.mjs +0 -1
  103. package/dist/pptx/render/custom-fonts.cjs +0 -1
  104. package/dist/pptx/render/custom-fonts.mjs +0 -1
  105. package/dist/pptx/render/customization/customization-regions.d.ts +15 -32
  106. package/dist/pptx/render/customization/customization-regions.d.ts.map +1 -1
  107. package/dist/pptx/render/customization/customization-surfaces.d.ts.map +1 -1
  108. package/dist/pptx/render/customization/customization-types.d.ts +3 -2
  109. package/dist/pptx/render/customization/customization-types.d.ts.map +1 -1
  110. package/dist/pptx/render/customization/host-menu-commands.d.ts +6 -25
  111. package/dist/pptx/render/customization/host-menu-commands.d.ts.map +1 -1
  112. package/dist/pptx/render/element-hit-test.cjs +0 -1
  113. package/dist/pptx/render/element-hit-test.mjs +0 -1
  114. package/dist/pptx/render/font-catalog.cjs +0 -1
  115. package/dist/pptx/render/font-catalog.mjs +0 -1
  116. package/dist/pptx/render/format-painter.cjs +5 -6
  117. package/dist/pptx/render/format-painter.mjs +2 -3
  118. package/dist/pptx/render/hyperlink-security.cjs +0 -1
  119. package/dist/pptx/render/hyperlink-security.mjs +0 -1
  120. package/dist/pptx/render/image-file-insertion.cjs +0 -1
  121. package/dist/pptx/render/image-file-insertion.mjs +0 -1
  122. package/dist/pptx/render/index.d.ts +3 -0
  123. package/dist/pptx/render/index.d.ts.map +1 -1
  124. package/dist/pptx/render/ink-rendering.cjs +0 -1
  125. package/dist/pptx/render/ink-rendering.mjs +0 -1
  126. package/dist/pptx/render/inspector-helpers.cjs +13 -14
  127. package/dist/pptx/render/inspector-helpers.mjs +1 -2
  128. package/dist/pptx/render/layout-gallery.cjs +0 -1
  129. package/dist/pptx/render/layout-gallery.mjs +0 -1
  130. package/dist/pptx/render/layout-preview.cjs +0 -1
  131. package/dist/pptx/render/layout-preview.mjs +0 -1
  132. package/dist/pptx/render/model3d-scene.cjs +0 -1
  133. package/dist/pptx/render/model3d-scene.mjs +0 -1
  134. package/dist/pptx/render/paragraph-geometry-overrides.d.ts +2 -1
  135. package/dist/pptx/render/paragraph-geometry-overrides.d.ts.map +1 -1
  136. package/dist/pptx/render/presentation-print-settings.cjs +0 -1
  137. package/dist/pptx/render/presentation-print-settings.mjs +0 -1
  138. package/dist/pptx/render/remap-text.cjs +0 -1
  139. package/dist/pptx/render/remap-text.mjs +0 -1
  140. package/dist/pptx/render/ribbon-animations-state.cjs +0 -1
  141. package/dist/pptx/render/ribbon-animations-state.mjs +0 -1
  142. package/dist/pptx/render/session-restore.d.ts +4 -2
  143. package/dist/pptx/render/session-restore.d.ts.map +1 -1
  144. package/dist/pptx/render/text-case-transform.cjs +0 -1
  145. package/dist/pptx/render/text-case-transform.mjs +0 -1
  146. package/dist/pptx/render/text-style-scope.d.ts +2 -1
  147. package/dist/pptx/render/text-style-scope.d.ts.map +1 -1
  148. package/dist/pptx/render/viewer-event-payloads.d.ts +21 -0
  149. package/dist/pptx/render/viewer-event-payloads.d.ts.map +1 -0
  150. package/dist/pptx/render/viewer-props-manifest.d.ts.map +1 -1
  151. package/dist/pptx/render/viewport-size.d.ts +85 -0
  152. package/dist/pptx/render/viewport-size.d.ts.map +1 -0
  153. package/dist/pptx/theme/index.cjs +0 -1
  154. package/dist/pptx/theme/index.mjs +0 -1
  155. package/dist/pptx/{view-scene-CKYHS2OP.cjs → view-scene-4ZFUCP6S.cjs} +0 -1
  156. package/dist/pptx/{view-scene-BSTOVMHA.mjs → view-scene-GHBN7QMR.mjs} +0 -1
  157. package/dist/teams.js +1 -1
  158. package/dist/visio/controller.d.ts +11 -0
  159. package/dist/visio/index.d.ts +2 -0
  160. package/dist/visio/viewer-autorecover.d.ts +10 -2
  161. package/dist/visio/viewer-backstage.d.ts +23 -0
  162. package/dist/visio/viewer-commands.d.ts +2 -0
  163. package/dist/visio/viewer-context-menu.d.ts +3 -1
  164. package/dist/visio/viewer-customization.d.ts +42 -0
  165. package/dist/visio/viewer-element.d.ts +25 -0
  166. package/dist/visio/viewer-file-commands.d.ts +12 -0
  167. package/dist/visio/worker-parser.d.ts +9 -1
  168. package/dist/visio.js +351 -37
  169. package/dist/xlsx/backstage/index.d.ts +4 -0
  170. package/dist/xlsx/backstage/parts.d.ts +6 -0
  171. package/dist/xlsx/collaboration.d.ts +2 -1
  172. package/dist/xlsx/component.d.ts +9 -1
  173. package/dist/xlsx/context-menu/hidden.d.ts +9 -0
  174. package/dist/xlsx/context-menu/menu.d.ts +7 -1
  175. package/dist/xlsx/customization.d.ts +27 -0
  176. package/dist/xlsx/editor-core.d.ts +22 -0
  177. package/dist/xlsx/editor-files.d.ts +2 -4
  178. package/dist/xlsx/element-api.d.ts +10 -0
  179. package/dist/xlsx/events.d.ts +13 -7
  180. package/dist/xlsx/file-commands.d.ts +0 -5
  181. package/dist/xlsx/index.d.ts +2 -0
  182. package/dist/xlsx.js +245 -48
  183. package/package.json +3 -2
  184. package/dist/chunk-C7B7TJ2J.js +0 -112
  185. package/dist/pptx/chunk-MF3JURQN.cjs +0 -22
  186. package/dist/pptx/chunk-U5DDQYSF.mjs +0 -19
package/dist/docx.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { statusLayout, watchStatusWidth, compactPageText } from './chunk-UBBC5FH7.js';
2
- import { syncRibbonAddIns } from './chunk-C7B7TJ2J.js';
3
- export { RIBBON_ADD_IN_EVENT } from './chunk-C7B7TJ2J.js';
2
+ import { syncRibbonAddIns, createHostBackstagePages, withHostMenuItems } from './chunk-HTIJ2EAA.js';
3
+ export { RIBBON_ADD_IN_EVENT } from './chunk-HTIJ2EAA.js';
4
4
  import { defineSmartArt } from './chunk-QBXYGKPB.js';
5
5
  import { legacyThemeAliases, legacyThemeBridge, installOfficeUiThemeFor } from './chunk-T5ARELU2.js';
6
6
  import { createRibbonOverflow, defineRibbon, defineRuler, defineCommentsPane, defineDialog, defineSearchField, defineSwitch, defineTitleBar, defineRibbonActions, defineBackstage, defineStatusBar, defineZoomSlider, defineContextMenu, defineColorGrid, runKeyTips, defineOptionsDialog, assignKeyTips, optionsLabels, userInterfaceSection, personalizeSection, optionText, unavailableCategory } from './chunk-TJ245GDD.js';
@@ -9,8 +9,8 @@ import './chunk-YZH2QS7J.js';
9
9
  import './chunk-QLHCGV4C.js';
10
10
  import './chunk-XL77FR4B.js';
11
11
  import { optionStrings, normalizeLocale, SUPPORTED_OFFICE_LOCALES, interpolate } from 'ooxml-core/i18n';
12
- import { markSpecs, imageNodeSpec, fieldMarkerNodeSpec, noteReferenceNodeSpec, pageBreakNodeSpec, hardBreakNodeSpec, commentHistoryAttributes, tableCellStyle, tableStyle, createToggleFormat, expectDefined, controlFromData, paragraphBoxCss, normalizeThemeMode, applyThemeColors, refreshWordYjsPresence, normalizeRibbonActions, DirtyState, isFormsProtected, isWordYjsRemoteTransaction, REMOTE_TRANSACTION_META, repairCollaborativeDocumentIds, HEADER_FOOTER_INPUT, wordYjsPluginKey, wordYjsRedo, wordYjsUndo, documentWordCount, restoreSectionParts, commentThreadsFromDoc, restoreNoteParts, CollaborationClient, createCollaborationIdGenerator, WordYjsCollaboration, insertContentControl, sectionPartsJson, NotePartsStep, notePartsJson, SectionPartsStep, fitZoomPercent, hasChangeAtCursor, hasAnyChange, commentIdsAtSelection, commentAnchors, fieldGuardPlugin, tableStructureGuardPlugin, contentControlPlugin, formFieldGuardPlugin, symbolFontPlugin, positionalTabInputPlugin, 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, setReviewRecordingPreferences, nodeNumbering, controlAtSelection, paragraphFormattingRevision, inlineNodeRun, formattingRevision, insertWordHardBreak, paragraphAttrs, resolveCellVisuals, themeDrawing, ribbonActionIdForLabel, removeWordLink, fieldResultRanges, wordLinkRangeAt, ligatureCss as ligatureCss$1, toggleCheckboxControl, formFieldBeside, formFieldOfNode, formFieldLocked, toggleFormCheckboxAt, runToInlineNodes as runToInlineNodes$1, insertedTextMarks, backstageFocus, applyRunFormattingPatch, clearDirectRunFormatting, applyWordLink, deleteFieldSelection, emptySimpleFieldResult, ligatureStyle, wordHighlightColors, swatchColor, cssBorderSide, countWords, chooseListItem, chooseDate, selectFormDropDownAt, updateControlProperties, resolveComment, replyToComment, CollaborationAuthority } from 'ooxml-core/docx/ui';
13
- export { CollaborationAuthority, CollaborationClient, RIBBON_ACTION_IDS, RIBBON_ACTION_LABELS, createCollaborationIdGenerator, darkTheme, isRibbonActionId, lightTheme, normalizeRibbonActions, repairCollaborativeDocumentIds, themeToCssVars } from 'ooxml-core/docx/ui';
12
+ import { markSpecs, imageNodeSpec, fieldMarkerNodeSpec, noteReferenceNodeSpec, pageBreakNodeSpec, hardBreakNodeSpec, commentHistoryAttributes, tableCellStyle, tableStyle, createToggleFormat, expectDefined, controlFromData, paragraphBoxCss, WORD_CAPABILITY_ACTIONS, normalizeThemeMode, applyThemeColors, refreshWordYjsPresence, normalizeRibbonActions, DirtyState, isFormsProtected, isWordYjsRemoteTransaction, REMOTE_TRANSACTION_META, repairCollaborativeDocumentIds, HEADER_FOOTER_INPUT, wordYjsPluginKey, wordYjsRedo, wordYjsUndo, documentWordCount, restoreSectionParts, commentThreadsFromDoc, restoreNoteParts, CollaborationClient, createCollaborationIdGenerator, WordYjsCollaboration, insertContentControl, sectionPartsJson, NotePartsStep, notePartsJson, SectionPartsStep, fitZoomPercent, hasChangeAtCursor, hasAnyChange, commentIdsAtSelection, commentAnchors, fieldGuardPlugin, tableStructureGuardPlugin, contentControlPlugin, formFieldGuardPlugin, symbolFontPlugin, positionalTabInputPlugin, 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, setReviewRecordingPreferences, nodeNumbering, controlAtSelection, paragraphFormattingRevision, inlineNodeRun, formattingRevision, insertWordHardBreak, paragraphAttrs, resolveCellVisuals, themeDrawing, ribbonActionIdForLabel, removeWordLink, fieldResultRanges, wordLinkRangeAt, ligatureCss as ligatureCss$1, toggleCheckboxControl, formFieldBeside, formFieldOfNode, formFieldLocked, toggleFormCheckboxAt, runToInlineNodes as runToInlineNodes$1, insertedTextMarks, backstageFocus, applyRunFormattingPatch, clearDirectRunFormatting, applyWordLink, deleteFieldSelection, emptySimpleFieldResult, ligatureStyle, wordHighlightColors, swatchColor, cssBorderSide, countWords, chooseListItem, chooseDate, selectFormDropDownAt, updateControlProperties, WORD_CAPABILITY_MENU_ITEMS, WORD_CAPABILITY_SHORTCUTS, WORD_CAPABILITY_BACKSTAGE_PAGES, WORD_CAPABILITY_FILE_COMMANDS, resolveComment, replyToComment, CollaborationAuthority } from 'ooxml-core/docx/ui';
13
+ export { CollaborationAuthority, CollaborationClient, RIBBON_ACTION_IDS, RIBBON_ACTION_LABELS, WORD_CAPABILITY_IDS, createCollaborationIdGenerator, darkTheme, isRibbonActionId, lightTheme, normalizeRibbonActions, repairCollaborativeDocumentIds, themeToCssVars } from 'ooxml-core/docx/ui';
14
14
  import { createDocument, saveDocx, sectionsFromLayout, sectionLayoutJson, sectionsOf, pageSizeOf, columnPreset, applyPageSetup, withSection, computeListLabels, numberNotesInOrder, tocEntries, resolveNumberingLevel, tableOfFiguresInstruction, findTableOfContents, ensureListDefinition, 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, cellSourceBlocks, reviewDocumentFormatting, reviewFormattingWarnings, listRevisions, plainText, resolveRunFormatting, removedByEdit, tocHyperlinks, DEFAULT_TOC_INSTRUCTION, tocBookmarks, buildTableOfContents, tocCaptionLabel, twips as twips$1, signedTwips, formatListNumber, columnTextWidth, validColumnDraft, validatePageSetup, presetOf, LIGATURE_VALUES, isLigatures, reviewRunFormatting, resolveThemeColorReference, lineSpacingValue, canEditControlContent, controlDate, formDropDownIndex, shapeSvg, isStHighlightColor, transformCase, DEFAULT_TABLE_BORDERS, parseLineSpacingValue, twipsAttr, SHAPE_PALETTE, isHeadingListKind, twipsFromPixels, isFieldLocked, styleRefSource, parseStyleReference, bodyStyleRefResult, isDirectionalPreset, headingLevel, reviewParagraphFormatting, isValidLanguageTag, WORD, newShape, withFieldCodeFormatting, fieldResultRun, DEFAULT_DRAWN_SHAPE, fieldName, lineSpacingOptions, createListDefinition, linkStylesToList, headingListLevels, halfPointsFromPoints, changeColumnWidth, changeColumnGap, documentStats } from 'ooxml-core/docx';
15
15
  import { loadDocument } from 'ooxml-core/docx/load';
16
16
  import { Schema, Fragment, DOMSerializer, Mark } from 'prosemirror-model';
@@ -23,6 +23,7 @@ import { keymap } from 'prosemirror-keymap';
23
23
  import { createLayoutSession, layoutDocumentModel, pageNumbers, createFakeMeasurer, ligatureCss, cssFontStack, tokenizeRun, reviewSourceLength, placeTab, cellVerticalOffset, fieldDisplayText, DEFAULT_FONT_SIZE_PT, pageNumberValues, sectionPageCounts, pageStyleRefs, headerFooterSlotForPage, headerFooterForPage, paragraphFloats, floatPosition } from 'ooxml-core/docx/layout';
24
24
  import { chainCommands, baseKeymap, selectAll, splitBlock } from 'prosemirror-commands';
25
25
  import { sendableSteps, getVersion } from 'prosemirror-collab';
26
+ import { isCapabilityEnabled, capabilityHiddenActions, mergeHiddenActions, saveToStorage, documentSaveMeta, fileCommandDetail, withoutHiddenEntries } from 'ooxml-core/embedding';
26
27
 
27
28
  var enOptions = {
28
29
  ...optionStrings.en,
@@ -5020,6 +5021,7 @@ function createShortcutRegistry(actions) {
5020
5021
  ];
5021
5022
  const attempt = (shortcut, context2) => {
5022
5023
  if (shortcut.editing && context2.readOnly) return "blocked";
5024
+ if (context2.disabled?.has(shortcut.id)) return "blocked";
5023
5025
  return shortcut.run() === false ? "ignored" : "ran";
5024
5026
  };
5025
5027
  const shown = (shortcut, mac) => shortcut.keys.filter((spec) => !(mac && parse(spec).tap));
@@ -12137,7 +12139,10 @@ function renderDocument(core) {
12137
12139
  reviewAuthor: () => core.reviewAuthor,
12138
12140
  reviewDisplayMode: () => core.reviewDisplayMode,
12139
12141
  insertNote: (kind) => core.parts.insertNote(kind, canvas, paper),
12140
- showSearch: () => core.shell.searchPanel?.open(),
12142
+ // ProseMirror's Mod-f reaches here before the shortcut registry: honour `find: false`.
12143
+ showSearch: () => {
12144
+ if (!core.viewOptions.customization.shortcuts.has("find")) core.shell.searchPanel?.open();
12145
+ },
12141
12146
  extraPlugins: core.inserts.plugins(),
12142
12147
  yjs: Boolean(yjs),
12143
12148
  revisionIds: core.collab.ids,
@@ -12392,6 +12397,7 @@ function joinYjs(core, session, options) {
12392
12397
  core.loadGeneration++;
12393
12398
  core.detachedState = void 0;
12394
12399
  renderDocument(core);
12400
+ core.roleChanged();
12395
12401
  }
12396
12402
  function leaveYjs(core) {
12397
12403
  const yjs = core.collab.yjs;
@@ -12403,6 +12409,7 @@ function leaveYjs(core) {
12403
12409
  core.collab.stop();
12404
12410
  core.detachedState = void 0;
12405
12411
  if (core.element.isConnected) renderDocument(core);
12412
+ core.roleChanged();
12406
12413
  }
12407
12414
  function roomFor(core) {
12408
12415
  return new DocxRoom({
@@ -19393,6 +19400,59 @@ var InsertController = class {
19393
19400
  }
19394
19401
  }
19395
19402
  };
19403
+ var DOCX_EDITOR_ATTRIBUTES = [
19404
+ "locale",
19405
+ "read-only",
19406
+ "file-name",
19407
+ "review-author",
19408
+ "theme",
19409
+ "show-thumbnails",
19410
+ "show-toolbar"
19411
+ ];
19412
+ var DEFAULT_FILE_NAME = "Document1.docx";
19413
+ var DEFAULT_REVIEW_AUTHOR = "Author";
19414
+ function isDocxEditorAttribute(name) {
19415
+ return DOCX_EDITOR_ATTRIBUTES.includes(name);
19416
+ }
19417
+ function applyAttribute(target, name, value) {
19418
+ if (name === "locale") {
19419
+ if (normalizeEditorLocale(value ?? "en") !== target.locale) target.locale = value ?? "en";
19420
+ } else if (name === "read-only") {
19421
+ target.readOnly = value !== null;
19422
+ } else if (name === "file-name") {
19423
+ const next = value ?? DEFAULT_FILE_NAME;
19424
+ if (next !== target.fileName) target.fileName = next;
19425
+ } else if (name === "theme") {
19426
+ const next = normalizeThemeMode(value);
19427
+ if (next !== target.theme) target.theme = next;
19428
+ } else if (name === "show-thumbnails") {
19429
+ const next = value !== null && value !== "false";
19430
+ if (next !== target.showThumbnails) target.showThumbnails = next;
19431
+ } else if (name === "show-toolbar") {
19432
+ const next = value !== "false";
19433
+ if (next !== target.showToolbar) target.showToolbar = next;
19434
+ } else {
19435
+ const next = value || DEFAULT_REVIEW_AUTHOR;
19436
+ if (next !== target.reviewAuthor) target.reviewAuthor = next;
19437
+ }
19438
+ }
19439
+ function reflectAttribute(element, name, value) {
19440
+ if (typeof element.setAttribute !== "function") return;
19441
+ if (name === "show-toolbar" && typeof value === "boolean") {
19442
+ if (element.getAttribute(name) !== (value ? null : "false"))
19443
+ if (value) element.removeAttribute(name);
19444
+ else element.setAttribute(name, "false");
19445
+ return;
19446
+ }
19447
+ if (typeof value === "boolean") {
19448
+ if (element.hasAttribute(name) !== value) element.toggleAttribute(name, value);
19449
+ return;
19450
+ }
19451
+ const current2 = element.getAttribute(name);
19452
+ if (current2 === value) return;
19453
+ if (name === "locale" && current2 !== null && normalizeEditorLocale(current2) === value) return;
19454
+ element.setAttribute(name, value);
19455
+ }
19396
19456
 
19397
19457
  // src/docx/page-sync.ts
19398
19458
  var PageTracker = class {
@@ -19448,19 +19508,43 @@ function applyRibbonVisibility(toolbar, showToolbar, hiddenActions) {
19448
19508
  for (const panel of panelsOf(toolbar))
19449
19509
  setTabHidden(toolbar, panel.dataset.ribbonTab, "custom", allHidden(panel));
19450
19510
  }
19511
+ function resolveWordCustomization(customization) {
19512
+ const capabilities = customization?.capabilities;
19513
+ const set = (map) => new Set(capabilityHiddenActions(capabilities, map));
19514
+ return {
19515
+ canEdit: isCapabilityEnabled(capabilities, "edit"),
19516
+ hiddenActions: capabilityHiddenActions(capabilities, WORD_CAPABILITY_ACTIONS),
19517
+ fileCommands: set(WORD_CAPABILITY_FILE_COMMANDS),
19518
+ backstagePages: set(WORD_CAPABILITY_BACKSTAGE_PAGES),
19519
+ shortcuts: set(WORD_CAPABILITY_SHORTCUTS),
19520
+ menuItems: set(WORD_CAPABILITY_MENU_ITEMS),
19521
+ blockCopy: !isCapabilityEnabled(capabilities, "copy"),
19522
+ extraPages: customization?.backstage?.extraPages ?? [],
19523
+ menuCommands: customization?.contextMenu?.extraCommands ?? []
19524
+ };
19525
+ }
19526
+ var EMPTY_WORD_CUSTOMIZATION = resolveWordCustomization();
19451
19527
 
19452
19528
  // src/docx/view-options.ts
19453
19529
  var ViewOptions = class {
19454
19530
  showThumbnails = false;
19455
19531
  showToolbar = true;
19456
19532
  hiddenActions = [];
19533
+ /** The host's `customization` object, as given. */
19534
+ customizationInput = null;
19535
+ /** `customizationInput` resolved for the render sites. */
19536
+ customization = EMPTY_WORD_CUSTOMIZATION;
19457
19537
  };
19458
19538
  function applyViewOptions(core) {
19459
19539
  const { toolbar, navigator: navigator2 } = core.shell;
19460
- const { showThumbnails, showToolbar, hiddenActions } = core.viewOptions;
19540
+ const { showThumbnails, showToolbar, hiddenActions, customization } = core.viewOptions;
19461
19541
  navigator2?.setOpen(showThumbnails);
19462
19542
  if (!toolbar) return;
19463
- applyRibbonVisibility(toolbar, showToolbar, hiddenActions);
19543
+ applyRibbonVisibility(
19544
+ toolbar,
19545
+ showToolbar,
19546
+ mergeHiddenActions(hiddenActions, customization.hiddenActions)
19547
+ );
19464
19548
  findLocalizedControl(toolbar, "Page thumbnails")?.setAttribute(
19465
19549
  "aria-pressed",
19466
19550
  String(showThumbnails)
@@ -19571,11 +19655,64 @@ var EditorCore = class {
19571
19655
  loaded;
19572
19656
  loadGeneration = 0;
19573
19657
  loading = false;
19574
- readOnly = false;
19658
+ /** The host's `readOnly` switch. A collaboration `viewer` role locks the editor on top of it. */
19659
+ hostReadOnly = false;
19660
+ /** True while `applyReadOnly` writes the `read-only` attribute. */
19661
+ reflectingReadOnly = false;
19662
+ shownReadOnly = false;
19663
+ shownHostReadOnly = false;
19664
+ /**
19665
+ * Effective: the host's switch, a `viewer` role, or `capabilities.edit` off. Assigning sets
19666
+ * the host's switch only, so nothing that assigns it can lift the other two.
19667
+ */
19668
+ get readOnly() {
19669
+ return this.hostReadOnly || this.roleLocked || !this.viewOptions.customization.canEdit;
19670
+ }
19671
+ set readOnly(value) {
19672
+ this.hostReadOnly = value;
19673
+ }
19674
+ /** Applies the effective value to the view, controls and attribute. */
19675
+ applyReadOnly() {
19676
+ this.view?.setProps({ editable: () => this.canEditBody() });
19677
+ if (this.readOnly) this.parts.closeHeaderFooter(this.shell.canvas, this.shell.paper);
19678
+ this.refreshControls();
19679
+ this.reflectingReadOnly = true;
19680
+ try {
19681
+ reflectAttribute(this.element, "read-only", this.hostReadOnly);
19682
+ } finally {
19683
+ this.reflectingReadOnly = false;
19684
+ }
19685
+ this.shownReadOnly = this.readOnly;
19686
+ this.shownHostReadOnly = this.hostReadOnly;
19687
+ }
19688
+ /** True while a collaboration `viewer` role holds the editor read-only. */
19689
+ get roleLocked() {
19690
+ return this.collab.yjs?.session.role === "viewer";
19691
+ }
19692
+ /** Applies the effective value, then reports it when it or the host's switch changed. */
19693
+ reportReadOnly(change) {
19694
+ const wasReadOnly = this.shownReadOnly;
19695
+ const wasHost = this.shownHostReadOnly;
19696
+ change?.();
19697
+ this.applyReadOnly();
19698
+ const readOnly = this.readOnly;
19699
+ if (readOnly === wasReadOnly && this.hostReadOnly === wasHost) return;
19700
+ emit(this.element, "readonly-change", {
19701
+ readOnly,
19702
+ locked: this.roleLocked,
19703
+ hostReadOnly: this.hostReadOnly
19704
+ });
19705
+ }
19706
+ /** Joining or leaving a room can change the role lock: apply it and report a change. */
19707
+ roleChanged() {
19708
+ this.reportReadOnly();
19709
+ }
19575
19710
  /** Set before mounting to render only the document surface. */
19576
19711
  surfaceOnly = false;
19577
19712
  /** Host-owned workflows for surface mode (link, find and replace, picture picker). */
19578
19713
  surfaceActions = {};
19714
+ /** Where File > Save and Open go instead of a download and the file picker (`storage`). */
19715
+ storage = void 0;
19579
19716
  locale = "en";
19580
19717
  reviewAuthor = "Author";
19581
19718
  theme = "auto";
@@ -23027,6 +23164,7 @@ function renderExport({ handlers, t, content }) {
23027
23164
  function renderCustomizeRibbon(host, handlers, t) {
23028
23165
  const ribbon = handlers.ribbon();
23029
23166
  const hidden = new Set(handlers.hiddenActions());
23167
+ const policy = new Set(handlers.customization().hiddenActions);
23030
23168
  const seen = /* @__PURE__ */ new Set();
23031
23169
  const boxes = [];
23032
23170
  const commit = () => handlers.setHiddenActions(boxes.filter((b) => !b.input.checked).map((b) => b.id));
@@ -23047,7 +23185,7 @@ function renderCustomizeRibbon(host, handlers, t) {
23047
23185
  "button[aria-label]:not(.ribbon-launcher):not(.ribbon-overflow-button):not(.style-tile), select[aria-label], input[aria-label]"
23048
23186
  )) {
23049
23187
  const id = ribbonControlId(control);
23050
- if (!id || seen.has(id)) continue;
23188
+ if (!id || seen.has(id) || policy.has(id)) continue;
23051
23189
  seen.add(id);
23052
23190
  const row3 = document.createElement("label");
23053
23191
  row3.className = "dve-customize-row";
@@ -23283,6 +23421,12 @@ function createBackstage(handlers) {
23283
23421
  pages.set(id, page2);
23284
23422
  element.append(page2);
23285
23423
  }
23424
+ const hostPages = createHostBackstagePages(element, {
23425
+ context: (region) => handlers.regionContext(region),
23426
+ pageClass: "dve-backstage-content",
23427
+ label: "[docx-editor]"
23428
+ });
23429
+ const hidden = (id) => handlers.customization().backstagePages.has(id);
23286
23430
  let current2 = "info";
23287
23431
  const options = createWordOptions(handlers, t);
23288
23432
  const draw = (page2) => {
@@ -23301,15 +23445,19 @@ function createBackstage(handlers) {
23301
23445
  const locale = normalizeEditorLocale(element.dataset.editorLocale);
23302
23446
  element.setAttribute("label", translate(locale, "File"));
23303
23447
  element.setAttribute("back-label", translate(locale, "Back to document"));
23304
- element.items = NAV.map(({ id, label, footer }) => ({
23305
- id,
23306
- label: t(label),
23307
- ...footer ? { group: "footer" } : {}
23308
- }));
23448
+ hostPages.setPages(handlers.customization().extraPages);
23449
+ element.items = hostPages.items(
23450
+ NAV.filter(({ id }) => !hidden(id)).map(({ id, label, footer }) => ({
23451
+ id,
23452
+ label: t(label),
23453
+ ...footer ? { group: "footer" } : {}
23454
+ }))
23455
+ );
23309
23456
  };
23310
23457
  localize();
23311
23458
  element.addEventListener("office-backstage-select", (event) => {
23312
23459
  const { id } = event.detail;
23460
+ if (hostPages.show(id)) return;
23313
23461
  if (id === "save") {
23314
23462
  event.preventDefault();
23315
23463
  handlers.close();
@@ -23327,7 +23475,8 @@ function createBackstage(handlers) {
23327
23475
  return {
23328
23476
  element,
23329
23477
  optionsDialog: options.element,
23330
- open(page2 = "home") {
23478
+ open(requested = "home") {
23479
+ const page2 = hidden(requested === "customize" ? "options" : requested) ? "home" : requested;
23331
23480
  if (page2 === "options" || page2 === "customize") {
23332
23481
  showOptions(page2 === "customize" ? "ribbon" : void 0);
23333
23482
  return;
@@ -23347,18 +23496,18 @@ function createBackstage(handlers) {
23347
23496
  localize();
23348
23497
  options.relocalize();
23349
23498
  if (element.open) draw(current2);
23499
+ },
23500
+ refresh() {
23501
+ localize();
23502
+ hostPages.refresh();
23503
+ },
23504
+ destroy() {
23505
+ hostPages.destroy();
23350
23506
  }
23351
23507
  };
23352
23508
  }
23353
-
23354
- // src/docx/file-commands.ts
23355
23509
  function announceFileCommand(host, command, fileName) {
23356
- return emit(
23357
- host,
23358
- "file-command",
23359
- { command, ...fileName === void 0 ? {} : { fileName } },
23360
- { cancelable: true }
23361
- );
23510
+ return emit(host, "file-command", fileCommandDetail(command, fileName), { cancelable: true });
23362
23511
  }
23363
23512
  var DOCX_TYPE = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
23364
23513
  var WORD_TYPES = {
@@ -23470,7 +23619,12 @@ function createTitleBar(handlers) {
23470
23619
  defineTitleBar();
23471
23620
  const element = document.createElement("office-ui-title-bar");
23472
23621
  element.className = "dve-titlebar";
23473
- const model = { fileName: "", saveState: "saved", readOnly: false };
23622
+ const model = {
23623
+ fileName: "",
23624
+ saveState: "saved",
23625
+ readOnly: false,
23626
+ hidden: /* @__PURE__ */ new Set()
23627
+ };
23474
23628
  let found = /* @__PURE__ */ new Map();
23475
23629
  const render = () => {
23476
23630
  const t = (text) => translateUiText(element, text);
@@ -23493,7 +23647,7 @@ function createTitleBar(handlers) {
23493
23647
  quick("save", "save", "Save"),
23494
23648
  quick("undo", "undo", "Undo", model.readOnly),
23495
23649
  quick("redo", "redo", "Redo", model.readOnly)
23496
- ]
23650
+ ].filter((item) => !model.hidden.has(item.id))
23497
23651
  },
23498
23652
  search: {
23499
23653
  placeholder: prompt,
@@ -23544,12 +23698,16 @@ function createTitleBar(handlers) {
23544
23698
  model.readOnly = readOnly;
23545
23699
  render();
23546
23700
  },
23701
+ setHiddenCommands(ids) {
23702
+ model.hidden = new Set(ids);
23703
+ render();
23704
+ },
23547
23705
  relocalize: render
23548
23706
  };
23549
23707
  }
23550
23708
 
23551
23709
  // src/docx/editor-chrome.ts
23552
- var DEFAULT_FILE_NAME = "Document1.docx";
23710
+ var DEFAULT_FILE_NAME2 = "Document1.docx";
23553
23711
  var EditorChrome = class {
23554
23712
  constructor(host) {
23555
23713
  this.host = host;
@@ -23587,7 +23745,9 @@ var EditorChrome = class {
23587
23745
  },
23588
23746
  ribbon: () => host.ribbon(),
23589
23747
  hiddenActions: () => host.hiddenActions(),
23590
- setHiddenActions: (ids) => host.setHiddenActions(ids)
23748
+ setHiddenActions: (ids) => host.setHiddenActions(ids),
23749
+ customization: () => host.customization(),
23750
+ regionContext: (region) => host.regionContext(region)
23591
23751
  });
23592
23752
  this.statusBar = createStatusBar({
23593
23753
  setViewMode: (mode) => host.setViewMode(mode),
@@ -23612,7 +23772,7 @@ var EditorChrome = class {
23612
23772
  statusBar;
23613
23773
  fileInput;
23614
23774
  ribbon;
23615
- _fileName = DEFAULT_FILE_NAME;
23775
+ _fileName = DEFAULT_FILE_NAME2;
23616
23776
  state = "saved";
23617
23777
  /** Adds the chrome around an existing frame: title bar first, status bar and backstage last. */
23618
23778
  mount(frame, ribbon) {
@@ -23631,7 +23791,7 @@ var EditorChrome = class {
23631
23791
  return this._fileName;
23632
23792
  }
23633
23793
  set fileName(value) {
23634
- this._fileName = value || DEFAULT_FILE_NAME;
23794
+ this._fileName = value || DEFAULT_FILE_NAME2;
23635
23795
  this.titleBar.setFileName(this._fileName);
23636
23796
  }
23637
23797
  get isDirty() {
@@ -23665,16 +23825,25 @@ var EditorChrome = class {
23665
23825
  this.ribbonActions.setReadOnly(this.host.readOnly());
23666
23826
  this.ribbonActions.setSharing(this.host.collaborating());
23667
23827
  }
23828
+ /** Re-applies the host customisation to the File tab, title bar and ribbon actions. */
23829
+ applyCustomization() {
23830
+ const resolved = this.host.customization();
23831
+ this.backstage.refresh();
23832
+ this.titleBar.setHiddenCommands(resolved.fileCommands);
23833
+ this.ribbonActions.element.noShare = resolved.fileCommands.has("share");
23834
+ }
23668
23835
  closeBackstage() {
23669
23836
  this.backstage.close();
23670
23837
  this.ribbon?.focusFile?.();
23671
23838
  }
23672
23839
  /** Runs a file command unless a host cancels the `file-command` event to handle it itself. */
23673
23840
  async run(command, fileName) {
23841
+ if (this.host.customization().fileCommands.has(command)) return;
23842
+ if ((command === "save" || command === "saveAs") && this.saving) return;
23674
23843
  if (!announceFileCommand(this.host.element, command, fileName)) return;
23675
23844
  try {
23676
23845
  if (command === "new") this.newDocument();
23677
- else if (command === "open") this.fileInput.click();
23846
+ else if (command === "open") await this.open();
23678
23847
  else if (command === "print") this.host.print();
23679
23848
  else if (command === "share") return;
23680
23849
  else if (command === "exportText")
@@ -23684,21 +23853,59 @@ var EditorChrome = class {
23684
23853
  if (!name) return;
23685
23854
  const extension = this._fileName.split(".").pop()?.toLowerCase() === "doc" ? "doc" : "docx";
23686
23855
  this.fileName = withExtension(name, extension);
23687
- await this.run("save");
23688
- } else if (command === "save") {
23689
- this.setSaveState("saving");
23690
- downloadBytes(await this.host.save(), this._fileName);
23691
- this.setSaveState("saved-local");
23692
- } else if (command === "export")
23856
+ if (this.host.customization().fileCommands.has("save"))
23857
+ await this.saveDocument("saveAs", false);
23858
+ else if (announceFileCommand(this.host.element, "save")) await this.saveDocument("saveAs");
23859
+ } else if (command === "save") await this.saveDocument("save");
23860
+ else if (command === "export")
23693
23861
  downloadBytes(
23694
23862
  await saveDocx(structuredClone(this.host.model())),
23695
23863
  withExtension(this._fileName, "docx")
23696
23864
  );
23697
23865
  } catch (cause) {
23698
- if (command === "save") this.setSaveState("dirty");
23866
+ if (command === "save" || command === "saveAs") this.setSaveState("dirty");
23699
23867
  this.host.reportError(cause instanceof Error ? cause : new Error(String(cause)));
23700
23868
  }
23701
23869
  }
23870
+ /** True while a save is pending. */
23871
+ saving = false;
23872
+ /**
23873
+ * Saves to the host's storage when there is one, else downloads a copy. An edit made while the
23874
+ * save runs keeps the document dirty: the saved bytes do not contain it.
23875
+ */
23876
+ async saveDocument(reason, useStorage = true) {
23877
+ const element = this.host.element;
23878
+ let edited = false;
23879
+ const changed = () => edited = true;
23880
+ this.saving = true;
23881
+ this.setSaveState("saving");
23882
+ element.addEventListener("document-change", changed);
23883
+ try {
23884
+ const bytes = await this.host.save();
23885
+ const storage = useStorage ? this.host.storage?.() : void 0;
23886
+ if (storage)
23887
+ this.fileName = await saveToStorage(
23888
+ storage,
23889
+ bytes,
23890
+ documentSaveMeta(this._fileName, reason)
23891
+ );
23892
+ else downloadBytes(bytes, this._fileName);
23893
+ this.setSaveState(edited ? "dirty" : storage ? "saved" : "saved-local");
23894
+ } finally {
23895
+ element.removeEventListener("document-change", changed);
23896
+ this.saving = false;
23897
+ }
23898
+ }
23899
+ /** Opens from the host's storage when it can open, else shows the file picker. */
23900
+ async open() {
23901
+ const storage = this.host.storage?.();
23902
+ if (!storage?.open) return this.fileInput.click();
23903
+ const file = await storage.open();
23904
+ if (!file) return;
23905
+ await this.host.load(file.bytes);
23906
+ this.fileName = file.fileName;
23907
+ this.setSaveState("saved");
23908
+ }
23702
23909
  newDocument() {
23703
23910
  const prompt = translate(
23704
23911
  this.host.locale(),
@@ -23706,7 +23913,7 @@ var EditorChrome = class {
23706
23913
  );
23707
23914
  if (this.isDirty && typeof confirm === "function" && !confirm(prompt)) return;
23708
23915
  this.host.newDocument();
23709
- this.fileName = DEFAULT_FILE_NAME;
23916
+ this.fileName = DEFAULT_FILE_NAME2;
23710
23917
  this.setSaveState("saved");
23711
23918
  }
23712
23919
  async openSelectedFile() {
@@ -24916,6 +25123,28 @@ var HeadingNavigator = class {
24916
25123
  }
24917
25124
  }
24918
25125
  };
25126
+
25127
+ // src/docx/customization-apply.ts
25128
+ function setWordCustomization(core, value) {
25129
+ const { viewOptions } = core;
25130
+ if (value === viewOptions.customizationInput) return;
25131
+ core.reportReadOnly(() => {
25132
+ viewOptions.customizationInput = value;
25133
+ viewOptions.customization = resolveWordCustomization(value);
25134
+ });
25135
+ applyViewOptions(core);
25136
+ core.shell.chrome?.applyCustomization();
25137
+ }
25138
+ function wordRegionContext(core, region) {
25139
+ return {
25140
+ region,
25141
+ editor: core.element,
25142
+ fileName: core.element.fileName,
25143
+ locale: core.locale,
25144
+ canEdit: !core.readOnly,
25145
+ close: () => core.shell.chrome?.closeBackstage()
25146
+ };
25147
+ }
24919
25148
  var clamp = (value, low, high) => Math.min(Math.max(value, low), Math.max(low, high));
24920
25149
  function attachCanvasClick(core) {
24921
25150
  const canvas = core.shell.canvas;
@@ -25034,8 +25263,21 @@ function menuStateFromView(view, readOnly) {
25034
25263
  canTable: (command) => canExecuteTableCommand(view, command)
25035
25264
  };
25036
25265
  }
25037
-
25038
- // src/docx/context-menu.ts
25266
+ function withoutMenuItems(items, hidden) {
25267
+ return withoutHiddenEntries(items, (item) => hidden.has(item.id));
25268
+ }
25269
+ function menuContext(view, readOnly) {
25270
+ const { from: from2, to } = view.state.selection;
25271
+ const state = menuStateFromView(view, readOnly);
25272
+ return {
25273
+ selectedText: view.state.doc.textBetween(from2, to, "\n"),
25274
+ from: from2,
25275
+ to,
25276
+ readOnly: state.readOnly,
25277
+ inTable: state.inTable,
25278
+ onLink: state.onLink
25279
+ };
25280
+ }
25039
25281
  var KEY_ECHO_MS = 500;
25040
25282
  function createContextMenu(host) {
25041
25283
  let menu;
@@ -25087,17 +25329,31 @@ function createContextMenu(host) {
25087
25329
  close3(false);
25088
25330
  defineContextMenu();
25089
25331
  const locale = host.locale();
25090
- const items = computeMenuItems(menuStateFromView(view, host.readOnly()));
25332
+ const resolved = host.customization();
25333
+ const items = withoutMenuItems(
25334
+ computeMenuItems(menuStateFromView(view, host.readOnly())),
25335
+ resolved.menuItems
25336
+ );
25337
+ const extra = withHostMenuItems(
25338
+ rows(items, locale),
25339
+ resolved.menuCommands,
25340
+ menuContext(view, host.readOnly())
25341
+ );
25091
25342
  const element = document.createElement("office-ui-context-menu");
25092
25343
  const state = {
25093
25344
  x,
25094
25345
  y,
25095
25346
  label: translate(locale, "menu.context"),
25096
- items: rows(items, locale)
25347
+ items: extra.items
25097
25348
  };
25098
25349
  element.state = state;
25099
25350
  element.addEventListener("office-menu-request", (event) => {
25100
25351
  const id = event.detail.id;
25352
+ if (id.startsWith("host:")) {
25353
+ close3();
25354
+ extra.run(id);
25355
+ return;
25356
+ }
25101
25357
  const item = items.find((candidate) => candidate.id === id);
25102
25358
  const current2 = host.view();
25103
25359
  if (!item || !current2) return;
@@ -25159,8 +25415,8 @@ function editorShortcutRows(mac, bindings = editorBindings) {
25159
25415
  }
25160
25416
  return [...rows].map(([label, keys2]) => ({ label, keys: keys2.join(" / ") }));
25161
25417
  }
25162
- function shortcutRows(registry, mac) {
25163
- const general = registry.shortcuts.map((shortcut) => ({
25418
+ function shortcutRows(registry, mac, disabled = /* @__PURE__ */ new Set()) {
25419
+ const general = registry.shortcuts.filter((shortcut) => !disabled.has(shortcut.id)).map((shortcut) => ({
25164
25420
  label: shortcut.label,
25165
25421
  keys: registry.keysFor(shortcut.id, mac).join(" / ")
25166
25422
  }));
@@ -25240,8 +25496,19 @@ function attachEditorInteractions(core, frame) {
25240
25496
  readOnly: () => core.readOnly,
25241
25497
  locale: () => core.locale,
25242
25498
  run: (action) => routeRibbonAction(core, action),
25243
- warn: (message) => emit(element, "document-warning", message)
25499
+ warn: (message) => emit(element, "document-warning", message),
25500
+ customization: () => core.viewOptions.customization
25244
25501
  });
25502
+ for (const type of ["copy", "cut"])
25503
+ element.addEventListener(
25504
+ type,
25505
+ (event) => {
25506
+ if (!core.viewOptions.customization.blockCopy) return;
25507
+ event.preventDefault();
25508
+ event.stopPropagation();
25509
+ },
25510
+ true
25511
+ );
25245
25512
  const regionElement = (region) => region === "ribbon" ? shell.toolbar : region === "status" ? shell.chrome?.statusBar.element : void 0;
25246
25513
  const currentRegion = () => {
25247
25514
  const active = activeElement();
@@ -25330,7 +25597,10 @@ function attachEditorInteractions(core, frame) {
25330
25597
  },
25331
25598
  help: () => {
25332
25599
  menu.close(false);
25333
- help.open(shortcutRows(registry, mac()), core.locale);
25600
+ help.open(
25601
+ shortcutRows(registry, mac(), core.viewOptions.customization.shortcuts),
25602
+ core.locale
25603
+ );
25334
25604
  },
25335
25605
  escape: () => {
25336
25606
  if (escapeOwned) return false;
@@ -25343,7 +25613,11 @@ function attachEditorInteractions(core, frame) {
25343
25613
  };
25344
25614
  const mac = () => isMacPlatform();
25345
25615
  const registry = createShortcutRegistry(actions);
25346
- installKeyboard(element, registry, () => ({ readOnly: core.readOnly, mac: mac() }));
25616
+ installKeyboard(element, registry, () => ({
25617
+ readOnly: core.readOnly,
25618
+ mac: mac(),
25619
+ disabled: core.viewOptions.customization.shortcuts
25620
+ }));
25347
25621
  }
25348
25622
 
25349
25623
  // src/docx/editor-shell.ts
@@ -25361,12 +25635,12 @@ function createChrome(core, api) {
25361
25635
  locale: () => core.locale,
25362
25636
  readOnly: () => core.readOnly,
25363
25637
  setReadOnly: (readOnly) => {
25364
- api.setReadOnly(readOnly);
25365
- emit(element, "readonly-change", readOnly);
25638
+ core.reportReadOnly(() => api.setReadOnly(readOnly));
25366
25639
  },
25367
25640
  newDocument: () => api.setDocumentModel(createDocument()),
25368
25641
  load: (bytes) => api.load(bytes),
25369
25642
  save: () => api.saveBytes(),
25643
+ storage: () => core.storage,
25370
25644
  saveStateChanged: (state) => {
25371
25645
  if (state !== "saving") core.dirtyState.set(state === "dirty");
25372
25646
  },
@@ -25407,6 +25681,8 @@ function createChrome(core, api) {
25407
25681
  host().hiddenActions = ids;
25408
25682
  emit(element, "ribbon-customize", host().hiddenActions);
25409
25683
  },
25684
+ customization: () => core.viewOptions.customization,
25685
+ regionContext: (region) => wordRegionContext(core, region),
25410
25686
  reportError: (error) => dispatchDocumentError(element, error)
25411
25687
  });
25412
25688
  }
@@ -25538,6 +25814,7 @@ function buildShell(core, api) {
25538
25814
  applyRibbonAddIns(core);
25539
25815
  chrome.setLocale(core.locale);
25540
25816
  applyViewOptions(core);
25817
+ chrome.applyCustomization();
25541
25818
  attachEditorInteractions(core, frame);
25542
25819
  element.setAttribute("role", "region");
25543
25820
  applyShellLabels(element, paper, core.locale);
@@ -25588,59 +25865,6 @@ function attachPrintEditing(core) {
25588
25865
  showBlock: (id, offset) => printLayout.ensureBlock(id, offset)
25589
25866
  });
25590
25867
  }
25591
- var DOCX_EDITOR_ATTRIBUTES = [
25592
- "locale",
25593
- "read-only",
25594
- "file-name",
25595
- "review-author",
25596
- "theme",
25597
- "show-thumbnails",
25598
- "show-toolbar"
25599
- ];
25600
- var DEFAULT_FILE_NAME2 = "Document1.docx";
25601
- var DEFAULT_REVIEW_AUTHOR = "Author";
25602
- function isDocxEditorAttribute(name) {
25603
- return DOCX_EDITOR_ATTRIBUTES.includes(name);
25604
- }
25605
- function applyAttribute(target, name, value) {
25606
- if (name === "locale") {
25607
- if (normalizeEditorLocale(value ?? "en") !== target.locale) target.locale = value ?? "en";
25608
- } else if (name === "read-only") {
25609
- if (value !== null !== target.readOnly) target.readOnly = value !== null;
25610
- } else if (name === "file-name") {
25611
- const next = value ?? DEFAULT_FILE_NAME2;
25612
- if (next !== target.fileName) target.fileName = next;
25613
- } else if (name === "theme") {
25614
- const next = normalizeThemeMode(value);
25615
- if (next !== target.theme) target.theme = next;
25616
- } else if (name === "show-thumbnails") {
25617
- const next = value !== null && value !== "false";
25618
- if (next !== target.showThumbnails) target.showThumbnails = next;
25619
- } else if (name === "show-toolbar") {
25620
- const next = value !== "false";
25621
- if (next !== target.showToolbar) target.showToolbar = next;
25622
- } else {
25623
- const next = value || DEFAULT_REVIEW_AUTHOR;
25624
- if (next !== target.reviewAuthor) target.reviewAuthor = next;
25625
- }
25626
- }
25627
- function reflectAttribute(element, name, value) {
25628
- if (typeof element.setAttribute !== "function") return;
25629
- if (name === "show-toolbar" && typeof value === "boolean") {
25630
- if (element.getAttribute(name) !== (value ? null : "false"))
25631
- if (value) element.removeAttribute(name);
25632
- else element.setAttribute(name, "false");
25633
- return;
25634
- }
25635
- if (typeof value === "boolean") {
25636
- if (element.hasAttribute(name) !== value) element.toggleAttribute(name, value);
25637
- return;
25638
- }
25639
- const current2 = element.getAttribute(name);
25640
- if (current2 === value) return;
25641
- if (name === "locale" && current2 !== null && normalizeEditorLocale(current2) === value) return;
25642
- element.setAttribute(name, value);
25643
- }
25644
25868
 
25645
25869
  // src/docx/building-blocks-actions.ts
25646
25870
  function hyperlinkRequest(core) {
@@ -25923,6 +26147,18 @@ var DocxEditorApi = class extends HTMLElementBase {
25923
26147
  this.core.surfaceActions = { ...value };
25924
26148
  if (this.core.view) this.core.refreshControls();
25925
26149
  }
26150
+ /**
26151
+ * Host-owned storage. When set, File > Save and Save As hand the saved bytes to
26152
+ * `storage.save()` instead of downloading them, and File > Open asks `storage.open()` (when it
26153
+ * has one) instead of showing the file picker. The cancelable `file-command` event still fires
26154
+ * first; a host that prevents it handles the command itself.
26155
+ */
26156
+ get storage() {
26157
+ return this.core.storage;
26158
+ }
26159
+ set storage(value) {
26160
+ this.core.storage = value ?? void 0;
26161
+ }
25926
26162
  get loading() {
25927
26163
  return this.core.loading;
25928
26164
  }
@@ -26025,6 +26261,18 @@ var DocxEditorApi = class extends HTMLElementBase {
26025
26261
  this.core.viewOptions.hiddenActions = next;
26026
26262
  applyViewOptions(this.core);
26027
26263
  }
26264
+ /**
26265
+ * The host customisation (`WordCustomization`): `capabilities` (removing every UI path to
26266
+ * what is switched off), `backstage.extraPages` (host File tab pages) and
26267
+ * `contextMenu.extraCommands` (host context-menu commands). The object is applied when its
26268
+ * identity changes, so keep it stable; `null` restores the defaults.
26269
+ */
26270
+ get customization() {
26271
+ return this.core.viewOptions.customizationInput;
26272
+ }
26273
+ set customization(value) {
26274
+ setWordCustomization(this.core, value ?? null);
26275
+ }
26028
26276
  /** True after an edit until the document is saved through File > Save, `download()`, loaded or `markClean()`. */
26029
26277
  get dirty() {
26030
26278
  return this.core.dirtyState.dirty;
@@ -26088,6 +26336,7 @@ var DocxEditorElement = class extends DocxEditorApi {
26088
26336
  return this.core.inserts;
26089
26337
  }
26090
26338
  attributeChangedCallback(name, _old, value) {
26339
+ if (name === "read-only" && this.core.reflectingReadOnly) return;
26091
26340
  if (isDocxEditorAttribute(name)) applyAttribute(this, name, value);
26092
26341
  }
26093
26342
  get reviewAuthor() {
@@ -26100,7 +26349,7 @@ var DocxEditorElement = class extends DocxEditorApi {
26100
26349
  /** File name shown in the title bar and used for downloads from the built-in File commands. */
26101
26350
  get fileName() {
26102
26351
  const { chrome } = this.core.shell;
26103
- return chrome?.fileName ?? this.core.pendingFileName ?? DEFAULT_FILE_NAME2;
26352
+ return chrome?.fileName ?? this.core.pendingFileName ?? DEFAULT_FILE_NAME;
26104
26353
  }
26105
26354
  set fileName(value) {
26106
26355
  const { chrome } = this.core.shell;
@@ -26161,13 +26410,10 @@ var DocxEditorElement = class extends DocxEditorApi {
26161
26410
  get readOnly() {
26162
26411
  return this.core.readOnly;
26163
26412
  }
26413
+ /** True when the document cannot be edited: this switch, a `viewer` role or `capabilities.edit` off. */
26164
26414
  set readOnly(value) {
26165
26415
  this.core.readOnly = Boolean(value);
26166
- this.core.view?.setProps({ editable: () => this.core.canEditBody() });
26167
- if (this.core.readOnly)
26168
- this.core.parts.closeHeaderFooter(this.core.shell.canvas, this.core.shell.paper);
26169
- this.core.refreshControls();
26170
- reflectAttribute(this, "read-only", this.core.readOnly);
26416
+ this.core.applyReadOnly();
26171
26417
  }
26172
26418
  /**
26173
26419
  * Shares the loaded document in a room while set; `null` leaves (see
@@ -26207,6 +26453,7 @@ var DocxEditorElement = class extends DocxEditorApi {
26207
26453
  core.view?.destroy();
26208
26454
  core.view = void 0;
26209
26455
  core.imageMedia.release();
26456
+ core.shell.chrome?.backstage.destroy();
26210
26457
  }
26211
26458
  async load(input) {
26212
26459
  const { core } = this;