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
@@ -1,5 +1,5 @@
1
1
  import { defineSmartArt } from './chunk-QBXYGKPB.js';
2
- import { TEAMS_TAGS, registerTeams } from './chunk-DRBAJ5UO.js';
2
+ import { TEAMS_TAGS, registerTeams } from './chunk-FX6CF43K.js';
3
3
  import { installOfficeUiTheme } from './chunk-T5ARELU2.js';
4
4
  import { registerControls } from './chunk-TJ245GDD.js';
5
5
  import { definePresence } from './chunk-YZH2QS7J.js';
@@ -9,6 +9,7 @@ import { filterActivity, ACTIVITY_FILTERS, localZone, startOfDay, occurrencesBet
9
9
  import { repeat } from 'lit/directives/repeat.js';
10
10
  import { live } from 'lit/directives/live.js';
11
11
  import { keyed } from 'lit/directives/keyed.js';
12
+ import { fileCommandDetail } from 'ooxml-core/embedding';
12
13
 
13
14
  // raw-css:/home/runner/work/ooxml/ooxml/src/ui/src/teams/reset.css?raw
14
15
  var reset_default = ":host {\n box-sizing: border-box;\n font: var(--office-font-size) var(--office-font);\n color: var(--office-foreground);\n}\n*,\n*::before,\n*::after {\n box-sizing: inherit;\n}\nbutton {\n font: inherit;\n color: inherit;\n cursor: pointer;\n}\nbutton:focus-visible,\ntextarea:focus-visible,\ninput:focus-visible {\n outline: var(--office-focus-width) solid var(--office-ring);\n outline-offset: var(--office-focus-offset);\n}\nsvg.icon {\n width: 1.25em;\n height: 1.25em;\n flex: none;\n fill: none;\n stroke: currentColor;\n stroke-width: var(--office-icon-stroke);\n stroke-linecap: round;\n stroke-linejoin: round;\n}\n";
@@ -2022,7 +2023,7 @@ var TYPES = {
2022
2023
  };
2023
2024
  var OPEN_ACCEPT = ".xlsx,.xlsm,.xltx,.xls,.csv,.tsv,.txt";
2024
2025
  function announceFileCommand(host, command, fileName) {
2025
- return emit(host, "file-command", { command, ...fileName === void 0 ? {} : { fileName } });
2026
+ return emit(host, "file-command", fileCommandDetail(command, fileName));
2026
2027
  }
2027
2028
  var extensionOf = (fileName) => /\.([^./\\]+)$/.exec(fileName)?.[1]?.toLowerCase() ?? "";
2028
2029
  function withExtension(fileName, extension) {
@@ -0,0 +1,364 @@
1
+ import { defineRibbonGroup, defineRibbonStack, defineButton, defineMenuItem, defineMenuButton } from './chunk-TJ245GDD.js';
2
+ import { acceptedRibbonAddIns, findRibbonAddInCommand, RIBBON_ADD_IN_EVENT } from 'ooxml-core/ribbon';
3
+ export { RIBBON_ADD_IN_EVENT } from 'ooxml-core/ribbon';
4
+ import { sameRenderer, sameRegionContext, hostBackstagePageId, acceptedHostBackstagePages, placeHostBackstagePages, hostBackstageItemId, withHostMenuCommands, isHostMenuEntry, resolveHostMenuCommands, withoutHiddenEntries, hostBackstageRegionId } from 'ooxml-core/embedding';
5
+
6
+ function defineRibbonAddInElements(registry) {
7
+ if (!registry) return;
8
+ for (const define of [
9
+ defineRibbonGroup,
10
+ defineRibbonStack,
11
+ defineButton,
12
+ defineMenuItem,
13
+ defineMenuButton
14
+ ])
15
+ define(registry);
16
+ }
17
+ var SMALL_ROWS = 3;
18
+ function button(doc, spec) {
19
+ const menu = !!spec.items?.length;
20
+ const el = doc.createElement(menu ? "office-ui-menu-button" : "office-ui-button");
21
+ if (!menu) el.setAttribute("command", spec.id);
22
+ el.dataset.addInCommand = spec.id;
23
+ el.setAttribute("label", spec.label);
24
+ el.setAttribute("title", spec.title ?? spec.label);
25
+ if (spec.icon) el.setAttribute("icon", spec.icon);
26
+ const small = spec.size === "small";
27
+ if (!menu) el.setAttribute("size", small ? "small" : "large");
28
+ else if (!small) el.setAttribute("variant", "stacked");
29
+ else el.style.setProperty("--office-target-size", "var(--office-control-height)");
30
+ if (spec.disabled) el.setAttribute("disabled", "");
31
+ for (const item of spec.items ?? []) {
32
+ const entry = doc.createElement("office-ui-menu-item");
33
+ entry.setAttribute("command", item.id);
34
+ entry.dataset.addInCommand = item.id;
35
+ entry.setAttribute("label", item.label);
36
+ if (item.title) entry.setAttribute("title", item.title);
37
+ if (item.icon) entry.setAttribute("icon", item.icon);
38
+ if (item.disabled) entry.setAttribute("disabled", "");
39
+ el.append(entry);
40
+ }
41
+ return el;
42
+ }
43
+ function group(doc, spec) {
44
+ const el = doc.createElement("office-ui-ribbon-group");
45
+ el.setAttribute("label", spec.label);
46
+ let column;
47
+ for (const command of spec.commands) {
48
+ if (command.size !== "small") {
49
+ column = void 0;
50
+ el.append(button(doc, command));
51
+ continue;
52
+ }
53
+ if (!column || column.childElementCount >= SMALL_ROWS) {
54
+ column = doc.createElement("office-ui-ribbon-stack");
55
+ el.append(column);
56
+ }
57
+ column.append(button(doc, command));
58
+ }
59
+ return el;
60
+ }
61
+ var ownTabs = (ribbon) => new Set(
62
+ [...ribbon.children].flatMap(
63
+ (child) => child instanceof HTMLElement && child.dataset.ribbonTab && !("addIn" in child.dataset) ? [child.dataset.ribbonTab] : []
64
+ )
65
+ );
66
+ var shown = /* @__PURE__ */ new WeakMap();
67
+ var addInPanels = (ribbon) => [...ribbon.children].filter(
68
+ (child) => child instanceof HTMLElement && "addIn" in child.dataset
69
+ );
70
+ function syncRibbonAddIns(ribbon, tabs, options = {}) {
71
+ const doc = ribbon.ownerDocument;
72
+ const accepted = acceptedRibbonAddIns(tabs, ownTabs(ribbon));
73
+ if (accepted.length) defineRibbonAddInElements(doc.defaultView?.customElements);
74
+ const ids = accepted.map((tab) => tab.id);
75
+ const look = JSON.stringify([options.panelClass ?? "", accepted]);
76
+ const current = new Map(accepted.map((tab) => [tab.id, tab]));
77
+ const existing = addInPanels(ribbon);
78
+ const before = shown.get(ribbon);
79
+ shown.set(ribbon, { look, tabs: current });
80
+ if (before?.look === look && existing.length === ids.length && existing.every((panel, index) => panel.dataset.ribbonTab === ids[index]))
81
+ return ids;
82
+ for (const panel of existing) panel.remove();
83
+ for (const tab of accepted) {
84
+ const panel = doc.createElement("div");
85
+ if (options.panelClass) panel.className = options.panelClass;
86
+ panel.id = `add-in-${tab.id}-panel`;
87
+ panel.dataset.addIn = "";
88
+ panel.dataset.ribbonTab = tab.id;
89
+ panel.dataset.label = tab.label;
90
+ if (tab.keytip) panel.dataset.tabKeytip = tab.keytip;
91
+ const groups = tab.groups.map((spec) => group(doc, spec));
92
+ panel.append(...options.wrap ? options.wrap(doc, tab, groups) : groups);
93
+ panel.addEventListener("office-command", (event) => {
94
+ event.stopPropagation();
95
+ const id = event.detail?.command;
96
+ const latest = shown.get(ribbon)?.tabs.get(tab.id);
97
+ const command = latest && findRibbonAddInCommand(latest, id);
98
+ if (!command) return;
99
+ command.run?.();
100
+ ribbon.dispatchEvent(
101
+ new CustomEvent(RIBBON_ADD_IN_EVENT, {
102
+ detail: { tab: tab.id, command: command.id },
103
+ bubbles: true,
104
+ composed: true
105
+ })
106
+ );
107
+ });
108
+ ribbon.append(panel);
109
+ }
110
+ return ids;
111
+ }
112
+ var HOST_REGION_ATTRIBUTE = "data-office-region";
113
+ var HostRegionHost = class {
114
+ #container;
115
+ #callbackKeys;
116
+ #attribute;
117
+ #label;
118
+ #renderer;
119
+ #context;
120
+ #result;
121
+ #element;
122
+ /** The latest context as the product passed it, callbacks included. */
123
+ #latest;
124
+ constructor(container, options = {}) {
125
+ this.#container = container;
126
+ this.#callbackKeys = /* @__PURE__ */ new Set(["close", ...options.callbackKeys ?? []]);
127
+ this.#attribute = options.attribute ?? HOST_REGION_ATTRIBUTE;
128
+ this.#label = options.label ?? "[ooxml-ui]";
129
+ }
130
+ /** The container this host fills. */
131
+ get container() {
132
+ return this.#container;
133
+ }
134
+ /** True while a renderer is mounted. */
135
+ get mounted() {
136
+ return this.#renderer !== void 0;
137
+ }
138
+ /** Mount `renderer`, or deliver a changed `context` to the mounted one. */
139
+ render(renderer, latest) {
140
+ this.#latest = latest;
141
+ const context = this.#stable(latest);
142
+ this.#container.setAttribute(this.#attribute, context.region);
143
+ if (!sameRenderer(renderer, this.#renderer)) {
144
+ this.#unmount();
145
+ this.#renderer = renderer;
146
+ this.#context = context;
147
+ this.#mount(renderer, context);
148
+ return;
149
+ }
150
+ if (this.#context && sameRegionContext(this.#context, context, this.#callbackKeys)) return;
151
+ this.#context = context;
152
+ if (this.#element) this.#element.context = context;
153
+ else this.#guard(() => this.#result?.update?.(context));
154
+ }
155
+ /** Tear the renderer down and empty the container. */
156
+ destroy() {
157
+ this.#unmount();
158
+ this.#renderer = void 0;
159
+ this.#context = void 0;
160
+ this.#latest = void 0;
161
+ }
162
+ /**
163
+ * `context` with its callbacks swapped for stable ones that call the latest product
164
+ * callback, so a renderer that kept an older context never calls a stale closure.
165
+ */
166
+ #stable(context) {
167
+ const latest = () => this.#latest ?? context;
168
+ const call = (key) => (...args) => latest()[key]?.(...args);
169
+ const stable = { ...context };
170
+ for (const key of this.#callbackKeys) if (key in context) stable[key] = call(key);
171
+ return stable;
172
+ }
173
+ #mount(renderer, context) {
174
+ if (typeof renderer === "function") {
175
+ const result = this.#guard(() => renderer(this.#container, context));
176
+ this.#result = typeof result === "function" ? { destroy: result } : result ?? void 0;
177
+ return;
178
+ }
179
+ const spec = typeof renderer === "string" ? { element: renderer } : renderer;
180
+ const element = this.#guard(() => this.#container.ownerDocument.createElement(spec.element));
181
+ if (!element) return;
182
+ Object.assign(element, spec.properties);
183
+ this.#element = element;
184
+ this.#element.context = context;
185
+ this.#container.append(element);
186
+ }
187
+ #unmount() {
188
+ const result = this.#result;
189
+ this.#result = void 0;
190
+ this.#guard(() => result?.destroy?.());
191
+ this.#element?.remove();
192
+ this.#element = void 0;
193
+ }
194
+ #guard(run) {
195
+ try {
196
+ return run();
197
+ } catch (error) {
198
+ console.error(`${this.#label} A host region renderer threw:`, error);
199
+ return void 0;
200
+ }
201
+ }
202
+ };
203
+ function createHostBackstagePages(backstage, options) {
204
+ let pages = [];
205
+ const hosts = /* @__PURE__ */ new Map();
206
+ const container = (page) => {
207
+ let host = hosts.get(page.id);
208
+ if (host) return host;
209
+ const element = backstage.ownerDocument.createElement("div");
210
+ element.dataset.backstagePage = hostBackstageItemId(page.id);
211
+ if (options.pageClass) element.className = options.pageClass;
212
+ element.hidden = true;
213
+ backstage.append(element);
214
+ host = new HostRegionHost(element, options.label ? { label: options.label } : {});
215
+ hosts.set(page.id, host);
216
+ return host;
217
+ };
218
+ const render = (page, host) => {
219
+ const region = hostBackstageRegionId(page.id);
220
+ host.render(page.render, options.context(region, page));
221
+ };
222
+ const drop = (id) => {
223
+ const host = hosts.get(id);
224
+ if (!host) return;
225
+ host.destroy();
226
+ host.container.remove();
227
+ hosts.delete(id);
228
+ };
229
+ return {
230
+ items(builtIn) {
231
+ return placeHostBackstagePages(builtIn, pages, (page) => ({
232
+ id: hostBackstageItemId(page.id),
233
+ label: page.label,
234
+ ...page.group === "footer" ? { group: "footer" } : {}
235
+ }));
236
+ },
237
+ setPages(next) {
238
+ pages = acceptedHostBackstagePages(next);
239
+ const kept = new Set(pages.map((page) => page.id));
240
+ for (const id of [...hosts.keys()]) if (!kept.has(id)) drop(id);
241
+ for (const page of pages) {
242
+ const host = hosts.get(page.id);
243
+ if (host?.mounted) render(page, host);
244
+ }
245
+ },
246
+ show(itemId) {
247
+ const id = hostBackstagePageId(itemId);
248
+ const page = id === void 0 ? void 0 : pages.find((candidate) => candidate.id === id);
249
+ if (!page) return false;
250
+ render(page, container(page));
251
+ return true;
252
+ },
253
+ refresh() {
254
+ for (const page of pages) {
255
+ const host = hosts.get(page.id);
256
+ if (host?.mounted) render(page, host);
257
+ }
258
+ },
259
+ destroy() {
260
+ for (const id of [...hosts.keys()]) drop(id);
261
+ }
262
+ };
263
+ }
264
+ function withHostMenuItems(items, commands, context) {
265
+ const rows = withHostMenuCommands(items, commands, context);
266
+ const host = /* @__PURE__ */ new Map();
267
+ const drawn = rows.map((row) => {
268
+ if (!isHostMenuEntry(row)) return row;
269
+ host.set(row.id, row);
270
+ return {
271
+ id: row.id,
272
+ label: row.label,
273
+ ...row.separatorBefore ? { separatorBefore: true } : {},
274
+ ...row.disabled ? { disabled: true } : {},
275
+ ...row.icon ? { icon: row.icon } : {}
276
+ };
277
+ });
278
+ return {
279
+ items: drawn,
280
+ run(id) {
281
+ const entry = host.get(id);
282
+ if (!entry) return false;
283
+ entry.onSelect();
284
+ return true;
285
+ }
286
+ };
287
+ }
288
+ var HOST_CHILD = "data-host-command";
289
+ var hostRuns = /* @__PURE__ */ new WeakMap();
290
+ function listen(menu) {
291
+ const runs = /* @__PURE__ */ new Map();
292
+ hostRuns.set(menu, runs);
293
+ menu.addEventListener("office-command", (event) => {
294
+ const id = event.detail?.command;
295
+ if (id) runs.get(id)?.onSelect();
296
+ });
297
+ return runs;
298
+ }
299
+ function syncHostMenuChildren(menu, commands, context) {
300
+ for (const child of [...menu.querySelectorAll(`:scope > [${HOST_CHILD}]`)]) child.remove();
301
+ const doc = menu.ownerDocument;
302
+ const { top, bottom } = resolveHostMenuCommands(commands, context);
303
+ const runs = hostRuns.get(menu) ?? listen(menu);
304
+ runs.clear();
305
+ const item = (entry) => {
306
+ runs.set(entry.id, entry);
307
+ const row = doc.createElement("office-ui-menu-item");
308
+ row.setAttribute(HOST_CHILD, "");
309
+ row.setAttribute("command", entry.id);
310
+ row.setAttribute("label", entry.label);
311
+ if (entry.icon) row.setAttribute("icon", entry.icon);
312
+ if (entry.disabled) row.setAttribute("disabled", "");
313
+ return row;
314
+ };
315
+ const separator = () => {
316
+ const rule = doc.createElement("office-ui-menu-separator");
317
+ rule.setAttribute(HOST_CHILD, "");
318
+ return rule;
319
+ };
320
+ const builtIn = menu.children.length > 0;
321
+ if (top.length) menu.prepend(...top.map(item), ...builtIn ? [separator()] : []);
322
+ if (bottom.length)
323
+ menu.append(...builtIn || top.length ? [separator()] : [], ...bottom.map(item));
324
+ }
325
+ var TIDY_HIDDEN = "data-separator-tidy";
326
+ function tidyMenuSeparators(menu) {
327
+ const isSeparator = (node) => node.localName === "office-ui-menu-separator";
328
+ const separators = [];
329
+ const rows = [];
330
+ let pending = [];
331
+ for (const child of menu.children) {
332
+ if (!(child instanceof HTMLElement)) continue;
333
+ if (isSeparator(child)) {
334
+ if (child.hidden && !child.hasAttribute(TIDY_HIDDEN)) continue;
335
+ separators.push(child);
336
+ pending.push(child);
337
+ continue;
338
+ }
339
+ rows.push({ row: child, before: pending, separatorBefore: pending.length > 0 });
340
+ pending = [];
341
+ }
342
+ const starts = new Map(
343
+ withoutHiddenEntries(rows, (entry) => entry.row.hidden !== false).map((entry) => [
344
+ entry.row,
345
+ entry.separatorBefore
346
+ ])
347
+ );
348
+ const shown2 = /* @__PURE__ */ new Set();
349
+ let carried = [];
350
+ for (const entry of rows) {
351
+ carried = [...carried, ...entry.before];
352
+ if (!starts.has(entry.row)) continue;
353
+ const separator = carried.at(-1);
354
+ if (starts.get(entry.row) && separator) shown2.add(separator);
355
+ carried = [];
356
+ }
357
+ for (const separator of separators) {
358
+ const hide = !shown2.has(separator);
359
+ separator.hidden = hide;
360
+ separator.toggleAttribute(TIDY_HIDDEN, hide);
361
+ }
362
+ }
363
+
364
+ export { HOST_REGION_ATTRIBUTE, HostRegionHost, createHostBackstagePages, defineRibbonAddInElements, syncHostMenuChildren, syncRibbonAddIns, tidyMenuSeparators, withHostMenuItems };
@@ -2,6 +2,7 @@ import { PROPERTY_FIELDS, type DocumentModel } from 'ooxml-core/docx';
2
2
  import type { DocumentStats } from 'ooxml-core/docx';
3
3
  import type { FileCommand } from './file-commands.js';
4
4
  import type { BackstageOptions, BackstageOptionKey } from './backstage-options.js';
5
+ import type { ResolvedWordCustomization, WordRegionContext } from './customization.js';
5
6
  /** What the File view needs from the editor; every value is read when a page opens. */
6
7
  export interface BackstageHandlers {
7
8
  fileCommand(command: FileCommand, fileName?: string): void;
@@ -21,6 +22,10 @@ export interface BackstageHandlers {
21
22
  ribbon(): HTMLElement | undefined;
22
23
  hiddenActions(): readonly string[];
23
24
  setHiddenActions(ids: string[]): void;
25
+ /** The host customisation: hidden pages and host pages (`backstage.extraPages`). */
26
+ customization(): ResolvedWordCustomization;
27
+ /** The context of a host page's region. */
28
+ regionContext(region: string): WordRegionContext;
24
29
  }
25
30
  export interface PageContext {
26
31
  handlers: BackstageHandlers;
@@ -11,6 +11,13 @@ export interface Backstage {
11
11
  readonly isOpen: boolean;
12
12
  /** Retranslates the navigation after the editor locale changed, and redraws the open page. */
13
13
  relocalize(): void;
14
+ /**
15
+ * Re-applies the host customisation: hides the pages disabled capabilities remove, places
16
+ * the host pages (`backstage.extraPages`) and delivers a fresh context to mounted ones.
17
+ */
18
+ refresh(): void;
19
+ /** Tears the host pages down. */
20
+ destroy(): void;
14
21
  }
15
22
  /**
16
23
  * Word's File view. Left: Back, Info, New, Open, Save and its siblings (Save As, Print, Export)
@@ -42,6 +42,7 @@ export declare class DocxEditorElement extends DocxEditorApi {
42
42
  get documentModel(): DocumentModel | null;
43
43
  set documentModel(value: DocumentModel | null);
44
44
  get readOnly(): boolean;
45
+ /** True when the document cannot be edited: this switch, a `viewer` role or `capabilities.edit` off. */
45
46
  set readOnly(value: boolean);
46
47
  /**
47
48
  * Shares the loaded document in a room while set; `null` leaves (see
@@ -1,6 +1,10 @@
1
1
  import type { EditorView } from 'prosemirror-view';
2
+ import { type MenuItem } from './context-menu-items.js';
2
3
  import { type EditorLocale } from './localization.js';
3
4
  import type { RibbonAction } from './ribbon-action.js';
5
+ import type { ResolvedWordCustomization } from './customization.js';
6
+ /** `items` without the `hidden` ids; a removed group start passes its separator on. */
7
+ export declare function withoutMenuItems(items: readonly MenuItem[], hidden: ReadonlySet<string>): MenuItem[];
4
8
  export interface ContextMenuHost {
5
9
  /** Element the menu is appended to (inside the shadow root, so theme tokens apply). */
6
10
  container: HTMLElement;
@@ -13,6 +17,8 @@ export interface ContextMenuHost {
13
17
  locale(): EditorLocale;
14
18
  run(action: RibbonAction): void;
15
19
  warn(message: string): void;
20
+ /** The host customisation: entries capabilities remove and host commands to add. */
21
+ customization(): ResolvedWordCustomization;
16
22
  }
17
23
  export interface ContextMenu {
18
24
  readonly isOpen: boolean;
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Applies `<docx-editor>`'s `customization` property: the capabilities reach the ribbon (through
3
+ * `hiddenActions`), the read-only state (a lock beside the host's switch and a viewer role), the
4
+ * File tab, the title bar, the context menu and the shortcuts, which all read the resolved object
5
+ * from `core.viewOptions.customization`.
6
+ */
7
+ import type { EditorCore } from './editor-core.js';
8
+ import { type WordCustomization, type WordRegionContext } from './customization.js';
9
+ /** Replaces the customisation (an equal object identity is a no-op) and re-applies it. */
10
+ export declare function setWordCustomization(core: EditorCore, value: WordCustomization | null): void;
11
+ /** The context of a host region of `<docx-editor>` (a File tab page). */
12
+ export declare function wordRegionContext(core: EditorCore, region: string): WordRegionContext;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * `<docx-editor>`'s `customization` property: the shared contract of `ooxml-core/embedding`
3
+ * (capabilities, host File tab pages, host context-menu commands) bound to Word. The host passes
4
+ * one plain object; `resolveWordCustomization` turns it into the sets every render site asks,
5
+ * so the ribbon, the File tab, the context menu, the shortcuts and the file commands agree.
6
+ */
7
+ import { type EditorCustomization, type HostBackstagePage, type HostMenuCommand, type HostRegionContextBase, type HostRegionRenderer } from 'ooxml-core/embedding';
8
+ import { type RibbonActionId, type WordBackstagePageId, type WordCapabilityId, type WordFileCommandId, type WordShortcutId } from 'ooxml-core/docx/ui';
9
+ /** What a host region (a File tab page) of `<docx-editor>` receives. */
10
+ export interface WordRegionContext extends HostRegionContextBase {
11
+ /** The `<docx-editor>` element: its whole public API (save, documentModel, readOnly...). */
12
+ readonly editor: HTMLElement;
13
+ /** The document's file name. */
14
+ readonly fileName: string;
15
+ }
16
+ /** What a host context-menu command of `<docx-editor>` receives: the menu's selection. */
17
+ export interface WordMenuContext {
18
+ /** The selected text; empty for a caret. */
19
+ readonly selectedText: string;
20
+ /** Selection start and end, as document positions (equal for a caret). */
21
+ readonly from: number;
22
+ readonly to: number;
23
+ /** True when the document cannot be edited (prop, capability, protection, collaboration). */
24
+ readonly readOnly: boolean;
25
+ readonly inTable: boolean;
26
+ readonly onLink: boolean;
27
+ }
28
+ export type WordRegionRenderer = HostRegionRenderer<HTMLElement, WordRegionContext>;
29
+ export type WordBackstagePage = HostBackstagePage<WordRegionRenderer>;
30
+ export type WordMenuCommand = HostMenuCommand<WordMenuContext>;
31
+ /** The whole `customization` object of `<docx-editor>`. Every field is optional. */
32
+ export type WordCustomization = EditorCustomization<WordCapabilityId, WordRegionRenderer, WordMenuContext>;
33
+ /** A customisation resolved into what each render site asks. */
34
+ export interface ResolvedWordCustomization {
35
+ /** False when `capabilities.edit` is off: the document opens read-only. */
36
+ readonly canEdit: boolean;
37
+ /** Ribbon controls the capabilities remove, unioned with `hiddenActions` by the ribbon. */
38
+ readonly hiddenActions: readonly RibbonActionId[];
39
+ readonly fileCommands: ReadonlySet<WordFileCommandId>;
40
+ readonly backstagePages: ReadonlySet<WordBackstagePageId>;
41
+ readonly shortcuts: ReadonlySet<WordShortcutId>;
42
+ /** Built-in context-menu entries to remove. */
43
+ readonly menuItems: ReadonlySet<string>;
44
+ /** True when `copy` is off: the editor also refuses copy and cut from the keyboard. */
45
+ readonly blockCopy: boolean;
46
+ readonly extraPages: readonly WordBackstagePage[];
47
+ readonly menuCommands: readonly WordMenuCommand[];
48
+ }
49
+ /** Resolves a host customisation (none: everything on, nothing added). */
50
+ export declare function resolveWordCustomization(customization?: WordCustomization | null): ResolvedWordCustomization;
51
+ /** The resolution of "no customisation", shared so it is allocated once. */
52
+ export declare const EMPTY_WORD_CUSTOMIZATION: ResolvedWordCustomization;
@@ -1,10 +1,12 @@
1
1
  import { type DocumentModel } from 'ooxml-core/docx';
2
+ import { type DocumentStorage } from 'ooxml-core/embedding';
2
3
  import { type Backstage } from './backstage.js';
3
4
  import type { BackstageOptions, BackstageOptionKey } from './backstage-options.js';
4
5
  import { type FileCommand } from './file-commands.js';
5
6
  import { type EditorLocale } from './localization.js';
6
7
  import { type RibbonActions } from './ribbon-actions.js';
7
8
  import { type StatusBar } from './status-bar.js';
9
+ import type { ResolvedWordCustomization, WordRegionContext } from './customization.js';
8
10
  import { type SaveState, type TitleBar } from './title-bar.js';
9
11
  /** What the chrome needs from the editor element; keeps component.ts free of chrome details. */
10
12
  export interface ChromeHost {
@@ -18,6 +20,8 @@ export interface ChromeHost {
18
20
  newDocument(): void;
19
21
  load(bytes: Uint8Array): Promise<void>;
20
22
  save(): Promise<Uint8Array>;
23
+ /** Host-owned storage for Save and Open, when the host set one. */
24
+ storage?(): DocumentStorage | undefined;
21
25
  print(): void;
22
26
  history(key: 'undo' | 'redo'): void;
23
27
  toggleComments(): void;
@@ -33,6 +37,10 @@ export interface ChromeHost {
33
37
  setOption(key: BackstageOptionKey, value: string): void;
34
38
  hiddenActions(): readonly string[];
35
39
  setHiddenActions(ids: string[]): void;
40
+ /** The resolved host customisation (`customization` property). */
41
+ customization(): ResolvedWordCustomization;
42
+ /** The context of a host region (a File tab page). */
43
+ regionContext(region: string): WordRegionContext;
36
44
  }
37
45
  export declare const DEFAULT_FILE_NAME = "Document1.docx";
38
46
  /**
@@ -58,9 +66,20 @@ export declare class EditorChrome {
58
66
  setSaveState(state: SaveState): void;
59
67
  setLocale(locale: EditorLocale): void;
60
68
  refresh(pageText: string, wordText: string): void;
69
+ /** Re-applies the host customisation to the File tab, title bar and ribbon actions. */
70
+ applyCustomization(): void;
61
71
  closeBackstage(): void;
62
72
  /** Runs a file command unless a host cancels the `file-command` event to handle it itself. */
63
73
  run(command: FileCommand, fileName?: string): Promise<void>;
74
+ /** True while a save is pending. */
75
+ saving: boolean;
76
+ /**
77
+ * Saves to the host's storage when there is one, else downloads a copy. An edit made while the
78
+ * save runs keeps the document dirty: the saved bytes do not contain it.
79
+ */
80
+ private saveDocument;
81
+ /** Opens from the host's storage when it can open, else shows the file picker. */
82
+ private open;
64
83
  private newDocument;
65
84
  private openSelectedFile;
66
85
  }
@@ -1,3 +1,4 @@
1
+ import type { DocumentStorage } from 'ooxml-core/embedding';
1
2
  import type { SurfaceHostActions } from './building-blocks-actions.js';
2
3
  import type { RibbonAddInTab } from '../ribbon/add-in-tabs.js';
3
4
  import { FormatDialogs } from './format-dialogs.js';
@@ -62,11 +63,32 @@ export declare class EditorCore {
62
63
  loaded?: LoadedDocument | undefined;
63
64
  loadGeneration: number;
64
65
  loading: boolean;
65
- readOnly: boolean;
66
+ /** The host's `readOnly` switch. A collaboration `viewer` role locks the editor on top of it. */
67
+ hostReadOnly: boolean;
68
+ /** True while `applyReadOnly` writes the `read-only` attribute. */
69
+ reflectingReadOnly: boolean;
70
+ private shownReadOnly;
71
+ private shownHostReadOnly;
72
+ /**
73
+ * Effective: the host's switch, a `viewer` role, or `capabilities.edit` off. Assigning sets
74
+ * the host's switch only, so nothing that assigns it can lift the other two.
75
+ */
76
+ get readOnly(): boolean;
77
+ set readOnly(value: boolean);
78
+ /** Applies the effective value to the view, controls and attribute. */
79
+ applyReadOnly(): void;
80
+ /** True while a collaboration `viewer` role holds the editor read-only. */
81
+ get roleLocked(): boolean;
82
+ /** Applies the effective value, then reports it when it or the host's switch changed. */
83
+ reportReadOnly(change?: () => void): void;
84
+ /** Joining or leaving a room can change the role lock: apply it and report a change. */
85
+ roleChanged(): void;
66
86
  /** Set before mounting to render only the document surface. */
67
87
  surfaceOnly: boolean;
68
88
  /** Host-owned workflows for surface mode (link, find and replace, picture picker). */
69
89
  surfaceActions: SurfaceHostActions;
90
+ /** Where File > Save and Open go instead of a download and the file picker (`storage`). */
91
+ storage: DocumentStorage | undefined;
70
92
  locale: EditorLocale;
71
93
  reviewAuthor: string;
72
94
  theme: EditorThemeMode;
@@ -1,9 +1,11 @@
1
+ import type { DocumentStorage } from 'ooxml-core/embedding';
1
2
  import type { RibbonAddInTab } from '../ribbon/add-in-tabs.js';
2
3
  import type { CollabSession } from 'ooxml-core/collab';
3
4
  import type { WordYjsOptions } from 'ooxml-core/docx/ui';
4
5
  import type { DocxCollaborationState } from './collaboration-types.js';
5
6
  import type { EditorCore } from './editor-core.js';
6
7
  import { type RibbonActionId, type RibbonActionInput } from 'ooxml-core/docx/ui';
8
+ import type { WordCustomization } from './customization.js';
7
9
  import { type WordToolbarProps } from './building-blocks.js';
8
10
  import { type WordNavigationProps, type WordStatusProps } from './building-blocks-status.js';
9
11
  import type { SurfaceHostActions } from './building-blocks-actions.js';
@@ -27,6 +29,14 @@ export declare abstract class DocxEditorApi extends HTMLElementBase {
27
29
  */
28
30
  get surfaceActions(): SurfaceHostActions;
29
31
  set surfaceActions(value: SurfaceHostActions);
32
+ /**
33
+ * Host-owned storage. When set, File > Save and Save As hand the saved bytes to
34
+ * `storage.save()` instead of downloading them, and File > Open asks `storage.open()` (when it
35
+ * has one) instead of showing the file picker. The cancelable `file-command` event still fires
36
+ * first; a host that prevents it handles the command itself.
37
+ */
38
+ get storage(): DocumentStorage | undefined;
39
+ set storage(value: DocumentStorage | null | undefined);
30
40
  get loading(): boolean;
31
41
  /** Selection and formatting updates, including changes which do not dirty the document. */
32
42
  subscribeEditorState(listener: () => void): () => void;
@@ -64,6 +74,14 @@ export declare abstract class DocxEditorApi extends HTMLElementBase {
64
74
  */
65
75
  get hiddenActions(): readonly RibbonActionId[];
66
76
  set hiddenActions(value: readonly RibbonActionInput[]);
77
+ /**
78
+ * The host customisation (`WordCustomization`): `capabilities` (removing every UI path to
79
+ * what is switched off), `backstage.extraPages` (host File tab pages) and
80
+ * `contextMenu.extraCommands` (host context-menu commands). The object is applied when its
81
+ * identity changes, so keep it stable; `null` restores the defaults.
82
+ */
83
+ get customization(): WordCustomization | null;
84
+ set customization(value: WordCustomization | null | undefined);
67
85
  /** True after an edit until the document is saved through File > Save, `download()`, loaded or `markClean()`. */
68
86
  get dirty(): boolean;
69
87
  /** Declares the current content saved, for hosts that persist the result of `save()` themselves. */